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
This commit is contained in:
Andrew Clark 2024-06-03 12:21:21 -04:00 committed by GitHub
parent 9598c41a20
commit bf3a29d097
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 37 additions and 1 deletions

View File

@ -28,6 +28,10 @@ const ReactVersion = '19.0.0';
// npm dist tags used during publish, refer to .circleci/config.yml.
const canaryChannelLabel = 'rc';
// If the canaryChannelLabel is "rc", the build pipeline will use this to build
// an RC version of the packages.
const rcNumber = 0;
const stablePackages = {
'eslint-plugin-react-hooks': '5.1.0',
'jest-react': '0.16.0',
@ -53,6 +57,7 @@ const experimentalPackages = [];
module.exports = {
ReactVersion,
canaryChannelLabel,
rcNumber,
stablePackages,
experimentalPackages,
};

View File

@ -50,6 +50,8 @@ const run = async ({build, cwd, releaseChannel}) => {
sourceDir = 'oss-stable';
} else if (releaseChannel === 'experimental') {
sourceDir = 'oss-experimental';
} else if (releaseChannel === 'rc') {
sourceDir = 'oss-stable-rc';
} else if (releaseChannel === 'latest') {
sourceDir = 'oss-stable-semver';
} else {

View File

@ -50,10 +50,11 @@ module.exports = async () => {
if (
channel !== 'experimental' &&
channel !== 'stable' &&
channel !== 'rc' &&
channel !== 'latest'
) {
console.error(
theme.error`Invalid release channel (-r) "${channel}". Must be "stable", "experimental", or "latest".`
theme.error`Invalid release channel (-r) "${channel}". Must be "stable", "experimental", "rc", or "latest".`
);
process.exit(1);
}

View File

@ -13,6 +13,7 @@ const {
stablePackages,
experimentalPackages,
canaryChannelLabel,
rcNumber,
} = require('../../ReactVersions');
// Runs the build script for both stable and experimental release channels,
@ -118,6 +119,13 @@ function processStable(buildDir) {
// Identical to `oss-stable` but with real, semver versions. This is what
// will get published to @latest.
shell.cp('-r', buildDir + '/node_modules', buildDir + '/oss-stable-semver');
if (canaryChannelLabel === 'rc') {
// During the RC phase, we also generate an RC build that pins to exact
// versions but does not include a SHA, e.g. `19.0.0-rc.0`. This is purely
// for signaling purposes — aside from the version, it's no different from
// the corresponding canary.
shell.cp('-r', buildDir + '/node_modules', buildDir + '/oss-stable-rc');
}
const defaultVersionIfNotFound = '0.0.0' + '-' + sha + '-' + dateString;
const versionsMap = new Map();
@ -141,6 +149,25 @@ function processStable(buildDir) {
ReactVersion + '-' + canaryChannelLabel + '-' + sha + '-' + dateString
);
if (canaryChannelLabel === 'rc') {
const rcVersionsMap = new Map();
for (const moduleName in stablePackages) {
const version = stablePackages[moduleName];
rcVersionsMap.set(moduleName, version + `-rc.${rcNumber}`);
}
updatePackageVersions(
buildDir + '/oss-stable-rc',
rcVersionsMap,
defaultVersionIfNotFound,
// For RCs, we pin to exact versions, like we do for canaries.
true
);
updatePlaceholderReactVersionInCompiledArtifacts(
buildDir + '/oss-stable-rc',
ReactVersion
);
}
// Now do the semver ones
const semverVersionsMap = new Map();
for (const moduleName in stablePackages) {
@ -151,6 +178,7 @@ function processStable(buildDir) {
buildDir + '/oss-stable-semver',
semverVersionsMap,
defaultVersionIfNotFound,
// Use ^ only for non-prerelease versions
false
);
updatePlaceholderReactVersionInCompiledArtifacts(