diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5cec2b6..6e694df 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -32,7 +32,17 @@ jobs: id: version run: echo "name=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT" + - name: Decode release keystore + env: + RELEASE_KEYSTORE_BASE64: ${{ secrets.RELEASE_KEYSTORE_BASE64 }} + run: echo "$RELEASE_KEYSTORE_BASE64" | base64 -d > "$RUNNER_TEMP/release.jks" + - name: Build release APK + env: + RELEASE_KEYSTORE_FILE: ${{ runner.temp }}/release.jks + RELEASE_KEYSTORE_PASSWORD: ${{ secrets.RELEASE_KEYSTORE_PASSWORD }} + RELEASE_KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }} + RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }} run: | chmod +x gradlew ./gradlew :app:assembleRelease \ diff --git a/.gitignore b/.gitignore index aa724b7..cdf1c34 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,7 @@ .externalNativeBuild .cxx local.properties + +# Signing keys — never commit these +*.jks +*.keystore diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 1083ad1..91d7bcc 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -15,8 +15,8 @@ android { targetSdk = 36 // Defaults for local builds; the release CI workflow overrides these from the git tag // (-PappVersionName) and the run number (-PappVersionCode). - versionCode = (project.findProperty("appVersionCode") as String?)?.toInt() ?: 3 - versionName = (project.findProperty("appVersionName") as String?) ?: "1.2" + versionCode = (project.findProperty("appVersionCode") as String?)?.toInt() ?: 4 + versionName = (project.findProperty("appVersionName") as String?) ?: "1.3" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" vectorDrawables { @@ -24,6 +24,22 @@ android { } } + // Release signing key. Provided by the CI workflow via environment variables (decoded from + // GitHub secrets); when absent (local builds) we fall back to the debug key below. Using a + // single, stable key for every release is what lets users update in place instead of + // hitting a signature mismatch. + val releaseKeystoreFile = System.getenv("RELEASE_KEYSTORE_FILE") + signingConfigs { + if (releaseKeystoreFile != null) { + create("release") { + storeFile = file(releaseKeystoreFile) + storePassword = System.getenv("RELEASE_KEYSTORE_PASSWORD") + keyAlias = System.getenv("RELEASE_KEY_ALIAS") + keyPassword = System.getenv("RELEASE_KEY_PASSWORD") + } + } + } + buildTypes { release { isMinifyEnabled = false @@ -31,10 +47,12 @@ android { getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" ) - // Sign release builds with the debug key so the CI-produced APK is installable - // without any keystore secrets. Replace with a real signingConfig if you ever - // want to publish properly signed builds. - signingConfig = signingConfigs.getByName("debug") + signingConfig = if (releaseKeystoreFile != null) { + signingConfigs.getByName("release") + } else { + // Local builds without the release secrets: debug-sign so the APK still installs. + signingConfigs.getByName("debug") + } } } compileOptions {