# Releasing React Native Navigation
The [Release workflow](https://github.com/wix/react-native-navigation/actions/workflows/release.yml)
is the only supported npm publisher. Repository admins start it manually on `master`.
Both regular releases and snapshots use npm trusted publishing with GitHub OIDC.
Buildkite runs native tests; it no longer versions or publishes packages. Its expired npm
credentials must not be renewed as a fallback.
## One-time configuration
A repository admin and an npm package administrator must complete these steps before
enabling publication. Creating or merging the workflow does not configure npm trust.
1. Create the GitHub environment `npm-release`. Under deployment branches and tags,
select only the **branch** `master`. Protect `master` and review changes to release
workflows and helpers. Required environment reviewers are optional; enabling them
introduces approvals for the record, publish, and finalize jobs.
2. In the npm settings for `react-native-navigation`, add a GitHub Actions trusted publisher:
| Field | Value |
| ----------------- | ------------------------- |
| Organization | `wix` |
| Repository | `react-native-navigation` |
| Workflow filename | `release.yml` |
| Environment | `npm-release` |
| Allowed action | Direct `npm publish` |
Explicitly allow direct publication: a stage-only configuration cannot complete this
workflow. Standalone `npm dist-tag` permission is not needed. See
[npm trusted publishing](https://docs.npmjs.com/trusted-publishers/).
3. Enable GitHub Actions for this repository. Check Wix's Actions policy permits the pinned checkout, setup-node, upload-artifact,
and download-artifact actions. Allow workflow-created pull requests. Ensure existing
repository rules permit version branches and release tags without a bypass.
4. Check the GitHub commit status `buildkite/react-native-navigation` represents all
Android/iOS lanes in `.buildkite/pipeline.sh`. It must finish successfully on the
exact `master` commit selected by the release run. The status creator must match
the Buildkite app ID/login pinned in `scripts/release/rnn.cjs`. A failed, absent, or pending status
blocks real publication, including snapshots. A dry run reports it without publishing.
5. Verify a dry run and inspect its artifact. Then set the repository Actions variable
`RELEASE_PUBLISH_ENABLED` to `true`. Without it, publish and resume fail closed.
6. Run an intentional snapshot publication and verify the npm version, integrity,
provenance, and `snapshot` dist-tag. Confirm that `latest` did not change.
7. Remove obsolete release-only npm secret injection and restrict traditional token
publishing in npm's package settings. Do not renew expired tokens. A shared credential
must not be revoked until its other consumers have been identified.
No npm write token is needed in GitHub. `GITHUB_TOKEN` performs repository bookkeeping;
only the publish job has `id-token: write`. Publishing runs on a GitHub-hosted Ubuntu
runner. The workflow uses Node 24.22.1, including npm 11.19.1; update this tested pair
together. Older npm releases can execute `prepare` during `npm pack --ignore-scripts`.
## Start a release
Open **Actions → Release → Run workflow**, select `master`, and supply:
| Input | Meaning |
| ------------------------------ | ------------------------------------------------------------------------------ |
| `operation` | `dry-run` (default), `publish`, or `resume` |
| `kind` | `release` or `snapshot` |
| `version` | Exact semver for releases; empty for snapshots |
| `npm_tag` | `latest` for stable versions, `next` for prereleases, `snapshot` for snapshots |
| `documentation_version` | Optional numeric `x.y.z` documentation snapshot |
| `remove_documentation_version` | Optional existing version to remove while generating its replacement |
| `source_run_id` | Original publishing run ID, for resume only |
Examples:
- Stable: `kind=release`, `version=8.9.1`, `npm_tag=latest`.
- Prerelease: `kind=release`, `version=8.9.0-rc.1`, `npm_tag=next`.
- Snapshot: `kind=snapshot`, leave version empty, `npm_tag=snapshot`.
The selected version must be newer than npm `latest`. Build metadata such as `+build.1`
is intentionally unsupported. Snapshots use `-snapshot.gha.`, with the
base derived from the greater of the source package version and npm `latest`. The
run attempt is not part of the version. Snapshots do not create tags, GitHub releases,
version PRs, or documentation changes.
Users with write access may see GitHub's Run workflow button, but both the original
actor and the user rerunning/resuming the workflow must have repository-admin permission.
The workflow rechecks authorization before every job that changes external state.
## What the workflow does
1. Records the exact source SHA, chosen version/channel, and native CI result.
2. Installs the locked Yarn dependencies, changes release metadata, builds JS and
declarations with Bob, and runs JavaScript and release-helper tests on Linux.
3. Optionally installs the locked website dependencies, generates the requested docs
version, and builds the site. Removal requires an existing numeric version; replacing
an existing version requires explicitly selecting that same version for removal.
4. Creates a local release commit containing only the version and optional versioned
docs, then packs the already built package. Package contents and exported paths are
checked. Android/iOS sources ship in the package; this job does not compile native apps.
5. Uploads a versioned manifest, the tarball, release notes, and a Git bundle as
`release--`. A dry run ends here with no external release mutations.
6. For real releases, persists `ci/update-version-`, then publishes the verified
tarball using OIDC. The publisher does not install project dependencies or rebuild it.
7. Verifies npm integrity, tags the source commit on `master` with the bare version (for example
`8.9.1`), creates a GitHub release, and opens a version/documentation PR with the
`release` label. An existing PR template is included with its checkboxes left for review.
Release notes include merged PRs from the preceding reachable stable tag through the
source commit. They preserve feature/enhancement/fix categories, platform groups, and
`skip-changelog` exclusions. No second `gren` invocation or timed retry is involved.
Review and merge the version PR after publication. Documentation deploys through the
existing documentation workflow after that merge. Events created with `GITHUB_TOKEN` do not
start Actions workflows, so Release checks will not run on the version PR; Buildkite still
builds it through its webhook. Inspect the PR's checks before merging. The release workflow
does not invoke engine notification.
## Resume a partial release
Use **Re-run failed jobs** when the original run still has its preparation outputs, or
dispatch `operation=resume` with `source_run_id` set to the original **publish** run.
Other release inputs are ignored in resume mode. Do not enter a different version to
recover from a GitHub or network error.
Recovery validates the upstream workflow identity, source SHA, native CI, artifact
integrity, release commit, and package metadata. It downloads the saved artifacts and
does not rebuild against the current branch. If the version is still absent from npm and
`master` has advanced, re-run the original publishing run instead of dispatching a new
resume run: npm provenance must identify the source commit that built the package. A new
resume dispatch may finish GitHub bookkeeping for an already published matching tarball.
| State | Result |
| ------------------------------------------------- | -------------------------------------------------------------------------- |
| Version absent from npm | Publish the original tarball, provided its channel would not move backward |
| Same version and same integrity already published | Skip publication and finish GitHub steps |
| Same version with different integrity | Stop; investigate the conflicting publication |
| Registry failure or lost response | Fail without choosing another version; resume when healthy |
| Existing branch/tag/PR matches | Reuse it |
| Existing branch/tag/PR conflicts | Stop; never force-push or move a tag |
| Dry-run artifact selected | Reject; start a fresh publish run |
| Artifact expired/deleted | Stop automatic recovery |
Artifacts request 90-day retention, subject to organization limits. Retain artifacts until
the version PR is merged and the release is verified. After artifact loss, an admin must
investigate the existing registry version and persisted release branch manually; do not
reconstruct and publish different bytes under the same version or automatically fall back
to the old pipeline. npm and GitHub do not provide a cross-service atomic transaction.
The concurrency group serializes all release attempts. GitHub may replace a pending run
when another dispatch is queued; it does not cancel the running publisher. Check each run's
state rather than assuming every click is queued indefinitely.
## Validate changes to the release tooling
With Node 24.22.1 and npm 11.19.1:
```sh
node --test scripts/release/*.test.cjs
node .yarn/releases/yarn-4.12.0.cjs install --immutable
node .yarn/releases/yarn-4.12.0.cjs prepare
node .yarn/releases/yarn-4.12.0.cjs test-js
RELEASE_DIR=/tmp/rnn-package node scripts/release/index.cjs pack-check
```
`pack-check` only prepares and inspects a local tarball. The read-only Release checks
workflow runs the tests and clean Linux package check on PRs. A real OIDC publication
still needs the default-branch workflow and the npm/GitHub configuration above.
## Removed release paths and retained consumers
The Buildkite release form, publishing job, legacy `scripts/release.js`, `gren` config,
and root/playground `github-release-notes` dependencies have been removed. Automatic
Buildkite snapshots are replaced by manual snapshots. Native Buildkite testing remains.
Outside the repository, remove obsolete release schedules/hooks and release-only
`NPM_TOKEN`/`NPM_EMAIL` injection. Inspect any old Jenkins configuration referenced by
historical setup; the old README badge alone does not prove an active publisher exists.
Keep the tracked registry-only `.npmrc`, documentation deployment's `GH_PAGES_DEPLOY`,
and any Git credential still used by `scripts/test-snapshot.js` to record reference images.
Do not delete shared secrets merely because the old publisher also used them.
For the next repository, use [the migration checklist](release-migration-checklist.md).