diff --git a/tools/deploy/index.ts b/tools/deploy/index.ts index 1ffd6c5c..ab02a72e 100644 --- a/tools/deploy/index.ts +++ b/tools/deploy/index.ts @@ -210,9 +210,12 @@ common(program.command('deploy [names...]')) console.log(`${name}: ${matched.size} files | ${entry.cmd}`); const upload = spawn(entry.cmd, {shell: true, stdio: ['pipe', 'inherit', 'inherit']}); // If the command dies early we report its exit code; don't - // also crash on the resulting EPIPE. + // also crash on the resulting EPIPE, which reaches both + // stdin and (via streamx's destroy propagation) the pack. upload.stdin!.on('error', () => {}); - aq.pack(dst => matched.has(dst)).pipe(upload.stdin!); + const pack = aq.pack(dst => matched.has(dst)); + pack.on('error', () => {}); + pack.pipe(upload.stdin!); if (await waitExit(upload) !== 0) { return 1; } diff --git a/tools/deploy/queue.ts b/tools/deploy/queue.ts index bba14691..5fb8734d 100644 --- a/tools/deploy/queue.ts +++ b/tools/deploy/queue.ts @@ -168,11 +168,11 @@ export class ActionQueue { if (entry.type !== 'Op' || (filter !== undefined && !filter(entry.dst))) continue; const op = entry.op; - if (op.type === 'Copy'){ - t.entry({name: entry.dst}, fs.readFileSync(op.src)); - } else if (op.type === 'Write') { - t.entry({name: entry.dst}, op.data); - } + const data = op.type === 'Copy' ? fs.readFileSync(op.src) : op.data; + // A dying consumer destroys the pack and every pending entry + // sink, and each sink emits the error; the consumer is the one + // reporting the failure, so keep the sinks quiet. + t.entry({name: entry.dst}, data).on('error', () => {}); } // Without this the archive has no end-of-archive marker, and strict // readers (Python tarfile in stream mode) die on the truncation.