From c2a1f19401b549177080c2cae9519965d18f4ad1 Mon Sep 17 00:00:00 2001 From: Braxton Ward Date: Wed, 29 Apr 2026 09:59:10 -0600 Subject: [PATCH] fix: use ios sdk version to fetch frameworks --- .github/workflows/publish.yml | 16 ++++++--- .github/workflows/release-dynamic.yml | 51 ++++++++++++++++++--------- 2 files changed, 46 insertions(+), 21 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 2f8e4bf..178535e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -40,11 +40,17 @@ jobs: env: VERSION: ${{ steps.version.outputs.version }} run: | - # *-dynamic releases publish under the `dynamic` dist-tag so they - # don't displace `latest`. Existing static-using clients keep getting - # the static variant; dynamic is opt-in via @dynamic or explicit pin. - if [[ "$VERSION" == *-dynamic* ]]; then - npm publish --access public --tag dynamic + # Prereleases (anything with a `-` per semver — e.g. *-dynamic, + # *-beta.1) publish under a dist-tag derived from the prerelease + # label so they don't displace `latest`. npm rejects prerelease + # publishes without --tag, so this also prevents the failure mode + # where a wrapper tag predates the dist-tag mapping. + if [[ "$VERSION" == *-* ]]; then + PRERELEASE_LABEL="${VERSION#*-}" + # Use just the first dot-segment as the dist-tag (e.g. beta.1 → beta) + DIST_TAG="${PRERELEASE_LABEL%%.*}" + echo "Publishing prerelease $VERSION under dist-tag '$DIST_TAG'" + npm publish --access public --tag "$DIST_TAG" else npm publish --access public fi diff --git a/.github/workflows/release-dynamic.yml b/.github/workflows/release-dynamic.yml index 4a622c3..9d2e7fb 100644 --- a/.github/workflows/release-dynamic.yml +++ b/.github/workflows/release-dynamic.yml @@ -53,35 +53,59 @@ jobs: git config user.name "github-actions[bot]" git config user.email "github-actions[bot]@users.noreply.github.com" + - name: Read pinned iOS SDK version + id: sdk + env: + STATIC_TAG: ${{ steps.version.outputs.static_tag }} + run: | + # The script downloads from atomicfi/atomic-transact-ios releases, + # which are versioned by the iOS SDK — not the wrapper. Pull the + # iOS SDK version pinned at this static tag so we hit the right + # release URL. + if [ ! -f ios/frameworks/.sdk-version ]; then + echo "Error: ios/frameworks/.sdk-version not found at $STATIC_TAG" >&2 + exit 1 + fi + IOS_SDK_VERSION="$(cat ios/frameworks/.sdk-version)" + echo "ios_sdk_version=${IOS_SDK_VERSION}" >> "$GITHUB_OUTPUT" + # Static tags from before the --dynamic flag existed ship the old - # script, which would treat --dynamic as the version arg and 404. Pull - # only the script file from the workflow's own commit so the rest of - # the v working tree stays intact for the tag commit below. - - name: Restore latest update-ios-sdk.sh + # update-ios-sdk.sh, which would treat --dynamic as the version arg and + # 404. Old static tags also ship a publish.yml without prerelease-tag + # handling — npm rejects prerelease versions without --tag, so the + # dynamic commit would fail to publish. Pull both files from the + # workflow's own commit so the rest of the v working tree + # stays intact for the tag commit below. + - name: Restore latest update-ios-sdk.sh and publish.yml env: # github.sha is the commit the workflow file was loaded from # (master HEAD on workflow_dispatch). Pinning to it guarantees the - # script matches this workflow even if master moves mid-run. + # files match this workflow even if master moves mid-run. WORKFLOW_SHA: ${{ github.sha }} run: | # Fetch is needed because actions/checkout only pulled history # reachable from the static tag. git fetch origin "$WORKFLOW_SHA" - # Pathspec form: overwrites just this file in the working tree + # Pathspec form: overwrites just these files in the working tree # without moving HEAD or switching branches. - git checkout "$WORKFLOW_SHA" -- scripts/update-ios-sdk.sh + git checkout "$WORKFLOW_SHA" -- \ + scripts/update-ios-sdk.sh \ + .github/workflows/publish.yml - name: Swap to dynamic xcframeworks env: - STATIC_VERSION: ${{ steps.version.outputs.static_version }} - run: ./scripts/update-ios-sdk.sh --dynamic "$STATIC_VERSION" + IOS_SDK_VERSION: ${{ steps.sdk.outputs.ios_sdk_version }} + run: ./scripts/update-ios-sdk.sh --dynamic "$IOS_SDK_VERSION" - name: Commit and push dynamic-variant tag env: DYNAMIC_VERSION: ${{ steps.version.outputs.dynamic_version }} DYNAMIC_TAG: ${{ steps.version.outputs.dynamic_tag }} run: | - git add ios/frameworks/ + # publish.yml is committed alongside the framework swap so the + # release: published event runs the modern, prerelease-aware + # publish workflow even for static tags that predate it. + git add ios/frameworks/ .github/workflows/publish.yml git commit -m "chore: dynamic xcframework variant for ${DYNAMIC_VERSION}" git tag "$DYNAMIC_TAG" git push origin "$DYNAMIC_TAG" @@ -94,7 +118,6 @@ jobs: DYNAMIC_VERSION: ${{ steps.version.outputs.dynamic_version }} run: | gh release create "$DYNAMIC_TAG" \ - --target "$DYNAMIC_TAG" \ --title "v${DYNAMIC_VERSION}" \ --notes "Dynamic xcframework variant of [${STATIC_TAG}](https://github.com/atomicfi/atomic-transact-react-native/releases/tag/${STATIC_TAG}). @@ -108,8 +131,4 @@ jobs: # Or pin explicitly npm install @atomicfi/transact-react-native@${DYNAMIC_VERSION} - \`\`\` - - ## What's different - - The wrapper source (TypeScript, Swift bridge, Kotlin module) is identical to ${STATIC_TAG}. Only the vendored iOS xcframeworks (\`AtomicTransact\`, \`MuppetIOS\`, \`QuantumIOS\`) are swapped to their dynamic-framework Mach-O builds. This isolates each framework's Swift witness thunks inside its own image instead of letting them participate in app-binary \`linkonce_odr\` dedup, which is what triggers the crash on Xcode 26 / iOS 26." + \`\`\`"