Skip to content

Commit

Permalink
feat: use workspace client
Browse files Browse the repository at this point in the history
  • Loading branch information
teodora-sandu committed Apr 5, 2024
1 parent b20292c commit bcf0295
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 33 deletions.
45 changes: 16 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,44 +38,31 @@ The HTTP client exposes a `DoCall` function.

Implement the `http.Config` interface to configure the Snyk Code API client from applications.

### Snyk Code Client

Use the Snyk Code Client to make calls to the DeepCode API using the `httpClient` HTTP client created above.

```go
snykCode := deepcode.NewSnykCodeClient(logger, httpClient, testutil.NewTestInstrumentor())
```

The Snyk Code Client exposes the following functions:
- `GetFilters`
- `CreateBundle`
- `ExtendBundle`

### Bundle Manager

Use the Bundle Manager to create bundles using the `snykCode` Snyk Code Client created above and then to extend it by uploading more files to it.

```go
bundleManager := bundle.NewBundleManager(logger, snykCode, testutil.NewTestInstrumentor(), testutil.NewTestCodeInstrumentor())
```

The Bundle Manager exposes the following functions:
- `Create`
- `Upload`

### Code Scanner

Use the Code Scanner to trigger a scan for a Snyk Code workspace using the Bundle Manager created above.
The Code Scanner exposes a `UploadAndAnalyze` function, which can be used like this:

```go
codeScanner := codeclient.NewCodeScanner(
import (
"net/http"

"github.com/rs/zerolog"
code "github.com/snyk/code-client-go"
)

logger := zerlog.NewLogger(...)
config := newConfigForMyApp()

codeScanner := code.NewCodeScanner(
httpClient,
config,
bundleManager,
testutil.NewTestInstrumentor(),
testutil.NewTestErrorReporter(),
codeInstrumentor,
codeErrorReporter,
logger,
)
codeScanner.UploadAndAnalyze(context.Background(), "path/to/workspace", channelForWalkingFiles, changedFiles)
code.UploadAndAnalyze(context.Background(), "orgId", "requestId", "path/to/workspace", channelForWalkingFiles, changedFiles)
```


Expand Down
3 changes: 3 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ type Config interface {
// SnykCodeApi returns the Snyk Code API URL configured to run against, which could be
// the one used by the Local Code Engine.
SnykCodeApi() string

// SnykApi returns the Snyk REST API URL configured to run against,
SnykApi() string
}
14 changes: 14 additions & 0 deletions config/mocks/config.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

67 changes: 65 additions & 2 deletions scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ package codeclient

import (
"context"
"fmt"

"github.com/google/uuid"
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
Expand All @@ -29,19 +31,24 @@ import (
"github.com/snyk/code-client-go/internal/analysis"
"github.com/snyk/code-client-go/internal/bundle"
"github.com/snyk/code-client-go/internal/deepcode"
"github.com/snyk/code-client-go/internal/util"
workspaceClient "github.com/snyk/code-client-go/internal/workspace/2024-03-12"
externalRef3 "github.com/snyk/code-client-go/internal/workspace/2024-03-12/workspaces"
"github.com/snyk/code-client-go/observability"
"github.com/snyk/code-client-go/sarif"
)

type codeScanner struct {
bundleManager bundle.BundleManager
workspace *workspaceClient.ClientWithResponses
errorReporter observability.ErrorReporter
logger *zerolog.Logger
}

type CodeScanner interface {
UploadAndAnalyze(
ctx context.Context,
orgId string,
requestId string,
path string,
files <-chan string,
Expand All @@ -56,14 +63,19 @@ func NewCodeScanner(
instrumentor observability.Instrumentor,
errorReporter observability.ErrorReporter,
logger *zerolog.Logger,
) *codeScanner {
) (*codeScanner, error) {
snykCode := deepcode.NewSnykCodeClient(logger, httpClient, instrumentor, errorReporter, config)
bundleManager := bundle.NewBundleManager(logger, snykCode, instrumentor, errorReporter)
workspace, err := workspaceClient.NewClientWithResponses(config.SnykApi(), workspaceClient.WithHTTPClient(httpClient))
if err != nil {
return nil, err
}
return &codeScanner{
bundleManager: bundleManager,
workspace: workspace,
errorReporter: errorReporter,
logger: logger,
}
}, nil
}

// WithBundleManager creates a new Code Scanner from the current one and replaces the bundle manager.
Expand All @@ -79,6 +91,7 @@ func (c *codeScanner) WithBundleManager(bundleManager bundle.BundleManager) *cod
// UploadAndAnalyze returns a fake SARIF response for testing. Use target-service to run analysis on.
func (c *codeScanner) UploadAndAnalyze(
ctx context.Context,
orgId string,
requestId string,
path string,
files <-chan string,
Expand Down Expand Up @@ -128,6 +141,56 @@ func (c *codeScanner) UploadAndAnalyze(
return nil, bundleHash, nil
}

orgUUID := uuid.MustParse(orgId)
repositoryUri, err := util.GetRepositoryUrl(path)
if err != nil {
if ctx.Err() != nil { // Only handle errors that are not intentional cancellations
msg := "error retrieving Git info..."
c.errorReporter.CaptureError(errors.Wrap(err, msg), observability.ErrorReporterOptions{ErrorDiagnosticPath: path})
return nil, bundleHash, err
} else {
log.Info().Msg("Canceling Code scan - Code scanner received cancellation signal")
return nil, bundleHash, nil
}
}

workspaceResponse, err := c.workspace.CreateWorkspaceWithApplicationVndAPIPlusJSONBodyWithResponse(ctx, orgUUID, &workspaceClient.CreateWorkspaceParams{
Version: "2024-03-12~experimental",
SnykRequestId: uuid.MustParse(requestId),
}, workspaceClient.CreateWorkspaceApplicationVndAPIPlusJSONRequestBody{
Data: struct {
Attributes struct {
BundleId string `json:"bundle_id"`
RepositoryUri string `json:"repository_uri"`
WorkspaceType externalRef3.WorkspacePostRequestDataAttributesWorkspaceType `json:"workspace_type"`
} `json:"attributes"`
Type externalRef3.WorkspacePostRequestDataType `json:"type"`
}(struct {
Attributes struct {
BundleId string `json:"bundle_id"`
RepositoryUri string `json:"repository_uri"`
WorkspaceType externalRef3.WorkspacePostRequestDataAttributesWorkspaceType `json:"workspace_type"`
}
Type externalRef3.WorkspacePostRequestDataType
}{Attributes: struct {
BundleId string `json:"bundle_id"`
RepositoryUri string `json:"repository_uri"`
WorkspaceType externalRef3.WorkspacePostRequestDataAttributesWorkspaceType `json:"workspace_type"`
}(struct {
BundleId string
RepositoryUri string
WorkspaceType externalRef3.WorkspacePostRequestDataAttributesWorkspaceType
}{
BundleId: b.GetBundleHash(),
RepositoryUri: repositoryUri,
WorkspaceType: "workspaceUri",
}),
Type: "workspace",
}),
})

fmt.Println(workspaceResponse.ApplicationvndApiJSON201.Data.Id)

response, err := analysis.RunAnalysis()
if ctx.Err() != nil {
c.logger.Info().Msg("Canceling Code scan - Code scanner received cancellation signal")
Expand Down
6 changes: 4 additions & 2 deletions scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ func Test_UploadAndAnalyze(t *testing.T) {
mockBundleManager.EXPECT().Create(gomock.Any(), "testRequestId", baseDir, gomock.Any(), map[string]bool{}).Return(mockBundle, nil)
mockBundleManager.EXPECT().Upload(gomock.Any(), "testRequestId", mockBundle, files).Return(mockBundle, nil)

codeScanner := codeclient.NewCodeScanner(mockHTTPClient, mockConfig, mockInstrumentor, mockErrorReporter, &logger)
codeScanner, err := codeclient.NewCodeScanner(mockHTTPClient, mockConfig, mockInstrumentor, mockErrorReporter, &logger)
require.NoError(t, err)

response, bundleHash, err := codeScanner.WithBundleManager(mockBundleManager).UploadAndAnalyze(context.Background(), "testRequestId", baseDir, docs, map[string]bool{})
require.NoError(t, err)
Expand All @@ -83,7 +84,8 @@ func Test_UploadAndAnalyze(t *testing.T) {
mockBundleManager.EXPECT().Create(gomock.Any(), "testRequestId", baseDir, gomock.Any(), map[string]bool{}).Return(mockBundle, nil)
mockBundleManager.EXPECT().Upload(gomock.Any(), "testRequestId", mockBundle, files).Return(mockBundle, nil)

codeScanner := codeclient.NewCodeScanner(mockHTTPClient, mockConfig, mockInstrumentor, mockErrorReporter, &logger)
codeScanner, err := codeclient.NewCodeScanner(mockHTTPClient, mockConfig, mockInstrumentor, mockErrorReporter, &logger)
require.NoError(t, err)

response, bundleHash, err := codeScanner.WithBundleManager(mockBundleManager).UploadAndAnalyze(context.Background(), "testRequestId", baseDir, docs, map[string]bool{})
require.NoError(t, err)
Expand Down

0 comments on commit bcf0295

Please sign in to comment.