Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use this for any kind of alternate version now

else
npm publish --access public
fi
51 changes: 35 additions & 16 deletions .github/workflows/release-dynamic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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<version> 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<version> 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"
Expand All @@ -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}).

Expand All @@ -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."
\`\`\`"
Loading