From 9fde4fec680f2ae0650baf6b1cfed5908984e9ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Scha=CC=88fer?= <101886095+PeterSchafer@users.noreply.github.com> Date: Wed, 24 Jul 2024 12:03:56 +0200 Subject: [PATCH] fix: map subprocess errors to exit code 2 and improve logging --- cliv2/cmd/cliv2/main.go | 2 +- cliv2/internal/cliv2/cliv2.go | 4 ++++ src/cli/commands/woof/getWoof.ts | 9 +++++++++ test/jest/acceptance/exitcode.spec.ts | 21 +++++++++++++++++++++ 4 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test/jest/acceptance/exitcode.spec.ts diff --git a/cliv2/cmd/cliv2/main.go b/cliv2/cmd/cliv2/main.go index 67eca31c9f..b9778aa946 100644 --- a/cliv2/cmd/cliv2/main.go +++ b/cliv2/cmd/cliv2/main.go @@ -558,7 +558,7 @@ func MainWithErrorCode() int { displayError(err, globalEngine.GetUserInterface(), globalConfiguration) exitCode := cliv2.DeriveExitCode(err) - globalLogger.Printf("Exiting with %d", exitCode) + globalLogger.Printf("Exiting with %d (cause: %v)", exitCode, err) targetId, targetIdError := instrumentation.GetTargetId(globalConfiguration.GetString(configuration.INPUT_DIRECTORY), instrumentation.AutoDetectedTargetId, instrumentation.WithConfiguredRepository(globalConfiguration)) if targetIdError != nil { diff --git a/cliv2/internal/cliv2/cliv2.go b/cliv2/internal/cliv2/cliv2.go index 020e9cbddf..2ab8d77b81 100644 --- a/cliv2/internal/cliv2/cliv2.go +++ b/cliv2/internal/cliv2/cliv2.go @@ -527,6 +527,10 @@ func DeriveExitCode(err error) int { if errors.As(err, &exitError) { returnCode = exitError.ExitCode() + // map errors in subprocesses to exit code 2 to remain the documented exit code range + if returnCode < 0 { + returnCode = constants.SNYK_EXIT_CODE_ERROR + } } else if errors.Is(err, context.DeadlineExceeded) { returnCode = constants.SNYK_EXIT_CODE_EX_UNAVAILABLE } else if errors.As(err, &errorWithExitCode) { diff --git a/src/cli/commands/woof/getWoof.ts b/src/cli/commands/woof/getWoof.ts index 14751adc91..af6c78dc5a 100644 --- a/src/cli/commands/woof/getWoof.ts +++ b/src/cli/commands/woof/getWoof.ts @@ -37,6 +37,15 @@ export default function getWoof(args: MethodArgs): string { if (previewFeaturesEnabled()) { console.debug('This is a previewoof!'); } + + if (options['exit-code'] != undefined) { + const exitCode = Number(options['exit-code']); + if (exitCode < 0) { + process.abort(); + } else { + process.exit(exitCode); + } + } } return woofs[lang]; diff --git a/test/jest/acceptance/exitcode.spec.ts b/test/jest/acceptance/exitcode.spec.ts new file mode 100644 index 0000000000..2d855786e9 --- /dev/null +++ b/test/jest/acceptance/exitcode.spec.ts @@ -0,0 +1,21 @@ +import { runSnykCLI } from '../util/runSnykCLI'; + +jest.setTimeout(1000 * 60); + +describe('exit code behaviour', () => { + it.each([ + { input: 0, expected: 0 }, + { input: 1, expected: 1 }, + { input: 2, expected: 2 }, + { input: 3, expected: 3 }, + { input: -1, expected: 2 }, + ])( + 'map legacy cli exit code $input to $expected', + async ({ input, expected }) => { + const { code } = await runSnykCLI( + `woof --exit-code=${input} --language=cat -d`, + ); + expect(code).toEqual(expected); + }, + ); +});