Skip to content

Commit 2b90ce2

Browse files
evan-masseauclaude
andcommitted
fix(ci): correct Android preflight endpoint and force iOS Distribution signing
- Android: switch preflight from /edits/{editId}/bundles (scoped to the current edit, always empty) to /edits/{editId}/tracks. Iterate every active release across every track and pick max(versionCode)+1. Fixes versionCode-1 collisions caused by the bundles endpoint reporting empty for a fresh edit. - iOS: pbxproj inherits the RN-template default CODE_SIGN_IDENTITY[sdk=iphoneos*] = "iPhone Developer" which forces Development signing on Release archives. That made -allowProvisioningUpdates request a Development profile (and try to register the runner machine as a dev device). Override at xcodebuild invocation time with CODE_SIGN_IDENTITY="Apple Distribution" (and the same SDK-conditional variant) so xcodebuild provisions an App Store distribution profile via the API key. Part of MAGE-464 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 307d161 commit 2b90ce2

1 file changed

Lines changed: 28 additions & 14 deletions

File tree

.github/workflows/publish-example.yml

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,17 +78,20 @@ jobs:
7878
with:
7979
credentials_json: ${{ secrets.SERVICE_ACCOUNT_JSON }}
8080

81-
# Find the highest versionCode already uploaded for this package and
82-
# pick highest+1 as our target. This handles two collision sources in
83-
# one shot:
84-
# - github.run_number resetting (workflow rename, repo migration)
85-
# - manual Play Console uploads outside of CI
86-
# versionCode is baked into the AAB at bundle time, so determining it
87-
# before the build is the only path that doesn't require a retry-rebuild
88-
# loop. Race condition risk (two concurrent runs picking the same
89-
# versionCode) is real in theory but a non-issue for our trigger set
90-
# (workflow_dispatch, release: published, branch push).
91-
- name: Resolve next versionCode from Play track
81+
# Find the highest versionCode currently in any active track release
82+
# and pick highest+1 as our target. The Play Edits API doesn't expose
83+
# a flat "all bundles ever uploaded" list — `/edits/{editId}/bundles`
84+
# is scoped to the current edit (always empty here since we open one
85+
# just to query). Iterating active releases across every track gives
86+
# us the highest live versionCode, which is enough to leapfrog past
87+
# any prior CI run, manual upload, or workflow rename collision.
88+
#
89+
# Caveat: Play also rejects upload of a versionCode that was used in
90+
# a deleted/archived draft. Those don't appear in tracks.list. If we
91+
# ever hit that edge case, the manual fix is to re-run with a higher
92+
# number (push a no-op commit to bump github.run_number, or upload a
93+
# placeholder bundle outside CI).
94+
- name: Resolve next versionCode from Play tracks
9295
shell: bash
9396
env:
9497
PACKAGE_NAME: com.klaviyoreactnativesdkexample
@@ -99,12 +102,14 @@ jobs:
99102
API="https://androidpublisher.googleapis.com/androidpublisher/v3/applications/$PACKAGE_NAME"
100103
101104
EDIT_ID=$(curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" "$API/edits" -d '{}' | jq -r '.id')
102-
BUNDLES=$(curl -sS -H "$AUTH" "$API/edits/$EDIT_ID/bundles")
105+
TRACKS=$(curl -sS -H "$AUTH" "$API/edits/$EDIT_ID/tracks")
103106
curl -sS -X DELETE -H "$AUTH" "$API/edits/$EDIT_ID" >/dev/null
104107
105-
HIGHEST=$(echo "$BUNDLES" | jq '[.bundles[]?.versionCode // 0] | max // 0')
108+
# Walk every track → release → versionCodes, coerce to int, take max.
109+
# `// 0` makes the jq pipeline yield 0 for an app with no releases yet.
110+
HIGHEST=$(echo "$TRACKS" | jq '[.tracks[]?.releases[]?.versionCodes[]? | tonumber] | max // 0')
106111
NEXT=$(( HIGHEST + 1 ))
107-
echo "Highest existing versionCode: $HIGHEST"
112+
echo "Highest active versionCode across all tracks: $HIGHEST"
108113
echo "Next versionCode: $NEXT"
109114
echo "VERSION_CODE=$NEXT" >> $GITHUB_ENV
110115
@@ -332,6 +337,13 @@ jobs:
332337
shell: bash
333338
run: |
334339
rm -rf ./build KlaviyoReactNativeSdkExample.xcarchive
340+
# CODE_SIGN_IDENTITY override: the .pbxproj has the RN-template default
341+
# `CODE_SIGN_IDENTITY[sdk=iphoneos*] = "iPhone Developer"` baked in,
342+
# which forces Development signing even on Release archives. That makes
343+
# -allowProvisioningUpdates ask for a Development profile (and try to
344+
# register the runner machine as a dev device, which fails). Forcing
345+
# "Apple Distribution" here gets Xcode to provision an App Store
346+
# distribution profile via the API key instead.
335347
xcodebuild -workspace KlaviyoReactNativeSdkExample.xcworkspace \
336348
-scheme KlaviyoReactNativeSdkExample \
337349
-configuration Release \
@@ -340,6 +352,8 @@ jobs:
340352
-authenticationKeyID "$ASC_KEY_ID" \
341353
-authenticationKeyIssuerID "$ASC_ISSUER_ID" \
342354
-authenticationKeyPath "$HOME/.appstoreconnect/private_keys/AuthKey_${ASC_KEY_ID}.p8" \
355+
CODE_SIGN_IDENTITY="Apple Distribution" \
356+
"CODE_SIGN_IDENTITY[sdk=iphoneos*]=Apple Distribution" \
343357
DEVELOPMENT_TEAM="$APPLE_TEAM_ID"
344358
345359
- name: Export IPA

0 commit comments

Comments
 (0)