ci(play): publish release tags straight to production, not internal (#177)

Play production served versionCode 136 (v0.4.5, 2026-06-22) for eight weeks
because a tag push only reached the `internal` track and production needed a
second, easily-forgotten workflow_dispatch. Sentry release health on 2026-08-14
shows the cost: 64% of 30d-active users pinned to v0.4.10 and 0.2% on the
gated v0.4.14, which caps the AGE-105 client-side noise gate at a small slice
of the error volume it was written to remove.

- non-dispatch runs (tag push / release published) resolve to
  track=production, status=completed
- workflow_dispatch keeps its track/status inputs (default internal) for dry runs
- serialize per-ref with a concurrency group so a tag push and a
  `release: published` for the same version cannot race two uploads
- job summary records event -> resolved track/status + the real versionCode
- PUBLISHING.md claimed the service account is "internal track only"; run
  31807432647 published to production successfully on 2026-08-14, so that
  claim is removed rather than worked around

Co-authored-by: engineer <engineer@macbookpro.lan>
Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Den
2026-08-14 09:36:16 -07:00
committed by GitHub
parent 1852eb8466
commit dde4553016
3 changed files with 70 additions and 18 deletions

View File

@@ -26,6 +26,13 @@ on:
- completed
- draft
# A tag push and a `release: published` for the same version must not race two
# uploads into the same track. Serialize per ref instead of cancelling, because
# cancelling mid-upload can leave a half-created Play release.
concurrency:
group: publish-play-store-${{ github.ref }}
cancel-in-progress: false
jobs:
publish:
runs-on: ubuntu-latest
@@ -143,12 +150,47 @@ jobs:
name: app-release-bundle
path: android/app/build/outputs/bundle/release/app-release.aab
- name: Resolve Play track
id: channel
# AGE-110: releases used to land on `internal` and stop there — production
# only moved when a human remembered to run workflow_dispatch. It served
# versionCode 136 (v0.4.5, 2026-06-22) for EIGHT weeks for that reason,
# which is why a client-side fix shipped in v0.4.14 could not reach the
# install base. A release tag is already a deliberate act; treat it as one
# and publish it to the auto-updating channel. Manual dispatch keeps its
# inputs so `internal`/`draft` dry runs are still one click away.
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
TRACK="${{ github.event.inputs.track || 'internal' }}"
STATUS="${{ github.event.inputs.status || 'completed' }}"
else
TRACK=production
STATUS=completed
fi
echo "track=$TRACK" >> "$GITHUB_OUTPUT"
echo "status=$STATUS" >> "$GITHUB_OUTPUT"
echo "event=${{ github.event_name }} -> track=$TRACK status=$STATUS"
- name: Publish to Play Store
uses: r0adkll/upload-google-play@e738b9dd8f2476ea806d921b64aacd24f34515a5 # v1.1.5
with:
serviceAccountJsonPlainText: ${{ secrets.PLAY_STORE_SERVICE_ACCOUNT_JSON }}
packageName: cc.agentlabs.opencode
releaseFiles: android/app/build/outputs/bundle/release/app-release.aab
track: ${{ github.event.inputs.track || 'internal' }}
status: ${{ github.event.inputs.status || 'completed' }}
track: ${{ steps.channel.outputs.track }}
status: ${{ steps.channel.outputs.status }}
whatsNewDirectory: distribution/whatsnew
- name: Record where it landed
if: always()
run: |
{
echo "### Play publish"
echo ""
echo "- event: \`${{ github.event_name }}\`"
echo "- track: \`${{ steps.channel.outputs.track }}\`"
echo "- status: \`${{ steps.channel.outputs.status }}\`"
echo "- versionCode: \`$(node -p "require('./app.json').expo.android.versionCode" 2>/dev/null || echo unknown)\`"
echo "- version: \`$(node -p "require('./app.json').expo.version" 2>/dev/null || echo unknown)\`"
} >> "$GITHUB_STEP_SUMMARY"