Skip to content

Commit 279a5c4

Browse files
feat: add React Native release publishing
1 parent 5e10d4e commit 279a5c4

6 files changed

Lines changed: 184 additions & 11 deletions

File tree

.github/CONTRIBUTING.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,3 +159,20 @@ If your change intentionally modifies the public API:
159159
3. Commit the updated `.api.md` file in the same PR.
160160

161161
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.
162+
163+
### Releasing a new React Native version
164+
165+
Open a pull request with the following changes:
166+
167+
1. Bump the `version` in `platforms/react-native/modules/@shopify/checkout-kit-react-native/package.json`.
168+
2. Add an entry to the React Native changelog.
169+
170+
Supported release versions are `X.Y.Z` and prerelease versions are `X.Y.Z-{alpha|beta|rc}.N`.
171+
172+
Once merged, run the [Release package workflow](../../actions/workflows/release.yml):
173+
174+
1. Select `React Native` as the platform.
175+
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.
176+
3. Leave `dry-run` enabled first to review the release plan.
177+
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.
178+
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.

.github/scripts/validate-release-version

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Usage: validate-release-version <platform> [expected-version] [expected-tag]
88
Validates the selected SDK's checked-in version declarations, optional user
99
version input, optional git tag, and prints GitHub Actions outputs to stdout.
1010
11-
Platforms: iOS, Android
11+
Platforms: iOS, Android, React Native
1212
USAGE
1313
}
1414

@@ -42,6 +42,17 @@ extract_first_match() {
4242
printf '%s\n' "$value"
4343
}
4444

45+
json_version() {
46+
local file="$1"
47+
48+
if [ ! -f "$file" ]; then
49+
echo "::error file=$file::Version source file does not exist." >&2
50+
exit 1
51+
fi
52+
53+
node -e "const pkg = require('./${file}'); if (!pkg.version) process.exit(1); process.stdout.write(pkg.version);"
54+
}
55+
4556
check_same_version() {
4657
local expected="$1"
4758
local file="$2"
@@ -82,8 +93,18 @@ case "$PLATFORM_INPUT" in
8293
VERSION=$(extract_first_match "$ANDROID_VERSION_FILE" 's/^[[:space:]]*def[[:space:]]+versionName[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/p')
8394
;;
8495

96+
"React Native"|react-native|ReactNative|rn|RN)
97+
PLATFORM="react-native"
98+
DISPLAY_PLATFORM="React Native"
99+
TAG_PREFIX="react-native/"
100+
PUBLISH_WORKFLOW="rn-publish.yml"
101+
102+
RN_PACKAGE_FILE="platforms/react-native/modules/@shopify/checkout-kit-react-native/package.json"
103+
VERSION=$(json_version "$RN_PACKAGE_FILE")
104+
;;
105+
85106
*)
86-
echo "::error::Unsupported platform '$PLATFORM_INPUT'. Expected one of: iOS, Android." >&2
107+
echo "::error::Unsupported platform '$PLATFORM_INPUT'. Expected one of: iOS, Android, React Native." >&2
87108
exit 1
88109
;;
89110
esac
@@ -107,8 +128,10 @@ fi
107128

108129
if [[ "$VERSION" == *-* ]]; then
109130
PRERELEASE="true"
131+
NPM_TAG="next"
110132
else
111133
PRERELEASE="false"
134+
NPM_TAG="latest"
112135
fi
113136

114137
{
@@ -118,6 +141,7 @@ fi
118141
echo "tag=$TAG"
119142
echo "publish_workflow=$PUBLISH_WORKFLOW"
120143
echo "prerelease=$PRERELEASE"
144+
echo "npm_tag=$NPM_TAG"
121145
}
122146

123147
echo "${DISPLAY_PLATFORM} version '$VERSION' validates and maps to tag '$TAG'." >&2

.github/workflows/release.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ on:
1010
options:
1111
- iOS
1212
- Android
13+
- React Native
1314
version:
1415
description: Expected SDK version. Must match the checked-in SDK version for the selected platform.
1516
required: true
@@ -135,7 +136,11 @@ jobs:
135136
GH_TOKEN: ${{ github.token }}
136137
run: |
137138
set -euo pipefail
138-
gh workflow run "$PUBLISH_WORKFLOW" --ref "$TAG"
139+
if [ "$PUBLISH_WORKFLOW" = "rn-publish.yml" ]; then
140+
gh workflow run "$PUBLISH_WORKFLOW" --ref "$TAG" -f dry-run=false
141+
else
142+
gh workflow run "$PUBLISH_WORKFLOW" --ref "$TAG"
143+
fi
139144
echo "::notice::Dispatched ${PUBLISH_WORKFLOW} at ${TAG}."
140145
141146
- name: Summary

.github/workflows/rn-publish.yml

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
name: React Native — Publish to npm
2+
3+
on:
4+
release:
5+
types:
6+
- published
7+
workflow_dispatch:
8+
inputs:
9+
dry-run:
10+
description: Run the full pipeline and pack the package, but skip npm publish.
11+
required: false
12+
type: boolean
13+
default: true
14+
15+
permissions:
16+
contents: read
17+
id-token: write
18+
19+
concurrency:
20+
group: react-native-publish
21+
cancel-in-progress: false
22+
23+
jobs:
24+
release:
25+
name: Publish @shopify/checkout-kit-react-native to npm
26+
if: |
27+
(github.event_name == 'release' && startsWith(github.event.release.tag_name, 'react-native/'))
28+
|| github.event_name == 'workflow_dispatch'
29+
runs-on: ubuntu-latest
30+
timeout-minutes: 15
31+
defaults:
32+
run:
33+
working-directory: platforms/react-native
34+
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
38+
39+
- name: Validate release tag matches package.json version
40+
id: release
41+
working-directory: ${{ github.workspace }}
42+
env:
43+
RELEASE_TAG: ${{ github.event.release.tag_name }}
44+
run: |
45+
set -euo pipefail
46+
if [ "$GITHUB_EVENT_NAME" = "release" ]; then
47+
TAG="$RELEASE_TAG"
48+
else
49+
TAG="$GITHUB_REF_NAME"
50+
fi
51+
52+
.github/scripts/validate-release-version "React Native" "" "$TAG" >> "$GITHUB_OUTPUT"
53+
54+
# `ignore-scripts` prevents dependency postinstall scripts from running in
55+
# this privileged npm publishing job.
56+
- name: Setup Node.js, pnpm, and install dependencies
57+
uses: ./.github/actions/setup
58+
with:
59+
node-version-file: platforms/react-native/package.json
60+
cache-dependency-path: platforms/react-native/pnpm-lock.yaml
61+
package-json-file: platforms/react-native/package.json
62+
working-directory: platforms/react-native
63+
ignore-scripts: "true"
64+
65+
- name: Verify version is not already published
66+
run: |
67+
set -euo pipefail
68+
NAME=$(node -p "require('./modules/@shopify/checkout-kit-react-native/package.json').name")
69+
VERSION=$(node -p "require('./modules/@shopify/checkout-kit-react-native/package.json').version")
70+
ENCODED_NAME=$(node -p "encodeURIComponent(require('./modules/@shopify/checkout-kit-react-native/package.json').name)")
71+
URL="https://registry.npmjs.org/${ENCODED_NAME}/${VERSION}"
72+
if curl -fs "$URL" > /dev/null; then
73+
echo "::error::${NAME}@${VERSION} is already published on npm. Bump platforms/react-native/modules/@shopify/checkout-kit-react-native/package.json before re-running."
74+
exit 1
75+
fi
76+
echo "::notice::${NAME}@${VERSION} is not yet on npm — safe to proceed."
77+
78+
- name: Build package
79+
run: |
80+
set -euo pipefail
81+
cp README.md modules/@shopify/checkout-kit-react-native/README.md
82+
pnpm module clean
83+
pnpm module build
84+
85+
- name: Pack and inspect contents
86+
run: |
87+
set -euo pipefail
88+
mkdir -p /tmp/react-native-publish
89+
cd modules/@shopify/checkout-kit-react-native
90+
npm pack --dry-run
91+
npm pack --pack-destination /tmp/react-native-publish
92+
echo "Tarball contents:"
93+
tar -tzf /tmp/react-native-publish/*.tgz | sort
94+
95+
- name: Publish to npm
96+
if: ${{ !inputs.dry-run }}
97+
run: |
98+
set -euo pipefail
99+
cd modules/@shopify/checkout-kit-react-native
100+
npm publish --access public --tag "$NPM_TAG" --provenance
101+
env:
102+
NPM_TAG: ${{ steps.release.outputs.npm_tag }}
103+
NPM_CONFIG_PROVENANCE: "true"
104+
NPM_TOKEN: ""
105+
NODE_AUTH_TOKEN: ""
106+
107+
- name: Dry-run summary
108+
if: ${{ inputs.dry-run }}
109+
env:
110+
NPM_TAG: ${{ steps.release.outputs.npm_tag }}
111+
run: |
112+
echo "::notice::Dry-run requested — skipped npm publish."
113+
echo "Would have published with: --access public --tag $NPM_TAG --provenance"

platforms/react-native/docs/contributing/release.md

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,26 @@ following steps:
1010
appropriate value.
1111
2. Add a [Changelog](./CHANGELOG.md) entry.
1212
3. Merge your PR to `main`.
13-
4. Create a [Release](/releases) for your new version.
13+
4. Run the [Release package workflow](/actions/workflows/release.yml).
1414

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

20-
You can follow the release action process via
21-
https://github.com/Shopify/checkout-kit/actions/workflows/publish.yml.
17+
- Stable: `X.Y.Z`
18+
- Prerelease: `X.Y.Z-{alpha|beta|rc}.N`
19+
20+
The release workflow reads the version from
21+
`modules/@shopify/checkout-kit-react-native/package.json`, validates it, and
22+
creates the correctly namespaced `react-native/` tag (for example,
23+
`react-native/4.0.1`). The manually entered workflow version is only a safety
24+
check; it must match the package version exactly.
25+
26+
Leave `dry-run` enabled on the first run to review the planned tag. Rerun with
27+
`dry-run` disabled to create the GitHub Release. By default the release workflow
28+
creates a draft release for human review; publish the draft release when ready
29+
to start the React Native publish workflow.
30+
31+
The publish workflow cleans the module folder, builds a new version, runs
32+
`npm pack --dry-run` to verify the contents, and publishes to the NPM registry.
33+
34+
You can follow the publish action process via
35+
https://github.com/Shopify/checkout-kit/actions/workflows/rn-publish.yml.

platforms/react-native/modules/@shopify/checkout-kit-react-native/RNShopifyCheckoutKit.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Pod::Spec.new do |s|
1111
s.authors = package["author"]
1212

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

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

0 commit comments

Comments
 (0)