@@ -39,24 +39,40 @@ official release builds for Node.js, hosted on <https://nodejs.org/>.
3939
4040## Who can make a release?
4141
42- Release authorization is given by the Node.js TSC. Once authorized, an
43- individual must have the following:
42+ Individuals who are Members of the
43+ [ backporters team] ( https://github.com/orgs/nodejs/teams/backporters ) can
44+ land things on the staging branches and prepare releases. This is a
45+ prerequisite to being able to prepare releases which is the first step
46+ to becoming a releaser.
47+
48+ Release authorization is given by the Node.js TSC. This is required to
49+ publish a release after it has been prepared. If you are working on
50+ preparing a release for the first time you can do that and have someone else
51+ who is already onboarded publish the release on your behalf. Once
52+ authorized by the TSC, an individual will be require the following:
4453
4554### 1. Jenkins release access
4655
47- There are three relevant Jenkins jobs that should be used for a release flow:
56+ There are four relevant Jenkins jobs that should be used for a release flow:
4857
4958** a.** ** Test runs:**
5059** [ node-test-pull-request] ( https://ci.nodejs.org/job/node-test-pull-request/ ) **
5160is used for a final full-test run to ensure that the current _ HEAD_ is stable.
5261
53- ** b.** ** Nightly builds:** (optional)
62+ ** b.** ** CITGM:**
63+ ** [ citgm-smoker] ( https://ci.nodejs.org/job/citgm-smoker/ ) ** is used to run
64+ the citgm tool which tests a build of node.js against a defined set of
65+ community modules. This is used during a release process to ensure that
66+ none of the commonly used modules which are tested by CITGM show functional
67+ regressions with the new Node.js version which could impact users.
68+
69+ ** c.** ** Nightly builds:** (optional)
5470** [ iojs+release] ( https://ci-release.nodejs.org/job/iojs+release/ ) ** can be used
5571to create a nightly release for the current _ HEAD_ if public test releases are
5672required. Builds triggered with this job are published straight to
5773< https://nodejs.org/download/nightly/ > and are available for public download.
5874
59- ** c .** ** Release builds:**
75+ ** d .** ** Release builds:**
6076** [ iojs+release] ( https://ci-release.nodejs.org/job/iojs+release/ ) ** does all of
6177the work to build all required release assets. Promotion of the release files is
6278a manual step once they are ready (see below).
@@ -66,8 +82,8 @@ this access to individuals authorized by the TSC.
6682
6783### 2. \< nodejs.org> access
6884
69- The _ dist_ user on nodejs.org controls the assets available in
70- < https://nodejs.org/download/ > . < https://nodejs.org/dist/ > is an alias for
85+ The _ dist_ user on the ` nodejs.org ` host controls the assets available in
86+ < https://nodejs.org/download/ > . < https://nodejs.org/dist/ > is an alias for
7187< https://nodejs.org/download/release/ > .
7288
7389The Jenkins release build workers upload their artifacts to the web server as
@@ -90,6 +106,12 @@ responsible for that release. In order to be able to verify downloaded binaries,
90106the public should be able to check that the ` SHASUMS256.txt ` file has been
91107signed by someone who has been authorized to create a release.
92108
109+ If you do not currently have a key then you should create one with a
110+ suitable strength with ` gpg --full-generate-key ` . The default options
111+ (currently "ECC sign and encrypt" and "Curve 25519") are good choices and
112+ consistent with the
113+ [ ssh key recommendations in the GOVERNANCE.md file] ( https://github.com/nodejs/Release/blob/main/GOVERNANCE.md#ssh-key-guidance ) .
114+
93115The public keys should be fetchable from a known third-party keyserver.
94116The OpenPGP keyserver at < https://keys.openpgp.org/ > is recommended.
95117Use the [ submission] ( https://keys.openpgp.org/upload ) form to submit
@@ -108,11 +130,23 @@ gpg --keyserver hkps://keys.openpgp.org --recv-keys <FINGERPRINT>
108130
109131The key you use may be a child/subkey of an existing key.
110132
133+ If you wish to also upload your key to the commonly used Ubuntu keyservers
134+ you can do so with `gpg --keyserver keyserver.ubuntu.com --send-keys
135+ <FINGERPRINT >` and check it by switching the server name in the
136+ ` --recv-keys ` operation list above to the Ubuntu keyserver.
137+
111138Additionally, full GPG key fingerprints for individuals authorized to release
112139should be listed in the Node.js GitHub README.md file.
113140
114- > It is recommended to sign all commits under the Node.js repository.
115- > Run: ` git config commit.gpgsign true ` inside the ` node ` folder.
141+ > All commits to branches in ` nodejs/node ` other than ` main ` MUST be signed
142+ > otherwise pushing to those branches will fail
143+ > Run: ` git config commit.gpgsign true ` inside the ` node ` folder or use the
144+ > ` -S ` flag on your git operations (The examples in this document will
145+ > include ` -S ` expliticlty)
146+
147+ Note that while GitHub allows signing individual commits using an ssh key,
148+ that is not covered here as this will not allow you to sign releases, so you
149+ will need to set up a GPG signing key in GitHub.
116150
117151## How to create a release
118152
@@ -123,7 +157,7 @@ Notes:
123157* Version strings are listed below as _ "vx.y.z"_ or _ "x.y.z"_ . Substitute for
124158 the release version.
125159* Examples will use the fictional release version ` 1.2.3 ` .
126- * When preparing a security release, follow the security steps in the details
160+ * * When preparing a security release* , follow the security steps in the details
127161 sections.
128162
129163### 0. Pre-release steps
@@ -136,13 +170,6 @@ and the release blog post is available on the project website.
136170Build can be contacted best by opening up an issue on the [ Build issue
137171tracker] [ ] .
138172
139- When preparing a security release, contact Build at least two weekdays in
140- advance of the expected release. To ensure that the security patch(es) can be
141- properly tested, run a ` node-test-pull-request ` job against the ` main ` branch
142- of the ` nodejs-private/node-private ` repository a day or so before the
143- [ CI lockdown procedure] [ ] begins. This is to confirm that Jenkins can properly
144- access the private repository.
145-
146173### 1. Update the staging branch
147174
148175Checkout the staging branch locally.
@@ -174,11 +201,11 @@ When landing the PR add the `Backport-PR-URL:` line to each commit. Close the
174201backport PR with ` Landed in ... ` . Update the label on the original PR from
175202` backport-requested-vN.x ` to ` backported-to-vN.x ` .
176203
177- You can add the ` Backport-PR-URL ` metadata by using ` --backport ` with
178- ` git node land `
204+ You can add the ` Backport-PR-URL ` metadata automatically when landing by
205+ using ` --backport ` with ` git node land ` :
179206
180207``` bash
181- git node land --backport $PR -NUMBER
208+ git node land --backport $PR -NUMBER -S
182209```
183210
184211To determine the relevant commits, use
@@ -189,16 +216,34 @@ metadata, as well as the GitHub labels such as `semver-minor` and
189216omitted from a commit, the commit will show up because it's unsure if it's a
190217duplicate or not.
191218
219+ Note that a branch-diff run can use a lot of credits and users are
220+ [ limited by default to 5000 per hour] ( https://docs.github.com/en/rest/using-the-rest-api/rate-limits-for-the-rest-api?apiVersion=2026-03-10 ) .
221+ It is not unusual for a run of branch-diff to
222+ use around 1000 of these. For this reason it is recommended that when you
223+ run branch-diff you redirect the output to a file and then process it. You
224+ can check your current usage with ` gh rate_limit ` if you have the GitHub CLI
225+ installed and configured, or using the curl command from
226+ [ this link] ( https://docs.github.com/en/rest/rate-limit/rate-limit?apiVersion=2026-03-10 )
227+ with authentication e.g.
228+
229+ ```
230+ curl -H "Authorization: token $YOURGITHUBTOKEN" -X GET https://api.github.com/rate_limit
231+ ```
232+
192233For a list of commits that could be landed in a minor release on v1.x:
193234
194235``` bash
195236N=1 sh -c ' branch-diff v$N.x-staging upstream/main --exclude-label=semver-major,dont-land-on-v$N.x,backport-requested-v$N.x,backport-blocked-v$N.x,backport-open-v$N.x,backported-to-v$N.x --filter-release --format=simple'
196237```
197238
198- If the target branch is an LTS line, you should also exclude the ` baking-for-lts ` :
239+ If the target branch is an LTS line, you should also exclude the
240+ ` baking-for-lts ` and use a version other than ` main ` (usually a tag of the
241+ next actively supported version which has been available for at least two
242+ weeks). In this example we use v26.5.0 as the version to compare with if
243+ we are preparing a release for v24:
199244
200245``` bash
201- N=1 sh -c ' branch-diff v$N.x-staging upstream/main --exclude-label=semver-major,dont-land-on-v$N.x,backport-requested-v$N.x,backport-blocked-v$N.x,backport-open-v$N.x,backported-to-v$N.x,baking-for-lts --filter-release --format=simple'
246+ N=24 sh -c ' branch-diff v$N.x-staging v26.5.0 --exclude-label=semver-major,dont-land-on-v$N.x,backport-requested-v$N.x,backport-blocked-v$N.x,backport-open-v$N.x,backported-to-v$N.x,baking-for-lts --filter-release --format=simple'
202247```
203248
204249Previously released commits and version bumps do not need to be
@@ -216,6 +261,11 @@ Carefully review the list of commits:
216261When you are ready to cherry-pick commits, you can automate with the following
217262command.
218263
264+ Since this is slightly different from the previous branch-diff output - it
265+ contains only the commit shas and in revert order - you may wish to save
266+ this before piping it directly to ` git cherry-pick ` in case it does not go
267+ cleanly.
268+
219269``` bash
220270N=1 sh -c ' branch-diff v$N.x-staging upstream/main --exclude-label=semver-major,dont-land-on-v$N.x,backport-requested-v$N.x,backport-blocked-v$N.x,backport-open-v$N.x,backported-to-v$N.x --filter-release --format=sha --reverse' | xargs git cherry-pick -S
221271```
@@ -351,6 +401,8 @@ This will ensure they are included in the "Notable Changes" section of the CHANG
351401
352402### 3. Update ` src/node_version.h `
353403
404+ _ (This step will be done automatically if you are using ` create-release-proposal ` or ` git node release --prepare ` )_
405+
354406Set the version for the proposed release using the following macros, which are
355407already defined in ` src/node_version.h ` :
356408
@@ -369,6 +421,8 @@ be produced with a version string that does not have a trailing pre-release tag:
369421
370422### 4 . Update the changelog
371423
424+ _ (This step will be done automatically if you are using ` create-release-proposal ` or ` git node release --prepare ` )_
425+
372426#### Step 1: Collect the formatted list of changes
373427
374428Collect a formatted list of commits since the last release. Use
@@ -485,7 +539,8 @@ are formatted correctly.
485539If this release includes new APIs then it is necessary to document that they
486540were first added in this version. The relevant commits should already include
487541` REPLACEME ` tags (see [ Writing Documentation] ( ./api-documentation.md#writing-documentation ) ).
488- Check for these tags with
542+ Check for these tags with either ` sed ` or ` perl ` as follows, ensuring the
543+ ` $VERSION ` is prefixed with a ` v ` .
489544
490545``` bash
491546grep REPLACEME doc/api/* .md
509564perl -pi -e " s/REPLACEME/$VERSION /g" doc/api/* .md
510565```
511566
512- ` $VERSION ` should be prefixed with a ` v ` .
513-
514567If this release includes any new deprecations it is necessary to ensure that
515568those are assigned a proper static deprecation code. These are listed in the
516569docs (see ` doc/api/deprecations.md ` ) and in the source as ` DEP00XX ` . The code
520573
521574### 5. Create release commit
522575
576+ _ (This step will be done automatically if you are using ` create-release-proposal ` or ` git node release --prepare ` )_
577+
523578The ` CHANGELOG.md ` , ` doc/changelogs/CHANGELOG_Vx.md ` , ` src/node_version.h ` , and
524579` REPLACEME ` changes should be the final commit that will be tagged for the
525580release. When committing these to git, use the following message format:
@@ -561,6 +616,8 @@ Otherwise, you will leak the commits before the security release.
561616
562617### 6. Propose release on GitHub
563618
619+ _ (This step will be done automatically if you are using ` create-release-proposal ` or ` git node release --prepare ` )_
620+
564621Push the release branch to ` nodejs/node ` , not to your own fork. This allows
565622release branches to more easily be passed between members of the release team if
566623necessary.
@@ -612,13 +669,18 @@ purpose. Run it once with the base `vx.x` branch as a reference and with the
612669proposal branch to check if new regressions could be introduced in the
613670ecosystem.
614671
615- Use ` ncu-ci ` to compare ` vx.x ` run (10) and proposal branch (11)
672+ Use ` ncu-ci ` with the two build numbers from the ` citgm-smoker ` job to
673+ compare the base ` vx.x ` run (10) and the new proposal branch (11).
616674
617675``` bash
618676npm i -g @node-core/utils
619677ncu-ci citgm 10 11
620678```
621679
680+ Note that a number of the modules tested by CITGM are not completely
681+ reliable so differences shown by the comparison are not immediately cause
682+ for concern.
683+
622684<details >
623685<summary >Security release</summary >
624686
0 commit comments