From 53651e353ff838fc5b727317e34ca4416e47b842 Mon Sep 17 00:00:00 2001 From: baked-mac <164051931+baked-mac@users.noreply.github.com> Date: Thu, 9 Jul 2026 19:39:08 +0800 Subject: [PATCH] Add release signing config and link README to GitHub Releases Wires a release keystore (gitignored) into the app signing config so assembleRelease produces a signed APK, and points the README at the published v1.0.0 release for direct APK downloads. --- .gitignore | 6 +++++ README.md | 7 ++++- app/keystore.properties.example | 4 +++ .../AndroidApplicationConventionPlugin.kt | 27 ++++++++++++++++++- 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 app/keystore.properties.example diff --git a/.gitignore b/.gitignore index 88e5b0c..3282f43 100644 --- a/.gitignore +++ b/.gitignore @@ -17,5 +17,11 @@ local.properties # Firebase config — each developer supplies their own (see README) app/google-services.json +# Release signing — never commit the keystore or its credentials +app/keystore/ +app/keystore.properties +*.jks +*.keystore + # Internal planning docs — not part of the public repo docs/ diff --git a/README.md b/README.md index 6141106..30a8437 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,12 @@ An editorial cooking companion for Android. Browse, cook, and remember — the f ![Room](https://img.shields.io/badge/Room-2.7.1-48B983?style=flat-square) ![Koin](https://img.shields.io/badge/Koin-4.0.0-F88909?style=flat-square) ![Min SDK](https://img.shields.io/badge/minSdk-24-3DDC84?style=flat-square&logo=android&logoColor=white) -[![CI](https://github.com/whatsername0414/saffron/actions/workflows/ci.yml/badge.svg)](https://github.com/whatsername0414/saffron/actions/workflows/ci.yml) +[![CI](https://github.com/maceljonray/saffron/actions/workflows/ci.yml/badge.svg)](https://github.com/maceljonray/saffron/actions/workflows/ci.yml) +[![Latest release](https://img.shields.io/github/v/release/maceljonray/saffron?style=flat-square&color=C8860A&label=release)](https://github.com/maceljonray/saffron/releases/latest) + +## Download + +Grab a signed release build from the [Releases page](https://github.com/maceljonray/saffron/releases/latest) — no build required. This is a portfolio/demo app, not published on the Play Store, so you'll need to sideload the APK (enable "install from unknown sources" if prompted). Requires Android 7.0 (API 24) or higher. ## Screenshots diff --git a/app/keystore.properties.example b/app/keystore.properties.example new file mode 100644 index 0000000..61390ef --- /dev/null +++ b/app/keystore.properties.example @@ -0,0 +1,4 @@ +storeFile=keystore/release.jks +storePassword=changeme +keyAlias=saffron-release +keyPassword=changeme diff --git a/build-logic/src/main/kotlin/AndroidApplicationConventionPlugin.kt b/build-logic/src/main/kotlin/AndroidApplicationConventionPlugin.kt index 365d669..688a64b 100644 --- a/build-logic/src/main/kotlin/AndroidApplicationConventionPlugin.kt +++ b/build-logic/src/main/kotlin/AndroidApplicationConventionPlugin.kt @@ -3,6 +3,8 @@ import org.gradle.api.JavaVersion import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.kotlin.dsl.configure +import java.io.FileInputStream +import java.util.Properties /** * Convention plugin for the `:app` module: AGP application + Compose, SDK levels, @@ -11,7 +13,9 @@ import org.gradle.kotlin.dsl.configure * debug: `.debug` applicationIdSuffix/versionNameSuffix so it can install alongside release; * requires a matching Firebase Android app (`com.saffron.cook.debug`) in `google-services.json`. * release: R8 shrink+obfuscate enabled via `optimization { enable = true }`, picking up keep - * rules from every module's `src/main/keepRules/rules.keep`. + * rules from every module's `src/main/keepRules/rules.keep`. Signed via `app/keystore.properties` + * (gitignored, see `app/keystore.properties.example`) when present; falls back to the default + * (unsigned) release config otherwise, so a clone without the keystore still builds. * * Module-specific config (namespace, applicationId, versionCode/Name, testInstrumentationRunner) * stays in `app/build.gradle.kts`. @@ -24,6 +28,13 @@ class AndroidApplicationConventionPlugin : Plugin { apply("saffron.android.compose") } + val keystorePropertiesFile = target.file("keystore.properties") + val keystoreProperties = Properties() + val hasSigningConfig = keystorePropertiesFile.exists() + if (hasSigningConfig) { + keystoreProperties.load(FileInputStream(keystorePropertiesFile)) + } + extensions.configure { compileSdk = 37 @@ -41,6 +52,17 @@ class AndroidApplicationConventionPlugin : Plugin { buildConfig = true } + if (hasSigningConfig) { + signingConfigs { + create("release") { + storeFile = target.file(keystoreProperties.getProperty("storeFile")) + storePassword = keystoreProperties.getProperty("storePassword") + keyAlias = keystoreProperties.getProperty("keyAlias") + keyPassword = keystoreProperties.getProperty("keyPassword") + } + } + } + buildTypes { debug { applicationIdSuffix = ".debug" @@ -52,6 +74,9 @@ class AndroidApplicationConventionPlugin : Plugin { optimization { enable = true } + if (hasSigningConfig) { + signingConfig = signingConfigs.getByName("release") + } } } }