From a3547633485282d621acf63c0c150ae74214384d Mon Sep 17 00:00:00 2001 From: Luke Watts Date: Tue, 28 May 2024 16:56:06 +0100 Subject: [PATCH 1/4] feat: determine exit code from data error [CLI-309] --- cliv2/cmd/cliv2/main.go | 9 ++++ cliv2/cmd/cliv2/main_test.go | 60 ++++++++++++++++++++++++++- cliv2/internal/constants/constants.go | 1 + 3 files changed, 69 insertions(+), 1 deletion(-) diff --git a/cliv2/cmd/cliv2/main.go b/cliv2/cmd/cliv2/main.go index b8d04374a2..fa62886ee4 100644 --- a/cliv2/cmd/cliv2/main.go +++ b/cliv2/cmd/cliv2/main.go @@ -213,6 +213,15 @@ func getErrorFromWorkFlowData(engine workflow.Engine, data []workflow.Data) erro } } + dataErrors := data[i].GetErrorList() + for _, dataError := range dataErrors { + if dataError.ErrorCode == "SNYK-CODE-0006" { + return &cli_errors.ErrorWithExitCode{ + ExitCode: constants.SNYK_EXIT_CODE_UNSUPPORTED_PROJECTS, + } + } + } + return nil } } diff --git a/cliv2/cmd/cliv2/main_test.go b/cliv2/cmd/cliv2/main_test.go index 66e478b137..a57a699c23 100644 --- a/cliv2/cmd/cliv2/main_test.go +++ b/cliv2/cmd/cliv2/main_test.go @@ -11,6 +11,7 @@ import ( "github.com/golang/mock/gomock" "github.com/rs/zerolog" + "github.com/snyk/error-catalog-golang-public/code" "github.com/snyk/go-application-framework/pkg/configuration" localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" "github.com/snyk/go-application-framework/pkg/local_workflows/content_type" @@ -263,7 +264,7 @@ func Test_getErrorFromWorkFlowData(t *testing.T) { assert.Equal(t, constants.SNYK_EXIT_CODE_VULNERABILITIES_FOUND, expectedError.ExitCode) }) - t.Run("workflow with empty testing findings", func(t *testing.T) { + t.Run("workflow with zero count test summary", func(t *testing.T) { workflowId := workflow.NewWorkflowIdentifier("output") workflowIdentifier := workflow.NewTypeIdentifier(workflowId, "output") d, err := json.Marshal(json_schemas.TestSummary{ @@ -280,6 +281,63 @@ func Test_getErrorFromWorkFlowData(t *testing.T) { err = getErrorFromWorkFlowData(engine, []workflow.Data{data}) assert.Nil(t, err) }) + + t.Run("workflow with empty test summary and unsupported error annotation", func(t *testing.T) { + workflowId := workflow.NewWorkflowIdentifier("output") + workflowIdentifier := workflow.NewTypeIdentifier(workflowId, "output") + d, err := json.Marshal(json_schemas.NewTestSummary("sast")) + assert.Nil(t, err) + data := workflow.NewData(workflowIdentifier, content_type.TEST_SUMMARY, d) + data.AddError(code.NewUnsupportedProjectError("")) + err = getErrorFromWorkFlowData(engine, []workflow.Data{data}) + + var expectedError *clierrors.ErrorWithExitCode + assert.ErrorAs(t, err, &expectedError) + assert.Equal(t, constants.SNYK_EXIT_CODE_UNSUPPORTED_PROJECTS, expectedError.ExitCode) + }) + + t.Run("workflow with empty testing and unsupported project error annotation", func(t *testing.T) { + workflowId := workflow.NewWorkflowIdentifier("output") + workflowIdentifier := workflow.NewTypeIdentifier(workflowId, "output") + d, err := json.Marshal(json_schemas.TestSummary{ + Results: []json_schemas.TestSummaryResult{{ + Severity: "critical", + Total: 0, + Open: 0, + Ignored: 0, + }}, + Artifacts: 0, + Type: "sast", + }) + assert.Nil(t, err) + data := workflow.NewData(workflowIdentifier, content_type.TEST_SUMMARY, d) + data.AddError(code.NewUnsupportedProjectError("")) + err = getErrorFromWorkFlowData(engine, []workflow.Data{data}) + + var expectedError *clierrors.ErrorWithExitCode + assert.ErrorAs(t, err, &expectedError) + assert.Equal(t, constants.SNYK_EXIT_CODE_UNSUPPORTED_PROJECTS, expectedError.ExitCode) + }) + + t.Run("workflow with empty testing and misc error annotation", func(t *testing.T) { + workflowId := workflow.NewWorkflowIdentifier("output") + workflowIdentifier := workflow.NewTypeIdentifier(workflowId, "output") + d, err := json.Marshal(json_schemas.TestSummary{ + Results: []json_schemas.TestSummaryResult{{ + Severity: "critical", + Total: 0, + Open: 0, + Ignored: 0, + }}, + Artifacts: 0, + Type: "sast", + }) + assert.Nil(t, err) + data := workflow.NewData(workflowIdentifier, content_type.TEST_SUMMARY, d) + data.AddError(code.NewAnalysisFileCountLimitExceededError("")) + err = getErrorFromWorkFlowData(engine, []workflow.Data{data}) + assert.NoError(t, err) + }) } func Test_runWorkflowAndProcessData(t *testing.T) { diff --git a/cliv2/internal/constants/constants.go b/cliv2/internal/constants/constants.go index fa01a6b831..ffc2d0783b 100644 --- a/cliv2/internal/constants/constants.go +++ b/cliv2/internal/constants/constants.go @@ -3,6 +3,7 @@ package constants const SNYK_EXIT_CODE_OK = 0 const SNYK_EXIT_CODE_VULNERABILITIES_FOUND = 1 const SNYK_EXIT_CODE_ERROR = 2 +const SNYK_EXIT_CODE_UNSUPPORTED_PROJECTS = 3 const SNYK_EXIT_CODE_EX_UNAVAILABLE = 69 const SNYK_INTEGRATION_NAME = "CLI_V1_PLUGIN" const SNYK_INTEGRATION_NAME_ENV = "SNYK_INTEGRATION_NAME" From 5f9a02bd97701f27cc91d7213ae4863d6173d145 Mon Sep 17 00:00:00 2001 From: Luke Watts Date: Wed, 29 May 2024 12:15:17 +0100 Subject: [PATCH 2/4] test: remove unused test --- cliv2/cmd/cliv2/main_test.go | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/cliv2/cmd/cliv2/main_test.go b/cliv2/cmd/cliv2/main_test.go index a57a699c23..889ff6cd33 100644 --- a/cliv2/cmd/cliv2/main_test.go +++ b/cliv2/cmd/cliv2/main_test.go @@ -296,29 +296,6 @@ func Test_getErrorFromWorkFlowData(t *testing.T) { assert.Equal(t, constants.SNYK_EXIT_CODE_UNSUPPORTED_PROJECTS, expectedError.ExitCode) }) - t.Run("workflow with empty testing and unsupported project error annotation", func(t *testing.T) { - workflowId := workflow.NewWorkflowIdentifier("output") - workflowIdentifier := workflow.NewTypeIdentifier(workflowId, "output") - d, err := json.Marshal(json_schemas.TestSummary{ - Results: []json_schemas.TestSummaryResult{{ - Severity: "critical", - Total: 0, - Open: 0, - Ignored: 0, - }}, - Artifacts: 0, - Type: "sast", - }) - assert.Nil(t, err) - data := workflow.NewData(workflowIdentifier, content_type.TEST_SUMMARY, d) - data.AddError(code.NewUnsupportedProjectError("")) - err = getErrorFromWorkFlowData(engine, []workflow.Data{data}) - - var expectedError *clierrors.ErrorWithExitCode - assert.ErrorAs(t, err, &expectedError) - assert.Equal(t, constants.SNYK_EXIT_CODE_UNSUPPORTED_PROJECTS, expectedError.ExitCode) - }) - t.Run("workflow with empty testing and misc error annotation", func(t *testing.T) { workflowId := workflow.NewWorkflowIdentifier("output") workflowIdentifier := workflow.NewTypeIdentifier(workflowId, "output") From 2aedc2e5c5a1c6877d650860db350a6ffb8e1487 Mon Sep 17 00:00:00 2001 From: Luke Watts Date: Wed, 29 May 2024 12:52:43 +0100 Subject: [PATCH 3/4] chore(deps): bump GAF to include error handling behaviour --- cliv2/go.mod | 4 ++-- cliv2/go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cliv2/go.mod b/cliv2/go.mod index 6c78095c5a..d6600182a3 100644 --- a/cliv2/go.mod +++ b/cliv2/go.mod @@ -14,7 +14,8 @@ require ( github.com/snyk/cli-extension-iac-rules v0.0.0-20240422133948-ae17a4306672 github.com/snyk/cli-extension-sbom v0.0.0-20240523084359-a2830fadb001 github.com/snyk/container-cli v0.0.0-20240322120441-6d9b9482f9b1 - github.com/snyk/go-application-framework v0.0.0-20240528170035-ab13975bf74d + github.com/snyk/error-catalog-golang-public v0.0.0-20240527112826-2b77438d25f1 + github.com/snyk/go-application-framework v0.0.0-20240529115017-973f3ab671e4 github.com/snyk/go-httpauth v0.0.0-20240307114523-1f5ea3f55c65 github.com/snyk/snyk-iac-capture v0.6.5 github.com/snyk/snyk-ls v0.0.0-20240524141328-ca2e2955918a @@ -150,7 +151,6 @@ require ( github.com/shirou/gopsutil v3.21.11+incompatible // indirect github.com/skeema/knownhosts v1.2.2 // indirect github.com/snyk/code-client-go v1.6.1 // indirect - github.com/snyk/error-catalog-golang-public v0.0.0-20240425141803-2516e42296c3 // indirect github.com/snyk/policy-engine v0.30.11 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/sourcegraph/go-lsp v0.0.0-20240223163137-f80c5dd31dfd // indirect diff --git a/cliv2/go.sum b/cliv2/go.sum index e67a60f28b..1a69b50443 100644 --- a/cliv2/go.sum +++ b/cliv2/go.sum @@ -729,10 +729,10 @@ github.com/snyk/code-client-go v1.6.1 h1:wCCcsTLsk5ZAUwwAHiU35/hmmYzJ5lgFbcJ1fOk github.com/snyk/code-client-go v1.6.1/go.mod h1:Kkr7pQc8ItsBZSYd6A1S4r4VHO6HNyTWZsqi18sAtwQ= github.com/snyk/container-cli v0.0.0-20240322120441-6d9b9482f9b1 h1:9RKY9NdX5DrJAoVXDP0JiqrXT+4Nb9NH8pjEcA0NsLA= github.com/snyk/container-cli v0.0.0-20240322120441-6d9b9482f9b1/go.mod h1:38w+dcAQp9eG3P5t2eNS9eG0reut10AeJjLv5lJ5lpM= -github.com/snyk/error-catalog-golang-public v0.0.0-20240425141803-2516e42296c3 h1:ZUaY5LIVGQ0GScf1SsaqvUxaiGbBKgBBLsQUgB4Zx5o= -github.com/snyk/error-catalog-golang-public v0.0.0-20240425141803-2516e42296c3/go.mod h1:Ytttq7Pw4vOCu9NtRQaOeDU2dhBYUyNBe6kX4+nIIQ4= -github.com/snyk/go-application-framework v0.0.0-20240528170035-ab13975bf74d h1:OChBTTRBxQe455GQ0Sbyh6KybHCkk6bQltMCdURUeYc= -github.com/snyk/go-application-framework v0.0.0-20240528170035-ab13975bf74d/go.mod h1:ZMl89wenxt+xaRtHvI2uvWwVJjFPv3b5qzT3w+batgQ= +github.com/snyk/error-catalog-golang-public v0.0.0-20240527112826-2b77438d25f1 h1:49X/bTeiWdi+DrkTbTSw5BePpQ6LiucIt++/Z+MB95U= +github.com/snyk/error-catalog-golang-public v0.0.0-20240527112826-2b77438d25f1/go.mod h1:Ytttq7Pw4vOCu9NtRQaOeDU2dhBYUyNBe6kX4+nIIQ4= +github.com/snyk/go-application-framework v0.0.0-20240529115017-973f3ab671e4 h1:5xMDDbXOLhF8ga48Xs388Wk3LhldGW6Hl1VXimw1It8= +github.com/snyk/go-application-framework v0.0.0-20240529115017-973f3ab671e4/go.mod h1:1T6hnPUgT0lJPO0g3VjwvW0fCKDcgst8bgXs+wCfmW8= github.com/snyk/go-httpauth v0.0.0-20240307114523-1f5ea3f55c65 h1:CEQuYv0Go6MEyRCD3YjLYM2u3Oxkx8GpCpFBd4rUTUk= github.com/snyk/go-httpauth v0.0.0-20240307114523-1f5ea3f55c65/go.mod h1:88KbbvGYlmLgee4OcQ19yr0bNpXpOr2kciOthaSzCAg= github.com/snyk/policy-engine v0.30.11 h1:wUy5LMar2vccMbNM62MSBRdjAQAhAbIm7aNXXO+g2tk= From 00ccc9486985f28992f34945fceee56e4d04d62e Mon Sep 17 00:00:00 2001 From: Luke Watts Date: Wed, 29 May 2024 17:51:15 +0100 Subject: [PATCH 4/4] fix: wrap errors for use in presentation --- cliv2/cmd/cliv2/main.go | 7 +++---- cliv2/cmd/cliv2/main_test.go | 14 ++++++++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/cliv2/cmd/cliv2/main.go b/cliv2/cmd/cliv2/main.go index fa62886ee4..7f1b86da7b 100644 --- a/cliv2/cmd/cliv2/main.go +++ b/cliv2/cmd/cliv2/main.go @@ -216,9 +216,9 @@ func getErrorFromWorkFlowData(engine workflow.Engine, data []workflow.Data) erro dataErrors := data[i].GetErrorList() for _, dataError := range dataErrors { if dataError.ErrorCode == "SNYK-CODE-0006" { - return &cli_errors.ErrorWithExitCode{ + return errors.Join(dataError, &cli_errors.ErrorWithExitCode{ ExitCode: constants.SNYK_EXIT_CODE_UNSUPPORTED_PROJECTS, - } + }) } } @@ -404,9 +404,8 @@ func handleError(err error) HandleError { func displayError(err error, userInterface ui.UserInterface, config configuration.Configuration) { if err != nil { - var exitCode *cli_errors.ErrorWithExitCode _, isExitError := err.(*exec.ExitError) - isErrorWithCode := errors.As(err, &exitCode) + _, isErrorWithCode := err.(*cli_errors.ErrorWithExitCode) if isExitError || isErrorWithCode { return } diff --git a/cliv2/cmd/cliv2/main_test.go b/cliv2/cmd/cliv2/main_test.go index 889ff6cd33..1c3c7da89e 100644 --- a/cliv2/cmd/cliv2/main_test.go +++ b/cliv2/cmd/cliv2/main_test.go @@ -12,6 +12,7 @@ import ( "github.com/golang/mock/gomock" "github.com/rs/zerolog" "github.com/snyk/error-catalog-golang-public/code" + "github.com/snyk/error-catalog-golang-public/snyk_errors" "github.com/snyk/go-application-framework/pkg/configuration" localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" "github.com/snyk/go-application-framework/pkg/local_workflows/content_type" @@ -288,12 +289,17 @@ func Test_getErrorFromWorkFlowData(t *testing.T) { d, err := json.Marshal(json_schemas.NewTestSummary("sast")) assert.Nil(t, err) data := workflow.NewData(workflowIdentifier, content_type.TEST_SUMMARY, d) - data.AddError(code.NewUnsupportedProjectError("")) + expectedCodeErr := code.NewUnsupportedProjectError("") + data.AddError(expectedCodeErr) err = getErrorFromWorkFlowData(engine, []workflow.Data{data}) - var expectedError *clierrors.ErrorWithExitCode - assert.ErrorAs(t, err, &expectedError) - assert.Equal(t, constants.SNYK_EXIT_CODE_UNSUPPORTED_PROJECTS, expectedError.ExitCode) + var actualError *clierrors.ErrorWithExitCode + var actualSnykCatalogError snyk_errors.Error + assert.ErrorAs(t, err, &actualError) + assert.ErrorAs(t, err, &actualSnykCatalogError) + + assert.Equal(t, expectedCodeErr, actualSnykCatalogError) + assert.Equal(t, constants.SNYK_EXIT_CODE_UNSUPPORTED_PROJECTS, actualError.ExitCode) }) t.Run("workflow with empty testing and misc error annotation", func(t *testing.T) {