From 95b03a5cd433070160e38ee3623cdc26635a537f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Peter=20Scha=CC=88fer?= <101886095+PeterSchafer@users.noreply.github.com> Date: Tue, 28 Jan 2025 18:31:08 +0100 Subject: [PATCH] chore: add generic catalog error for generic golang error --- cliv2/cmd/cliv2/errorhandling.go | 34 ++++++++++++++ cliv2/cmd/cliv2/errorhandling_test.go | 47 +++++++++++++++++++ cliv2/cmd/cliv2/main.go | 7 ++- .../snyk-sbom-test/all-projects.spec.ts | 2 +- .../acceptance/snyk-sbom/npm-options.spec.ts | 4 +- test/jest/acceptance/snyk-sbom/sbom.spec.ts | 2 +- 6 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 cliv2/cmd/cliv2/errorhandling.go create mode 100644 cliv2/cmd/cliv2/errorhandling_test.go diff --git a/cliv2/cmd/cliv2/errorhandling.go b/cliv2/cmd/cliv2/errorhandling.go new file mode 100644 index 0000000000..43a5058e14 --- /dev/null +++ b/cliv2/cmd/cliv2/errorhandling.go @@ -0,0 +1,34 @@ +package main + +import ( + "errors" + "os/exec" + + "github.com/snyk/error-catalog-golang-public/cli" + "github.com/snyk/error-catalog-golang-public/snyk_errors" + + cli_errors "github.com/snyk/cli/cliv2/internal/errors" +) + +// decorate generic errors that do not contain Error-Catalog Errors +func decorateError(err error) error { + if err == nil { + return nil + } + + if _, isExitError := err.(*exec.ExitError); isExitError { + return err + } + + if _, isErrorWithCode := err.(*cli_errors.ErrorWithExitCode); isErrorWithCode { + return err + } + + var errorCatalogError snyk_errors.Error + if !errors.As(err, &errorCatalogError) { + genericError := cli.NewGeneralCLIFailureError(err.Error()) + genericError.StatusCode = 0 + err = errors.Join(err, genericError) + } + return err +} diff --git a/cliv2/cmd/cliv2/errorhandling_test.go b/cliv2/cmd/cliv2/errorhandling_test.go new file mode 100644 index 0000000000..c5978e6573 --- /dev/null +++ b/cliv2/cmd/cliv2/errorhandling_test.go @@ -0,0 +1,47 @@ +package main + +import ( + "errors" + "os" + "os/exec" + "testing" + + "github.com/stretchr/testify/assert" + + "github.com/snyk/error-catalog-golang-public/cli" + + cli_errors "github.com/snyk/cli/cliv2/internal/errors" +) + +func Test_decorateError(t *testing.T) { + t.Run("is nil error", func(t *testing.T) { + assert.Nil(t, decorateError(nil)) + }) + + t.Run("is ErrorWithExitCode", func(t *testing.T) { + err := &cli_errors.ErrorWithExitCode{ + ExitCode: 2, + } + assert.Equal(t, err, decorateError(err)) + }) + + t.Run("is ExitError", func(t *testing.T) { + err := &exec.ExitError{ + ProcessState: &os.ProcessState{}, + } + assert.Equal(t, err, decorateError(err)) + }) + + t.Run("is already error catalog error", func(t *testing.T) { + err := cli.NewConnectionTimeoutError("") + assert.Equal(t, err, decorateError(err)) + }) + + t.Run("is a generic error", func(t *testing.T) { + err := errors.New("generic error") + actualErrr := decorateError(err) + expectedError := cli.NewGeneralCLIFailureError("") + assert.ErrorIs(t, actualErrr, err) + assert.ErrorAs(t, actualErrr, &expectedError) + }) +} diff --git a/cliv2/cmd/cliv2/main.go b/cliv2/cmd/cliv2/main.go index 2b11fd275d..12028bcc67 100644 --- a/cliv2/cmd/cliv2/main.go +++ b/cliv2/cmd/cliv2/main.go @@ -20,8 +20,6 @@ import ( "github.com/snyk/cli-extension-dep-graph/pkg/depgraph" "github.com/snyk/cli-extension-iac-rules/iacrules" "github.com/snyk/cli-extension-sbom/pkg/sbom" - "github.com/snyk/cli/cliv2/internal/cliv2" - "github.com/snyk/cli/cliv2/internal/constants" "github.com/snyk/container-cli/pkg/container" "github.com/snyk/go-application-framework/pkg/analytics" "github.com/snyk/go-application-framework/pkg/app" @@ -32,6 +30,9 @@ import ( "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/snyk/cli/cliv2/internal/cliv2" + "github.com/snyk/cli/cliv2/internal/constants" + localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" "github.com/snyk/go-application-framework/pkg/local_workflows/content_type" "github.com/snyk/go-application-framework/pkg/local_workflows/json_schemas" @@ -592,6 +593,8 @@ func MainWithErrorCode() (int, []error) { } if err != nil { + err = decorateError(err) + errorList = append(errorList, err) for _, tempError := range errorList { cliAnalytics.AddError(tempError) diff --git a/test/jest/acceptance/snyk-sbom-test/all-projects.spec.ts b/test/jest/acceptance/snyk-sbom-test/all-projects.spec.ts index 3c7fb8c5a4..da33ee76c5 100644 --- a/test/jest/acceptance/snyk-sbom-test/all-projects.spec.ts +++ b/test/jest/acceptance/snyk-sbom-test/all-projects.spec.ts @@ -130,7 +130,7 @@ describe('snyk sbom test (mocked server only)', () => { { env }, ); - expect(stdout).toMatch( + expect(stdout).toContainText( 'Flag `--file` is required to execute this command. Value should point to a valid SBOM document.', ); diff --git a/test/jest/acceptance/snyk-sbom/npm-options.spec.ts b/test/jest/acceptance/snyk-sbom/npm-options.spec.ts index b3f150e9ef..a8719509a8 100644 --- a/test/jest/acceptance/snyk-sbom/npm-options.spec.ts +++ b/test/jest/acceptance/snyk-sbom/npm-options.spec.ts @@ -67,10 +67,10 @@ describe('snyk sbom: npm options (mocked server only)', () => { ); expect(code).toEqual(2); - expect(stdout).toContain( + expect(stdout).toContainText( 'An error occurred while running the underlying analysis needed to generate the SBOM.', ); - expect(stderr).toContain( + expect(stderr).toContainText( 'OutOfSyncError: Dependency snyk was not found in package-lock.json.', ); }); diff --git a/test/jest/acceptance/snyk-sbom/sbom.spec.ts b/test/jest/acceptance/snyk-sbom/sbom.spec.ts index 13814ef1d1..055dd1c587 100644 --- a/test/jest/acceptance/snyk-sbom/sbom.spec.ts +++ b/test/jest/acceptance/snyk-sbom/sbom.spec.ts @@ -211,7 +211,7 @@ describe('snyk sbom (mocked server only)', () => { ); expect(code).toBe(3); - expect(stdout).toContain( + expect(stdout).toContainText( 'An error occurred while running the underlying analysis needed to generate the SBOM.', ); });