Skip to content

Commit

Permalink
fix(amplify-cli-core): gracefully handle execa race condition (#13692)
Browse files Browse the repository at this point in the history
  • Loading branch information
rtpascual authored Apr 3, 2024
1 parent 47e4100 commit dcafcb2
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -178,4 +178,40 @@ describe('hooksExecutioner tests', () => {
duplicateErrorThrown,
);
});

test('should not exit process if execa fails with exitCode being 0', async () => {
const execaMock = execa as jest.Mocked<typeof execa>;
(execaMock as any).mockReturnValue({
exitCode: 0,
errNo: -32,
code: 'EPIPE',
syscall: 'write',
originalMessage: 'write EPIPE',
shortMessage: 'Command failed with EPIPE',
escapedCommand: 'testCommand',
stderr: '',
failed: true,
timedOut: false,
isCanceled: false,
killed: false,
});
const processExitMock = jest.spyOn(process, 'exit').mockImplementation(() => undefined as never);
await executeHooks(HooksMeta.getInstance({ command: 'add', plugin: 'auth' } as CommandLineInput, 'pre'));
expect(processExitMock).toBeCalledTimes(0);
});

test('should exit process with exit code 76 if execa fails with exitCode other than 0', async () => {
const execaMock = execa as jest.Mocked<typeof execa>;
(execaMock as any).mockReturnValue({
exitCode: 1,
stderr: '',
failed: true,
timedOut: false,
isCanceled: false,
killed: false,
});
const processExitMock = jest.spyOn(process, 'exit').mockImplementation(() => undefined as never);
await executeHooks(HooksMeta.getInstance({ command: 'add', plugin: 'auth' } as CommandLineInput, 'pre'));
expect(processExitMock).toBeCalledWith(76);
});
});
10 changes: 9 additions & 1 deletion packages/amplify-cli-core/src/hooks/hooksExecutor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,17 @@ const execHelper = async (
error: errorParameter,
}),
stripFinalNewline: false,
stdout: 'inherit',
// added to do further checks before throwing due to EPIPE error
reject: false,
});
childProcess?.stdout?.pipe(process.stdout);
const childProcessResult = await childProcess;

// throw if child process ended with anything other than exitCode 0
if (childProcessResult && childProcess.exitCode !== 0) {
throw childProcessResult;
}

if (!childProcessResult?.stdout?.endsWith(EOL)) {
printer.blankLine();
}
Expand Down

0 comments on commit dcafcb2

Please sign in to comment.