|
| 1 | +'use strict'; |
| 2 | + |
| 3 | +/* eslint-disable no-for-of-loops/no-for-of-loops */ |
| 4 | + |
| 5 | +const fs = require('fs'); |
| 6 | +const {spawnSync} = require('child_process'); |
| 7 | +const tmp = require('tmp'); |
| 8 | + |
| 9 | +// Runs the build script for both stable and experimental release channels, |
| 10 | +// by configuring an environment variable. |
| 11 | + |
| 12 | +if (process.env.CIRCLE_NODE_TOTAL) { |
| 13 | + // In CI, we use multiple concurrent processes. Allocate half the processes to |
| 14 | + // build the stable channel, and the other half for experimental. Override |
| 15 | + // the environment variables to "trick" the underlying build script. |
| 16 | + const total = parseInt(process.env.CIRCLE_NODE_TOTAL, 10); |
| 17 | + const halfTotal = Math.floor(total / 2); |
| 18 | + const index = parseInt(process.env.CIRCLE_NODE_INDEX, 10); |
| 19 | + if (index < halfTotal) { |
| 20 | + const nodeTotal = halfTotal; |
| 21 | + const nodeIndex = index; |
| 22 | + buildForChannel('stable', nodeTotal, nodeIndex); |
| 23 | + processStable('./build'); |
| 24 | + } else { |
| 25 | + const nodeTotal = total - halfTotal; |
| 26 | + const nodeIndex = index - halfTotal; |
| 27 | + buildForChannel('experimental', nodeTotal, nodeIndex); |
| 28 | + processExperimental('./build'); |
| 29 | + } |
| 30 | + |
| 31 | + // TODO: Currently storing artifacts as `./build2` so that it doesn't conflict |
| 32 | + // with old build job. Remove once we migrate rest of build/test pipeline. |
| 33 | + fs.renameSync('./build', './build2'); |
| 34 | +} else { |
| 35 | + // Running locally, no concurrency. Move each channel's build artifacts into |
| 36 | + // a temporary directory so that they don't conflict. |
| 37 | + buildForChannel('stable', '', ''); |
| 38 | + const stableDir = tmp.dirSync().name; |
| 39 | + fs.renameSync('./build', stableDir); |
| 40 | + processStable(stableDir); |
| 41 | + |
| 42 | + buildForChannel('experimental', '', ''); |
| 43 | + const experimentalDir = tmp.dirSync().name; |
| 44 | + fs.renameSync('./build', experimentalDir); |
| 45 | + processExperimental(experimentalDir); |
| 46 | + |
| 47 | + // Then merge the experimental folder into the stable one. processExperimental |
| 48 | + // will have already removed conflicting files. |
| 49 | + // |
| 50 | + // In CI, merging is handled automatically by CircleCI's workspace feature. |
| 51 | + spawnSync('rsync', ['-ar', experimentalDir + '/', stableDir + '/']); |
| 52 | + |
| 53 | + // Now restore the combined directory back to its original name |
| 54 | + // TODO: Currently storing artifacts as `./build2` so that it doesn't conflict |
| 55 | + // with old build job. Remove once we migrate rest of build/test pipeline. |
| 56 | + fs.renameSync(stableDir, './build2'); |
| 57 | +} |
| 58 | + |
| 59 | +function buildForChannel(channel, nodeTotal, nodeIndex) { |
| 60 | + spawnSync('node', ['./scripts/rollup/build.js', ...process.argv.slice(2)], { |
| 61 | + stdio: ['pipe', process.stdout, process.stderr], |
| 62 | + env: { |
| 63 | + ...process.env, |
| 64 | + RELEASE_CHANNEL: channel, |
| 65 | + CIRCLE_NODE_TOTAL: nodeTotal, |
| 66 | + CIRCLE_NODE_INDEX: nodeIndex, |
| 67 | + }, |
| 68 | + }); |
| 69 | +} |
| 70 | + |
| 71 | +function processStable(buildDir) { |
| 72 | + if (fs.existsSync(buildDir + '/node_modules')) { |
| 73 | + fs.renameSync(buildDir + '/node_modules', buildDir + '/oss-stable'); |
| 74 | + } |
| 75 | + |
| 76 | + if (fs.existsSync(buildDir + '/facebook-www')) { |
| 77 | + for (const fileName of fs.readdirSync(buildDir + '/facebook-www')) { |
| 78 | + const filePath = buildDir + '/facebook-www/' + fileName; |
| 79 | + const stats = fs.statSync(filePath); |
| 80 | + if (!stats.isDirectory()) { |
| 81 | + fs.renameSync(filePath, filePath.replace('.js', '.classic.js')); |
| 82 | + } |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + if (fs.existsSync(buildDir + '/sizes')) { |
| 87 | + fs.renameSync(buildDir + '/sizes', buildDir + '/sizes-stable'); |
| 88 | + } |
| 89 | +} |
| 90 | + |
| 91 | +function processExperimental(buildDir) { |
| 92 | + if (fs.existsSync(buildDir + '/node_modules')) { |
| 93 | + fs.renameSync(buildDir + '/node_modules', buildDir + '/oss-experimental'); |
| 94 | + } |
| 95 | + |
| 96 | + if (fs.existsSync(buildDir + '/facebook-www')) { |
| 97 | + for (const fileName of fs.readdirSync(buildDir + '/facebook-www')) { |
| 98 | + const filePath = buildDir + '/facebook-www/' + fileName; |
| 99 | + const stats = fs.statSync(filePath); |
| 100 | + if (!stats.isDirectory()) { |
| 101 | + fs.renameSync(filePath, filePath.replace('.js', '.modern.js')); |
| 102 | + } |
| 103 | + } |
| 104 | + } |
| 105 | + |
| 106 | + if (fs.existsSync(buildDir + '/sizes')) { |
| 107 | + fs.renameSync(buildDir + '/sizes', buildDir + '/sizes-experimental'); |
| 108 | + } |
| 109 | + |
| 110 | + // Delete all other artifacts that weren't handled above. We assume they are |
| 111 | + // duplicates of the corresponding artifacts in the stable channel. Ideally, |
| 112 | + // the underlying build script should not have produced these files in the |
| 113 | + // first place. |
| 114 | + for (const pathName of fs.readdirSync(buildDir)) { |
| 115 | + if ( |
| 116 | + pathName !== 'oss-experimental' && |
| 117 | + pathName !== 'facebook-www' && |
| 118 | + pathName !== 'sizes-experimental' |
| 119 | + ) { |
| 120 | + spawnSync('rm', ['-rm', buildDir + '/' + pathName]); |
| 121 | + } |
| 122 | + } |
| 123 | +} |
0 commit comments