Skip to content

Commit 877cabc

Browse files
committed
Fail on a malformed signing secret at the step that reads it
The first run with secrets present died on `base64: invalid input`. The secret was there; it had a carriage return on the end, because piping a value into `gh secret set` from PowerShell appends CRLF and GNU base64 treats a lone CR as invalid. Nothing in that message points at the shell that set the secret. Whitespace is now stripped before decoding, and the keystore is opened with keytool right there. The password secrets carry the same CRLF hazard, and a trailing byte on the password would otherwise have surfaced much later as a signing failure blaming the keystore rather than the value.
1 parent 41df015 commit 877cabc

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

.github/workflows/android-build.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,23 @@ jobs:
7979
id: keystore
8080
env:
8181
KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
82+
KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
8283
run: |
8384
if [ -z "$KEYSTORE_BASE64" ]; then
8485
echo "No ANDROID_KEYSTORE_BASE64 secret; the release APK will be unsigned."
8586
echo "signed=false" >> "$GITHUB_OUTPUT"
8687
exit 0
8788
fi
88-
echo "$KEYSTORE_BASE64" | base64 -d > "$RUNNER_TEMP/release.jks"
89+
# Strip whitespace before decoding. GNU base64 rejects a lone CR as
90+
# invalid input, and a secret set from a Windows shell or pasted into
91+
# the web UI picks one up easily — the failure message says nothing
92+
# about where the stray byte came from.
93+
printf '%s' "$KEYSTORE_BASE64" | tr -d '[:space:]' | base64 -d > "$RUNNER_TEMP/release.jks"
94+
if ! keytool -list -keystore "$RUNNER_TEMP/release.jks" \
95+
-storepass "$KEYSTORE_PASSWORD" >/dev/null 2>&1; then
96+
echo "The keystore decoded but will not open. Check ANDROID_KEYSTORE_PASSWORD." >&2
97+
exit 1
98+
fi
8999
echo "signed=true" >> "$GITHUB_OUTPUT"
90100
91101
- name: Build the release APK

docs/android-release.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,24 @@ keyPassword=…
7070
| `ANDROID_KEY_ALIAS` | `vitranslate` |
7171
| `ANDROID_KEY_PASSWORD` | the key password |
7272

73+
Set them with `gh secret set NAME --body "<value>"`, not by piping. A pipe from
74+
PowerShell appends CRLF, and a password secret with a trailing carriage return
75+
fails later with a signing error that names the wrong cause. The workflow now
76+
strips whitespace from the base64 and opens the keystore with `keytool` before
77+
building, so a bad secret fails at the step that set it.
78+
79+
From PowerShell:
80+
81+
```powershell
82+
$d = "C:\path\to\signing"
83+
$pw = Get-Content "$d\password.txt" -Raw
84+
$b64 = [Convert]::ToBase64String([IO.File]::ReadAllBytes("$d\vitranslate-release.jks"))
85+
gh secret set ANDROID_KEYSTORE_BASE64 --body $b64
86+
gh secret set ANDROID_KEYSTORE_PASSWORD --body $pw
87+
gh secret set ANDROID_KEY_ALIAS --body "vitranslate"
88+
gh secret set ANDROID_KEY_PASSWORD --body $pw
89+
```
90+
7391
Without `ANDROID_KEYSTORE_BASE64` the workflow still builds, but the artifact
7492
is named `PDFTranslate-android-<version>-unsigned.apk` and the publish job
7593
refuses to release it. An unsigned APK will not install on a device; use the

0 commit comments

Comments
 (0)