44
55const fs = require ( 'fs' ) ;
66const { spawnSync} = require ( 'child_process' ) ;
7+ const path = require ( 'path' ) ;
78const tmp = require ( 'tmp' ) ;
89
910// Runs the build script for both stable and experimental release channels,
1011// by configuring an environment variable.
1112
13+ const sha = (
14+ spawnSync ( 'git' , [ 'show' , '-s' , '--format=%h' ] ) . stdout + ''
15+ ) . trim ( ) ;
16+ const ReactVersion = JSON . parse ( fs . readFileSync ( 'packages/react/package.json' ) )
17+ . version ;
18+
1219if ( process . env . CIRCLE_NODE_TOTAL ) {
1320 // In CI, we use multiple concurrent processes. Allocate half the processes to
1421 // build the stable channel, and the other half for experimental. Override
@@ -19,13 +26,19 @@ if (process.env.CIRCLE_NODE_TOTAL) {
1926 if ( index < halfTotal ) {
2027 const nodeTotal = halfTotal ;
2128 const nodeIndex = index ;
29+ const version = '0.0.0-' + sha ;
30+ updateTheReactVersionThatDevToolsReads ( ReactVersion + '-' + sha ) ;
2231 buildForChannel ( 'stable' , nodeTotal , nodeIndex ) ;
23- processStable ( './build' ) ;
32+ processStable ( './build' , version ) ;
2433 } else {
2534 const nodeTotal = total - halfTotal ;
2635 const nodeIndex = index - halfTotal ;
36+ const version = '0.0.0-experimental-' + sha ;
37+ updateTheReactVersionThatDevToolsReads (
38+ ReactVersion + '-experimental-' + sha
39+ ) ;
2740 buildForChannel ( 'experimental' , nodeTotal , nodeIndex ) ;
28- processExperimental ( './build' ) ;
41+ processExperimental ( './build' , version ) ;
2942 }
3043
3144 // TODO: Currently storing artifacts as `./build2` so that it doesn't conflict
@@ -34,15 +47,17 @@ if (process.env.CIRCLE_NODE_TOTAL) {
3447} else {
3548 // Running locally, no concurrency. Move each channel's build artifacts into
3649 // a temporary directory so that they don't conflict.
50+ const stableVersion = '0.0.0-' + sha ;
3751 buildForChannel ( 'stable' , '' , '' ) ;
3852 const stableDir = tmp . dirSync ( ) . name ;
3953 fs . renameSync ( './build' , stableDir ) ;
40- processStable ( stableDir ) ;
54+ processStable ( stableDir , stableVersion ) ;
4155
56+ const experimentalVersion = '0.0.0-experimental-' + sha ;
4257 buildForChannel ( 'experimental' , '' , '' ) ;
4358 const experimentalDir = tmp . dirSync ( ) . name ;
4459 fs . renameSync ( './build' , experimentalDir ) ;
45- processExperimental ( experimentalDir ) ;
60+ processExperimental ( experimentalDir , experimentalVersion ) ;
4661
4762 // Then merge the experimental folder into the stable one. processExperimental
4863 // will have already removed conflicting files.
@@ -68,8 +83,9 @@ function buildForChannel(channel, nodeTotal, nodeIndex) {
6883 } ) ;
6984}
7085
71- function processStable ( buildDir ) {
86+ function processStable ( buildDir , version ) {
7287 if ( fs . existsSync ( buildDir + '/node_modules' ) ) {
88+ updatePackageVersions ( buildDir + '/node_modules' , version ) ;
7389 fs . renameSync ( buildDir + '/node_modules' , buildDir + '/oss-stable' ) ;
7490 }
7591
@@ -88,8 +104,9 @@ function processStable(buildDir) {
88104 }
89105}
90106
91- function processExperimental ( buildDir ) {
107+ function processExperimental ( buildDir , version ) {
92108 if ( fs . existsSync ( buildDir + '/node_modules' ) ) {
109+ updatePackageVersions ( buildDir + '/node_modules' , version ) ;
93110 fs . renameSync ( buildDir + '/node_modules' , buildDir + '/oss-experimental' ) ;
94111 }
95112
@@ -121,3 +138,46 @@ function processExperimental(buildDir) {
121138 }
122139 }
123140}
141+
142+ function updatePackageVersions ( modulesDir , version ) {
143+ const allReactModuleNames = fs . readdirSync ( 'packages' ) ;
144+ for ( const moduleName of fs . readdirSync ( modulesDir ) ) {
145+ const packageJSONPath = path . join ( modulesDir , moduleName , 'package.json' ) ;
146+ const stats = fs . statSync ( packageJSONPath ) ;
147+ if ( stats . isFile ( ) ) {
148+ const packageInfo = JSON . parse ( fs . readFileSync ( packageJSONPath ) ) ;
149+
150+ // Update version
151+ packageInfo . version = version ;
152+
153+ // Update dependency versions
154+ if ( packageInfo . dependencies ) {
155+ for ( const dep of Object . keys ( packageInfo . dependencies ) ) {
156+ if ( allReactModuleNames . includes ( dep ) ) {
157+ packageInfo . dependencies [ dep ] = version ;
158+ }
159+ }
160+ }
161+ if ( packageInfo . peerDependencies ) {
162+ for ( const dep of Object . keys ( packageInfo . peerDependencies ) ) {
163+ if ( allReactModuleNames . includes ( dep ) ) {
164+ packageInfo . peerDependencies [ dep ] = version ;
165+ }
166+ }
167+ }
168+
169+ // Write out updated package.json
170+ fs . writeFileSync ( packageJSONPath , JSON . stringify ( packageInfo , null , 2 ) ) ;
171+ }
172+ }
173+ }
174+
175+ function updateTheReactVersionThatDevToolsReads ( version ) {
176+ // Overwrite the ReactVersion module before the build script runs so that it
177+ // is included in the final bundles. This only runs in CI, so it's fine to
178+ // edit the source file.
179+ fs . writeFileSync (
180+ './packages/shared/ReactVersion.js' ,
181+ `export default '${ version } ';\n`
182+ ) ;
183+ }
0 commit comments