From 91304e70a15159c6965574d1a53103a3f5bd82e6 Mon Sep 17 00:00:00 2001 From: Travis Ralston Date: Tue, 25 Sep 2018 15:49:14 -0600 Subject: [PATCH] Swap out the complicated canary stuff for serial execution Fixes https://github.com/vector-im/riot-web/issues/7386 --- README.md | 2 + package.json | 20 +++---- scripts/block-on-sdk-build.js | 46 ---------------- scripts/build-watch-sdk.js | 99 ----------------------------------- scripts/npm-sub.js | 21 ++++++++ 5 files changed, 33 insertions(+), 155 deletions(-) delete mode 100644 scripts/block-on-sdk-build.js delete mode 100644 scripts/build-watch-sdk.js create mode 100644 scripts/npm-sub.js diff --git a/README.md b/README.md index 52ffeafb..8267992c 100644 --- a/README.md +++ b/README.md @@ -256,6 +256,8 @@ First clone and build `matrix-js-sdk`: 1. `git clone https://github.com/matrix-org/matrix-js-sdk.git` 1. `pushd matrix-js-sdk` 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` Then similarly with `matrix-react-sdk`: diff --git a/package.json b/package.json index a3f6985c..a3c0e684 100644 --- a/package.json +++ b/package.json @@ -36,22 +36,22 @@ "build:bundle": "cross-env NODE_ENV=production webpack -p --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:react-sdk": "node scripts/build-watch-sdk.js build react", - "build:js-sdk": "node scripts//build-watch-sdk.js build js", + "build:react-sdk": "node scripts/npm-sub.js matrix-react-sdk run start:init", + "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: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", "install:electron": "install-app-deps", "electron": "npm run install:electron && electron .", "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: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-sdk": "node scripts/build-watch-sdk.js watch js", - "start:js-sdk:prod": "cross-env NODE_ENV=production node && scripts/build-watch-sdk.js watch js", - "start:react-sdk": "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/block-on-sdk-build.js js && node scripts//build-watch-sdk.js watch react", - "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: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: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 webpack-dev-server -w --progress", + "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/npm-sub.js matrix-js-sdk run start:watch", + "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/npm-sub.js matrix-react-sdk run start:all", + "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": "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/", "lintall": "eslint src/ test/", "clean": "rimraf lib webapp electron_app/dist", diff --git a/scripts/block-on-sdk-build.js b/scripts/block-on-sdk-build.js deleted file mode 100644 index eb359729..00000000 --- a/scripts/block-on-sdk-build.js +++ /dev/null @@ -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); -}); \ No newline at end of file diff --git a/scripts/build-watch-sdk.js b/scripts/build-watch-sdk.js deleted file mode 100644 index 44607f6b..00000000 --- a/scripts/build-watch-sdk.js +++ /dev/null @@ -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"); -} \ No newline at end of file diff --git a/scripts/npm-sub.js b/scripts/npm-sub.js new file mode 100644 index 00000000..e0ecbeda --- /dev/null +++ b/scripts/npm-sub.js @@ -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, +});