Skip to content

Commit 84218f7

Browse files
authored
Update release flow to be more robust (#3938)
## Description Overhaul of the release process: - adds `beta` and `rc` options to the previously existing `stable` and `commitly` - allows the release of a specific version, independent from the branch name (optional, will still detect the version from the branch name when unspecified) - verifies that the latest version is either one patch, one minor, or one major higher than the currently published version (ATM throws on major change) - verifies that beta, rc and commitly releases aren't done for an already published version (i.e. will disallow publishing `2.30.0-beta.1` when stable `2.30.0` is published`). - automatic numbering of beta and rc releases Internally: - moved most of the helpers to separate files - moved version numbering helpers to `version-utils` - added tests covering the release scripts ## Test plan Tested on a fork: - Fails when trying to skip minor on latest release: https://github.com/j-piasecki/react-native-gesture-handler/actions/runs/21475940199/job/61859862583 - Fails when trying to skip patch on latest release: https://github.com/j-piasecki/react-native-gesture-handler/actions/runs/21476045075/job/61860214823 - Fails when trying to publish on existing versions (checks base version for beta, rc, and commitly): https://github.com/j-piasecki/react-native-gesture-handler/actions/runs/21476741044/job/61862557674 - Succeeds when not skipping any minor: https://github.com/j-piasecki/react-native-gesture-handler/actions/runs/21476056662/job/61860252565 - Succeeds when not skipping any patch: https://github.com/j-piasecki/react-native-gesture-handler/actions/runs/21476183083/job/61860683061 - Succeeds when publishing a non-latest release: https://github.com/j-piasecki/react-native-gesture-handler/actions/runs/21476510871/job/61861782101
1 parent 9f573ef commit 84218f7

18 files changed

+1239
-173
lines changed

.github/actions/publish-npm-package/action.yml

Lines changed: 55 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
name: publish-npm-package
22
description: Build and publish react-native-gesture-handler package to npm
33
inputs:
4-
is-commitly:
5-
description: Whether the release should be marked as nightly.
6-
default: "true"
4+
release-type:
5+
description: Release type to be published (stable, commitly, beta, rc).
6+
default: "commitly"
7+
version:
8+
description: Specific version to publish (usually inferred from x.y-stable branch name).
9+
default: ""
710
dry-run:
811
description: Whether to perform a dry run of the publish.
912
default: "true"
@@ -28,10 +31,49 @@ runs:
2831
id: set-package-version
2932
shell: bash
3033
run: |
31-
VERSION=$(node ./scripts/release/set-package-version.js ${{ inputs.is-commitly == 'true' && '--commitly' || '' }})
34+
VERSION=$(node ./scripts/release/set-package-version.js ${{ inputs.release-type == 'commitly' && '--commitly' || '' }} ${{ inputs.release-type == 'beta' && '--beta' || '' }} ${{ inputs.release-type == 'rc' && '--rc' || '' }} ${{ inputs.version != '' && format('--version ''{0}''', inputs.version) || '' }})
3235
echo "Updated package version to $VERSION"
3336
echo "version=$VERSION" >> $GITHUB_OUTPUT
3437
38+
- name: Figure out the correct npm tag
39+
id: figure-out-npm-tag
40+
shell: bash
41+
run: |
42+
if [ "${{ inputs.release-type == 'commitly' }}" = "true" ]; then
43+
TAG_ARGUMENT="--tag nightly"
44+
else
45+
if [ "${{ inputs.release-type == 'beta' || inputs.release-type == 'rc' }}" = "true" ]; then
46+
TAG_ARGUMENT="--tag next"
47+
else
48+
if [ $(node ./scripts/release/should-be-latest.js ${{ steps.set-package-version.outputs.version }}) = "true" ]; then
49+
TAG_ARGUMENT="--tag latest"
50+
else
51+
TAG_ARGUMENT="--tag legacy"
52+
fi
53+
fi
54+
fi
55+
56+
echo "Determined tag argument: $TAG_ARGUMENT"
57+
echo "tag-argument=$TAG_ARGUMENT" >> $GITHUB_OUTPUT
58+
59+
- name: Validate latest version
60+
if: steps.figure-out-npm-tag.outputs.tag-argument == '--tag latest'
61+
shell: bash
62+
run: |
63+
node ./scripts/release/validate-latest-version.js ${{ steps.set-package-version.outputs.version }}
64+
65+
- name: Validate non-latest version
66+
if: steps.figure-out-npm-tag.outputs.tag-argument != '--tag latest'
67+
shell: bash
68+
run: |
69+
node ./scripts/release/validate-non-latest-version.js ${{ steps.set-package-version.outputs.version }}
70+
71+
- name: Print outputs
72+
shell: bash
73+
run: |
74+
echo "Version to be published: ${{ steps.set-package-version.outputs.version }}"
75+
echo "NPM tag argument: ${{ steps.figure-out-npm-tag.outputs.tag-argument }}"
76+
3577
# Ensure npm 11.5.1 or later is installed for OIDC
3678
- name: Update npm
3779
shell: bash
@@ -63,51 +105,29 @@ runs:
63105
name: ${{ env.PACKAGE_NAME }}
64106
path: './packages/react-native-gesture-handler/${{ env.PACKAGE_NAME }}'
65107

66-
- name: Figure out the correct npm tag
67-
id: figure-out-npm-tag
68-
shell: bash
69-
run: |
70-
if [ "${{ inputs.is-commitly }}" = "true" ]; then
71-
TAG_ARGUMENT="--tag nightly"
72-
else
73-
if [ $(node ./scripts/release/should-be-latest.js ${{ steps.set-package-version.outputs.version }}) = "true" ]; then
74-
TAG_ARGUMENT="--tag latest"
75-
else
76-
TAG_ARGUMENT=""
77-
fi
78-
fi
79-
80-
echo "Determined tag argument: $TAG_ARGUMENT"
81-
echo "tag-argument=$TAG_ARGUMENT" >> $GITHUB_OUTPUT
82-
83-
- name: Print outputs
84-
shell: bash
85-
run: |
86-
echo "Version to be published: ${{ steps.set-package-version.outputs.version }}"
87-
echo "NPM tag argument: ${{ steps.figure-out-npm-tag.outputs.tag-argument }}"
88-
89108
- name: Publish npm package
90109
shell: bash
91-
if: inputs.dry-run == 'false'
92110
working-directory: packages/react-native-gesture-handler
93111
run: |
94-
npm publish $PACKAGE_NAME --provenance ${{ steps.figure-out-npm-tag.outputs.tag-argument }}
112+
npm publish $PACKAGE_NAME --provenance ${{ steps.figure-out-npm-tag.outputs.tag-argument }} ${{ inputs.dry-run == 'true' && '--dry-run' || '' }}
95113
96-
- name: Don't publish if dry-run is true
114+
- name: Delete legacy tag
115+
if: inputs.dry-run == 'false' && steps.figure-out-npm-tag.outputs.tag-argument == '--tag legacy'
97116
shell: bash
98-
if: inputs.dry-run == 'true'
99117
run: |
100-
echo "At this point, the following command would have been run: npm publish $PACKAGE_NAME --provenance ${{ steps.figure-out-npm-tag.outputs.tag-argument }}"
118+
npm dist-tag rm react-native-gesture-handler legacy || echo "No legacy tag to remove"
101119
102120
- name: Configure git
103-
if: inputs.is-commitly == 'false'
121+
if: inputs.release-type == 'stable'
122+
id: configure-git
104123
shell: bash
105124
run: |
106125
git config --local user.email "action@github.com"
107126
git config --local user.name "GitHub Action"
127+
echo "branch-name=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT
108128
109129
- name: Create release commit
110-
if: inputs.is-commitly == 'false'
130+
if: inputs.release-type == 'stable' && steps.configure-git.outputs.branch-name != 'main'
111131
shell: bash
112132
run: |
113133
git add packages/react-native-gesture-handler/package.json
@@ -121,7 +141,7 @@ runs:
121141
fi
122142
123143
- name: Create release tag
124-
if: inputs.is-commitly == 'false'
144+
if: inputs.release-type == 'stable'
125145
shell: bash
126146
run: |
127147
git tag -a "v${{ steps.set-package-version.outputs.version }}" -m "Release v${{ steps.set-package-version.outputs.version }}"

.github/workflows/publish-release.yml

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,22 @@ on:
66
- main
77
paths:
88
- packages/react-native-gesture-handler/**
9-
# For stable releases
9+
# For manual releases
1010
workflow_dispatch:
1111
inputs:
12+
release-type:
13+
description: Type of release to publish.
14+
type: choice
15+
options:
16+
- stable
17+
- beta
18+
- rc
19+
default: stable
20+
version:
21+
description: Specific version to publish (usually inferred from x.y-stable branch name).
22+
type: string
23+
required: false
24+
default: ''
1225
dry-run:
1326
description: Whether to perform a dry run of the publish.
1427
type: boolean
@@ -31,16 +44,17 @@ jobs:
3144
- name: Check out
3245
uses: actions/checkout@v4
3346

34-
- name: Publish stable release
47+
- name: Publish manual release
3548
if: ${{ github.event_name == 'workflow_dispatch' }}
3649
uses: ./.github/actions/publish-npm-package
3750
with:
38-
is-commitly: false
51+
release-type: ${{ inputs.release-type }}
52+
version: ${{ inputs.version }}
3953
dry-run: ${{ inputs.dry-run }}
4054

41-
- name: Publish commitly release
55+
- name: Publish automatic commitly release
4256
if: ${{ github.event_name == 'push' }}
4357
uses: ./.github/actions/publish-npm-package
4458
with:
45-
is-commitly: true
59+
release-type: 'commitly'
4660
dry-run: false
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
name: Run Jest tests
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- '**/*.js'
7+
- '**/*.jsx'
8+
- '**/*.ts'
9+
- '**/*.tsx'
10+
push:
11+
branches:
12+
- main
13+
workflow_dispatch:
14+
15+
jobs:
16+
build:
17+
if: github.repository == 'software-mansion/react-native-gesture-handler'
18+
19+
runs-on: ubuntu-latest
20+
concurrency:
21+
group: jest-${{ github.ref }}
22+
cancel-in-progress: true
23+
24+
steps:
25+
- name: checkout
26+
uses: actions/checkout@v4
27+
28+
- name: Use Node.js 24
29+
uses: actions/setup-node@v6
30+
with:
31+
node-version: 24
32+
cache: yarn
33+
34+
- name: Install node dependencies
35+
run: yarn --immutable
36+
37+
- name: Run jest scripts tests
38+
run: yarn test:scripts
39+
40+
- name: Run jest package tests
41+
# always run this step even if the previous step fails
42+
if: ${{ always() }}
43+
run: yarn workspace react-native-gesture-handler test

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"ts-check": "yarn workspaces foreach --all --parallel --topological-dev run ts-check",
1616
"lint-js": "yarn workspaces foreach --all --parallel --topological-dev run lint-js",
1717
"format-js": "yarn workspaces foreach --all --parallel --topological-dev run format-js",
18-
"clean": "yarn workspaces foreach --all --parallel --topological-dev run clean && rm -rf node_modules yarn.lock"
18+
"clean": "yarn workspaces foreach --all --parallel --topological-dev run clean && rm -rf node_modules yarn.lock",
19+
"test:scripts": "jest ./scripts"
1920
},
2021
"devDependencies": {
2122
"@types/react": "^19.0.12",
@@ -28,6 +29,7 @@
2829
"eslint-plugin-prettier": "^5.0.1",
2930
"eslint-plugin-react": "^7.37.5",
3031
"husky": "^8.0.1",
32+
"jest": "^28.1.0",
3133
"lint-staged": "^12.3.2",
3234
"prettier": "3.3.3",
3335
"typescript": "~5.8.3"

0 commit comments

Comments
 (0)