renovate/lib/util/exec/common.ts

152 lines
4.2 KiB
TypeScript
Raw Normal View History

feat(util/exec): use spawn instead of exec (#16414) * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - init spawn-util * refactor(util): use spawn instead of exec - spawn-util * refactor(util): use spawn instead of exec - init index-spawn.spec.ts * refactor(util): use spawn instead of exec - fixed various tests * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix npm post update imports * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff - destroy stdio when terminating child process * refactor(util): use spawn instead of exec - delete and revert dev related changes * refactor(util): use spawn instead of exec - fix support for windows * refactor(util): use spawn instead of exec - handle SIGSTOP and such - add test coverage * refactor(util): use spawn instead of exec - now converts to strings when resolving/rejecting * refactor(util): use spawn instead of exec - logs improvements - force shell (exec like) - fix tests * refactor(util): use spawn instead of exec - strongly type listeners * refactor(util): use spawn instead of exec - create helper mock for spawn * refactor(util): use spawn instead of exec - cr changes * Update lib/util/exec/common.ts Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec - documentation * refactor(util): use spawn instead of exec - revert unnecessary formatting * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - added ExecError class * refactor(util): use spawn instead of exec - exec-error.ts restructure * refactor(util): use spawn instead of exec * Apply suggestions from code review Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - deprecated RawExecOptions.encoding property * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2022-07-22 15:43:28 +00:00
import { ChildProcess, spawn } from 'child_process';
import { ExecError, ExecErrorData } from './exec-error';
2021-12-04 06:12:27 +00:00
import type { ExecResult, RawExecOptions } from './types';
feat(util/exec): use spawn instead of exec (#16414) * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - init spawn-util * refactor(util): use spawn instead of exec - spawn-util * refactor(util): use spawn instead of exec - init index-spawn.spec.ts * refactor(util): use spawn instead of exec - fixed various tests * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix npm post update imports * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff - destroy stdio when terminating child process * refactor(util): use spawn instead of exec - delete and revert dev related changes * refactor(util): use spawn instead of exec - fix support for windows * refactor(util): use spawn instead of exec - handle SIGSTOP and such - add test coverage * refactor(util): use spawn instead of exec - now converts to strings when resolving/rejecting * refactor(util): use spawn instead of exec - logs improvements - force shell (exec like) - fix tests * refactor(util): use spawn instead of exec - strongly type listeners * refactor(util): use spawn instead of exec - create helper mock for spawn * refactor(util): use spawn instead of exec - cr changes * Update lib/util/exec/common.ts Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec - documentation * refactor(util): use spawn instead of exec - revert unnecessary formatting * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - added ExecError class * refactor(util): use spawn instead of exec - exec-error.ts restructure * refactor(util): use spawn instead of exec * Apply suggestions from code review Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - deprecated RawExecOptions.encoding property * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2022-07-22 15:43:28 +00:00
// https://man7.org/linux/man-pages/man7/signal.7.html#NAME
// Non TERM/CORE signals
// The following is step 3. in https://github.com/renovatebot/renovate/issues/16197#issuecomment-1171423890
const NONTERM = [
'SIGCHLD',
'SIGCLD',
'SIGCONT',
'SIGSTOP',
'SIGTSTP',
'SIGTTIN',
'SIGTTOU',
'SIGURG',
'SIGWINCH',
];
const encoding = 'utf8';
function stringify(list: Buffer[]): string {
return Buffer.concat(list).toString(encoding);
}
function initStreamListeners(
cp: ChildProcess,
opts: RawExecOptions & { maxBuffer: number }
): [Buffer[], Buffer[]] {
const stdout: Buffer[] = [];
const stderr: Buffer[] = [];
let stdoutLen = 0;
let stderrLen = 0;
cp.stdout?.on('data', (chunk: Buffer) => {
// process.stdout.write(data.toString());
const len = Buffer.byteLength(chunk, encoding);
stdoutLen += len;
if (stdoutLen > opts.maxBuffer) {
cp.emit('error', new Error('stdout maxBuffer exceeded'));
} else {
stdout.push(chunk);
}
});
cp.stderr?.on('data', (chunk: Buffer) => {
// process.stderr.write(data.toString());
const len = Buffer.byteLength(chunk, encoding);
stderrLen += len;
if (stderrLen > opts.maxBuffer) {
cp.emit('error', new Error('stderr maxBuffer exceeded'));
} else {
stderr.push(chunk);
}
});
return [stdout, stderr];
}
export function exec(cmd: string, opts: RawExecOptions): Promise<ExecResult> {
return new Promise((resolve, reject) => {
const maxBuffer = opts.maxBuffer ?? 10 * 1024 * 1024; // Set default max buffer size to 10MB
const cp = spawn(cmd, {
...opts,
// force detached on non WIN platforms
// https://github.com/nodejs/node/issues/21825#issuecomment-611328888
detached: process.platform !== 'win32',
shell: typeof opts.shell === 'string' ? opts.shell : true, // force shell
});
// handle streams
const [stdout, stderr] = initStreamListeners(cp, {
...opts,
maxBuffer,
});
// handle process events
cp.on('error', (error) => {
kill(cp, 'SIGTERM');
// rethrowing, use originally emitted error message
feat(util/exec): use spawn instead of exec (#16414) * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - init spawn-util * refactor(util): use spawn instead of exec - spawn-util * refactor(util): use spawn instead of exec - init index-spawn.spec.ts * refactor(util): use spawn instead of exec - fixed various tests * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix npm post update imports * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff - destroy stdio when terminating child process * refactor(util): use spawn instead of exec - delete and revert dev related changes * refactor(util): use spawn instead of exec - fix support for windows * refactor(util): use spawn instead of exec - handle SIGSTOP and such - add test coverage * refactor(util): use spawn instead of exec - now converts to strings when resolving/rejecting * refactor(util): use spawn instead of exec - logs improvements - force shell (exec like) - fix tests * refactor(util): use spawn instead of exec - strongly type listeners * refactor(util): use spawn instead of exec - create helper mock for spawn * refactor(util): use spawn instead of exec - cr changes * Update lib/util/exec/common.ts Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec - documentation * refactor(util): use spawn instead of exec - revert unnecessary formatting * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - added ExecError class * refactor(util): use spawn instead of exec - exec-error.ts restructure * refactor(util): use spawn instead of exec * Apply suggestions from code review Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - deprecated RawExecOptions.encoding property * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2022-07-22 15:43:28 +00:00
reject(new ExecError(error.message, rejectInfo(), error));
});
cp.on('exit', (code: number, signal: NodeJS.Signals) => {
if (NONTERM.includes(signal)) {
return;
}
if (signal) {
kill(cp, signal);
reject(
new ExecError(`Command failed: ${cmd}\nInterrupted by ${signal}`, {
...rejectInfo(),
signal,
})
);
feat(util/exec): use spawn instead of exec (#16414) * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - init spawn-util * refactor(util): use spawn instead of exec - spawn-util * refactor(util): use spawn instead of exec - init index-spawn.spec.ts * refactor(util): use spawn instead of exec - fixed various tests * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix npm post update imports * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff - destroy stdio when terminating child process * refactor(util): use spawn instead of exec - delete and revert dev related changes * refactor(util): use spawn instead of exec - fix support for windows * refactor(util): use spawn instead of exec - handle SIGSTOP and such - add test coverage * refactor(util): use spawn instead of exec - now converts to strings when resolving/rejecting * refactor(util): use spawn instead of exec - logs improvements - force shell (exec like) - fix tests * refactor(util): use spawn instead of exec - strongly type listeners * refactor(util): use spawn instead of exec - create helper mock for spawn * refactor(util): use spawn instead of exec - cr changes * Update lib/util/exec/common.ts Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec - documentation * refactor(util): use spawn instead of exec - revert unnecessary formatting * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - added ExecError class * refactor(util): use spawn instead of exec - exec-error.ts restructure * refactor(util): use spawn instead of exec * Apply suggestions from code review Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - deprecated RawExecOptions.encoding property * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2022-07-22 15:43:28 +00:00
return;
}
if (code !== 0) {
reject(
new ExecError(`Command failed: ${cmd}\n${stringify(stderr)}`, {
...rejectInfo(),
exitCode: code,
})
);
feat(util/exec): use spawn instead of exec (#16414) * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - init spawn-util * refactor(util): use spawn instead of exec - spawn-util * refactor(util): use spawn instead of exec - init index-spawn.spec.ts * refactor(util): use spawn instead of exec - fixed various tests * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix npm post update imports * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff - destroy stdio when terminating child process * refactor(util): use spawn instead of exec - delete and revert dev related changes * refactor(util): use spawn instead of exec - fix support for windows * refactor(util): use spawn instead of exec - handle SIGSTOP and such - add test coverage * refactor(util): use spawn instead of exec - now converts to strings when resolving/rejecting * refactor(util): use spawn instead of exec - logs improvements - force shell (exec like) - fix tests * refactor(util): use spawn instead of exec - strongly type listeners * refactor(util): use spawn instead of exec - create helper mock for spawn * refactor(util): use spawn instead of exec - cr changes * Update lib/util/exec/common.ts Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec - documentation * refactor(util): use spawn instead of exec - revert unnecessary formatting * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - added ExecError class * refactor(util): use spawn instead of exec - exec-error.ts restructure * refactor(util): use spawn instead of exec * Apply suggestions from code review Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - deprecated RawExecOptions.encoding property * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2022-07-22 15:43:28 +00:00
return;
}
resolve({
stderr: stringify(stderr),
stdout: stringify(stdout),
});
});
function rejectInfo(): ExecErrorData {
return {
cmd: cp.spawnargs.join(' '),
options: opts,
stdout: stringify(stdout),
stderr: stringify(stderr),
};
}
});
}
function kill(cp: ChildProcess, signal: NodeJS.Signals): boolean {
try {
if (cp.pid && process.env.RENOVATE_X_EXEC_GPID_HANDLE) {
/**
* If `pid` is negative, but not `-1`, signal shall be sent to all processes
* (excluding an unspecified set of system processes),
* whose process group ID (pgid) is equal to the absolute value of pid,
* and for which the process has permission to send a signal.
*/
return process.kill(-cp.pid, signal);
} else {
// destroying stdio is needed for unref to work
// https://nodejs.org/api/child_process.html#subprocessunref
// https://github.com/nodejs/node/blob/4d5ff25a813fd18939c9f76b17e36291e3ea15c3/lib/child_process.js#L412-L426
cp.stderr?.destroy();
cp.stdout?.destroy();
cp.unref();
return cp.kill(signal);
}
feat(util/exec): use spawn instead of exec (#16414) * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - Use child_process.spawn instead of child_process.exec * refactor(util): use spawn instead of exec - init spawn-util * refactor(util): use spawn instead of exec - spawn-util * refactor(util): use spawn instead of exec - init index-spawn.spec.ts * refactor(util): use spawn instead of exec - fixed various tests * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix all artifacts.spec.ts * refactor(util): use spawn instead of exec - fix npm post update imports * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff * refactor(util): use spawn instead of exec - revert renaming to minimize PR diff - destroy stdio when terminating child process * refactor(util): use spawn instead of exec - delete and revert dev related changes * refactor(util): use spawn instead of exec - fix support for windows * refactor(util): use spawn instead of exec - handle SIGSTOP and such - add test coverage * refactor(util): use spawn instead of exec - now converts to strings when resolving/rejecting * refactor(util): use spawn instead of exec - logs improvements - force shell (exec like) - fix tests * refactor(util): use spawn instead of exec - strongly type listeners * refactor(util): use spawn instead of exec - create helper mock for spawn * refactor(util): use spawn instead of exec - cr changes * Update lib/util/exec/common.ts Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec - documentation * refactor(util): use spawn instead of exec - revert unnecessary formatting * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - added ExecError class * refactor(util): use spawn instead of exec - exec-error.ts restructure * refactor(util): use spawn instead of exec * Apply suggestions from code review Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com> * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec - deprecated RawExecOptions.encoding property * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec * refactor(util): use spawn instead of exec Co-authored-by: Sergei Zharinov <zharinov@users.noreply.github.com>
2022-07-22 15:43:28 +00:00
} catch (err) {
// cp is a single node tree, therefore -pid is invalid as there is no such pgid,
return false;
}
}
export const rawExec: (
cmd: string,
opts: RawExecOptions
) => Promise<ExecResult> = exec;