Skip to content
Draft
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
17 changes: 17 additions & 0 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,3 +159,20 @@ If your change intentionally modifies the public API:
3. Commit the updated `.api.md` file in the same PR.

If you did *not* intend to change public API and `api:check` is failing, the diff shows what your change inadvertently affected — treat it as a signal that something in your PR has consumer-visible impact.

### Releasing a new React Native version

Open a pull request with the following changes:

1. Bump the `version` in `platforms/react-native/modules/@shopify/checkout-kit-react-native/package.json`.
2. Add an entry to the React Native changelog.

Supported release versions are `X.Y.Z` and prerelease versions are `X.Y.Z-{alpha|beta|rc}.N`.

Once merged, run the [Release package workflow](../../actions/workflows/release.yml):

1. Select `React Native` as the platform.
2. Enter the expected version. The workflow reads the SDK version from `platforms/react-native/modules/@shopify/checkout-kit-react-native/package.json` and fails if the typed version does not match.
3. Leave `dry-run` enabled first to review the release plan.
4. Rerun with `dry-run` disabled. By default this creates a draft GitHub Release with the `react-native/`-prefixed tag (e.g. `react-native/4.0.1`) for human review.
5. Publish the draft release when ready. Publishing the draft kicks off the [React Native publish workflow](../../actions/workflows/rn-publish.yml), which publishes `@shopify/checkout-kit-react-native` to npm.
28 changes: 26 additions & 2 deletions .github/scripts/validate-release-version
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ Usage: validate-release-version <platform> [expected-version] [expected-tag]
Validates the selected SDK's checked-in version declarations, optional user
version input, optional git tag, and prints GitHub Actions outputs to stdout.

Platforms: iOS, Android
Platforms: iOS, Android, React Native
USAGE
}

Expand Down Expand Up @@ -42,6 +42,17 @@ extract_first_match() {
printf '%s\n' "$value"
}

json_version() {
local file="$1"

if [ ! -f "$file" ]; then
echo "::error file=$file::Version source file does not exist." >&2
exit 1
fi

node -e "const pkg = require('./${file}'); if (!pkg.version) process.exit(1); process.stdout.write(pkg.version);"
}

check_same_version() {
local expected="$1"
local file="$2"
Expand Down Expand Up @@ -82,8 +93,18 @@ case "$PLATFORM_INPUT" in
VERSION=$(extract_first_match "$ANDROID_VERSION_FILE" 's/^[[:space:]]*def[[:space:]]+versionName[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/p')
;;

"React Native"|react-native|ReactNative|rn|RN)
PLATFORM="react-native"
DISPLAY_PLATFORM="React Native"
TAG_PREFIX="react-native/"
PUBLISH_WORKFLOW="rn-publish.yml"

RN_PACKAGE_FILE="platforms/react-native/modules/@shopify/checkout-kit-react-native/package.json"
VERSION=$(json_version "$RN_PACKAGE_FILE")
;;

*)
echo "::error::Unsupported platform '$PLATFORM_INPUT'. Expected one of: iOS, Android." >&2
echo "::error::Unsupported platform '$PLATFORM_INPUT'. Expected one of: iOS, Android, React Native." >&2
exit 1
;;
esac
Expand All @@ -107,8 +128,10 @@ fi

if [[ "$VERSION" == *-* ]]; then
PRERELEASE="true"
NPM_TAG="next"
else
PRERELEASE="false"
NPM_TAG="latest"
fi

{
Expand All @@ -118,6 +141,7 @@ fi
echo "tag=$TAG"
echo "publish_workflow=$PUBLISH_WORKFLOW"
echo "prerelease=$PRERELEASE"
echo "npm_tag=$NPM_TAG"
}

echo "✓ ${DISPLAY_PLATFORM} version '$VERSION' validates and maps to tag '$TAG'." >&2
7 changes: 6 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
options:
- iOS
- Android
- React Native
version:
description: Expected SDK version. Must match the checked-in SDK version for the selected platform.
required: true
Expand Down Expand Up @@ -135,7 +136,11 @@ jobs:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
gh workflow run "$PUBLISH_WORKFLOW" --ref "$TAG"
if [ "$PUBLISH_WORKFLOW" = "rn-publish.yml" ]; then
gh workflow run "$PUBLISH_WORKFLOW" --ref "$TAG" -f dry-run=false
else
gh workflow run "$PUBLISH_WORKFLOW" --ref "$TAG"
fi
echo "::notice::Dispatched ${PUBLISH_WORKFLOW} at ${TAG}."

- name: Summary
Expand Down
113 changes: 113 additions & 0 deletions .github/workflows/rn-publish.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
name: React Native — Publish to npm

on:
release:
types:
- published
workflow_dispatch:
inputs:
dry-run:
description: Run the full pipeline and pack the package, but skip npm publish.
required: false
type: boolean
default: true

permissions:
contents: read
id-token: write

concurrency:
group: react-native-publish
cancel-in-progress: false

jobs:
release:
name: Publish @shopify/checkout-kit-react-native to npm
if: |
(github.event_name == 'release' && startsWith(github.event.release.tag_name, 'react-native/'))
|| github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
timeout-minutes: 15
defaults:
run:
working-directory: platforms/react-native

steps:
- name: Checkout
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Validate release tag matches package.json version
id: release
working-directory: ${{ github.workspace }}
env:
RELEASE_TAG: ${{ github.event.release.tag_name }}
run: |
set -euo pipefail
if [ "$GITHUB_EVENT_NAME" = "release" ]; then
TAG="$RELEASE_TAG"
else
TAG="$GITHUB_REF_NAME"
fi

.github/scripts/validate-release-version "React Native" "" "$TAG" >> "$GITHUB_OUTPUT"

# `ignore-scripts` prevents dependency postinstall scripts from running in
# this privileged npm publishing job.
- name: Setup Node.js, pnpm, and install dependencies
uses: ./.github/actions/setup
with:
node-version-file: platforms/react-native/package.json
cache-dependency-path: platforms/react-native/pnpm-lock.yaml
package-json-file: platforms/react-native/package.json
working-directory: platforms/react-native
ignore-scripts: "true"

- name: Verify version is not already published
run: |
set -euo pipefail
NAME=$(node -p "require('./modules/@shopify/checkout-kit-react-native/package.json').name")
VERSION=$(node -p "require('./modules/@shopify/checkout-kit-react-native/package.json').version")
ENCODED_NAME=$(node -p "encodeURIComponent(require('./modules/@shopify/checkout-kit-react-native/package.json').name)")
URL="https://registry.npmjs.org/${ENCODED_NAME}/${VERSION}"
if curl -fs "$URL" > /dev/null; then
echo "::error::${NAME}@${VERSION} is already published on npm. Bump platforms/react-native/modules/@shopify/checkout-kit-react-native/package.json before re-running."
exit 1
fi
echo "::notice::${NAME}@${VERSION} is not yet on npm — safe to proceed."

- name: Build package
run: |
set -euo pipefail
cp README.md modules/@shopify/checkout-kit-react-native/README.md
pnpm module clean
pnpm module build

- name: Pack and inspect contents
run: |
set -euo pipefail
mkdir -p /tmp/react-native-publish
cd modules/@shopify/checkout-kit-react-native
npm pack --dry-run
npm pack --pack-destination /tmp/react-native-publish
echo "Tarball contents:"
tar -tzf /tmp/react-native-publish/*.tgz | sort

- name: Publish to npm
if: ${{ !inputs.dry-run }}
run: |
set -euo pipefail
cd modules/@shopify/checkout-kit-react-native
npm publish --access public --tag "$NPM_TAG" --provenance
env:
NPM_TAG: ${{ steps.release.outputs.npm_tag }}
NPM_CONFIG_PROVENANCE: "true"
NPM_TOKEN: ""
NODE_AUTH_TOKEN: ""

- name: Dry-run summary
if: ${{ inputs.dry-run }}
env:
NPM_TAG: ${{ steps.release.outputs.npm_tag }}
run: |
echo "::notice::Dry-run requested — skipped npm publish."
echo "Would have published with: --access public --tag $NPM_TAG --provenance"
28 changes: 21 additions & 7 deletions platforms/react-native/docs/contributing/release.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,26 @@ following steps:
appropriate value.
2. Add a [Changelog](./CHANGELOG.md) entry.
3. Merge your PR to `main`.
4. Create a [Release](/releases) for your new version.
4. Run the [Release package workflow](/actions/workflows/release.yml).

Creating and publishing a Github release with begin the automated process of
publishing the latest version of the package to NPM. It will clean the module
folder, build a new version, run `npm pack --dry-run` to verify the contents and
publish to the NPM registry.
Supported release versions are:

You can follow the release action process via
https://github.com/Shopify/checkout-kit/actions/workflows/publish.yml.
- Stable: `X.Y.Z`
- Prerelease: `X.Y.Z-{alpha|beta|rc}.N`

The release workflow reads the version from
`modules/@shopify/checkout-kit-react-native/package.json`, validates it, and
creates the correctly namespaced `react-native/` tag (for example,
`react-native/4.0.1`). The manually entered workflow version is only a safety
check; it must match the package version exactly.

Leave `dry-run` enabled on the first run to review the planned tag. Rerun with
`dry-run` disabled to create the GitHub Release. By default the release workflow
creates a draft release for human review; publish the draft release when ready
to start the React Native publish workflow.

The publish workflow cleans the module folder, builds a new version, runs
`npm pack --dry-run` to verify the contents, and publishes to the NPM registry.

You can follow the publish action process via
https://github.com/Shopify/checkout-kit/actions/workflows/rn-publish.yml.
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Pod::Spec.new do |s|
s.authors = package["author"]

s.platforms = { :ios => "13.0" }
s.source = { :git => "https://github.com/Shopify/checkout-kit.git", :tag => "#{s.version}" }
s.source = { :git => "https://github.com/Shopify/checkout-kit.git", :tag => "react-native/#{s.version}" }

s.source_files = "ios/*.{h,m,mm,swift}"

Expand Down
Loading