Skip to content

Commit 20955bf

Browse files
feat: read snyk code timeout from config [IDE-399] (#56)
1 parent 9beb7fa commit 20955bf

File tree

6 files changed

+59
-37
lines changed

6 files changed

+59
-37
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11

2+
23
# code-client-go
34

45
A library that exposes scanning capabilities for Snyk Code that can be used in the [Snyk CLI](https://github.com/snyk/cli) as well as Snyk IDE plugins using the [Snyk Language Server](https://github.com/snyk/snyk-ls).

config/config.go

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

3+
import "time"
4+
35
// Config defines the configurable options for the HTTP client.
46
//
57
//go:generate mockgen -destination=mocks/config.go -source=config.go -package mocks
@@ -19,4 +21,7 @@ type Config interface {
1921

2022
// SnykApi returns the Snyk REST API URL configured to run against,
2123
SnykApi() string
24+
25+
// SnykCodeAnalysisTimeout returns the timeout for analysis
26+
SnykCodeAnalysisTimeout() time.Duration
2227
}

config/mocks/config.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/analysis/analysis.go

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,13 @@ type AnalysisOrchestrator interface {
5151
}
5252

5353
type analysisOrchestrator struct {
54-
httpClient codeClientHTTP.HTTPClient
55-
instrumentor observability.Instrumentor
56-
errorReporter observability.ErrorReporter
57-
logger *zerolog.Logger
58-
trackerFactory scan.TrackerFactory
59-
config config.Config
60-
timeoutInSeconds time.Duration
61-
flow scans.Flow
54+
httpClient codeClientHTTP.HTTPClient
55+
instrumentor observability.Instrumentor
56+
errorReporter observability.ErrorReporter
57+
logger *zerolog.Logger
58+
trackerFactory scan.TrackerFactory
59+
config config.Config
60+
flow scans.Flow
6261
}
6362

6463
type OptionFunc func(*analysisOrchestrator)
@@ -87,12 +86,6 @@ func WithTrackerFactory(factory scan.TrackerFactory) func(*analysisOrchestrator)
8786
}
8887
}
8988

90-
func WithTimeoutInSeconds(timeoutInSeconds time.Duration) func(*analysisOrchestrator) {
91-
return func(a *analysisOrchestrator) {
92-
a.timeoutInSeconds = timeoutInSeconds
93-
}
94-
}
95-
9689
func WithFlow(flow string) func(*analysisOrchestrator) {
9790
return func(a *analysisOrchestrator) {
9891
a.flow = scans.Flow{}
@@ -110,14 +103,13 @@ func NewAnalysisOrchestrator(
110103
_ = flow.UnmarshalJSON([]byte(fmt.Sprintf(`{"name": "%s"}`, scans.IdeTest)))
111104

112105
a := &analysisOrchestrator{
113-
httpClient: httpClient,
114-
config: config,
115-
instrumentor: observability.NewInstrumentor(),
116-
trackerFactory: scan.NewNoopTrackerFactory(),
117-
errorReporter: observability.NewErrorReporter(&nopLogger),
118-
logger: &nopLogger,
119-
timeoutInSeconds: 120 * time.Second,
120-
flow: flow,
106+
httpClient: httpClient,
107+
config: config,
108+
instrumentor: observability.NewInstrumentor(),
109+
trackerFactory: scan.NewNoopTrackerFactory(),
110+
errorReporter: observability.NewErrorReporter(&nopLogger),
111+
logger: &nopLogger,
112+
flow: flow,
121113
}
122114

123115
for _, option := range options {
@@ -354,7 +346,7 @@ func (a *analysisOrchestrator) pollScanForFindings(ctx context.Context, client *
354346

355347
pollingTicker := time.NewTicker(1 * time.Second)
356348
defer pollingTicker.Stop()
357-
timeoutTimer := time.NewTimer(a.timeoutInSeconds)
349+
timeoutTimer := time.NewTimer(a.config.SnykCodeAnalysisTimeout())
358350
defer timeoutTimer.Stop()
359351
for {
360352
select {

internal/analysis/analysis_test.go

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import (
4141
trackerMocks "github.com/snyk/code-client-go/scan/mocks"
4242
)
4343

44-
func setup(t *testing.T) (*confMocks.MockConfig, *httpmocks.MockHTTPClient, *mocks.MockInstrumentor, *mocks.MockErrorReporter, *trackerMocks.MockTracker, *trackerMocks.MockTrackerFactory, zerolog.Logger) {
44+
func setup(t *testing.T, timeout *time.Duration) (*confMocks.MockConfig, *httpmocks.MockHTTPClient, *mocks.MockInstrumentor, *mocks.MockErrorReporter, *trackerMocks.MockTracker, *trackerMocks.MockTrackerFactory, zerolog.Logger) {
4545
t.Helper()
4646
ctrl := gomock.NewController(t)
4747
mockSpan := mocks.NewMockSpan(ctrl)
@@ -50,6 +50,11 @@ func setup(t *testing.T) (*confMocks.MockConfig, *httpmocks.MockHTTPClient, *moc
5050
mockConfig := confMocks.NewMockConfig(ctrl)
5151
mockConfig.EXPECT().Organization().AnyTimes().Return("")
5252
mockConfig.EXPECT().SnykApi().AnyTimes().Return("http://localhost")
53+
if timeout == nil {
54+
defaultTimeout := 120 * time.Second
55+
timeout = &defaultTimeout
56+
}
57+
mockConfig.EXPECT().SnykCodeAnalysisTimeout().AnyTimes().Return(*timeout)
5358

5459
mockHTTPClient := httpmocks.NewMockHTTPClient(ctrl)
5560

@@ -66,7 +71,7 @@ func setup(t *testing.T) (*confMocks.MockConfig, *httpmocks.MockHTTPClient, *moc
6671
}
6772

6873
func TestAnalysis_CreateWorkspace(t *testing.T) {
69-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
74+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
7075

7176
mockTracker.EXPECT().Begin(gomock.Eq("Creating file bundle workspace"), gomock.Eq("")).Return()
7277
mockTracker.EXPECT().End(gomock.Eq("")).Return()
@@ -109,7 +114,7 @@ func TestAnalysis_CreateWorkspace(t *testing.T) {
109114
}
110115

111116
func TestAnalysis_CreateWorkspace_NotARepository(t *testing.T) {
112-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
117+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
113118

114119
mockTracker.EXPECT().Begin(gomock.Eq("Creating file bundle workspace"), gomock.Eq("")).Return()
115120
mockTracker.EXPECT().End(gomock.Eq("")).Return()
@@ -155,7 +160,7 @@ func TestAnalysis_CreateWorkspace_NotARepository(t *testing.T) {
155160
}
156161

157162
func TestAnalysis_CreateWorkspace_Failure(t *testing.T) {
158-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
163+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
159164

160165
mockTracker.EXPECT().Begin(gomock.Eq("Creating file bundle workspace"), gomock.Eq("")).Return()
161166
mockTracker.EXPECT().End(gomock.Eq("")).Return()
@@ -291,7 +296,7 @@ func TestAnalysis_CreateWorkspace_KnownErrors(t *testing.T) {
291296
var fakeResponse []byte
292297

293298
func TestAnalysis_RunAnalysis(t *testing.T) {
294-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
299+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
295300

296301
mockTracker.EXPECT().Begin(gomock.Eq("Snyk Code analysis for rootPath"), gomock.Eq("Retrieving results...")).Return()
297302
mockTracker.EXPECT().End(gomock.Eq("Analysis complete.")).Return()
@@ -338,15 +343,14 @@ func TestAnalysis_RunAnalysis(t *testing.T) {
338343
analysis.WithErrorReporter(mockErrorReporter),
339344
)
340345

341-
analysis.WithTimeoutInSeconds(120 * time.Second)
342346
actual, err := analysisOrchestrator.RunAnalysis(context.Background(), "b6fc8954-5918-45ce-bc89-54591815ce1b", "rootPath", "c172d1db-b465-4764-99e1-ecedad03b06a")
343347

344348
require.NoError(t, err)
345349
assert.Equal(t, "scripts/db/migrations/20230811153738_add_generated_grouping_columns_to_collections_table.ts", actual.Sarif.Runs[0].Results[0].Locations[0].PhysicalLocation.ArtifactLocation.URI)
346350
}
347351

348352
func TestAnalysis_RunAnalysis_TriggerFunctionError(t *testing.T) {
349-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
353+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
350354

351355
mockTracker.EXPECT().Begin(gomock.Eq("Snyk Code analysis for rootPath"), gomock.Eq("Retrieving results...")).Return()
352356
mockTracker.EXPECT().End(gomock.Eq("Analysis failed: failed to trigger scan: error")).Return()
@@ -412,7 +416,7 @@ func TestAnalysis_RunAnalysis_TriggerFunctionErrorCodes(t *testing.T) {
412416

413417
for _, tc := range testCases {
414418
t.Run(tc.name, func(t *testing.T) {
415-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
419+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
416420

417421
mockTracker.EXPECT().Begin(gomock.Eq("Snyk Code analysis for rootPath"), gomock.Eq("Retrieving results...")).Return()
418422
mockTracker.EXPECT().End(gomock.Eq("Analysis failed: failed to trigger scan: " + tc.expectedError)).Return()
@@ -439,7 +443,7 @@ func TestAnalysis_RunAnalysis_TriggerFunctionErrorCodes(t *testing.T) {
439443
}
440444

441445
func TestAnalysis_RunAnalysis_PollingFunctionError(t *testing.T) {
442-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
446+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
443447

444448
mockTracker.EXPECT().Begin(gomock.Eq("Snyk Code analysis for rootPath"), gomock.Eq("Retrieving results...")).Return()
445449
mockTracker.EXPECT().End(gomock.Eq("Analysis failed: error")).Return()
@@ -517,7 +521,7 @@ func TestAnalysis_RunAnalysis_PollingFunctionErrorCodes(t *testing.T) {
517521

518522
for _, tc := range testCases {
519523
t.Run(tc.name, func(t *testing.T) {
520-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
524+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
521525

522526
mockTracker.EXPECT().Begin(gomock.Eq("Snyk Code analysis for rootPath"), gomock.Eq("Retrieving results...")).Return()
523527
mockTracker.EXPECT().End(gomock.Eq("Analysis failed: " + tc.expectedError)).Return()
@@ -556,7 +560,8 @@ func TestAnalysis_RunAnalysis_PollingFunctionErrorCodes(t *testing.T) {
556560
}
557561

558562
func TestAnalysis_RunAnalysis_PollingFunctionTimeout(t *testing.T) {
559-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
563+
timeout := 1 * time.Second
564+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, &timeout)
560565

561566
mockTracker.EXPECT().Begin(gomock.Eq("Snyk Code analysis for rootPath"), gomock.Eq("Retrieving results...")).Return()
562567
mockTracker.EXPECT().End(gomock.Eq("Analysis failed: Snyk Code analysis timed out")).Return()
@@ -593,15 +598,14 @@ func TestAnalysis_RunAnalysis_PollingFunctionTimeout(t *testing.T) {
593598
analysis.WithInstrumentor(mockInstrumentor),
594599
analysis.WithTrackerFactory(mockTrackerFactory),
595600
analysis.WithErrorReporter(mockErrorReporter),
596-
analysis.WithTimeoutInSeconds(1*time.Second),
597601
)
598602

599603
_, err := analysisOrchestrator.RunAnalysis(context.Background(), "b6fc8954-5918-45ce-bc89-54591815ce1b", "rootPath", "c172d1db-b465-4764-99e1-ecedad03b06a")
600604
assert.ErrorContains(t, err, "Snyk Code analysis timed out")
601605
}
602606

603607
func TestAnalysis_RunAnalysis_GetFindingsError(t *testing.T) {
604-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
608+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
605609

606610
mockTracker.EXPECT().Begin(gomock.Eq("Snyk Code analysis for rootPath"), gomock.Eq("Retrieving results...")).Return()
607611
mockTracker.EXPECT().End(gomock.Eq("Analysis failed: error")).Return()
@@ -649,7 +653,7 @@ func TestAnalysis_RunAnalysis_GetFindingsError(t *testing.T) {
649653
require.ErrorContains(t, err, "error")
650654
}
651655
func TestAnalysis_RunAnalysis_GetFindingsNotSuccessful(t *testing.T) {
652-
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t)
656+
mockConfig, mockHTTPClient, mockInstrumentor, mockErrorReporter, mockTracker, mockTrackerFactory, logger := setup(t, nil)
653657

654658
mockTracker.EXPECT().Begin(gomock.Eq("Snyk Code analysis for rootPath"), gomock.Eq("Retrieving results...")).Return()
655659
mockTracker.EXPECT().End(gomock.Eq("Analysis failed: failed to retrieve findings from findings URL")).Return()

internal/util/testutil/test_config.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package testutil
1717

1818
import (
1919
"github.com/snyk/code-client-go/config"
20+
"time"
2021
)
2122

2223
type localConfig struct {
@@ -38,6 +39,10 @@ func (l localConfig) SnykApi() string {
3839
return "https://app.dev.snyk.io/api"
3940
}
4041

42+
func (l localConfig) SnykCodeAnalysisTimeout() time.Duration {
43+
return 120 * time.Second
44+
}
45+
4146
// NewTestConfig is used in pact testing.
4247
func NewTestConfig() config.Config {
4348
return &localConfig{}

0 commit comments

Comments
 (0)