From b1346b3ba7708ccc817df7763616a00ce4397b87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=80=9CJamesHenry=E2=80=9D?= Date: Tue, 26 Jul 2022 18:50:15 +0400 Subject: [PATCH] fix(run-lifecycle): lifecycle events should run to completion in series --- commands/bootstrap/package.json | 2 +- package-lock.json | 83 ++++++++------------- package.json | 4 +- utils/pack-directory/lib/pack-directory.js | 1 + utils/run-lifecycle/package.json | 5 +- utils/run-lifecycle/run-lifecycle.js | 84 ++++++++++++---------- 6 files changed, 83 insertions(+), 96 deletions(-) diff --git a/commands/bootstrap/package.json b/commands/bootstrap/package.json index da08c20680..11769ece8a 100644 --- a/commands/bootstrap/package.json +++ b/commands/bootstrap/package.json @@ -45,7 +45,7 @@ "@lerna/symlink-binary": "file:../../utils/symlink-binary", "@lerna/symlink-dependencies": "file:../../utils/symlink-dependencies", "@lerna/validation-error": "file:../../core/validation-error", - "@npmcli/arborist": "5.2.0", + "@npmcli/arborist": "5.3.0", "dedent": "^0.7.0", "get-port": "^5.1.1", "multimatch": "^5.0.0", diff --git a/package-lock.json b/package-lock.json index 5846d40355..7a43fd9c6f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,8 +14,8 @@ "e2e" ], "dependencies": { - "@npmcli/arborist": "5.2.0", - "@npmcli/run-script": "^3.0.2", + "@npmcli/arborist": "5.3.0", + "@npmcli/run-script": "^4.1.7", "@octokit/plugin-enterprise-rest": "^6.0.1", "@octokit/rest": "^19.0.3", "byte-size": "^7.0.0", @@ -162,7 +162,7 @@ "@lerna/symlink-binary": "file:../../utils/symlink-binary", "@lerna/symlink-dependencies": "file:../../utils/symlink-dependencies", "@lerna/validation-error": "file:../../core/validation-error", - "@npmcli/arborist": "5.2.0", + "@npmcli/arborist": "5.3.0", "dedent": "^0.7.0", "get-port": "^5.1.1", "multimatch": "^5.0.0", @@ -2657,9 +2657,9 @@ } }, "node_modules/@npmcli/arborist": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.2.0.tgz", - "integrity": "sha512-zWV7scFGL0SmpvfQyIWnMFbU/0YgtMNyvJiJwR98kyjUSntJGWFFR0O600d5W+TrDcTg0GyDbY+HdzGEg+GXLg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.3.0.tgz", + "integrity": "sha512-+rZ9zgL1lnbl8Xbb1NQdMjveOMwj4lIYfcDtyJHHi5x4X8jtR6m8SXooJMZy5vmFVZ8w7A2Bnd/oX9eTuU8w5A==", "dependencies": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/installed-package-contents": "^1.0.7", @@ -2669,7 +2669,7 @@ "@npmcli/name-from-folder": "^1.0.1", "@npmcli/node-gyp": "^2.0.0", "@npmcli/package-json": "^2.0.0", - "@npmcli/run-script": "^3.0.0", + "@npmcli/run-script": "^4.1.3", "bin-links": "^3.0.0", "cacache": "^16.0.6", "common-ancestor-path": "^1.0.1", @@ -2683,7 +2683,7 @@ "npm-pick-manifest": "^7.0.0", "npm-registry-fetch": "^13.0.0", "npmlog": "^6.0.2", - "pacote": "^13.0.5", + "pacote": "^13.6.1", "parse-conflict-json": "^2.0.1", "proc-log": "^2.0.0", "promise-all-reject-late": "^1.0.0", @@ -3336,14 +3336,15 @@ } }, "node_modules/@npmcli/run-script": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-3.0.2.tgz", - "integrity": "sha512-vdjD/PMBl+OX9j9C9irx5sCCIKfp2PWkpPNH9zxvlJAfSZ3Qp5aU412v+O3PFJl3R1PFNwuyChCqHg4ma6ci2Q==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.1.7.tgz", + "integrity": "sha512-WXr/MyM4tpKA4BotB81NccGAv8B48lNH0gRoILucbcAhTQXLCoi6HflMV3KdXubIqvP9SuLsFn68Z7r4jl+ppw==", "dependencies": { "@npmcli/node-gyp": "^2.0.0", "@npmcli/promise-spawn": "^3.0.0", "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3" + "read-package-json-fast": "^2.0.3", + "which": "^2.0.2" }, "engines": { "node": "^12.13.0 || ^14.15.0 || >=16.0.0" @@ -14582,21 +14583,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/pacote/node_modules/@npmcli/run-script": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.1.7.tgz", - "integrity": "sha512-WXr/MyM4tpKA4BotB81NccGAv8B48lNH0gRoILucbcAhTQXLCoi6HflMV3KdXubIqvP9SuLsFn68Z7r4jl+ppw==", - "dependencies": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3", - "which": "^2.0.2" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/pacote/node_modules/@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", @@ -18652,8 +18638,9 @@ "license": "MIT", "dependencies": { "@lerna/npm-conf": "file:../npm-conf", - "@npmcli/run-script": "^3.0.2", - "npmlog": "^6.0.2" + "@npmcli/run-script": "^4.1.7", + "npmlog": "^6.0.2", + "p-queue": "^6.6.2" }, "engines": { "node": "^14.15.0 || >=16.0.0" @@ -20206,7 +20193,7 @@ "@lerna/symlink-binary": "file:../../utils/symlink-binary", "@lerna/symlink-dependencies": "file:../../utils/symlink-dependencies", "@lerna/validation-error": "file:../../core/validation-error", - "@npmcli/arborist": "5.2.0", + "@npmcli/arborist": "5.3.0", "dedent": "^0.7.0", "get-port": "^5.1.1", "multimatch": "^5.0.0", @@ -20718,8 +20705,9 @@ "version": "file:utils/run-lifecycle", "requires": { "@lerna/npm-conf": "file:../npm-conf", - "@npmcli/run-script": "^3.0.2", - "npmlog": "^6.0.2" + "@npmcli/run-script": "^4.1.7", + "npmlog": "^6.0.2", + "p-queue": "^6.6.2" } }, "@lerna/run-topologically": { @@ -20830,9 +20818,9 @@ } }, "@npmcli/arborist": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.2.0.tgz", - "integrity": "sha512-zWV7scFGL0SmpvfQyIWnMFbU/0YgtMNyvJiJwR98kyjUSntJGWFFR0O600d5W+TrDcTg0GyDbY+HdzGEg+GXLg==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@npmcli/arborist/-/arborist-5.3.0.tgz", + "integrity": "sha512-+rZ9zgL1lnbl8Xbb1NQdMjveOMwj4lIYfcDtyJHHi5x4X8jtR6m8SXooJMZy5vmFVZ8w7A2Bnd/oX9eTuU8w5A==", "requires": { "@isaacs/string-locale-compare": "^1.1.0", "@npmcli/installed-package-contents": "^1.0.7", @@ -20842,7 +20830,7 @@ "@npmcli/name-from-folder": "^1.0.1", "@npmcli/node-gyp": "^2.0.0", "@npmcli/package-json": "^2.0.0", - "@npmcli/run-script": "^3.0.0", + "@npmcli/run-script": "^4.1.3", "bin-links": "^3.0.0", "cacache": "^16.0.6", "common-ancestor-path": "^1.0.1", @@ -20856,7 +20844,7 @@ "npm-pick-manifest": "^7.0.0", "npm-registry-fetch": "^13.0.0", "npmlog": "^6.0.2", - "pacote": "^13.0.5", + "pacote": "^13.6.1", "parse-conflict-json": "^2.0.1", "proc-log": "^2.0.0", "promise-all-reject-late": "^1.0.0", @@ -21365,14 +21353,15 @@ } }, "@npmcli/run-script": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-3.0.2.tgz", - "integrity": "sha512-vdjD/PMBl+OX9j9C9irx5sCCIKfp2PWkpPNH9zxvlJAfSZ3Qp5aU412v+O3PFJl3R1PFNwuyChCqHg4ma6ci2Q==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.1.7.tgz", + "integrity": "sha512-WXr/MyM4tpKA4BotB81NccGAv8B48lNH0gRoILucbcAhTQXLCoi6HflMV3KdXubIqvP9SuLsFn68Z7r4jl+ppw==", "requires": { "@npmcli/node-gyp": "^2.0.0", "@npmcli/promise-spawn": "^3.0.0", "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3" + "read-package-json-fast": "^2.0.3", + "which": "^2.0.2" } }, "@nrwl/cli": { @@ -30066,18 +30055,6 @@ "rimraf": "^3.0.2" } }, - "@npmcli/run-script": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/@npmcli/run-script/-/run-script-4.1.7.tgz", - "integrity": "sha512-WXr/MyM4tpKA4BotB81NccGAv8B48lNH0gRoILucbcAhTQXLCoi6HflMV3KdXubIqvP9SuLsFn68Z7r4jl+ppw==", - "requires": { - "@npmcli/node-gyp": "^2.0.0", - "@npmcli/promise-spawn": "^3.0.0", - "node-gyp": "^9.0.0", - "read-package-json-fast": "^2.0.3", - "which": "^2.0.2" - } - }, "@tootallnate/once": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", diff --git a/package.json b/package.json index 9aac2fea85..75086a6ec4 100644 --- a/package.json +++ b/package.json @@ -42,8 +42,8 @@ "license": "MIT", "homepage": "https://lerna.js.org", "dependencies": { - "@npmcli/arborist": "5.2.0", - "@npmcli/run-script": "^3.0.2", + "@npmcli/arborist": "5.3.0", + "@npmcli/run-script": "^4.1.7", "@octokit/plugin-enterprise-rest": "^6.0.1", "@octokit/rest": "^19.0.3", "byte-size": "^7.0.0", diff --git a/utils/pack-directory/lib/pack-directory.js b/utils/pack-directory/lib/pack-directory.js index ea7a7257bb..044155f1fb 100644 --- a/utils/pack-directory/lib/pack-directory.js +++ b/utils/pack-directory/lib/pack-directory.js @@ -42,6 +42,7 @@ function packDirectory(_pkg, dir, options) { chain = chain.then(() => runLifecycle(pkg, "prepare", opts)); if (opts.lernaCommand === "publish") { + opts.stdio = "inherit"; chain = chain.then(() => pkg.refresh()); chain = chain.then(() => runLifecycle(pkg, "prepublishOnly", opts)); chain = chain.then(() => pkg.refresh()); diff --git a/utils/run-lifecycle/package.json b/utils/run-lifecycle/package.json index 21e7ab880a..37c1576583 100644 --- a/utils/run-lifecycle/package.json +++ b/utils/run-lifecycle/package.json @@ -32,7 +32,8 @@ }, "dependencies": { "@lerna/npm-conf": "file:../npm-conf", - "@npmcli/run-script": "^3.0.2", - "npmlog": "^6.0.2" + "@npmcli/run-script": "^4.1.7", + "npmlog": "^6.0.2", + "p-queue": "^6.6.2" } } diff --git a/utils/run-lifecycle/run-lifecycle.js b/utils/run-lifecycle/run-lifecycle.js index f59e3b4b9e..42b6dd6ba4 100644 --- a/utils/run-lifecycle/run-lifecycle.js +++ b/utils/run-lifecycle/run-lifecycle.js @@ -5,6 +5,9 @@ const log = require("npmlog"); const runScript = require("@npmcli/run-script"); const npmConf = require("@lerna/npm-conf"); +const PQueue = require("p-queue").default; + +const queue = new PQueue({ concurrency: 1 }); module.exports.runLifecycle = runLifecycle; module.exports.createRunner = createRunner; @@ -18,6 +21,7 @@ module.exports.createRunner = createRunner; * @property {string} [scriptShell] * @property {boolean} [scriptsPrependNodePath] * @property {boolean} [unsafePerm=true] + * @property {string} [stdio] */ /** @@ -115,49 +119,53 @@ function runLifecycle(pkg, stage, options) { /** * In order to match the previous behavior of "npm-lifecycle", we have to disable the writing - * to the parent process and print the command banner ourself. + * to the parent process and print the command banner ourselves, unless overridden by the options. */ - const stdio = "pipe"; + const stdio = opts.stdio || "pipe"; if (log.level !== "silent") { printCommandBanner(id, stage, pkg.scripts[stage], dir); } - return runScript({ - event: stage, - path: dir, - pkg, - args: [], - stdio, - banner: false, - scriptShell: config.scriptShell, - }).then( - ({ stdout }) => { - /** - * This adjustment is based on trying to match the existing integration test outputs when migrating - * from "npm-lifecycle" to "@npmcli/run-script". - */ - // eslint-disable-next-line no-console - console.log(stdout.toString().trimEnd()); - - opts.log.silly("lifecycle", "%j finished in %j", stage, pkg.name); - }, - (err) => { - // propagate the exit code - const exitCode = err.code || 1; - - // error logging has already occurred on stderr, but we need to stop the chain - log.error("lifecycle", "%j errored in %j, exiting %d", stage, pkg.name, exitCode); - - // ensure clean logging, avoiding spurious log dump - err.name = "ValidationError"; - - // our yargs.fail() handler expects a numeric .exitCode, not .errno - err.exitCode = exitCode; - process.exitCode = exitCode; - - // stop the chain - throw err; - } + return queue.add(async () => + runScript({ + event: stage, + path: dir, + pkg, + args: [], + stdio, + banner: false, + scriptShell: config.scriptShell, + }).then( + ({ stdout }) => { + if (stdout) { + /** + * This adjustment is based on trying to match the existing integration test outputs when migrating + * from "npm-lifecycle" to "@npmcli/run-script". + */ + // eslint-disable-next-line no-console + console.log(stdout.toString().trimEnd()); + } + + opts.log.silly("lifecycle", "%j finished in %j", stage, pkg.name); + }, + (err) => { + // propagate the exit code + const exitCode = err.code || 1; + + // error logging has already occurred on stderr, but we need to stop the chain + log.error("lifecycle", "%j errored in %j, exiting %d", stage, pkg.name, exitCode); + + // ensure clean logging, avoiding spurious log dump + err.name = "ValidationError"; + + // our yargs.fail() handler expects a numeric .exitCode, not .errno + err.exitCode = exitCode; + process.exitCode = exitCode; + + // stop the chain + throw err; + } + ) ); }