Skip to content

Commit f6d1268

Browse files
authored
Add new release process (#14916)
1 parent c29295c commit f6d1268

File tree

32 files changed

+2894
-430
lines changed

32 files changed

+2894
-430
lines changed

.github/workflows/release.yml

Lines changed: 48 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -1,234 +1,82 @@
1-
# We use this singular file for all of our releases because we can only specify
2-
# a singular GitHub workflow file in npm's Trusted Publishing configuration.
3-
# See https://docs.npmjs.com/trusted-publishers for more info.
4-
#
5-
# Specific jobs only run on the proper trigger:
6-
#
7-
# - Changesets-driven pre-releases/stable releases
8-
# - Trigger: push to release-next/release-v6 branch
9-
# - jobs: release -> find_package_version -> comment
10-
# - Nightly releases
11-
# - Trigger: schedule/cron
12-
# - jobs: release-nightly
13-
# - Experimental releases (from a workflow_dispatch trigger)
14-
# - Trigger: workflow_dispatch
15-
# - jobs: release-experimental
1+
name: 🚢 Release/Publish
162

17-
name: 🚢 Release
183
on:
19-
# Changesets-driven prereleases and stable releases
204
push:
215
branches:
22-
- "release-next"
23-
- "release-v6"
24-
# Nightly releases
25-
schedule:
26-
- cron: "0 7 * * *" # every day at 12AM PST
27-
# Experimental Releases
28-
workflow_dispatch:
29-
inputs:
30-
branch:
31-
required: true
6+
- "release"
7+
- "hotfix"
328

339
concurrency:
3410
group: ${{ github.workflow }}-${{ github.ref }}
3511
cancel-in-progress: true
3612

37-
env:
38-
CI: true
39-
4013
jobs:
41-
release:
42-
name: 🦋 Changesets Release
43-
if: github.repository == 'remix-run/react-router' && github.event_name == 'push'
14+
check:
15+
name: Check release readiness
16+
if: github.repository == 'remix-run/react-router'
4417
runs-on: ubuntu-latest
4518
outputs:
46-
published_packages: ${{ steps.changesets.outputs.publishedPackages }}
47-
published: ${{ steps.changesets.outputs.published }}
48-
permissions:
49-
contents: write # enable pushing changes to the origin
50-
id-token: write # enable generation of an ID token for publishing
51-
pull-requests: write # enable opening a PR for the release
19+
has_change_files: ${{ steps.check.outputs.has_change_files }}
5220
steps:
53-
- name: ⬇️ Checkout repo
54-
uses: actions/checkout@v6
55-
with:
56-
fetch-depth: 0
57-
58-
- name: 📦 Setup pnpm
59-
uses: pnpm/action-setup@v4
60-
61-
- name: ⎔ Setup node
62-
uses: actions/setup-node@v6
63-
with:
64-
node-version: 24 # Needed for npm@11 for Trusted Publishing
65-
cache: "pnpm"
66-
67-
- name: 📥 Install deps
68-
run: pnpm install --frozen-lockfile
69-
70-
# This action has two responsibilities. The first time the workflow runs
71-
# (initial push to a `release-*` branch) it will create a new branch and
72-
# then open a PR with the related changes for the new version. After the
73-
# PR is merged, the workflow will run again and this action will build +
74-
# publish to npm.
75-
- name: 🚀 PR / Publish
76-
id: changesets
77-
# PLEASE KEEP THIS PINNED TO 1.4.10 to avoid a regression in 1.5.*
78-
# See https://github.com/changesets/action/issues/465
79-
uses: changesets/action@v1.4.10
80-
with:
81-
version: pnpm run changeset:version
82-
commit: "chore: Update version for release"
83-
title: "chore: Update version for release"
84-
publish: pnpm run release
85-
createGithubReleases: false
86-
env:
87-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
88-
89-
find_package_version:
90-
name: 🦋 Find Package
91-
needs: [release]
92-
runs-on: ubuntu-latest
93-
if: github.repository == 'remix-run/react-router' && github.event_name == 'push' && github.ref_name != 'release-v6' && needs.release.outputs.published == 'true'
94-
outputs:
95-
package_version: ${{ steps.find_package_version.outputs.package_version }}
96-
steps:
97-
- name: ⬇️ Checkout repo
98-
uses: actions/checkout@v6
99-
100-
- name: 📦 Setup pnpm
101-
uses: pnpm/action-setup@v4
102-
103-
- name: ⎔ Setup node
104-
uses: actions/setup-node@v6
105-
with:
106-
node-version: 24 # Needed for npm@11 for Trusted Publishing
107-
cache: "pnpm"
21+
- name: Checkout
22+
uses: actions/checkout@v4
10823

109-
- id: find_package_version
24+
- name: Check for change files
25+
id: check
11026
run: |
111-
package_version=$(node ./scripts/find-release-from-changeset.js)
112-
echo "package_version=${package_version}" >> $GITHUB_OUTPUT
113-
env:
114-
PACKAGE_VERSION_TO_FOLLOW: "react-router"
115-
PUBLISHED_PACKAGES: ${{ needs.release.outputs.published_packages }}
116-
117-
comment:
118-
name: 📝 Comment on related issues and pull requests
119-
if: github.repository == 'remix-run/react-router' && github.event_name == 'push' && github.ref_name != 'release-v6' && needs.find_package_version.outputs.package_version != ''
120-
needs: [release, find_package_version]
121-
runs-on: ubuntu-latest
122-
permissions:
123-
issues: write # enable commenting on released issues
124-
pull-requests: write # enable commenting on released pull requests
125-
steps:
126-
- name: ⬇️ Checkout repo
127-
uses: actions/checkout@v6
128-
with:
129-
fetch-depth: 0
130-
131-
# IMPORTANT: if you make changes here, also make them in release-comment-manual.yml
132-
- name: 📝 Comment on related issues and pull requests
133-
uses: remix-run/release-comment-action@v0.5.1
134-
with:
135-
DIRECTORY_TO_CHECK: "./packages"
136-
PACKAGE_NAME: "react-router"
137-
ISSUE_LABELS_TO_REMOVE: "awaiting release"
138-
ISSUE_LABELS_TO_KEEP_OPEN: "🗺 Roadmap"
27+
# Look for change files in any package's .changes directory (excluding README.md)
28+
change_files=$(find packages/*/.changes -name "*.md" ! -name "README.md" 2>/dev/null)
29+
if [ -n "$change_files" ]; then
30+
echo "Change files found (blocking publish):"
31+
echo "$change_files"
32+
echo "has_change_files=true" >> $GITHUB_OUTPUT
33+
else
34+
echo "No change files found, proceeding to publish."
35+
echo "has_change_files=false" >> $GITHUB_OUTPUT
36+
fi
13937
140-
# HEADS UP! this "nightly" job will only ever run on the `main` branch due to
141-
# it being a cron job, and the last commit on main will be what github shows
142-
# as the trigger however in the checkout below we specify the `dev` branch,
143-
# so all the scripts in this job will be ran from that, confusing i know, so
144-
# in some cases we'll need to create multiple PRs when modifying nightly
145-
# release processes
146-
release-nightly:
147-
name: 🌒 Nightly Release
148-
if: github.repository == 'remix-run/react-router' && github.event_name == 'schedule'
38+
pull_request:
39+
name: Open pull request
40+
needs: check
41+
if: needs.check.outputs.has_change_files == 'true'
14942
runs-on: ubuntu-latest
15043
permissions:
15144
contents: write # enable pushing changes to the origin
152-
id-token: write # enable generation of an ID token for publishing
153-
outputs:
154-
# will be undefined if there's no release necessary
155-
NEXT_VERSION: ${{ steps.version.outputs.NEXT_VERSION }}
45+
pull-requests: write # enable opening a PR for the release
15646
steps:
157-
- name: ⬇️ Checkout repo
158-
uses: actions/checkout@v6
47+
- name: Checkout
48+
uses: actions/checkout@v4
15949
with:
160-
ref: dev
161-
# checkout using a custom token so that we can push later on
162-
token: ${{ secrets.GITHUB_TOKEN }}
163-
fetch-depth: 0
50+
token: ${{ secrets.FORMAT_PAT }}
16451

165-
- name: 📦 Setup pnpm
52+
- name: Install pnpm
16653
uses: pnpm/action-setup@v4
16754

168-
- name: ⎔ Setup node
169-
uses: actions/setup-node@v6
55+
- name: Install Node.js
56+
uses: actions/setup-node@v4
17057
with:
171-
node-version: 24 # Needed for npm@11 for Trusted Publishing
172-
cache: "pnpm"
58+
node-version: 24 # Needed to run typescript scripts directly
59+
cache: pnpm
17360

174-
- name: 📥 Install deps
61+
- name: Install dependencies
17562
run: pnpm install --frozen-lockfile
17663

177-
- name: 🕵️ Check for changes
178-
id: version
179-
run: |
180-
SHORT_SHA=$(git rev-parse --short HEAD)
181-
182-
# get latest nightly tag
183-
LATEST_NIGHTLY_TAG=$(git tag -l v0.0.0-nightly-\* --sort=-creatordate | head -n 1)
184-
185-
# check if last commit to dev starts with the nightly tag we're about
186-
# to create (minus the date)
187-
# if it is, we'll skip the nightly creation
188-
# if not, we'll create a new nightly tag
189-
if [[ ${LATEST_NIGHTLY_TAG} == v0.0.0-nightly-${SHORT_SHA}-* ]]; then
190-
echo "🛑 Latest nightly tag is the same as the latest commit sha, skipping nightly release"
191-
else
192-
# yyyyMMdd format (e.g. 20221207)
193-
DATE=$(date '+%Y%m%d')
194-
# v0.0.0-nightly-<short sha>-<date>
195-
NEXT_VERSION=0.0.0-nightly-${SHORT_SHA}-${DATE}
196-
# set output so it can be used in other jobs
197-
echo "NEXT_VERSION=${NEXT_VERSION}" >> $GITHUB_OUTPUT
198-
fi
199-
200-
- name: ⤴️ Update version
201-
if: steps.version.outputs.NEXT_VERSION
202-
run: |
203-
git config --local user.email "hello@remix.run"
204-
git config --local user.name "Remix Run Bot"
205-
git checkout -b nightly/${{ steps.version.outputs.NEXT_VERSION }}
206-
pnpm run version ${{steps.version.outputs.NEXT_VERSION}}
207-
git push origin --tags
208-
209-
- name: 🏗 Build
210-
if: steps.version.outputs.NEXT_VERSION
211-
run: pnpm build
212-
213-
- name: 🚀 Publish
214-
if: steps.version.outputs.NEXT_VERSION
215-
run: pnpm run publish
64+
- name: Update PR
65+
run: pnpm changes:pr
66+
env:
67+
GITHUB_TOKEN: ${{ secrets.FORMAT_PAT }}
21668

217-
release-experimental:
218-
name: 🧪 Experimental Release
219-
if: github.repository == 'remix-run/react-router' && github.event_name == 'workflow_dispatch'
69+
publish:
70+
name: Publish
71+
needs: check
72+
if: needs.check.outputs.has_change_files == 'false'
22073
runs-on: ubuntu-latest
22174
permissions:
22275
contents: write # enable pushing changes to the origin
22376
id-token: write # enable generation of an ID token for publishing
22477
steps:
22578
- name: ⬇️ Checkout repo
22679
uses: actions/checkout@v6
227-
with:
228-
ref: ${{ github.event.inputs.branch }}
229-
# checkout using a custom token so that we can push later on
230-
token: ${{ secrets.GITHUB_TOKEN }}
231-
fetch-depth: 0
23280

23381
- name: 📦 Setup pnpm
23482
uses: pnpm/action-setup@v4
@@ -242,18 +90,10 @@ jobs:
24290
- name: 📥 Install deps
24391
run: pnpm install --frozen-lockfile
24492

245-
- name: ⤴️ Update version
246-
run: |
247-
git config --local user.email "hello@remix.run"
248-
git config --local user.name "Remix Run Bot"
249-
SHORT_SHA=$(git rev-parse --short HEAD)
250-
NEXT_VERSION=0.0.0-experimental-${SHORT_SHA}
251-
git checkout -b experimental/${NEXT_VERSION}
252-
pnpm run version ${NEXT_VERSION}
253-
git push origin --tags
254-
255-
- name: 🏗 Build
93+
- name: Build packages
25694
run: pnpm build
25795

258-
- name: 🚀 Publish
259-
run: pnpm run publish
96+
- name: Publish to npm and create releases
97+
run: pnpm changes:publish
98+
env:
99+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

CHANGELOG.md

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ We manage release notes in this file instead of the paginated Github Releases Pa
2424
- [Patch Changes](#patch-changes-1)
2525
- [Unstable Changes](#unstable-changes-1)
2626
- [v7.13.1](#v7131)
27-
- [What's Changed](#whats-changed-1)
28-
- [URL Masking (unstable)](#url-masking-unstable)
27+
- [What's Changed](#whats-changed-1)
28+
- [URL Masking (unstable)](#url-masking-unstable)
2929
- [Patch Changes](#patch-changes-2)
3030
- [Unstable Changes](#unstable-changes-2)
3131
- [v7.13.0](#v7130)
@@ -408,29 +408,6 @@ We manage release notes in this file instead of the paginated Github Releases Pa
408408

409409
</details>
410410

411-
<!-- To add a new release, copy from this template:
412-
413-
## v7.X.Y
414-
415-
Date: YYYY-MM-DD
416-
417-
### What's Changed
418-
419-
#### Big New Feature 1
420-
421-
#### Big New Feature 2
422-
423-
### Minor Changes
424-
425-
### Patch Changes
426-
427-
### Unstable Changes
428-
429-
⚠️ _[Unstable features](https://reactrouter.com/community/api-development-strategy#unstable-flags) are not recommended for production use_
430-
431-
**Full Changelog**: [`v7.X.Y...v7.X.Y`](https://github.com/remix-run/react-router/compare/react-router@7.X.Y...react-router@7.X.Y)
432-
-->
433-
434411
## v7.14.0
435412

436413
Date: 2026-04-02
@@ -576,9 +553,9 @@ This parameter is primarily needed when adopting the new `future.unstable_passth
576553

577554
Date: 2026-02-23
578555

579-
## What's Changed
556+
### What's Changed
580557

581-
### URL Masking (unstable)
558+
#### URL Masking (unstable)
582559

583560
This release includes a new `<Link unstable_mask>` API which brings first-class support for URL masking to Framework/Data Mode ([RFC](https://github.com/remix-run/react-router/discussions/9864)). This allows the same type of UI you could achieve in Declarative Mode via [manual `backgroundLocation` management](https://github.com/remix-run/react-router/tree/main/examples/modal). That example has been converted to Data Mode using the new API [here](https://github.com/remix-run/react-router/tree/main/examples/modal-data-router).
584561

0 commit comments

Comments
 (0)