@samitouri / QOS-React-2 / commits / bf3a29d097

Update build script to automatically generate RCs (#29736)

RC releases are a special kind of prerelease build because unlike canaries we shouldn't publish new RCs from any commit on `main`, only when we intentionally bump the RC number. But they are still prerelases — like canary and experimental releases, they should use exact version numbers in their dependencies (no ^). We only need to generate these builds during the RC phase, i.e. when the canary channel label is set to "rc". Example of resulting package.json output: ```json { "name": "react-dom", "version": "19.0.0-rc.0", "dependencies": { "scheduler": "0.25.0-rc.0" }, "peerDependencies": { "react": "19.0.0-rc.0" } } ``` https://react-builds.vercel.app/prs/29736/files/oss-stable-rc/react-dom/package.json

Andrew Clark committed Jun 3, 2024 at 12:21 UTC bf3a29d097a5d457e85a58a183fb9e12714fbece
4 files changed +37 -1
ReactVersions.js
+5
@@ -28,6 +28,10 @@ const ReactVersion = '19.0.0';
28 // npm dist tags used during publish, refer to .circleci/config.yml.
29 const canaryChannelLabel = 'rc';
30
31 +// If the canaryChannelLabel is "rc", the build pipeline will use this to build
32 +// an RC version of the packages.
33 +const rcNumber = 0;
34 +
35 const stablePackages = {
36 'eslint-plugin-react-hooks': '5.1.0',
37 'jest-react': '0.16.0',
@@ -53,6 +57,7 @@ const experimentalPackages = [];
57 module.exports = {
58 ReactVersion,
59 canaryChannelLabel,
60 + rcNumber,
61 stablePackages,
62 experimentalPackages,
63 };
scripts/release/shared-commands/download-build-artifacts.js
+2
@@ -50,6 +50,8 @@ const run = async ({build, cwd, releaseChannel}) => {
50 sourceDir = 'oss-stable';
51 } else if (releaseChannel === 'experimental') {
52 sourceDir = 'oss-experimental';
53 + } else if (releaseChannel === 'rc') {
54 + sourceDir = 'oss-stable-rc';
55 } else if (releaseChannel === 'latest') {
56 sourceDir = 'oss-stable-semver';
57 } else {
scripts/release/shared-commands/parse-params.js
+2 -1
@@ -50,10 +50,11 @@ module.exports = async () => {
50 if (
51 channel !== 'experimental' &&
52 channel !== 'stable' &&
53 + channel !== 'rc' &&
54 channel !== 'latest'
55 ) {
56 console.error(
56 - theme.error`Invalid release channel (-r) "${channel}". Must be "stable", "experimental", or "latest".`
57 + theme.error`Invalid release channel (-r) "${channel}". Must be "stable", "experimental", "rc", or "latest".`
58 );
59 process.exit(1);
60 }
scripts/rollup/build-all-release-channels.js
+28
@@ -13,6 +13,7 @@ const {
13 stablePackages,
14 experimentalPackages,
15 canaryChannelLabel,
16 + rcNumber,
17 } = require('../../ReactVersions');
18
19 // Runs the build script for both stable and experimental release channels,
@@ -118,6 +119,13 @@ function processStable(buildDir) {
119 // Identical to `oss-stable` but with real, semver versions. This is what
120 // will get published to @latest.
121 shell.cp('-r', buildDir + '/node_modules', buildDir + '/oss-stable-semver');
122 + if (canaryChannelLabel === 'rc') {
123 + // During the RC phase, we also generate an RC build that pins to exact
124 + // versions but does not include a SHA, e.g. `19.0.0-rc.0`. This is purely
125 + // for signaling purposes — aside from the version, it's no different from
126 + // the corresponding canary.
127 + shell.cp('-r', buildDir + '/node_modules', buildDir + '/oss-stable-rc');
128 + }
129
130 const defaultVersionIfNotFound = '0.0.0' + '-' + sha + '-' + dateString;
131 const versionsMap = new Map();
@@ -141,6 +149,25 @@ function processStable(buildDir) {
149 ReactVersion + '-' + canaryChannelLabel + '-' + sha + '-' + dateString
150 );
151
152 + if (canaryChannelLabel === 'rc') {
153 + const rcVersionsMap = new Map();
154 + for (const moduleName in stablePackages) {
155 + const version = stablePackages[moduleName];
156 + rcVersionsMap.set(moduleName, version + `-rc.${rcNumber}`);
157 + }
158 + updatePackageVersions(
159 + buildDir + '/oss-stable-rc',
160 + rcVersionsMap,
161 + defaultVersionIfNotFound,
162 + // For RCs, we pin to exact versions, like we do for canaries.
163 + true
164 + );
165 + updatePlaceholderReactVersionInCompiledArtifacts(
166 + buildDir + '/oss-stable-rc',
167 + ReactVersion
168 + );
169 + }
170 +
171 // Now do the semver ones
172 const semverVersionsMap = new Map();
173 for (const moduleName in stablePackages) {
@@ -151,6 +178,7 @@ function processStable(buildDir) {
178 buildDir + '/oss-stable-semver',
179 semverVersionsMap,
180 defaultVersionIfNotFound,
181 + // Use ^ only for non-prerelease versions
182 false
183 );
184 updatePlaceholderReactVersionInCompiledArtifacts(