Repository navigation
ci(publish): finalize the Publish to Google Play workflow - #31
Conversation
- One clean keystore step: decode KEYSTORE_BASE64 keeping only base64 characters, keep only printable ASCII in the password/alias secrets (the repo's secrets were pasted with a UTF-8 BOM, which broke signing on the first run), verify the keystore opens and the alias exists, mask the values. No diagnostics, no secret values in logs. - Remove the never-active copy under store_assets/workflows/ (GitHub only runs workflows in .github/workflows/); document the CI path in store_assets/README.md and PLAY_SUBMISSION.md. - Manual trigger only (workflow_dispatch); Play itself refuses a reused version code, so a re-run with the same number cannot double-upload. Proven on 2026-10-09: built, signed and uploaded 1.1.1 (versionCode 4) to the production track.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4929b2cfa5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # KEY_ALIAS, GOOGLE_PLAY_SERVICE_ACCOUNT_JSON, ADMOB_*), then uploads it to the | ||
| # chosen Play track. Manual trigger only, so nothing publishes by accident. | ||
| # status "draft" -> stages the release; review it and send for review in Play Console | ||
| # status "completed" -> rolls the release out (Play still reviews it first) |
There was a problem hiding this comment.
Do not promise rollout while opting out of review
When an operator selects completed, this comment says the release will roll out after Play reviews it, but the upload step still sets changesNotSentForReview: true at line 125. The action documents that this value prevents review until someone explicitly sends the changes from Play Console, so the workflow can finish successfully while the expected production rollout never begins; either retain the documented manual Console step or conditionally disable this option for completed. See the action input documentation.
Useful? React with 👍 / 👎.
| echo "keystore opens OK" | ||
| { echo "KEYSTORE_FILE=$RUNNER_TEMP/release.jks"; echo "KEYSTORE_PASSWORD=$STORE_PW"; echo "KEY_PASSWORD=$KP_USE"; echo "KEY_ALIAS=$ALIAS_T"; } >> "$GITHUB_ENV" | ||
| printf '%s' "$KEYSTORE_BASE64" | tr -cd 'A-Za-z0-9+/=' | base64 -d > "$RUNNER_TEMP/release.jks" | ||
| STORE_PW="$(ascii "$KEYSTORE_PASSWORD")"; KEY_PW="$(ascii "$KEY_PASSWORD")"; ALIAS="$(ascii "$KEY_ALIAS")" |
There was a problem hiding this comment.
Preserve valid non-ASCII keystore passwords
For a JKS whose store password legitimately contains a non-ASCII character, ascii removes the UTF-8 bytes before invoking keytool, so every publish run now fails the keystore validation. The previous candidate loop eventually tried the raw or newline-trimmed KEYSTORE_PASSWORD, whereas this assignment unconditionally uses the lossy value; strip only the known BOM/line-ending contamination rather than restricting valid passwords to printable ASCII.
Useful? React with 👍 / 👎.
| echo "base64 secret: chars ${#KEYSTORE_BASE64}, bytes $(printf '%s' "$KEYSTORE_BASE64" | wc -c), non-base64 bytes: $(printf '%s' "$KEYSTORE_BASE64" | tr -d 'A-Za-z0-9+/=' | wc -c) (hex of those: $(printf '%s' "$KEYSTORE_BASE64" | tr -d 'A-Za-z0-9+/=' | xxd -p | head -c 40))" | ||
| # Secrets pasted from files can carry invisible characters: try as stored, trimmed, and printable-ASCII only. | ||
| trim() { printf '%s' "$1" | tr -d '\r\n\t'; } | ||
| for v in KEYSTORE_BASE64 KEYSTORE_PASSWORD KEY_PASSWORD KEY_ALIAS; do |
There was a problem hiding this comment.
WARNING: Missing validation for GOOGLE_PLAY_SERVICE_ACCOUNT_JSON secret
The workflow validates KEYSTORE_BASE64, KEYSTORE_PASSWORD, KEY_PASSWORD, and KEY_ALIAS here (lines 70-72), but GOOGLE_PLAY_SERVICE_ACCOUNT_JSON (used at line 118 for the upload step) is not validated. If this secret is missing, the workflow will fail at the upload step with an unclear authentication error rather than a clear "secret is missing" message.
Consider adding it to the validation loop:
| for v in KEYSTORE_BASE64 KEYSTORE_PASSWORD KEY_PASSWORD KEY_ALIAS; do | |
| for v in KEYSTORE_BASE64 KEYSTORE_PASSWORD KEY_PASSWORD KEY_ALIAS GOOGLE_PLAY_SERVICE_ACCOUNT_JSON; do |
And mask it (optional, since it's JSON):
| for v in KEYSTORE_BASE64 KEYSTORE_PASSWORD KEY_PASSWORD KEY_ALIAS; do | |
| echo "::add-mask::$STORE_PW"; echo "::add-mask::$KEY_PW"; echo "::add-mask::${GOOGLE_PLAY_SERVICE_ACCOUNT_JSON}" |
Reply with @kilocode-bot fix it to have Kilo Code address this issue.
Code Review SummaryStatus: 1 Issue Found | Recommendation: Address before merge Overview
Issue Details (click to expand)WARNING
Files Reviewed (4 files)
Fix these issues in Kilo Cloud Reviewed by free · Input: 201.1K · Output: 7.8K · Cached: 47.5K |
Follow-up to #30. Makes the Publish to Google Play workflow the one way to build and upload a signed release.
What it does
track(internal/alpha/beta/production),status(draft= stage for review in Play Console,completed= roll out),version_code,version_name, release notesKEYSTORE_BASE64, usesKEYSTORE_PASSWORD/KEY_PASSWORD/KEY_ALIAS, verifies the keystore opens and the alias exists (values masked, never printed), builds:app:bundleRelease, runsjarsigner -verify, keeps the AAB as a run artifact, uploads to Play withGOOGLE_PLAY_SERVICE_ACCOUNT_JSONAlso
store_assets/workflows/(GitHub only runs.github/workflows/)store_assets/README.mdandPLAY_SUBMISSION.mdProven today: run #37951289668 built, signed and uploaded 1.1.1 (versionCode 4) to production, now in review.