Skip to content

Commit 5ddaf20

Browse files
authored
chore(release): set main sentinel version and guard stable publishes (#3923)
## Description Adds two coupled changes for the release-branch workflow. ### 1. Pin `main` to a sentinel version (`1000.0.0`) Bumps `package.json#version` on `main` to `1000.0.0`, per the release guide (see [labs#726](software-mansion/react-native-screens-labs#726)). In the release-branch workflow, the version in `main/package.json` is not a real release version — releases are cut from dedicated `<major>.<minor>-stable` branches where the version is set independently. Keeping `main` pinned to a recently-released value (e.g. `4.24.0`) invites confusion and requires a bump on every release cut. Alternatives have their own trade-offs — `react-native-reanimated` uses a `<version>-main` suffix, which demands format discipline on every bump; `react-native-gesture-handler` does nothing, and the version on `main` silently drifts behind the real latest release. The sentinel `1000.0.0` is deliberately absurd so nobody mistakes it for a real release, requires no maintenance on release cuts, and still parses as valid semver for tooling. Closes software-mansion/react-native-screens-labs#1167. ### 2. Guard the publish workflow against non-nightly publishes from `main` The sentinel is a clear *signal*, but without enforcement nothing prevents an operator from triggering **Publish release to npm** on `main` and pushing `[email protected]` to the registry. Adds a pre-publish validation step in `publish-npm.yml` that invokes `scripts/validate-publish-target.sh` whenever a non-nightly release is triggered via `workflow_dispatch`. The script rejects: - the sentinel version (`1000.*`), - runs targeting `main`, - branches that do not match the documented release-branch patterns (`<major>.<minor>-stable` or `v<major>-main`). All failures are surfaced in a single run so an operator sees every problem at once, not one at a time. Nightly publishes from `main` remain intentionally untouched — they are the designed exception per the release guide. ## Changes - `package.json`: version `4.24.0` → `1000.0.0`. - `.github/workflows/publish-npm.yml`: new `Validate publish target` step, gated on `workflow_dispatch` with non-nightly `release-type`. - `scripts/validate-publish-target.sh` (new): runs the three checks; exit `0` on success, `1` on validation failure, `2` on usage error. ## Test plan - Locally: `./scripts/validate-publish-target.sh main stable` against current repo state → all three checks fail (sentinel + main + bad pattern), exit `1`. - Locally: `./scripts/validate-publish-target.sh 4.25-stable stable` → sentinel check fires (`1000.0.0` on this branch), branch checks pass, exit `1`. - Locally: invocation with missing args → usage error, exit `2`. - Post-merge: run `publish-npm.yml` in dry-run against `main` with `release-type=stable` → expect the guard step to fail the workflow before the publish action runs. ## Checklist - [ ] Included code example that can be used to test this change. - [ ] For visual changes, included screenshots / GIFs / recordings documenting the change. - [ ] For API changes, updated relevant public types. - [ ] Ensured that CI passes
1 parent ac58fdd commit 5ddaf20

3 files changed

Lines changed: 92 additions & 1 deletion

File tree

.github/workflows/publish-npm.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,17 @@ jobs:
5656
cache: "yarn"
5757
registry-url: https://registry.npmjs.org/
5858

59+
# Guards against publishing a stable / beta / rc release from an
60+
# inappropriate target. Intentionally skipped for nightly releases,
61+
# which are published from main by design.
62+
- name: Validate publish target
63+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.release-type != 'nightly' }}
64+
shell: bash
65+
env:
66+
BRANCH: ${{ github.ref_name }}
67+
RELEASE_TYPE: ${{ inputs.release-type }}
68+
run: ./scripts/validate-publish-target.sh "$BRANCH" "$RELEASE_TYPE"
69+
5970
- name: Publish manual release
6071
if: ${{ github.event_name == 'workflow_dispatch' }}
6172
uses: software-mansion/npm-package-publish@264013301cc21350186b190f1f6dd10ae4c8ee04

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "react-native-screens",
3-
"version": "4.24.0",
3+
"version": "1000.0.0",
44
"description": "Native navigation primitives for your React Native app.",
55
"scripts": {
66
"submodules": "git submodule update --init --recursive && (cd react-navigation && yarn && yarn build && cd ../)",

scripts/validate-publish-target.sh

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/bin/bash
2+
3+
# Validates that the current branch and package.json version are appropriate
4+
# for publishing the requested release.
5+
#
6+
# Handles all four release types:
7+
# - nightly: always valid — nightly publishes are allowed from any branch
8+
# per the release guide; the script returns success without running the
9+
# branch/version checks.
10+
# - stable / beta / rc: rejects the main-branch sentinel version, refuses
11+
# publishes from `main`, and requires the branch to match a documented
12+
# release-branch pattern.
13+
#
14+
# Exits 0 if the target is valid; 1 if a validation check fails (with one or
15+
# more error messages); 2 on usage error (missing arguments or unknown
16+
# release-type). For validation failures all checks are reported before exit
17+
# so the operator sees every problem in a single run.
18+
#
19+
# This script assumes it is run from the top level repo directory.
20+
#
21+
# Requires `jq` on PATH (pre-installed on GitHub-hosted ubuntu runners).
22+
#
23+
# Usage: scripts/validate-publish-target.sh <branch> <release-type>
24+
# <release-type>: one of stable | beta | rc | nightly
25+
26+
set -euo pipefail
27+
28+
if [[ $# -ne 2 ]]; then
29+
echo "Usage: $0 <branch> <release-type>" >&2
30+
exit 2
31+
fi
32+
33+
BRANCH="$1"
34+
RELEASE_TYPE="$2"
35+
36+
case "$RELEASE_TYPE" in
37+
stable|beta|rc|nightly) ;;
38+
*)
39+
echo "error: unknown release-type '$RELEASE_TYPE' (expected: stable | beta | rc | nightly)" >&2
40+
exit 2
41+
;;
42+
esac
43+
44+
VERSION=$(jq -r .version package.json)
45+
46+
echo "ref=$BRANCH version=$VERSION release-type=$RELEASE_TYPE"
47+
48+
# Nightly publishes are the designed exception per the release guide: they are
49+
# allowed from any branch (scheduled cron runs from main; manual dispatch can
50+
# target a release branch). No further checks apply.
51+
if [[ "$RELEASE_TYPE" == "nightly" ]]; then
52+
exit 0
53+
fi
54+
55+
emit_error() {
56+
if [[ -n "${GITHUB_ACTIONS:-}" ]]; then
57+
echo "::error::$1"
58+
else
59+
echo "error: $1" >&2
60+
fi
61+
}
62+
63+
FAIL=0
64+
65+
if [[ "$VERSION" == 1000.* ]]; then
66+
emit_error "package.json version is '$VERSION' — this is the main-branch sentinel. Bump the version on a release branch before publishing a $RELEASE_TYPE release."
67+
FAIL=1
68+
fi
69+
70+
if [[ "$BRANCH" == "main" ]]; then
71+
emit_error "Refusing to publish a $RELEASE_TYPE release from 'main'. Release from a *-stable or v*-main branch."
72+
FAIL=1
73+
fi
74+
75+
if ! [[ "$BRANCH" =~ ^(v[0-9]+-main|[0-9]+\.[0-9]+-stable)$ ]]; then
76+
emit_error "Branch '$BRANCH' does not match an allowed release-branch pattern (v<major>-main or <major>.<minor>-stable). Publish from a dedicated release branch."
77+
FAIL=1
78+
fi
79+
80+
exit $FAIL

0 commit comments

Comments
 (0)