main
js 152 lines 4.67 KB
Raw
1 #!/usr/bin/env node
2
3 'use strict';
4
5 const {exec} = require('child-process-promise');
6 const chalk = require('chalk');
7 const {join} = require('path');
8 const semver = require('semver');
9 const yargs = require('yargs');
10 const fs = require('fs');
11
12 const REGRESSION_FOLDER = 'build-regression';
13
14 const ROOT_PATH = join(__dirname, '..', '..');
15
16 const buildPath = join(ROOT_PATH, `build`, 'oss-experimental');
17 const regressionBuildPath = join(ROOT_PATH, REGRESSION_FOLDER);
18
19 const argv = yargs(process.argv.slice(2)).argv;
20
21 const version = process.argv[2];
22 const shouldReplaceBuild = !!argv.replaceBuild;
23
24 async function downloadRegressionBuild() {
25 const reactVersion = semver.coerce(version).version;
26 const installPackages = ['react-dom', 'react', 'react-test-renderer'];
27 if (semver.gte(reactVersion, '16.3.0')) {
28 installPackages.push('react-is');
29 }
30
31 console.log(chalk.bold.white(`Downloading React v${version}\n`));
32
33 // Make build directory for temporary modules we're going to download
34 // from NPM
35 console.log(
36 chalk.white(
37 `Make Build directory at ${chalk.underline.blue(regressionBuildPath)}\n`
38 )
39 );
40 await exec(`mkdir ${regressionBuildPath}`);
41
42 // Install all necessary React packages that have the same version
43 const downloadPackagesStr = installPackages.reduce(
44 (str, name) => `${str} ${name}@${version}`,
45 ''
46 );
47 await exec(
48 `npm install --prefix ${REGRESSION_FOLDER} ${downloadPackagesStr}`
49 );
50
51 // If we shouldn't replace the build folder, we can stop here now
52 // before we modify anything
53 if (!shouldReplaceBuild) {
54 return;
55 }
56
57 // Remove all the packages that we downloaded in the original build folder
58 // so we can move the modules from the regression build over
59 const removePackagesStr = installPackages.reduce(
60 (str, name) => `${str} ${join(buildPath, name)}`,
61 ''
62 );
63 console.log(
64 chalk.white(
65 `Removing ${removePackagesStr
66 .split(' ')
67 .map(str => chalk.underline.blue(str) + '\n')
68 .join(' ')}\n`
69 )
70 );
71 await exec(`rm -rf ${removePackagesStr}`);
72
73 // Move all packages that we downloaded to the original build folder
74 // We need to separately move the scheduler package because it might
75 // be called schedule
76 const movePackageString = installPackages.reduce(
77 (str, name) => `${str} ${join(regressionBuildPath, 'node_modules', name)}`,
78 ''
79 );
80 console.log(
81 chalk.white(
82 `Moving ${movePackageString
83 .split(' ')
84 .map(str => chalk.underline.blue(str) + '\n')
85 .join(' ')} to ${chalk.underline.blue(buildPath)}\n`
86 )
87 );
88 fs.mkdirSync(buildPath, {recursive: true});
89 await exec(`mv ${movePackageString} ${buildPath}`);
90
91 // For React versions earlier than 18.0.0, we explicitly scheduler v0.20.1, which
92 // is the first version that has unstable_mock, which DevTools tests need, but also
93 // has Scheduler.unstable_trace, which, although we don't use in DevTools tests
94 // is imported by older React versions and will break if it's not there
95 if (semver.lte(reactVersion, '18.0.0')) {
96 await exec(`npm install --prefix ${REGRESSION_FOLDER} scheduler@0.20.1`);
97 }
98
99 // In v16.5, scheduler is called schedule. We need to make sure we also move
100 // this over. Otherwise the code will break.
101 if (fs.existsSync(join(regressionBuildPath, 'node_modules', 'schedule'))) {
102 console.log(chalk.white(`Downloading schedule\n`));
103 await exec(
104 `mv ${join(regressionBuildPath, 'node_modules', 'schedule')} ${buildPath}`
105 );
106 } else {
107 console.log(chalk.white(`Downloading scheduler\n`));
108 await exec(`rm -rf ${join(buildPath, 'scheduler')}`);
109 await exec(
110 `mv ${join(
111 regressionBuildPath,
112 'node_modules',
113 'scheduler'
114 )} ${buildPath}`
115 );
116 }
117
118 if (semver.gte(reactVersion, '18.2.0') && semver.lt(reactVersion, '19.0.0')) {
119 console.log(chalk.white(`Downloading react-compiler-runtime\n`));
120 await exec(
121 `npm install --prefix ${REGRESSION_FOLDER} react-compiler-runtime`
122 );
123
124 console.log(
125 chalk.white(
126 `Moving react-compiler-runtime to react/compiler-runtime.js\n`
127 )
128 );
129 await exec(
130 `mv ${REGRESSION_FOLDER}/node_modules/react-compiler-runtime/dist/index.js ${buildPath}/react/compiler-runtime.js`
131 );
132 }
133 }
134
135 async function main() {
136 try {
137 if (!version) {
138 console.log(chalk.red('Must specify React version to download'));
139 return;
140 }
141 await downloadRegressionBuild();
142 } finally {
143 // We shouldn't remove the regression-build folder unless we're using
144 // it to replace the build folder
145 if (shouldReplaceBuild) {
146 console.log(chalk.bold.white(`Removing regression build`));
147 await exec(`rm -r ${regressionBuildPath}`);
148 }
149 }
150 }
151
152 main();