From 35b75a2ed88fcd3a28d51e16af0ef3efa3ad56f6 Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Tue, 21 Apr 2026 19:55:55 +0300 Subject: [PATCH] ci(android): fix keystore env scoping, fail loudly on release without key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Primary bug — step-level env is not visible in that same step's `if:` expression. `Decode signing keystore` had if: env.ANDROID_KEYSTORE_BASE64 != '' env: ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} so the env context seen by the `if:` evaluator was empty regardless of whether the secret was configured. The step was skipped, keystore.present never became 'true', and every release tag silently fell back to assembleDebug. Result: APKs named `LedGrab-0.4.0-android-debug.apk` that can't upgrade a previously-release-signed install (signature mismatch). Fix — move ANDROID_KEYSTORE_BASE64 to the job-level env block. It's now resolvable in the if-expression of any step in the job, and the shell inherits it exactly the same way as before. Secondary — add a "Guard release tag against missing keystore" step that fires between the decode attempt and the gradle build. If is_release=true but keystore.present!='true', the job fails with a clear error directing the operator to configure the four signing secrets. Previously a misconfigured Gitea silently shipped debug APKs labeled as releases. --- .gitea/workflows/build-android.yml | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/build-android.yml b/.gitea/workflows/build-android.yml index 16130ee..f27cf42 100644 --- a/.gitea/workflows/build-android.yml +++ b/.gitea/workflows/build-android.yml @@ -23,6 +23,12 @@ jobs: ANDROID_SDK_PLATFORM: 'android-34' ANDROID_BUILD_TOOLS: '34.0.0' ANDROID_NDK_VERSION: '26.1.10909125' + # Surfaced at job level (not step level) so the `if: env.X != ''` + # check on the Decode step actually sees it — step-level env is + # NOT available in that step's own `if:` expression, which + # silently skipped the decode and produced debug-signed release + # APKs until it was noticed. + ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} steps: - name: Checkout uses: actions/checkout@v4 @@ -108,15 +114,23 @@ jobs: - name: Decode signing keystore id: keystore - if: ${{ env.ANDROID_KEYSTORE_BASE64 != '' }} - env: - ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} + if: env.ANDROID_KEYSTORE_BASE64 != '' run: | + set -euo pipefail mkdir -p android/keystore echo "$ANDROID_KEYSTORE_BASE64" | base64 -d > android/keystore/release.jks echo "path=$(pwd)/android/keystore/release.jks" >> "$GITHUB_OUTPUT" echo "present=true" >> "$GITHUB_OUTPUT" + - name: Guard release tag against missing keystore + # Release tags MUST produce a release-signed APK, otherwise existing + # installs can't upgrade (signature mismatch). Fail loudly instead + # of silently falling back to the debug signing config. + if: ${{ steps.label.outputs.is_release == 'true' && steps.keystore.outputs.present != 'true' }} + run: | + echo "::error::Release tag ${{ gitea.ref_name }} requires ANDROID_KEYSTORE_BASE64 (plus KEYSTORE_PASSWORD, KEY_ALIAS, KEY_PASSWORD) to be configured in Gitea → Settings → Secrets." + exit 1 + - name: Build APK working-directory: android env: