From a6ef73bbb6ceb6e4a066cf95f1c1421fbecc80fb Mon Sep 17 00:00:00 2001 From: Dylan Audius Date: Fri, 15 May 2026 15:07:54 -0700 Subject: [PATCH] ci(mobile): stop OTA workflow from wiping CodePush release history The OTA jobs called `code-push create-history` on every push and every workflow_dispatch. That command writes a fresh history JSON containing only the binary-version placeholder and uploads it to s3://.../mobile-ota/histories///.json, overwriting every prior entry. The subsequent `code-push release` step then read that wiped file and wrote it back with just `[placeholder, latest_OTA]`, so each run silently dropped every previously-published OTA bundle for that binary version. Live state today across all four files (verified via download.audius.co/mobile-ota/histories/{ios,android}/{rc,production}/1.5.179.json): iOS rc -> [1.5.179, 1.5.100776] iOS prod -> [1.5.179, 1.5.100775] Android rc -> [1.5.179, 1.5.100776] Android prod -> [1.5.179, 1.5.100775] Per packages/mobile/OTA_UPDATES.md, `create-history` is meant to be a one-time init when shipping a new native binary, not part of the OTA release loop. The client (packages/mobile/src/app/ota-updates.ts) already substitutes a no-update placeholder if the history JSON is missing or empty, so the call isn't needed to keep CodePush from throwing "There is no latest release." Also adds a per-platform concurrency group so two pushes landing close together can't race on the same S3 history file: with the wipe gone, each run still does a read-modify-write on the history JSON, and an unserialized race would let a later writer clobber an earlier release's entry. `cancel-in-progress: false` queues subsequent runs instead of killing an in-flight publish mid-upload. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/mobile.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/mobile.yml b/.github/workflows/mobile.yml index 64a3e6ccf0f..b662c7dfe9b 100644 --- a/.github/workflows/mobile.yml +++ b/.github/workflows/mobile.yml @@ -197,6 +197,12 @@ jobs: runs-on: ubuntu-latest needs: [mobile-install, mobile-version-check] if: (github.event_name == 'push' && github.ref == 'refs/heads/main' && needs.mobile-version-check.outputs.version_unchanged == 'true') || (github.event_name == 'workflow_dispatch' && (github.event.inputs.ota_channel == 'rc' || github.event.inputs.ota_channel == '')) + # Serialize per-platform publishes so two concurrent runs can't read-modify-write + # the same s3://.../mobile-ota/histories//rc/.json and clobber each + # other's release entry. + concurrency: + group: mobile-ota-release-rc-${{ matrix.platform }} + cancel-in-progress: false strategy: fail-fast: false matrix: @@ -288,8 +294,6 @@ jobs: OTA_APP_VERSION="${MAJOR}.${MINOR}.${OTA_PATCH}" cd packages/mobile - npx code-push create-history --binary-version "$BINARY_VERSION" --platform ${{ matrix.platform }} --identifier "$OTA_CHANNEL" || true - npx code-push release \ --binary-version "$BINARY_VERSION" \ --app-version "$OTA_APP_VERSION" \ @@ -307,6 +311,9 @@ jobs: environment: name: mobile-production-ota url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} + concurrency: + group: mobile-ota-release-production-${{ matrix.platform }} + cancel-in-progress: false strategy: fail-fast: false matrix: @@ -388,8 +395,6 @@ jobs: OTA_APP_VERSION="${MAJOR}.${MINOR}.${OTA_PATCH}" cd packages/mobile - npx code-push create-history --binary-version "$BINARY_VERSION" --platform ${{ matrix.platform }} --identifier "$OTA_CHANNEL" || true - npx code-push release \ --binary-version "$BINARY_VERSION" \ --app-version "$OTA_APP_VERSION" \