forked from facebook/react
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathbuild.js
175 lines (146 loc) · 5.54 KB
/
build.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
#!/usr/bin/env node
'use strict';
const archiver = require('archiver');
const {execSync} = require('child_process');
const {readFileSync, writeFileSync, createWriteStream} = require('fs');
const {copy, ensureDir, move, remove, pathExistsSync} = require('fs-extra');
const {join, resolve} = require('path');
const {getGitCommit} = require('./utils');
// These files are copied along with Webpack-bundled files
// to produce the final web extension
const STATIC_FILES = ['icons', 'popups', 'main.html', 'panel.html'];
/**
* Ensures that a local build of the dependencies exist either by downloading
* or running a local build via one of the `react-build-fordevtools*` scripts.
*/
const ensureLocalBuild = async () => {
const buildDir = resolve(__dirname, '..', '..', 'build');
const nodeModulesDir = join(buildDir, 'node_modules');
// TODO: remove this check whenever the CI pipeline is complete.
// See build-all-release-channels.js
const currentBuildDir = resolve(
__dirname,
'..',
'..',
'build',
'oss-experimental',
);
if (pathExistsSync(buildDir)) {
return; // all good.
}
if (pathExistsSync(currentBuildDir)) {
await ensureDir(buildDir);
await copy(currentBuildDir, nodeModulesDir);
return; // all good.
}
throw Error(
'Could not find build artifacts in repo root. See README for prerequisites.',
);
};
const preProcess = async (destinationPath, tempPath) => {
await remove(destinationPath); // Clean up from previously completed builds
await remove(tempPath); // Clean up from any previously failed builds
await ensureDir(tempPath); // Create temp dir for this new build
};
const build = async (tempPath, manifestPath, envExtension = {}) => {
const binPath = join(tempPath, 'bin');
const zipPath = join(tempPath, 'zip');
const mergedEnv = {...process.env, ...envExtension};
const webpackPath = join(__dirname, 'node_modules', '.bin', 'webpack');
execSync(
`${webpackPath} --config webpack.config.js --output-path ${binPath}`,
{
cwd: __dirname,
env: mergedEnv,
stdio: 'inherit',
},
);
execSync(
`${webpackPath} --config webpack.backend.js --output-path ${binPath}`,
{
cwd: __dirname,
env: mergedEnv,
stdio: 'inherit',
},
);
// Make temp dir
await ensureDir(zipPath);
const copiedManifestPath = join(zipPath, 'manifest.json');
// Copy unbuilt source files to zip dir to be packaged:
await copy(binPath, join(zipPath, 'build'));
await copy(manifestPath, copiedManifestPath);
await Promise.all(
STATIC_FILES.map(file => copy(join(__dirname, file), join(zipPath, file))),
);
const commit = getGitCommit();
const dateString = new Date().toLocaleDateString();
const manifest = JSON.parse(readFileSync(copiedManifestPath).toString());
const versionDateString = `${manifest.version} (${dateString})`;
if (manifest.version_name) {
manifest.version_name = versionDateString;
}
manifest.description += `\n\nCreated from revision ${commit} on ${dateString}.`;
if (process.env.NODE_ENV === 'development') {
// When building the local development version of the
// extension we want to be able to have a stable extension ID
// for the local build (in order to be able to reliably detect
// duplicate installations of DevTools).
// By specifying a key in the built manifest.json file,
// we can make it so the generated extension ID is stable.
// For more details see the docs here: https://developer.chrome.com/docs/extensions/mv2/manifest/key/
manifest.key = 'reactdevtoolslocalbuilduniquekey';
}
writeFileSync(copiedManifestPath, JSON.stringify(manifest, null, 2));
// Pack the extension
const archive = archiver('zip', {zlib: {level: 9}});
const zipStream = createWriteStream(join(tempPath, 'ReactDevTools.zip'));
await new Promise((resolvePromise, rejectPromise) => {
archive
.directory(zipPath, false)
.on('error', err => rejectPromise(err))
.pipe(zipStream);
archive.finalize();
zipStream.on('close', () => resolvePromise());
});
};
const postProcess = async (tempPath, destinationPath) => {
const unpackedSourcePath = join(tempPath, 'zip');
const packedSourcePath = join(tempPath, 'ReactDevTools.zip');
const packedDestPath = join(destinationPath, 'ReactDevTools.zip');
const unpackedDestPath = join(destinationPath, 'unpacked');
await move(unpackedSourcePath, unpackedDestPath); // Copy built files to destination
await move(packedSourcePath, packedDestPath); // Copy built files to destination
await remove(tempPath); // Clean up temp directory and files
};
const SUPPORTED_BUILDS = ['chrome', 'firefox', 'edge'];
const main = async buildId => {
if (!SUPPORTED_BUILDS.includes(buildId)) {
throw new Error(
`Unexpected build id - "${buildId}". Use one of ${JSON.stringify(
SUPPORTED_BUILDS,
)}.`,
);
}
const root = join(__dirname, buildId);
const manifestPath = join(root, 'manifest.json');
const destinationPath = join(root, 'build');
const envExtension = {
IS_CHROME: buildId === 'chrome',
IS_FIREFOX: buildId === 'firefox',
IS_EDGE: buildId === 'edge',
};
try {
const tempPath = join(__dirname, 'build', buildId);
await ensureLocalBuild();
await preProcess(destinationPath, tempPath);
await build(tempPath, manifestPath, envExtension);
const builtUnpackedPath = join(destinationPath, 'unpacked');
await postProcess(tempPath, destinationPath);
return builtUnpackedPath;
} catch (error) {
console.error(error);
process.exit(1);
}
return null;
};
module.exports = main;