Skip to content

Commit 2ea0e4a

Browse files
committed
feat: add pre-release workflow for alpha/beta/rc versions
Enables creating pre-release tags from any branch with configurable version numbers and types (alpha/beta/rc), with dry-run support for safe testing before publishing.
1 parent 2f00545 commit 2ea0e4a

File tree

3 files changed

+303
-7
lines changed

3 files changed

+303
-7
lines changed

.github/workflows/prerelease.yml

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
name: Release Pre-release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
version_base:
7+
description: 'Version base (e.g., 3.5.0)'
8+
required: true
9+
type: string
10+
prerelease_type:
11+
description: 'Pre-release type'
12+
required: true
13+
type: choice
14+
options:
15+
- alpha
16+
- beta
17+
- rc
18+
default: 'alpha'
19+
prerelease_number:
20+
description: 'Pre-release number (e.g., 1)'
21+
required: true
22+
type: string
23+
branch:
24+
description: 'Branch to create release from'
25+
required: true
26+
type: string
27+
default: 'main'
28+
dry_run:
29+
description: 'Dry run (validate only, do not create tag/release)'
30+
required: false
31+
type: boolean
32+
default: false
33+
34+
jobs:
35+
validate-and-release:
36+
runs-on: ubuntu-latest
37+
38+
steps:
39+
- name: Construct and validate version
40+
id: version
41+
run: |
42+
VERSION_BASE="${{ github.event.inputs.version_base }}"
43+
PRERELEASE_TYPE="${{ github.event.inputs.prerelease_type }}"
44+
PRERELEASE_NUMBER="${{ github.event.inputs.prerelease_number }}"
45+
46+
if [[ ! "$VERSION_BASE" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
47+
echo "Invalid version base: $VERSION_BASE (expected X.Y.Z)"
48+
exit 1
49+
fi
50+
51+
if [[ ! "$PRERELEASE_NUMBER" =~ ^[0-9]+$ ]]; then
52+
echo "Invalid pre-release number: $PRERELEASE_NUMBER"
53+
exit 1
54+
fi
55+
56+
FULL_VERSION="${VERSION_BASE}-${PRERELEASE_TYPE}.${PRERELEASE_NUMBER}"
57+
echo "version=${FULL_VERSION}" >> $GITHUB_OUTPUT
58+
echo "Version: $FULL_VERSION"
59+
60+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
61+
with:
62+
ref: ${{ github.event.inputs.branch }}
63+
fetch-depth: 0
64+
65+
- name: Check if tag already exists
66+
run: |
67+
VERSION="${{ steps.version.outputs.version }}"
68+
if git rev-parse "refs/tags/$VERSION" >/dev/null 2>&1; then
69+
echo "Tag $VERSION already exists"
70+
git tag -l "${{ github.event.inputs.version_base }}-*"
71+
exit 1
72+
fi
73+
74+
- name: Setup
75+
uses: ./.github/actions/setup
76+
77+
- name: Verify pre-release version format
78+
run: |
79+
VERSION="${{ steps.version.outputs.version }}"
80+
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+-(alpha|beta|rc)\.[0-9]+$ ]]; then
81+
echo "ERROR: Version $VERSION does not match pre-release format"
82+
echo "Expected format: X.Y.Z-{alpha|beta|rc}.N"
83+
exit 1
84+
fi
85+
echo "✅ Version format verified: $VERSION"
86+
87+
- name: Update package.json version
88+
run: |
89+
VERSION="${{ steps.version.outputs.version }}"
90+
cd modules/@shopify/checkout-sheet-kit
91+
npm version "$VERSION" --no-git-tag-version
92+
echo "Updated package.json to version: $VERSION"
93+
cat package.json | grep '"version"'
94+
95+
- name: Validate build
96+
run: |
97+
set -eo pipefail
98+
yarn module build
99+
echo "Build successful"
100+
101+
- name: Dry Run Summary
102+
if: github.event.inputs.dry_run == 'true'
103+
run: |
104+
VERSION="${{ steps.version.outputs.version }}"
105+
BRANCH="${{ github.event.inputs.branch }}"
106+
echo "DRY RUN - Would create $VERSION from $BRANCH"
107+
echo "All validations passed"
108+
echo ""
109+
echo "Next steps (not executed in dry run):"
110+
echo " 1. Commit package.json changes"
111+
echo " 2. Create and push git tag"
112+
echo " 3. Create GitHub pre-release"
113+
echo " 4. NPM publish will be triggered automatically with 'next' dist-tag"
114+
115+
- name: Commit package.json changes
116+
if: github.event.inputs.dry_run != 'true'
117+
run: |
118+
set -e
119+
VERSION="${{ steps.version.outputs.version }}"
120+
BRANCH="${{ github.event.inputs.branch }}"
121+
git config user.name "github-actions[bot]"
122+
git config user.email "github-actions[bot]@users.noreply.github.com"
123+
git add modules/@shopify/checkout-sheet-kit/package.json
124+
git commit -m "Bump version to $VERSION"
125+
126+
if ! git push origin "$BRANCH"; then
127+
echo "ERROR: Failed to push version bump to $BRANCH"
128+
echo "This could be due to branch protection rules or conflicts"
129+
exit 1
130+
fi
131+
echo "✅ Successfully pushed version bump to $BRANCH"
132+
133+
- name: Create and push tag
134+
if: github.event.inputs.dry_run != 'true'
135+
run: |
136+
set -e
137+
VERSION="${{ steps.version.outputs.version }}"
138+
BRANCH="${{ github.event.inputs.branch }}"
139+
PRERELEASE_TYPE="${{ github.event.inputs.prerelease_type }}"
140+
git config user.name "github-actions[bot]"
141+
git config user.email "github-actions[bot]@users.noreply.github.com"
142+
git tag -a "$VERSION" -m "$PRERELEASE_TYPE release $VERSION from branch $BRANCH"
143+
144+
if ! git push origin "$VERSION"; then
145+
echo "ERROR: Failed to push tag $VERSION"
146+
exit 1
147+
fi
148+
echo "✅ Successfully pushed tag $VERSION"
149+
150+
- name: Create GitHub Pre-release
151+
if: github.event.inputs.dry_run != 'true'
152+
env:
153+
GH_TOKEN: ${{ github.token }}
154+
run: |
155+
VERSION="${{ steps.version.outputs.version }}"
156+
BRANCH="${{ github.event.inputs.branch }}"
157+
PRERELEASE_TYPE="${{ github.event.inputs.prerelease_type }}"
158+
159+
case "$PRERELEASE_TYPE" in
160+
alpha) EMOJI="🧪"; LABEL="Alpha" ;;
161+
beta) EMOJI="🚧"; LABEL="Beta" ;;
162+
rc) EMOJI="🎯"; LABEL="Release Candidate" ;;
163+
esac
164+
165+
RELEASE_NOTES=$(cat <<EOF
166+
Pre-release from branch: $BRANCH
167+
168+
⚠️ This pre-release will be published to NPM with the \`next\` dist-tag.
169+
⚠️ The \`latest\` tag will NOT be affected.
170+
EOF
171+
)
172+
173+
gh release create "$VERSION" \
174+
--title "$EMOJI $LABEL $VERSION" \
175+
--notes "$RELEASE_NOTES" \
176+
--prerelease \
177+
--target "$BRANCH"
178+
179+
echo ""
180+
echo "📦 Pre-release created successfully!"
181+
echo "🔗 View release: https://github.com/Shopify/checkout-sheet-kit-react-native/releases/tag/$VERSION"
182+
echo "📋 NPM publish will be triggered automatically by the publish workflow"
183+
echo "🏷️ Package will be available with 'next' dist-tag (NOT 'latest')"

.github/workflows/publish.yml

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,55 @@ jobs:
1717
- name: Setup
1818
uses: ./.github/actions/setup
1919

20+
- name: Check if GitHub release is prerelease
21+
id: github-release-type
22+
if: github.event_name == 'release'
23+
env:
24+
GH_TOKEN: ${{ github.token }}
25+
run: |
26+
TAG="${GITHUB_REF#refs/tags/}"
27+
IS_PRERELEASE=$(gh release view "$TAG" --json isPrerelease --jq .isPrerelease)
28+
echo "is_prerelease=$IS_PRERELEASE" >> $GITHUB_OUTPUT
29+
echo "GitHub release prerelease status: $IS_PRERELEASE"
30+
2031
- name: Determine NPM tag
2132
id: npm-tag
2233
run: |
2334
# Read the version from package.json
2435
VERSION=$(node -p "require('./modules/@shopify/checkout-sheet-kit/package.json').version")
2536
26-
# Check if it's a "beta" or "rc" version
27-
if [[ "$VERSION" == *"-beta"* ]] || [[ "$VERSION" == *"-rc"* ]]; then
37+
# Get GitHub prerelease status (only available when triggered by release event)
38+
GITHUB_IS_PRERELEASE="${{ steps.github-release-type.outputs.is_prerelease }}"
39+
40+
# Determine the appropriate tag
41+
TAG=""
42+
if [[ "$VERSION" == *"-alpha"* ]] || [[ "$VERSION" == *"-beta"* ]] || [[ "$VERSION" == *"-rc"* ]]; then
2843
echo "Version $VERSION is a prerelease, using 'next' tag"
29-
echo "tag=next" >> $GITHUB_OUTPUT
44+
TAG="next"
45+
elif [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+-.+ ]]; then
46+
echo "Version $VERSION appears to be a prerelease (contains hyphen), using 'next' tag"
47+
TAG="next"
48+
elif [[ -n "$GITHUB_IS_PRERELEASE" ]] && [[ "$GITHUB_IS_PRERELEASE" == "true" ]]; then
49+
echo "WARNING: GitHub release is marked as prerelease but version $VERSION does not match prerelease format"
50+
echo "Using 'next' tag for safety to avoid overwriting 'latest'"
51+
TAG="next"
3052
else
3153
echo "Version $VERSION is a stable release, using 'latest' tag"
32-
echo "tag=latest" >> $GITHUB_OUTPUT
54+
TAG="latest"
3355
fi
3456
57+
# Final safety check: ensure we're not accidentally using 'latest' for a prerelease
58+
if [[ "$VERSION" =~ - ]] && [[ "$TAG" == "latest" ]]; then
59+
echo "CRITICAL ERROR: Version $VERSION contains hyphen but 'latest' tag was selected"
60+
echo "This would overwrite the stable 'latest' release!"
61+
echo "Aborting to protect production"
62+
exit 1
63+
fi
64+
65+
# Output the tag
66+
echo "tag=$TAG" >> $GITHUB_OUTPUT
67+
echo "✅ Will publish with tag: $TAG"
68+
3569
- name: Prepare release
3670
run: |
3771
echo "//registry.npmjs.org/:_authToken=${NPM_TOKEN}" > .npmrc

docs/contributing/release.md

Lines changed: 82 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
The `@shopify/checkout-sheet-kit` module is published to the NPM package
44
registry with public access.
55

6-
In order to publish a new version of the package, you must complete the
6+
## Stable Releases
7+
8+
In order to publish a new stable version of the package, you must complete the
79
following steps:
810

911
1. Bump the version in `modules/@shopify/checkout-sheet-kit/package.json` to an
@@ -12,10 +14,87 @@ following steps:
1214
3. Merge your PR to `main`.
1315
4. Create a [Release](/releases) for your new version.
1416

15-
Creating and publishing a Github release with begin the automated process of
17+
Creating and publishing a Github release will begin the automated process of
1618
publishing the latest version of the package to NPM. It will clean the module
1719
folder, build a new version, run `npm pack --dry-run` to verify the contents and
18-
publish to the NPM registry.
20+
publish to the NPM registry with the `latest` dist-tag.
1921

2022
You can follow the release action process via
2123
https://github.com/Shopify/checkout-sheet-kit-react-native/actions/workflows/publish.yml.
24+
25+
## Pre-releases (Alpha, Beta, RC)
26+
27+
For pre-release versions, use the [Pre-release workflow](https://github.com/Shopify/checkout-sheet-kit-react-native/actions/workflows/prerelease.yml) instead of the manual process above.
28+
29+
### Creating a Pre-release
30+
31+
1. Go to Actions > Release Pre-release workflow
32+
2. Click "Run workflow" and provide:
33+
- **Version base**: The base version (e.g., `3.5.0`)
34+
- **Pre-release type**: Choose `alpha`, `beta`, or `rc`
35+
- **Pre-release number**: The pre-release number (e.g., `1`)
36+
- **Branch**: The branch to release from (default: `main`)
37+
- **Dry run**: Check this to validate without creating the release
38+
39+
3. The workflow will:
40+
- Validate the version format
41+
- Check if the tag already exists
42+
- Update `package.json` with the pre-release version
43+
- Build and validate the package
44+
- Commit the version change
45+
- Create and push a git tag
46+
- Create a GitHub pre-release
47+
- Trigger the publish workflow automatically
48+
49+
### Example Pre-release Versions
50+
51+
- `3.5.0-alpha.1`
52+
- `3.5.0-alpha.2`
53+
- `3.5.0-beta.1`
54+
- `3.5.0-rc.1`
55+
56+
### NPM Dist-tags
57+
58+
Pre-releases are automatically published with the `next` dist-tag, while stable releases use the `latest` tag. This allows users to opt-in to pre-release versions.
59+
60+
#### Installing a Specific Pre-release Version
61+
62+
```bash
63+
npm install @shopify/[email protected]
64+
# or
65+
yarn add @shopify/[email protected]
66+
```
67+
68+
#### Installing the Latest Pre-release
69+
70+
```bash
71+
npm install @shopify/checkout-sheet-kit@next
72+
# or
73+
yarn add @shopify/checkout-sheet-kit@next
74+
```
75+
76+
#### Installing the Latest Stable Release
77+
78+
```bash
79+
npm install @shopify/checkout-sheet-kit
80+
# or
81+
yarn add @shopify/checkout-sheet-kit
82+
```
83+
84+
### Managing Dist-tags Manually
85+
86+
If you need to manually manage dist-tags:
87+
88+
```bash
89+
# View all dist-tags
90+
npm dist-tag ls @shopify/checkout-sheet-kit
91+
92+
# Add a dist-tag
93+
npm dist-tag add @shopify/[email protected] next
94+
95+
# Remove a dist-tag
96+
npm dist-tag rm @shopify/checkout-sheet-kit next
97+
98+
# Move the 'latest' tag to a different version
99+
npm dist-tag add @shopify/[email protected] latest
100+
```

0 commit comments

Comments
 (0)