Skip to content

Commit b5fd0d9

Browse files
committed
chore: add api reference, catalogued error and tests
1 parent 49856e6 commit b5fd0d9

File tree

7 files changed

+132
-21
lines changed

7 files changed

+132
-21
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ require (
3131
github.com/oapi-codegen/oapi-codegen/v2 v2.4.1
3232
github.com/oapi-codegen/runtime v1.1.1
3333
github.com/patrickmn/go-cache v2.1.0+incompatible
34-
github.com/snyk/error-catalog-golang-public v0.0.0-20250625135845-2d6f9a31f318
34+
github.com/snyk/error-catalog-golang-public v0.0.0-20250812140843-a01d75260003
3535
github.com/subosito/gotenv v1.6.0
3636
golang.org/x/net v0.38.0
3737
golang.org/x/sync v0.13.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,8 +230,8 @@ github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnB
230230
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
231231
github.com/snyk/code-client-go v1.21.3 h1:2+HPXCA9FGn3gaI1Jw1C4Ifn/NRAbSnmohFUvz4GC4I=
232232
github.com/snyk/code-client-go v1.21.3/go.mod h1:WH6lNkJc785hfXmwhixxWHix3O6z+1zwz40oK8vl/zg=
233-
github.com/snyk/error-catalog-golang-public v0.0.0-20250625135845-2d6f9a31f318 h1:2bNOlUstBBWHa3doBvdOBlMSu8AC01IHyNexT9MoKiM=
234-
github.com/snyk/error-catalog-golang-public v0.0.0-20250625135845-2d6f9a31f318/go.mod h1:Ytttq7Pw4vOCu9NtRQaOeDU2dhBYUyNBe6kX4+nIIQ4=
233+
github.com/snyk/error-catalog-golang-public v0.0.0-20250812140843-a01d75260003 h1:qeXih9sVe/WvhccE3MfEgglnSVKN1xTQBcsA/N96Kzo=
234+
github.com/snyk/error-catalog-golang-public v0.0.0-20250812140843-a01d75260003/go.mod h1:Ytttq7Pw4vOCu9NtRQaOeDU2dhBYUyNBe6kX4+nIIQ4=
235235
github.com/snyk/go-httpauth v0.0.0-20231117135515-eb445fea7530 h1:s9PHNkL6ueYRiAKNfd8OVxlUOqU3qY0VDbgCD1f6WQY=
236236
github.com/snyk/go-httpauth v0.0.0-20231117135515-eb445fea7530/go.mod h1:88KbbvGYlmLgee4OcQ19yr0bNpXpOr2kciOthaSzCAg=
237237
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=

internal/api/api.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -249,15 +249,23 @@ func (a *snykApiClient) GetSastSettings(orgId string) (*sast_contract.SastRespon
249249
}
250250

251251
func (a *snykApiClient) GetOrgSettings(orgId string) (*contract.OrgSettingsResponse, error) {
252-
endpoint := fmt.Sprintf("/v1/org/%s/settings", url.QueryEscape(orgId))
253-
body, err := clientGet(a, endpoint, nil)
252+
endpoint := fmt.Sprintf("%s/v1/org/%s/settings", a.url, url.QueryEscape(orgId))
253+
254+
res, err := a.client.Get(endpoint)
255+
if err != nil {
256+
return nil, fmt.Errorf("unable to retrieve org settings: %w", err)
257+
}
258+
//goland:noinspection GoUnhandledErrorResult
259+
defer res.Body.Close()
260+
261+
body, err := io.ReadAll(res.Body)
254262
if err != nil {
255263
return nil, fmt.Errorf("unable to retrieve org settings: %w", err)
256264
}
257265

258266
var response contract.OrgSettingsResponse
259267
if err = json.Unmarshal(body, &response); err != nil {
260-
return nil, err
268+
return nil, fmt.Errorf("unable to retrieve org settings (status: %d): %w", res.StatusCode, err)
261269
}
262270

263271
return &response, err

internal/api/contract/OrgSettingsResponse.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package contract
22

3+
// API reference: https://docs.snyk.io/snyk-api/reference/organizations-v1#get-org-orgid-settings
4+
35
type OrgIgnoreSettings struct {
46
ReasonRequired bool `json:"reasonRequired,omitempty"`
57
AutoApproveIgnores bool `json:"autoApproveIgnores,omitempty"`

pkg/local_workflows/ignore_workflow/config.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@ func getOrgIgnoreApprovalEnabled(engine workflow.Engine) configuration.DefaultVa
6262
return nil, err
6363
}
6464

65-
if settings.Ignores == nil {
66-
return false, nil
65+
if settings.Ignores != nil && settings.Ignores.ApprovalWorkflowEnabled {
66+
return true, nil
6767
}
6868

69-
return settings.Ignores.ApprovalWorkflowEnabled, nil
69+
return false, nil
7070
}
7171
}
7272

pkg/local_workflows/ignore_workflow/ignore_workflow.go

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414

1515
"github.com/snyk/code-client-go/sarif"
1616
"github.com/snyk/error-catalog-golang-public/cli"
17-
"github.com/snyk/error-catalog-golang-public/snyk_errors"
1817

1918
policyApi "github.com/snyk/go-application-framework/internal/api/policy/2024-10-15"
2019
"github.com/snyk/go-application-framework/pkg/configuration"
@@ -104,17 +103,7 @@ func ignoreCreateWorkflowEntryPoint(invocationCtx workflow.InvocationContext, _
104103

105104
if !config.GetBool(ConfigIgnoreApprovalEnabled) {
106105
orgName := config.GetString(configuration.ORGANIZATION_SLUG)
107-
return nil, snyk_errors.Error{
108-
Type: "https://docs.snyk.io/scan-with-snyk/error-catalog#snyk-cli-0016",
109-
Title: "Feature not enabled",
110-
Description: "This feature is disabled for your current organization. You can enable it in the settings or switch to an organization where it's already enabled.",
111-
StatusCode: 403,
112-
ErrorCode: "SNYK-CLI-0016",
113-
Classification: "ACTIONABLE",
114-
Links: []string{},
115-
Level: "error",
116-
Detail: fmt.Sprintf("The Ignore Approval Workflow feature must be enabled for the %s organization. Enable it in your organization settings: Settings > General > Ignore approval workflow for Snyk Code.", orgName),
117-
}
106+
return nil, cli.NewFeatureNotEnabledError(fmt.Sprintf("The Ignore Approval Workflow feature must be enabled for the %s organization. Enable it in your organization settings: Settings > General > Ignore approval workflow for Snyk Code.", orgName))
118107
}
119108

120109
interactive := config.GetBool(InteractiveKey)

pkg/local_workflows/ignore_workflow/ignore_workflow_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import (
1717
"github.com/snyk/error-catalog-golang-public/snyk_errors"
1818
"github.com/stretchr/testify/assert"
1919

20+
"github.com/snyk/go-application-framework/internal/api/contract"
2021
policyApi "github.com/snyk/go-application-framework/internal/api/policy/2024-10-15"
2122
"github.com/snyk/go-application-framework/pkg/configuration"
2223
localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows"
@@ -705,3 +706,114 @@ func Test_getExpireValue(t *testing.T) {
705706
assert.Nil(t, result)
706707
})
707708
}
709+
710+
func Test_getOrgIgnoreApprovalEnabled(t *testing.T) {
711+
t.Run("returns existing value when not nil", func(t *testing.T) {
712+
ctrl := gomock.NewController(t)
713+
defer ctrl.Finish()
714+
715+
mockEngine := mocks.NewMockEngine(ctrl)
716+
defaultValueFunc := getOrgIgnoreApprovalEnabled(mockEngine)
717+
718+
result, err := defaultValueFunc(nil, true)
719+
assert.NoError(t, err)
720+
assert.Equal(t, true, result)
721+
722+
result, err = defaultValueFunc(nil, false)
723+
assert.NoError(t, err)
724+
assert.Equal(t, false, result)
725+
})
726+
727+
t.Run("approval workflow enabled", func(t *testing.T) {
728+
result, err := setupMockEngineForOrgSettings(t, &contract.OrgSettingsResponse{
729+
Ignores: &contract.OrgIgnoreSettings{ApprovalWorkflowEnabled: true},
730+
})
731+
732+
assert.NoError(t, err)
733+
assert.Equal(t, true, result)
734+
})
735+
736+
t.Run("approval workflow disabled", func(t *testing.T) {
737+
result, err := setupMockEngineForOrgSettings(t, &contract.OrgSettingsResponse{
738+
Ignores: &contract.OrgIgnoreSettings{ApprovalWorkflowEnabled: false},
739+
})
740+
741+
assert.NoError(t, err)
742+
assert.Equal(t, false, result)
743+
})
744+
745+
t.Run("ignores field is nil", func(t *testing.T) {
746+
result, err := setupMockEngineForOrgSettings(t, &contract.OrgSettingsResponse{
747+
Ignores: nil,
748+
})
749+
750+
assert.NoError(t, err)
751+
assert.Equal(t, false, result)
752+
})
753+
754+
t.Run("API call fails", func(t *testing.T) {
755+
ctrl := gomock.NewController(t)
756+
defer ctrl.Finish()
757+
758+
logger := zerolog.Logger{}
759+
orgId := uuid.New().String()
760+
apiUrl := "https://api.snyk.io"
761+
762+
mockEngine := mocks.NewMockEngine(ctrl)
763+
mockConfig := mocks.NewMockConfiguration(ctrl)
764+
mockNetworkAccess := mocks.NewMockNetworkAccess(ctrl)
765+
766+
httpClient := localworkflows.NewTestClient(func(req *http.Request) *http.Response {
767+
return &http.Response{
768+
StatusCode: http.StatusInternalServerError,
769+
Body: io.NopCloser(bytes.NewBufferString("Internal Server Error")),
770+
}
771+
})
772+
773+
mockEngine.EXPECT().GetConfiguration().Return(mockConfig)
774+
mockEngine.EXPECT().GetNetworkAccess().Return(mockNetworkAccess)
775+
mockEngine.EXPECT().GetLogger().Return(&logger)
776+
mockConfig.EXPECT().GetString(configuration.ORGANIZATION).Return(orgId)
777+
mockConfig.EXPECT().GetString(configuration.API_URL).Return(apiUrl)
778+
mockNetworkAccess.EXPECT().GetHttpClient().Return(httpClient)
779+
780+
defaultValueFunc := getOrgIgnoreApprovalEnabled(mockEngine)
781+
result, err := defaultValueFunc(nil, nil)
782+
783+
assert.Error(t, err)
784+
assert.Nil(t, result)
785+
assert.Contains(t, err.Error(), "unable to retrieve org settings")
786+
})
787+
}
788+
789+
func setupMockEngineForOrgSettings(t *testing.T, response *contract.OrgSettingsResponse) (interface{}, error) {
790+
t.Helper()
791+
ctrl := gomock.NewController(t)
792+
defer ctrl.Finish()
793+
794+
orgId := uuid.New().String()
795+
apiUrl := "https://api.snyk.io"
796+
797+
responseJSON, err := json.Marshal(response)
798+
assert.NoError(t, err)
799+
800+
mockEngine := mocks.NewMockEngine(ctrl)
801+
mockConfig := mocks.NewMockConfiguration(ctrl)
802+
mockNetworkAccess := mocks.NewMockNetworkAccess(ctrl)
803+
804+
httpClient := localworkflows.NewTestClient(func(req *http.Request) *http.Response {
805+
return &http.Response{
806+
StatusCode: http.StatusOK,
807+
Body: io.NopCloser(bytes.NewBuffer(responseJSON)),
808+
}
809+
})
810+
811+
mockEngine.EXPECT().GetConfiguration().Return(mockConfig)
812+
mockEngine.EXPECT().GetNetworkAccess().Return(mockNetworkAccess)
813+
mockConfig.EXPECT().GetString(configuration.ORGANIZATION).Return(orgId)
814+
mockConfig.EXPECT().GetString(configuration.API_URL).Return(apiUrl)
815+
mockNetworkAccess.EXPECT().GetHttpClient().Return(httpClient)
816+
817+
defaultValueFunc := getOrgIgnoreApprovalEnabled(mockEngine)
818+
return defaultValueFunc(nil, nil)
819+
}

0 commit comments

Comments
 (0)