Skip to content

Commit

Permalink
Update package.json versions as part of build step (#20579)
Browse files Browse the repository at this point in the history
Fixes issue in the new build workflow where the experimental packages do
not include "experimental" in the version string. This was because the
previous approach relied on the RELEASE_CHANNEL environment variable,
which we are no longer setting in the outer CI job, since we use the
same job to build both channels. To solve, I moved the version
post-processing into the build script itself.

Only affects the new build workflow. Old workflow is unchanged.

Longer term, I would like to remove version numbers from the source
entirely, including the package.jsons. We should use a placeholder
instead; that's mostly how it already works, since the release script
swaps out the versions before we publish to stable.
  • Loading branch information
acdlite committed Jan 13, 2021
1 parent b99ac3d commit e6ed2bc
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 11 deletions.
6 changes: 1 addition & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,11 +168,7 @@ jobs:
- checkout
- run: yarn workspaces info | head -n -1 > workspace_info.txt
- *restore_node_modules
- run:
command: |
./scripts/circleci/add_build_info_json.sh
./scripts/circleci/update_package_versions.sh
yarn build-combined
- run: yarn build-combined
- persist_to_workspace:
root: build2
paths:
Expand Down
72 changes: 66 additions & 6 deletions scripts/rollup/build-all-release-channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@

const fs = require('fs');
const {spawnSync} = require('child_process');
const path = require('path');
const tmp = require('tmp');

// Runs the build script for both stable and experimental release channels,
// by configuring an environment variable.

const sha = (
spawnSync('git', ['show', '-s', '--format=%h']).stdout + ''
).trim();
const ReactVersion = JSON.parse(fs.readFileSync('packages/react/package.json'))
.version;

if (process.env.CIRCLE_NODE_TOTAL) {
// In CI, we use multiple concurrent processes. Allocate half the processes to
// build the stable channel, and the other half for experimental. Override
Expand All @@ -19,13 +26,19 @@ if (process.env.CIRCLE_NODE_TOTAL) {
if (index < halfTotal) {
const nodeTotal = halfTotal;
const nodeIndex = index;
const version = '0.0.0-' + sha;
updateTheReactVersionThatDevToolsReads(ReactVersion + '-' + sha);
buildForChannel('stable', nodeTotal, nodeIndex);
processStable('./build');
processStable('./build', version);
} else {
const nodeTotal = total - halfTotal;
const nodeIndex = index - halfTotal;
const version = '0.0.0-experimental-' + sha;
updateTheReactVersionThatDevToolsReads(
ReactVersion + '-experimental-' + sha
);
buildForChannel('experimental', nodeTotal, nodeIndex);
processExperimental('./build');
processExperimental('./build', version);
}

// TODO: Currently storing artifacts as `./build2` so that it doesn't conflict
Expand All @@ -34,15 +47,17 @@ if (process.env.CIRCLE_NODE_TOTAL) {
} else {
// Running locally, no concurrency. Move each channel's build artifacts into
// a temporary directory so that they don't conflict.
const stableVersion = '0.0.0-' + sha;
buildForChannel('stable', '', '');
const stableDir = tmp.dirSync().name;
fs.renameSync('./build', stableDir);
processStable(stableDir);
processStable(stableDir, stableVersion);

const experimentalVersion = '0.0.0-experimental-' + sha;
buildForChannel('experimental', '', '');
const experimentalDir = tmp.dirSync().name;
fs.renameSync('./build', experimentalDir);
processExperimental(experimentalDir);
processExperimental(experimentalDir, experimentalVersion);

// Then merge the experimental folder into the stable one. processExperimental
// will have already removed conflicting files.
Expand All @@ -68,8 +83,9 @@ function buildForChannel(channel, nodeTotal, nodeIndex) {
});
}

function processStable(buildDir) {
function processStable(buildDir, version) {
if (fs.existsSync(buildDir + '/node_modules')) {
updatePackageVersions(buildDir + '/node_modules', version);
fs.renameSync(buildDir + '/node_modules', buildDir + '/oss-stable');
}

Expand All @@ -88,8 +104,9 @@ function processStable(buildDir) {
}
}

function processExperimental(buildDir) {
function processExperimental(buildDir, version) {
if (fs.existsSync(buildDir + '/node_modules')) {
updatePackageVersions(buildDir + '/node_modules', version);
fs.renameSync(buildDir + '/node_modules', buildDir + '/oss-experimental');
}

Expand Down Expand Up @@ -121,3 +138,46 @@ function processExperimental(buildDir) {
}
}
}

function updatePackageVersions(modulesDir, version) {
const allReactModuleNames = fs.readdirSync('packages');
for (const moduleName of fs.readdirSync(modulesDir)) {
const packageJSONPath = path.join(modulesDir, moduleName, 'package.json');
const stats = fs.statSync(packageJSONPath);
if (stats.isFile()) {
const packageInfo = JSON.parse(fs.readFileSync(packageJSONPath));

// Update version
packageInfo.version = version;

// Update dependency versions
if (packageInfo.dependencies) {
for (const dep of Object.keys(packageInfo.dependencies)) {
if (allReactModuleNames.includes(dep)) {
packageInfo.dependencies[dep] = version;
}
}
}
if (packageInfo.peerDependencies) {
for (const dep of Object.keys(packageInfo.peerDependencies)) {
if (allReactModuleNames.includes(dep)) {
packageInfo.peerDependencies[dep] = version;
}
}
}

// Write out updated package.json
fs.writeFileSync(packageJSONPath, JSON.stringify(packageInfo, null, 2));
}
}
}

function updateTheReactVersionThatDevToolsReads(version) {
// Overwrite the ReactVersion module before the build script runs so that it
// is included in the final bundles. This only runs in CI, so it's fine to
// edit the source file.
fs.writeFileSync(
'./packages/shared/ReactVersion.js',
`export default '${version}';\n`
);
}

0 comments on commit e6ed2bc

Please sign in to comment.