Skip to content

Commit 15ea3c4

Browse files
Merge pull request #505 from off-grid-ai/fix/release-apk-signing
fix(release): release-sign the GitHub-release APK (was debug-signed)
2 parents 362ca5b + 6a7bd4f commit 15ea3c4

1 file changed

Lines changed: 27 additions & 11 deletions

File tree

.github/workflows/release.yml

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,27 @@ jobs:
9999
100100
cat release-notes.md
101101
102+
# Decode the keystore BEFORE building the APK so the GitHub-release APK is RELEASE-signed,
103+
# not debug-signed. Gated on the KEYSTORE ALONE (not the Play key) — APK signing only needs
104+
# the keystore; coupling it to PLAY_STORE_JSON_KEY would debug-sign the APK in keystore-only
105+
# setups. Only the keystore FILE PATH goes into $GITHUB_ENV (a path, so newline-safe); the
106+
# secret-derived props are passed as static step env below (no env-file parsing). build.gradle
107+
# gates release signing on project.hasProperty('OFFGRID_UPLOAD_STORE_FILE'), so when the
108+
# keystore is absent the prop is unset and the build falls back to debug signing.
109+
- name: Decode keystore
110+
if: ${{ env.ANDROID_KEYSTORE_BASE64 != '' }}
111+
run: |
112+
echo "$ANDROID_KEYSTORE_BASE64" | base64 --decode > "$RUNNER_TEMP/release.keystore"
113+
echo "ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_STORE_FILE=$RUNNER_TEMP/release.keystore" >> "$GITHUB_ENV"
114+
102115
- name: Build Android Release APK
116+
env:
117+
# Secret-derived signing props: static step env (never $GITHUB_ENV) so a newline in a
118+
# secret can't corrupt the env file. build.gradle only reads these inside the
119+
# hasProperty(STORE_FILE) block, so when the keystore is absent they're simply unused.
120+
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_STORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
121+
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
122+
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}
103123
run: |
104124
cd android
105125
./gradlew assembleRelease
@@ -127,27 +147,23 @@ jobs:
127147
if-no-files-found: error
128148

129149
# ── Play Store upload (in addition to the GitHub Release above) ──────────
130-
# Decodes the production keystore + Play service-account key from secrets, builds
131-
# a signed AAB, and uploads to the Play production track as a DRAFT (a human
132-
# confirms rollout in the Play Console). Skipped automatically if the secrets are
133-
# absent, so the GitHub Release path still works without them.
134-
- name: Decode signing secrets
150+
# Decodes the Play service-account key, then builds the signed AAB and uploads it to the
151+
# Play production track as a DRAFT (a human confirms rollout in the Play Console). Needs
152+
# BOTH the keystore (decoded above → STORE_FILE prop) and the Play key, so it's gated on
153+
# both; skipped when either is absent, and the GitHub Release path above still works.
154+
- name: Decode Play service-account key
135155
if: ${{ env.ANDROID_KEYSTORE_BASE64 != '' && env.PLAY_STORE_JSON_KEY != '' }}
136156
run: |
137-
echo "$ANDROID_KEYSTORE_BASE64" | base64 --decode > "$RUNNER_TEMP/release.keystore"
138157
# PLAY_STORE_JSON_KEY may be stored raw-JSON or base64 — handle both (matches uat-dev.yml).
139158
echo "$PLAY_STORE_JSON_KEY" | base64 --decode > "$RUNNER_TEMP/play-key.json" \
140159
|| printf '%s' "$PLAY_STORE_JSON_KEY" > "$RUNNER_TEMP/play-key.json"
141-
echo "PLAY_UPLOAD=1" >> $GITHUB_ENV
160+
echo "PLAY_UPLOAD=1" >> "$GITHUB_ENV"
142161
143162
- name: Build signed AAB + upload to Play (draft)
144163
if: ${{ env.PLAY_UPLOAD == '1' }}
145164
env:
146165
PLAY_STORE_JSON_KEY_PATH: ${{ runner.temp }}/play-key.json
147-
# build.gradle gates release signing on project.hasProperty(...), so these must be
148-
# Gradle PROJECT properties (ORG_GRADLE_PROJECT_<name>), not plain env — otherwise
149-
# the AAB falls back to debug signing and Play rejects it.
150-
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_STORE_FILE: ${{ runner.temp }}/release.keystore
166+
# Same static signing props as the APK build (STORE_FILE comes from $GITHUB_ENV).
151167
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_STORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
152168
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
153169
ORG_GRADLE_PROJECT_OFFGRID_UPLOAD_KEY_PASSWORD: ${{ secrets.ANDROID_KEY_PASSWORD }}

0 commit comments

Comments
 (0)