Skip to content

Latest commit

 

History

History
482 lines (330 loc) · 24.1 KB

guide-release-process.md

File metadata and controls

482 lines (330 loc) · 24.1 KB

Release Process

Note

This documents the steps to releasing a stable React Native release.

Release candidates will generally follow the same steps but have some pre and post work, depending on if you're cutting, doing a patch, or promoting a release candidate to stable.

Follow the dedicated release candidate guide for more detail.

Tip

The steps below are automated by the rn-release-automator CLI — the recommended way to run a release. Each step leads with the CLI command and keeps the manual instructions in a collapsible Manual steps section. For a patch or incremental RC, the two commands you'll use most are:

npx rn-release-automator@latest prepare-release --series 0.85   # cherry-picks + choose next version
npx rn-release-automator@latest publish --version 0.85.0-rc.1   # trigger the release

Always preview mutating commands with --dry-run first. See the Release CLI guide for setup and the full command reference.

Release steps

These steps apply when making a patch release or an incremental release candidate. Typically we like to keep the #release-crew Discord channel up to date with progress. You're free to do this however you'd like. One method is it keep a progress message up-to-date (⌛ started, ✅ complete, 🚨 problem).

Tip

The CLI generates this progress template for you — run npx rn-release-automator@latest communicate --version <version> (or pick Communicate from the menu) and copy the Release Status Message.

Here is the template used for 0.78.0-rc.0:

# 0.78.0-rc.0

* ✅ Pick changes and push `0.78-stable`
* ⌛ Wait for `build_npm_package` (if <0.78) or `test_ios_rntester` (if >=0.78) to complete → https://github.com/facebook/react-native/actions/runs/12870884886
* ⌛ Verify that E2E tests are green → https://github.com/facebook/react-native/actions/runs/13634115054
* ⌛ (ONLY for RC0,1,4,stable) Test release → https://github.com/reactwg/react-native-releases/blob/main/docs/guide-release-testing.md
  * ⌛ <Tester Name>: https://github.com/reactwg/react-native-releases/issues/
* ⌛ Publish release job → https://github.com/facebook/react-native/actions/runs/12784528348
* ⌛ Verify template: `npx @react-native-community/cli init` + `build` for iOS + Android
* ⌛ Verify upgrade helper → https://react-native-community.github.io/upgrade-helper/?from=0.77.0&to=0.78.0-rc.0
* ⌛ Verify Maven assets → https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/0.78.0-rc.0
* ⌛ Generate changelog PR → https://github.com/facebook/react-native/pull/48685
* ⌛ Create GitHub release → https://github.com/facebook/react-native/releases/tag/v0.78.0-rc.0
* ⌛ Communicate release to `#releases-coordination` on Discord
* ⌛ Communicate release to `React Native Releases` on Workplace (Meta internal)
* ⌛ Update GitHub project

Step 1: Check out release branch locally

Tip

Get an overview of the series (branch, CI, npm, pending picks) first with:

npx rn-release-automator@latest status --series 0.85

Checking out the branch is a local git operation, so do it yourself as below. prepare-release (Step 2) will verify the branch exists before doing anything.

From your local facebook/react-native clone, check out the relevant release branch. Make sure your system is set up with the right tooling dependencies for the release. e.g. you may need to switch Node versions.

# Fetch new commits and tags (to prep for any cherry-picks)
git fetch --all --tags

# Check out release branch
git switch <release-branch> # e.g. 0.75-stable

# OR, if checking out a release branch for the first time
git switch -c <release-branch> upstream/<release-branch>

Step 2: Action cherry-picks and pull requests

New changes targeting a given release need to be replicated from main onto the release branch, via either a cherry-pick or pull request. See also Releases Support Policy. New change MUST be reflected on the release minor version project before picking / merging:

CleanShot 2024-12-09 at 11 08 50@2x

Once the project is up to date, let the CLI analyze the pending pick requests and process them for you. Preview first with --dry-run, then run it for real:

npx rn-release-automator@latest prepare-release --series 0.85 --dry-run
npx rn-release-automator@latest prepare-release --series 0.85

prepare-release will:

  • Fetch the latest published version in the series and let you pick the next version (next RC, promote to stable, or next patch).
  • Check CI status and list any unpublished commits already on the branch.
  • Classify each open pick request — e.g. 🟢 can be bot-merged, 🟡 not on main yet, 🔵 PR targets the branch, 🔴 Hermes / multi-target / complex — and, for bot-mergeable picks, comment @react-native-bot merge <sha> <branch> for you (skipped in dry-run). It can also close pick requests whose PR is already merged.

Warning

For any pick requests or merge requests for Hermes, notify a Meta Release Crew member. They'll need to publish and pick the Hermes release into the release branch. Do not proceed past step 3 until the the branch has been updated with the Hermes release. The CLI flags Hermes-related picks as 🔴 and leaves them for manual handling.

Manual steps — cherry-pick without the CLI

Once the project is up to date, you can pick these locally:

# Make sure to update the release branch
git pull

# [Optionally] Use this tool to help order the cherry-picks and identify PRs
npx rn-release-info 0.76.5

# Cherry-pick relevant commits
git cherry-pick <commit-on-main>

Alternatively, you can also pick via react-native-bot by leaving a comment: @react-native-bot merge <commit_id> 0.xx-stable

Step 3: Wait for Github Actions artifacts to build

Once all picks are complete, push your changes to the remote release branch.

git push

This will kick off a Github Action workflow called Test All that will build relevant artifacts (Hermes prebuilts, RNTester.apk) that will expedite local testing.

Tip

You don't have to watch the Actions tab manually — prepare-release, publish, and test-release all check CI status on the branch before continuing, and status --series 0.85 shows the latest workflow runs at any time.

Navigate to Github Actions and wait for the build_npm_package job to complete successfully (~30min into the test-all workflow). If the job fails, try and fix the issue so that the artifacts build.

Important

Release testing will only use the artifacts from the last workflow that ran on your release branch! This means that if you push more changes to your release branch, you must wait for it to complete the build_npm_package job again to use those artifacts in testing.

The takeaway here is to try and avoid pushing more commits to CI at this point. Otherwise, you'll have to wait for CI to build the assets again to use them in your testing.

See Github Actions Artifacts for more details.

Step 4: Test the release

Kick off local testing with the CLI, which verifies your repo/branch and CI, cleans the environment, wires up prebuild downloads, and prints the test matrix:

npx rn-release-automator@latest test-release --version 0.85.0-rc.0

Then follow the Release Testing guide for what and how to test.

  • We should have 1x Release Crew member testing the release:
    • Only the following releases should be manually tested.
      • RC0
      • RC1
      • RC4 (Golden RC)
    • All the other releases require no manual testing.
  • You should ensure that the E2E jobs on the release branch are green.

Step 5. Create release

Starting from React Native 0.75, a new release is created using a Github Action workflow called Create Release. The CLI runs its pre-flight checks (CI green? pending picks? already published on npm?), triggers that workflow, and monitors it to completion.

Caution

This publishes a release. Always preview with --dry-run first — it runs every read-only check and shows exactly what would be triggered, without triggering anything.

npx rn-release-automator@latest publish --version 0.85.0-rc.0 --dry-run
npx rn-release-automator@latest publish --version 0.85.0-rc.0

The CLI picks the stable branch from the version, sets the latest flag automatically for stable (non-RC) releases, and keeps the workflow's dry-run input false for a real run. It then triggers the Create Release workflow (create-release.yml), which syncs package versions (publish-bumped-packages.yml), commits and publishes a tag. The new tag then launches the Publish Release workflow (publish-release.yml) which builds and publishes the react-native npm package artifact.

Manual steps — trigger the workflow from the GitHub UI

The workflow requires 4 parameters:

  1. The branch we need to use to cut the release. Make sure to set it to your stable branch. e.g.: 0.75-stable
  2. The version we want to publish. For example, 0.75.0-rc.0.
  3. Check the latest checkbox, if you are publishing a patch on the latest version.
  4. The last checkbox is for a dry-run. If you need to run a release, keep it unchecked.

This runs the Create Release workflow (create-release.yml). It'll sync package versions (publish-bumped-packages.yml), commit and publish a tag:

The new tag will then launch a Publish Release workflow (publish-release.yml) which builds and publishes the react-native npm package artifact:

Step 6: Verify Release

Once all workflows above are complete, run the interactive verification checklist. It finds the latest published version in the series and walks you through 8 post-release checks — this single command covers Steps 6 through 9 and Step 11 below (npm, template, upgrade helper, Maven, changelog PR, GitHub release, communicate, and GitHub project):

npx rn-release-automator@latest verify-release --series 0.85

For each check the CLI offers to run it for you (e.g. npm view, npx …init, a Maven curl), open the relevant page in your browser, or skip.

Manual steps — verify each item by hand

Verify the following:

Verify npm publishes

Verify that react-native is published on npm with the correct tag.

npm view react-native

# Also verify that one or more subpackages are published
npm view @react-native/codegen

Init a new template app

Sanity check by initializing a new project and running for Android and iOS. We suggest setting the version as an environmental variable, having a GitHub personal token and the Github CLI tools installed to make it easy to copy-pasta these verifications:

export NEW_VERSION="v0.76.0-rc.3" # Should be prefixed with a 'v'
export GITHUB_TOKEN=<your token>

Verify the template with the version compatible with the release.

[!Note] For a new release, you might need to use a pre-released version. (e.g 20.0.0-alpha.0).

npm view @react-native-community/cli versions will print all available versions.

export VERSION=${NEW_VERSION#v}
export REACT_NATIVE_COMMUNITY_CLI_VERSION="^20.0.0"
npx @react-native-community/cli@${REACT_NATIVE_COMMUNITY_CLI_VERSION} init "ReactNative${VERSION//[.-]/_}" --version "$VERSION"

[!Tip] Keep this project around somewhere incase you need to repro something on this version.

Backup: How do I manually create a template for this version?

Run the Release workflow, making sure you use the correct branch. For example with the 0.76.* releases you would use the 0.76-stable branch:

You will need separate additional permissions to do this, reach out to the release crew on Discord for help.

Verify Upgrade Helper is updated

The publish_release job should also trigger the rn-diff-purge GitHub action (link). This action will update the Upgrade Helper with a diff of your latest release patch. Verify your release is visible in the dropdown.

Upgrade helper

Common Issues:

Why can't I see the upgrade helper diff between last set of releases, e.g. 0.75.4 → 0.76.0-rc.3?

Cause:

rn-diff-purge has to be run in order. That means 0.75.4 must be run before 0.76.0-rc.3. Sometimes during releases this can happen out of order when people don't anticipate having to coordinate.

Fix:

I'm going to use the above versions as examples, replace with your affected versions.

  1. Delete the tags:
git push --delete origin 0.75.4
git push --delete origin 0.76.0-rc.3
  1. Delete the versions from RELEASES
  2. Manually publish by calling the Github action in order: 0.75.4 first then 0.76.0-rc.3
  3. Confirm this is fixed: https://react-native-community.github.io/upgrade-helper/?from=0.75.4&to=0.76.0-rc.3
Manually Publish: How do I add an entry in the Upgrade Helper for this version? If there is a failure and you manually want to add your new tag to the `upgrade helper`, use:
curl -X POST https://api.github.com/repos/react-native-community/rn-diff-purge/dispatches \
            -H "Accept: application/vnd.github.v3+json" \
            -H "Authorization: Bearer $GITHUB_TOKEN" \
            -d "{\"event_type\": \"publish\", \"client_payload\": { \"version\": \"$NEW_VERSION\" }}"

Confirm the publish action completes before verifying the upgrade helper has been updated.

Verify assets have been uploaded to Maven

Verify release assets are uploaded to Maven for your release.

Note, this may take a moment to update. Later, we will link to some of these artifacts in the release notes.

export VERSION=${NEW_VERSION#v}
curl -I https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/$VERSION/react-native-artifacts-$VERSION-reactnative-core-dSYM-debug.tar.gz
curl -I https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/$VERSION/react-native-artifacts-$VERSION-reactnative-core-dSYM-release.tar.gz

Step 7: Update CHANGELOG.md

Tip

verify-release (Step 6) includes a step that opens the pending changelog PR for you to review and merge. This step describes what to do with it.

Now we need to update the CHANGELOG.md file at the react-native repo root.

Note

Changelog commits must be submitted to the main branch.

Starting from React Native (>= 0.80), the Publish Release action will generate a changelog PR such as changelog/v0.80.0-rc.0 for you.

Reformat and re-style the modified CHANGELOG.md on that branch based on previous changelog PRs. Then, a Meta engineer should:

  1. Import the PR in the Meta internal system,
  2. Get the resulting diff approved,
  3. Land the diff into main.

If it fails, or for (< 0.80), manually generate the updated changelog on main and open a PR to main after similar reformatting:

Manually Generate Changelog Updates
# Check out `main` branch
git switch main

# Pull new tags
git fetch --all --tags --force
git pull

BASE_VERSION=$(git tag -l --sort=-v:refname | grep -E '^v0\.' | head -n2 | tail -n1)

# Generate the changelog
npx @rnx-kit/rn-changelog-generator \
  --base $BASE_VERSION \
  --compare $NEW_VERSION \
  --repo . \
  --changelog ./CHANGELOG.md \
  --token $GITHUB_TOKEN

Step 8: Create the GitHub Release

Tip

verify-release (Step 6) opens the draft GitHub release for this tag and reminds you whether to mark it as Latest (stable) or Pre-release (RC). Use communicate --version <version> to generate a release body template.

Note

For large releases with many changelog changes such as RC0 (e.g. 0.81.0-rc.0) or Major release (e.g. 0.81.0) the link to CHANGELOG.md at the bottom of the Github release is enough.

For React Native (>= 0.80), a draft Github release is generated by the job Publish Release.

If there are problems with the automatic draft release generation, or for (< 0.80), manually create a Github release:

Manually Github release creation process:

Create a new GitHub release.

  • Set the release tag to the newly created tag.
  • Set the title to the release version (without preceding "v").
  • Set release type:
    • Select "Set as a pre-release" if you releasing a release candidate.
    • Select "Set as the latest release" if you releasing a patch for the latest version.
  • Run the below template generation from the changelog commit, pasting it in the release description:
cat <<EOF | pbcopy
<!-- TODO Copy and paste your formatted Changelog generated here. -->
<!-- For large releases with many changelog changes such as first RC (e.g. `0.81.0-rc.0`) or Major release (e.g. `0.81.0`) the link to CHANGELOG.md at the bottom is enough --> 

$(git show --patch | grep '^+[^+]' | sed 's/^\+//')

---

<!-- TODO Update these links for your release version -->
Hermes dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/$HERMES_VERSION/hermes-ios-$HERMES_VERSION-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/$HERMES_VERSION/hermes-ios-$HERMES_VERSION-hermes-framework-dSYM-release.tar.gz)

Hermes V1 dSYMS:
- [Debug](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/$HERMES_V1_VERSION/hermes-ios-$HERMES_V1_VERSION-hermes-framework-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/hermes/hermes-ios/$HERMES_V1_VERSION/hermes-ios-$HERMES_V1_VERSION-hermes-framework-dSYM-release.tar.gz)

ReactNativeDependencies dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/$VERSION/react-native-artifacts-$VERSION-reactnative-dependencies-dSYM-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/$VERSION/react-native-artifacts-$VERSION-reactnative-dependencies-dSYM-release.tar.gz)

ReactNative Core dSYMs:
- [Debug](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/$VERSION/react-native-artifacts-$VERSION-reactnative-core-debug.tar.gz)
- [Release](https://repo1.maven.org/maven2/com/facebook/react/react-native-artifacts/$VERSION/react-native-artifacts-$VERSION-reactnative-core-release.tar.gz)

---

You can file issues or pick requests against this release [here](https://github.com/reactwg/react-native-releases/issues/new/choose).

---

To help you upgrade to this version, you can use the [Upgrade Helper](https://react-native-community.github.io/upgrade-helper/) ⚛️.

---

View the whole changelog in the [CHANGELOG.md file](https://github.com/facebook/react-native/blob/main/CHANGELOG.md).
EOF

Step 9: Communicate Release

Generate the announcement templates with the CLI:

npx rn-release-automator@latest communicate --version 0.81.0-rc.0

This prints ready-to-copy templates: the release status tracker, the Discord announcement (long and short forms), and the GitHub release body. Pass --format discord-short (or discord, github, status, all) to print just one.

Send the short announcement in the Core Contributors Discord #release-coordination channel, and get a Meta engineer to send the same message in the React Native Releases Workplace group.

Manual steps — announcement template

Create and send a message with the template below:

📢 **0.81.0-rc.0 is out!**

📦 Release tag: https://github.com/facebook/react-native/releases/tag/v0.81.0-rc.0
📝 Changelog PR: https://github.com/facebook/react-native/pull/52517

Step 10: Ensure Podfile.lock is updated

Everytime we release a new version, there is a new hermes-engine version published. We need to update packages/rn-tester to use this new version. This is in preparation for the next release from this branch.

Since React Native (>= 0.80) this happens automatically by the Publish Release.

Ensure that there's a [LOCAL] Bump Podfile.lock commit on the release branch created by Publish Release.

If the automatic bump fails, or you are on (< 0.80):

Manually update `Podfile.lock`:

Note: If you just cloned the react-native repository, make sure to run yarn to install all dependencies. Additionally, we recommend installing the latest Ruby version using rbenv before proceeding.

# Check out release branch
git switch <release-branch>

# Make sure to update the release branch
git pull

# Head to rn-tester package and update pods (including parentheses in the second command to run the command in a subshell)
rm -rf packages/react-native-codegen/lib
(cd packages/rn-tester && bundle install && bundle exec pod update hermes-engine --no-repo-update)

# Commit only changes to packages/rn-tester/Podfile.lock
git add packages/rn-tester/Podfile.lock
git commit -m "Update Podfile.lock" -m "Changelog: [Internal]"
git push

Step 11: Update GitHub Project

Tip

verify-release (Step 6) finishes by opening this project for you (it tries to auto-detect the project for the series).

Make sure you've updated the status of completed and ongoing tasks in the relevant GitHub project. Unresolved items can be assigned to the following release.