Swap out the complicated canary stuff for serial execution
Fixes https://github.com/vector-im/riot-web/issues/7386
This commit is contained in:
parent
27c23058dc
commit
91304e70a1
5 changed files with 33 additions and 155 deletions
|
@ -256,6 +256,8 @@ First clone and build `matrix-js-sdk`:
|
||||||
1. `git clone https://github.com/matrix-org/matrix-js-sdk.git`
|
1. `git clone https://github.com/matrix-org/matrix-js-sdk.git`
|
||||||
1. `pushd matrix-js-sdk`
|
1. `pushd matrix-js-sdk`
|
||||||
1. `git checkout develop`
|
1. `git checkout develop`
|
||||||
|
1. `npm install`
|
||||||
|
1. `npm install source-map-loader` # because webpack is made of fail (https://github.com/webpack/webpack/issues/1472)
|
||||||
1. `popd`
|
1. `popd`
|
||||||
|
|
||||||
Then similarly with `matrix-react-sdk`:
|
Then similarly with `matrix-react-sdk`:
|
||||||
|
|
20
package.json
20
package.json
|
@ -36,22 +36,22 @@
|
||||||
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress --bail",
|
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress --bail",
|
||||||
"build:bundle:dev": "webpack --optimize-occurence-order --progress --bail",
|
"build:bundle:dev": "webpack --optimize-occurence-order --progress --bail",
|
||||||
"build:electron": "npm run clean && npm run build && npm run install:electron && build -wml --ia32 --x64",
|
"build:electron": "npm run clean && npm run build && npm run install:electron && build -wml --ia32 --x64",
|
||||||
"build:react-sdk": "node scripts/build-watch-sdk.js build react",
|
"build:react-sdk": "node scripts/npm-sub.js matrix-react-sdk run start:init",
|
||||||
"build:js-sdk": "node scripts//build-watch-sdk.js build js",
|
"build:js-sdk": "node scripts/npm-sub.js matrix-js-sdk run start:init",
|
||||||
"build": "npm run build:js-sdk && npm run build:react-sdk && npm run reskindex && npm run build:res && npm run build:bundle",
|
"build": "npm run build:js-sdk && npm run build:react-sdk && npm run reskindex && npm run build:res && npm run build:bundle",
|
||||||
"build:dev": "npm run build:js-sdk && npm run build:react-sdk && npm run reskindex && npm run build:res && npm run build:bundle:dev",
|
"build:dev": "npm run build:js-sdk && npm run build:react-sdk && npm run reskindex && npm run build:res && npm run build:bundle:dev",
|
||||||
"dist": "scripts/package.sh",
|
"dist": "scripts/package.sh",
|
||||||
"install:electron": "install-app-deps",
|
"install:electron": "install-app-deps",
|
||||||
"electron": "npm run install:electron && electron .",
|
"electron": "npm run install:electron && electron .",
|
||||||
"start:res": "node scripts/copy-res.js -w",
|
"start:res": "node scripts/copy-res.js -w",
|
||||||
"start:js": "node scripts/block-on-sdk-build.js js && node scripts/block-on-sdk-build.js react && webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-file=bundles/_dev_/[name].js -w --progress",
|
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-file=bundles/_dev_/[name].js -w --progress",
|
||||||
"start:js:prod": "cross-env NODE_ENV=production node scripts/block-on-sdk-build.js js && node scripts/block-on-sdk-build.js react && webpack-dev-server -w --progress",
|
"start:js:prod": "cross-env NODE_ENV=production webpack-dev-server -w --progress",
|
||||||
"start:js-sdk": "node scripts/build-watch-sdk.js watch js",
|
"start:js-sdk": "node scripts/npm-sub.js matrix-js-sdk run start:watch",
|
||||||
"start:js-sdk:prod": "cross-env NODE_ENV=production node && scripts/build-watch-sdk.js watch js",
|
"start:js-sdk:prod": "cross-env NODE_ENV=production node scripts/npm-sub.js matrix-js-sdk run start:watch",
|
||||||
"start:react-sdk": "node scripts/block-on-sdk-build.js js && node scripts/build-watch-sdk.js watch react",
|
"start:react-sdk": "node scripts/npm-sub.js matrix-react-sdk run start:all",
|
||||||
"start:react-sdk:prod": "cross-env NODE_ENV=production node && scripts/block-on-sdk-build.js js && node scripts//build-watch-sdk.js watch react",
|
"start:react-sdk:prod": "cross-env NODE_ENV=production node scripts/npm-sub.js matrix-react-sdk run start:all",
|
||||||
"start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n js-sdk,react-sdk,reskindex,res,riot-js \"npm run start:js-sdk\" \"npm run start:react-sdk\" \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js\"",
|
"start": "npm run build:js-sdk && npm run build:react-sdk && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n js-sdk,react-sdk,reskindex,res,riot-js \"npm run start:js-sdk\" \"npm run start:react-sdk\" \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js\"",
|
||||||
"start:prod": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n js-sdk,react-sdk,reskindex,res,riot-js \"npm run start:js-sdk:prod\" \"npm run start:react-sdk:prod\" \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js:prod\"",
|
"start:prod": "npm run build:js-sdk && npm run build:react-sdk && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n js-sdk,react-sdk,reskindex,res,riot-js \"npm run start:js-sdk:prod\" \"npm run start:react-sdk:prod\" \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js:prod\"",
|
||||||
"lint": "eslint src/",
|
"lint": "eslint src/",
|
||||||
"lintall": "eslint src/ test/",
|
"lintall": "eslint src/ test/",
|
||||||
"clean": "rimraf lib webapp electron_app/dist",
|
"clean": "rimraf lib webapp electron_app/dist",
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
const path = require('path');
|
|
||||||
const chokidar = require('chokidar');
|
|
||||||
|
|
||||||
|
|
||||||
// This script waits for a signal that an underlying SDK (js or react) has finished
|
|
||||||
// enough of the build process to be safe to rely on. In riot-web's case, this means
|
|
||||||
// that the underlying SDK has finished an initial build and is getting ready to watch
|
|
||||||
// for changes. This is done through use of a canary file that is deleted when it is
|
|
||||||
// safe to continue (see build-watch-sdk.js for why we listen for a delete event).
|
|
||||||
|
|
||||||
// Why do we block in the first place? Because if riot-web starts it's initial
|
|
||||||
// build (via webpack-dev-server) and the react-sdk or js-sdk are halfway through
|
|
||||||
// their initial builds, then riot-web's initial build fails out of the box. This
|
|
||||||
// can sometimes be corrected by waiting for the SDK build to complete and triggering
|
|
||||||
// a file change, thereby causing a cascading build, however it isn't great if the
|
|
||||||
// initial build of riot-web fails out of the box. We block at the js-sdk first so
|
|
||||||
// that the react-sdk build doesn't fall victim to the same problem, which also
|
|
||||||
// slows down the riot-web build. After the js-sdk completes, we start the react-sdk
|
|
||||||
// build which riot-web is waiting for. When complete, riot-web starts building as
|
|
||||||
// per normal.
|
|
||||||
|
|
||||||
|
|
||||||
function waitForCanary(canaryName) {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const filename = path.resolve(path.join(".tmp", canaryName + ".canary"));
|
|
||||||
|
|
||||||
// See build-watch-sdk.js for why we listen for 'unlink' specifically.
|
|
||||||
const watcher = chokidar.watch(filename).on('unlink', (path) => {
|
|
||||||
console.log("[block-on-build] Received signal to start watching for builds");
|
|
||||||
watcher.close();
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const sdkName = process.argv[2];
|
|
||||||
if (!sdkName) {
|
|
||||||
console.error("[block-on-build] No SDK name provided");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("[block-on-build] Waiting for SDK: " + sdkName);
|
|
||||||
waitForCanary(sdkName).then(() => {
|
|
||||||
console.log("[block-on-build] Unblocked");
|
|
||||||
process.exit(0);
|
|
||||||
});
|
|
|
@ -1,99 +0,0 @@
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const child_process = require('child_process');
|
|
||||||
|
|
||||||
|
|
||||||
const task = process.argv[2];
|
|
||||||
if (task !== "build" && task !== "watch") {
|
|
||||||
console.error("Expected a task of 'build' or 'watch'");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const sdkName = process.argv[3];
|
|
||||||
if (!sdkName) {
|
|
||||||
console.error("Missing SDK name");
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const sdkPath = path.dirname(require.resolve(`matrix-${sdkName}-sdk/package.json`));
|
|
||||||
|
|
||||||
// Note: we intentionally create then delete the canary file to work
|
|
||||||
// around a file watching problem where if the file exists on startup it
|
|
||||||
// may fire a "created" event for the file. By having the behaviour be "do
|
|
||||||
// something on delete" we avoid accidentally firing the signal too early.
|
|
||||||
// We also need to ensure the create and delete events are not too close
|
|
||||||
// together, otherwise the filesystem may not fire the watcher. Therefore
|
|
||||||
// we create the canary as early as possible and delete it as late as possible.
|
|
||||||
prepareCanarySignal(sdkName);
|
|
||||||
|
|
||||||
// We only want to build the SDK if it looks like it was `npm link`ed
|
|
||||||
if (fs.existsSync(path.join(sdkPath, '.git'))) {
|
|
||||||
// Install the develop dependencies just in case they were forgotten by the developer.
|
|
||||||
console.log("Installing develop dependencies");
|
|
||||||
const devEnv = Object.assign({}, process.env, {NODE_ENV: "development"});
|
|
||||||
child_process.execSync("npm install --only=dev", {
|
|
||||||
env: devEnv,
|
|
||||||
cwd: sdkPath,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Because webpack is made of fail
|
|
||||||
if (sdkName === "js") {
|
|
||||||
console.log("Installing source-map-loader");
|
|
||||||
child_process.execSync("npm install source-map-loader", {
|
|
||||||
env: devEnv,
|
|
||||||
cwd: sdkPath,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare an initial build of the SDK
|
|
||||||
child_process.execSync("npm run start:init", {
|
|
||||||
env: process.env,
|
|
||||||
cwd: sdkPath,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Send a signal to unblock the build for other processes. Used by block-on-sdk-build.js
|
|
||||||
console.log("Sending signal that other processes may unblock");
|
|
||||||
triggerCanarySignal(sdkName);
|
|
||||||
|
|
||||||
// Actually start the watcher process for the SDK (without an initial build)
|
|
||||||
console.log("Performing task: " + task);
|
|
||||||
const watchTask = sdkName === 'js' ? "start:watch" : "start:all";
|
|
||||||
const buildTask = "build";
|
|
||||||
child_process.execSync(`npm run ${task === "build" ? buildTask : watchTask}`, {
|
|
||||||
env: process.env,
|
|
||||||
cwd: sdkPath,
|
|
||||||
});
|
|
||||||
} else triggerCanarySignal(sdkName);
|
|
||||||
|
|
||||||
function triggerCanarySignal(sdkName) {
|
|
||||||
fs.unlinkSync(getCanaryPath(sdkName));
|
|
||||||
}
|
|
||||||
|
|
||||||
function prepareCanarySignal(sdkName) {
|
|
||||||
const canaryPath = getCanaryPath(sdkName);
|
|
||||||
const canaryDir = path.dirname(canaryPath);
|
|
||||||
|
|
||||||
try {
|
|
||||||
console.log("Creating canary temp path...");
|
|
||||||
fs.mkdirSync(canaryDir);
|
|
||||||
} catch (e) {
|
|
||||||
if (e.code !== 'EEXIST') {
|
|
||||||
console.error(e);
|
|
||||||
throw "Failed to create temporary directory";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
console.log("Creating canary file: " + canaryPath);
|
|
||||||
fs.closeSync(fs.openSync(canaryPath, 'w'));
|
|
||||||
} catch (e) {
|
|
||||||
if (e.code !== 'EEXIST') {
|
|
||||||
console.error(e);
|
|
||||||
throw "Failed to create canary file";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getCanaryPath(sdkName) {
|
|
||||||
return path.join(path.resolve(".tmp"), sdkName + ".canary");
|
|
||||||
}
|
|
21
scripts/npm-sub.js
Normal file
21
scripts/npm-sub.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
const path = require('path');
|
||||||
|
const child_process = require('child_process');
|
||||||
|
|
||||||
|
const moduleName = process.argv[2];
|
||||||
|
if (!moduleName) {
|
||||||
|
console.error("Expected module name");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const argString = process.argv.length > 3 ? process.argv.slice(3).join(" ") : "";
|
||||||
|
if (!argString) {
|
||||||
|
console.error("Expected an npm argument string to use");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
const modulePath = path.dirname(require.resolve(`${moduleName}/package.json`));
|
||||||
|
|
||||||
|
child_process.execSync("npm " + argString, {
|
||||||
|
env: process.env,
|
||||||
|
cwd: modulePath,
|
||||||
|
});
|
Loading…
Reference in a new issue