From 684903b5708805c3ed00c3bd3009cdf91530322a Mon Sep 17 00:00:00 2001 From: Rico Huijbers Date: Wed, 6 Nov 2019 16:02:24 +0100 Subject: [PATCH 1/2] fix(pacmak): occasional EISDIR failure There was a race condition in capturing the output of `npm pack`. Ocassionally we would miss the output, not get a tarball name, combine the empty string with a directory, and then get an EISDIR error when trying to copy the tarball as a file (but giving it a directory name). This race has been in there forever, but it became easier to trigger since we started running a lot of `npm pack`s in parallel. The solution is to wait for a different event on the `ChildProcess` object. --- packages/jsii-pacmak/lib/packaging.ts | 8 +++++++- packages/jsii-pacmak/lib/util.ts | 5 ++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/jsii-pacmak/lib/packaging.ts b/packages/jsii-pacmak/lib/packaging.ts index 11e60abcb2..c7d8040876 100644 --- a/packages/jsii-pacmak/lib/packaging.ts +++ b/packages/jsii-pacmak/lib/packaging.ts @@ -58,7 +58,13 @@ export class JsiiModule { // tarball name. otherwise, there can be a lot of extra noise there // from scripts that emit to STDOUT. const lines = out.trim().split(os.EOL); - return path.resolve(tmpdir, lines[lines.length - 1].trim()); + const lastLine = lines[lines.length - 1].trim(); + + if (!lastLine.endsWith('.tgz') && !lastLine.endsWith('.tar.gz')) { + throw new Error(`npm pack did not produce tarball from ${this.moduleDirectory} into ${tmpdir} (output was ${JSON.stringify(lines)})`); + } + + return path.resolve(tmpdir, lastLine); }); } diff --git a/packages/jsii-pacmak/lib/util.ts b/packages/jsii-pacmak/lib/util.ts index 81dca2fde4..2c6e2dc55d 100644 --- a/packages/jsii-pacmak/lib/util.ts +++ b/packages/jsii-pacmak/lib/util.ts @@ -52,7 +52,10 @@ export async function shell(cmd: string, args: string[], options: ShellOptions): stderr.push(Buffer.from(chunk)); }); child.once('error', ko); - child.once('exit', (code, signal) => { + + // Muse use CLOSE instead of EXIT; EXIT may fire while there is still data in the + // I/O pipes, which we will miss if we return at that point. + child.once('close', (code, signal) => { const out = Buffer.concat(stdout).toString('utf-8'); if (code === 0) { return ok(out); } const err = Buffer.concat(stderr).toString('utf-8'); From da5aebb827c6645b77d6e6bc8ebe2db821b784ff Mon Sep 17 00:00:00 2001 From: Elad Ben-Israel Date: Wed, 6 Nov 2019 17:10:21 +0200 Subject: [PATCH 2/2] Update util.ts --- packages/jsii-pacmak/lib/util.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/jsii-pacmak/lib/util.ts b/packages/jsii-pacmak/lib/util.ts index 2c6e2dc55d..0dbdafe0a9 100644 --- a/packages/jsii-pacmak/lib/util.ts +++ b/packages/jsii-pacmak/lib/util.ts @@ -53,7 +53,7 @@ export async function shell(cmd: string, args: string[], options: ShellOptions): }); child.once('error', ko); - // Muse use CLOSE instead of EXIT; EXIT may fire while there is still data in the + // Must use CLOSE instead of EXIT; EXIT may fire while there is still data in the // I/O pipes, which we will miss if we return at that point. child.once('close', (code, signal) => { const out = Buffer.concat(stdout).toString('utf-8');