4
4
5
5
const fs = require ( 'fs' ) ;
6
6
const { spawnSync} = require ( 'child_process' ) ;
7
+ const path = require ( 'path' ) ;
7
8
const tmp = require ( 'tmp' ) ;
8
9
9
10
// Runs the build script for both stable and experimental release channels,
10
11
// by configuring an environment variable.
11
12
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
+
12
19
if ( process . env . CIRCLE_NODE_TOTAL ) {
13
20
// In CI, we use multiple concurrent processes. Allocate half the processes to
14
21
// build the stable channel, and the other half for experimental. Override
@@ -19,13 +26,19 @@ if (process.env.CIRCLE_NODE_TOTAL) {
19
26
if ( index < halfTotal ) {
20
27
const nodeTotal = halfTotal ;
21
28
const nodeIndex = index ;
29
+ const version = '0.0.0-' + sha ;
30
+ updateTheReactVersionThatDevToolsReads ( ReactVersion + '-' + sha ) ;
22
31
buildForChannel ( 'stable' , nodeTotal , nodeIndex ) ;
23
- processStable ( './build' ) ;
32
+ processStable ( './build' , version ) ;
24
33
} else {
25
34
const nodeTotal = total - halfTotal ;
26
35
const nodeIndex = index - halfTotal ;
36
+ const version = '0.0.0-experimental-' + sha ;
37
+ updateTheReactVersionThatDevToolsReads (
38
+ ReactVersion + '-experimental-' + sha
39
+ ) ;
27
40
buildForChannel ( 'experimental' , nodeTotal , nodeIndex ) ;
28
- processExperimental ( './build' ) ;
41
+ processExperimental ( './build' , version ) ;
29
42
}
30
43
31
44
// TODO: Currently storing artifacts as `./build2` so that it doesn't conflict
@@ -34,15 +47,17 @@ if (process.env.CIRCLE_NODE_TOTAL) {
34
47
} else {
35
48
// Running locally, no concurrency. Move each channel's build artifacts into
36
49
// a temporary directory so that they don't conflict.
50
+ const stableVersion = '0.0.0-' + sha ;
37
51
buildForChannel ( 'stable' , '' , '' ) ;
38
52
const stableDir = tmp . dirSync ( ) . name ;
39
53
fs . renameSync ( './build' , stableDir ) ;
40
- processStable ( stableDir ) ;
54
+ processStable ( stableDir , stableVersion ) ;
41
55
56
+ const experimentalVersion = '0.0.0-experimental-' + sha ;
42
57
buildForChannel ( 'experimental' , '' , '' ) ;
43
58
const experimentalDir = tmp . dirSync ( ) . name ;
44
59
fs . renameSync ( './build' , experimentalDir ) ;
45
- processExperimental ( experimentalDir ) ;
60
+ processExperimental ( experimentalDir , experimentalVersion ) ;
46
61
47
62
// Then merge the experimental folder into the stable one. processExperimental
48
63
// will have already removed conflicting files.
@@ -68,8 +83,9 @@ function buildForChannel(channel, nodeTotal, nodeIndex) {
68
83
} ) ;
69
84
}
70
85
71
- function processStable ( buildDir ) {
86
+ function processStable ( buildDir , version ) {
72
87
if ( fs . existsSync ( buildDir + '/node_modules' ) ) {
88
+ updatePackageVersions ( buildDir + '/node_modules' , version ) ;
73
89
fs . renameSync ( buildDir + '/node_modules' , buildDir + '/oss-stable' ) ;
74
90
}
75
91
@@ -88,8 +104,9 @@ function processStable(buildDir) {
88
104
}
89
105
}
90
106
91
- function processExperimental ( buildDir ) {
107
+ function processExperimental ( buildDir , version ) {
92
108
if ( fs . existsSync ( buildDir + '/node_modules' ) ) {
109
+ updatePackageVersions ( buildDir + '/node_modules' , version ) ;
93
110
fs . renameSync ( buildDir + '/node_modules' , buildDir + '/oss-experimental' ) ;
94
111
}
95
112
@@ -121,3 +138,46 @@ function processExperimental(buildDir) {
121
138
}
122
139
}
123
140
}
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