From 85191c6b02f2b7e9d883e58fae32ad39fdd2d6a1 Mon Sep 17 00:00:00 2001 From: Ben Durrans Date: Wed, 27 Aug 2025 17:20:19 +0100 Subject: [PATCH 1/3] chore: update golangci-lint to v2.3.0 Migrate stylecheck, gosimple, and varcheck into staticcheck (they are now all combined). Add unused linter with `exported-fields-are-used: false`, this is to replace varcheck's `exported-fields: true`. Enable staticcheck explicitly, it was previously enabled, but was not listed. Remove deprecated `EXC####` exclusion rules. Disable package comment rules (ST1000). Disable naming convention rules (ST1003). Move the timeout to command-line arguments (v2 discourages timeouts in the config). Re-enable stuttering checks. Fix any new lint errors. --- .golangci.yaml | 223 +++++++++--------- Makefile | 22 +- internal/deepcode/client.go | 6 +- internal/util/hash_test.go | 6 +- internal/util/path_test.go | 6 +- internal/util/repository.go | 3 +- internal/util/repository_test.go | 4 +- internal/util/testutil/clone.go | 3 +- .../util/testutil/test_auth_round_tripper.go | 3 +- internal/util/testutil/test_config.go | 3 +- llm/convert.go | 2 +- llm/options.go | 1 + scan.go | 5 +- 13 files changed, 152 insertions(+), 135 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 2b3f961b..4f5a7114 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,91 +1,81 @@ +version: '2' run: build-tags: - integration concurrency: 4 issues-exit-code: 1 tests: true - timeout: 5m - -linters-settings: - errcheck: - check-blank: true - check-type-assertions: true - exhaustive: - default-signifies-exhaustive: true - goconst: - ignore-calls: false - gocritic: - enabled-tags: - - diagnostic - - experimental - - opinionated - - performance - - style - gocyclo: - min-complexity: 15 - gofumpt: - module-path: github.com/snyk/code-client-go - extra-rules: true - goimports: - local-prefixes: github.com/snyk/code-client-go - gosimple: - checks: ['all'] - govet: - enable-all: true - disable: - - fieldalignment - lll: - line-length: 160 - misspell: - locale: US - nolintlint: - allow-unused: false - require-explanation: true - require-specific: true - prealloc: - simple: true - range-loops: true - for-loops: true - promlinter: - strict: true - revive: - rules: - - name: blank-imports - disabled: true - - name: context-as-argument - - name: context-keys-type - - name: dot-imports - - name: error-return - - name: error-strings - - name: error-naming - - name: exported - disable-stuttering-check: true - - name: if-return - - name: increment-decrement - - name: var-naming - - name: var-declaration - disabled: true - - name: package-comments - - name: range - - name: receiver-naming - - name: time-naming - - name: unexported-return - - name: indent-error-flow - - name: errorf - - name: empty-block - - name: superfluous-else - - name: unused-parameter - - name: unreachable-code - - name: redefines-builtin-id - staticcheck: - checks: ['all'] - stylecheck: - checks: ['all'] - http-status-code-whitelist: [] - varcheck: - exported-fields: true - linters: + settings: + errcheck: + check-blank: true + check-type-assertions: true + exhaustive: + default-signifies-exhaustive: true + goconst: + ignore-calls: false + gocritic: + enabled-tags: + - diagnostic + - experimental + - opinionated + - performance + - style + gocyclo: + min-complexity: 15 + govet: + enable-all: true + disable: + - fieldalignment + lll: + line-length: 160 + misspell: + locale: US + nolintlint: + allow-unused: false + require-explanation: true + require-specific: true + prealloc: + simple: true + range-loops: true + for-loops: true + promlinter: + strict: true + revive: + rules: + - name: blank-imports + disabled: true + - name: context-as-argument + - name: context-keys-type + - name: dot-imports + - name: error-return + - name: error-strings + - name: error-naming + - name: exported + - name: if-return + - name: increment-decrement + - name: var-naming + - name: var-declaration + disabled: true + - name: package-comments + - name: range + - name: receiver-naming + - name: time-naming + - name: unexported-return + - name: indent-error-flow + - name: errorf + - name: empty-block + - name: superfluous-else + - name: unused-parameter + - name: unreachable-code + - name: redefines-builtin-id + staticcheck: + checks: + - all + - -ST1000 # Disable package comment enforcement. + - -ST1003 # Disable naming convention checks (e.g. myId -> myID). + unused: + exported-fields-are-used: false # Check unused exported fields enable: - asasalint - asciicheck @@ -146,6 +136,7 @@ linters: #- revive - rowserrcheck - sqlclosecheck + - staticcheck # TODO(stylecheck): revisit in a followup; some breaking API changes #- stylecheck # NOTE: removed tagliatelle as it conflicts too much with existing API wireformats @@ -156,36 +147,52 @@ linters: - unconvert # TODO(unparam): revisit #- unparam + - unused - usestdlibvars - usetesting - wastedassign - whitespace # TODO(wrapcheck): wrap errors in a followup #- wrapcheck - -issues: - exclude-dirs: - - "licenses" - - "pact" - - ".bin" - - ".github" - - ".vscode" - - "build" - - exclude-rules: - - path: _test\.go - linters: - - bodyclose - - forcetypeassert - - goconst - - ireturn - - path: test/ - linters: - - testpackage - - path: \.go - # TODO: remove this soon; unchecked errors are BAD - linters: - - errcheck - include: - - EXC0012 - - EXC0014 + exclusions: + paths: + - "licenses" + - "pact" + - ".bin" + - ".github" + - ".vscode" + - "build" + rules: + - path: _test\.go + linters: + - bodyclose + - forcetypeassert + - goconst + - ireturn + - path: test/ + linters: + - testpackage + - path: \.go + # TODO: remove this soon; unchecked errors are BAD + linters: + - errcheck +formatters: + enable: + # TODO(gofumpt): revisit + #- gofumpt + - goimports + settings: + gofumpt: + module-path: github.com/snyk/code-client-go + extra-rules: true + goimports: + local-prefixes: + - github.com/snyk/code-client-go + exclusions: + paths: + - "licenses" + - "pact" + - ".bin" + - ".github" + - ".vscode" + - "build" diff --git a/Makefile b/Makefile index be65c115..ef7567e6 100644 --- a/Makefile +++ b/Makefile @@ -4,8 +4,8 @@ GOARCH = $(shell go env GOARCH) TOOLS_BIN := $(shell pwd)/.bin -OVERRIDE_GOCI_LINT_V := v1.64.8 -GOCI_LINT_TARGETS := $(TOOLS_BIN)/golangci-lint $(TOOLS_BIN)/.golangci-lint_$(OVERRIDE_GOCI_LINT_V) +GOCI_LINT_V := v2.3.0 +GOCI_LINT_TARGETS := $(TOOLS_BIN)/golangci-lint $(TOOLS_BIN)/.golangci-lint_$(GOCI_LINT_V) PACT_CLI_V := v2.4.4 PACT_CLI_TARGETS := $(TOOLS_BIN)/pact/bin/pact-broker $(TOOLS_BIN)/.pact_$(PACT_CLI_V) @@ -23,8 +23,8 @@ $(TOOLS_BIN): $(GOCI_LINT_TARGETS): $(TOOLS_BIN) @rm -f $(TOOLS_BIN)/.golangci-lint_* - @curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/$(OVERRIDE_GOCI_LINT_V)/install.sh | sh -s -- -b $(TOOLS_BIN) $(OVERRIDE_GOCI_LINT_V) - @touch $(TOOLS_BIN)/.golangci-lint_$(OVERRIDE_GOCI_LINT_V) + @curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOCI_LINT_V)/install.sh | sh -s -- -b $(TOOLS_BIN) $(GOCI_LINT_V) + @touch $(TOOLS_BIN)/.golangci-lint_$(GOCI_LINT_V) $(PACT_CLI_TARGETS): $(TOOLS_BIN) @rm -f $(TOOLS_BIN)/.pact_* @@ -39,16 +39,16 @@ $(PACT_GO_LIB_TARGETS): .PHONY: format format: $(GOCI_LINT_TARGETS) @gofmt -w -l -e . - @$(TOOLS_BIN)/golangci-lint run --fix ./... + @$(TOOLS_BIN)/golangci-lint run --timeout=10m --fix ./... .PHONY: lint lint: $(GOCI_LINT_TARGETS) - ifdef CI - mkdir -p test/results - @$(TOOLS_BIN)/golangci-lint run --out-format junit-xml ./... > test/results/lint-tests.xml - else - @$(TOOLS_BIN)/golangci-lint run ./... - endif +ifdef CI + mkdir -p test/results + @$(TOOLS_BIN)/golangci-lint run --timeout=10m --output.junit-xml.path=test/results/lint-tests.xml ./... +else + @$(TOOLS_BIN)/golangci-lint run --timeout=10m ./... +endif .PHONY: build build: diff --git a/internal/deepcode/client.go b/internal/deepcode/client.go index 6b8f4bf3..d5555d9f 100644 --- a/internal/deepcode/client.go +++ b/internal/deepcode/client.go @@ -29,10 +29,10 @@ import ( "strconv" "github.com/rs/zerolog" - "github.com/snyk/code-client-go/config" - "github.com/snyk/code-client-go/internal/util/encoding" + "github.com/snyk/code-client-go/config" codeClientHTTP "github.com/snyk/code-client-go/http" + "github.com/snyk/code-client-go/internal/util/encoding" "github.com/snyk/code-client-go/observability" ) @@ -197,7 +197,7 @@ func (s *deepcodeClient) Host() (string, error) { organization := s.config.Organization() if organization == "" { - return "", errors.New("Organization is required in a fedramp environment") + return "", errors.New("organization is required in a fedramp environment") } u.Path = "/hidden/orgs/" + organization + "/code" diff --git a/internal/util/hash_test.go b/internal/util/hash_test.go index 0d226c15..175a0dd1 100644 --- a/internal/util/hash_test.go +++ b/internal/util/hash_test.go @@ -16,9 +16,11 @@ package util_test import ( - "github.com/snyk/code-client-go/internal/util" - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" + + "github.com/snyk/code-client-go/internal/util" ) func TestHttp_Hash(t *testing.T) { diff --git a/internal/util/path_test.go b/internal/util/path_test.go index d52b7c5e..5dd9fe59 100644 --- a/internal/util/path_test.go +++ b/internal/util/path_test.go @@ -16,9 +16,11 @@ package util_test import ( - "github.com/snyk/code-client-go/internal/util" - "github.com/stretchr/testify/assert" "testing" + + "github.com/stretchr/testify/assert" + + "github.com/snyk/code-client-go/internal/util" ) func TestHttp_ToRelativeUnixPath(t *testing.T) { diff --git a/internal/util/repository.go b/internal/util/repository.go index 348d995c..754dea5d 100644 --- a/internal/util/repository.go +++ b/internal/util/repository.go @@ -18,8 +18,9 @@ package util import ( "fmt" - "github.com/go-git/go-git/v5" "net/url" + + "github.com/go-git/go-git/v5" ) func GetRepositoryUrl(path string) (string, error) { diff --git a/internal/util/repository_test.go b/internal/util/repository_test.go index 832620e5..c54fa03b 100644 --- a/internal/util/repository_test.go +++ b/internal/util/repository_test.go @@ -16,13 +16,13 @@ package util_test import ( - "github.com/go-git/go-git/v5" - "github.com/stretchr/testify/require" "net/url" "path/filepath" "testing" + "github.com/go-git/go-git/v5" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/snyk/code-client-go/internal/util" "github.com/snyk/code-client-go/internal/util/testutil" diff --git a/internal/util/testutil/clone.go b/internal/util/testutil/clone.go index a56b767c..f42bc3e5 100644 --- a/internal/util/testutil/clone.go +++ b/internal/util/testutil/clone.go @@ -1,10 +1,11 @@ package testutil import ( - "github.com/rs/zerolog/log" "os/exec" "path/filepath" "testing" + + "github.com/rs/zerolog/log" ) func SetupCustomTestRepo(t *testing.T, url string, targetCommit string, parentDir, repoDir string) (string, error) { diff --git a/internal/util/testutil/test_auth_round_tripper.go b/internal/util/testutil/test_auth_round_tripper.go index ac8e221d..30a67286 100644 --- a/internal/util/testutil/test_auth_round_tripper.go +++ b/internal/util/testutil/test_auth_round_tripper.go @@ -2,9 +2,10 @@ package testutil import ( "fmt" - "github.com/google/uuid" "net/http" "os" + + "github.com/google/uuid" ) type TestAuthRoundTripper struct { diff --git a/internal/util/testutil/test_config.go b/internal/util/testutil/test_config.go index 3f1ac016..138a3bd3 100644 --- a/internal/util/testutil/test_config.go +++ b/internal/util/testutil/test_config.go @@ -16,8 +16,9 @@ package testutil import ( - "github.com/snyk/code-client-go/config" "time" + + "github.com/snyk/code-client-go/config" ) type localConfig struct { diff --git a/llm/convert.go b/llm/convert.go index d74a9c87..d229996f 100644 --- a/llm/convert.go +++ b/llm/convert.go @@ -49,7 +49,7 @@ func getPathAndUnifiedDiff(zeroLogger *zerolog.Logger, baseDir string, filePath } // Workaround: AI Suggestion API only returns \n new lines. It doesn't consider carriage returns. - contentBefore := strings.Replace(string(fileContent), "\r\n", "\n", -1) + contentBefore := strings.ReplaceAll(string(fileContent), "\r\n", "\n") edits := myers.ComputeEdits(span.URIFromPath(decodedPath), contentBefore, newText) unifiedDiff = fmt.Sprint(gotextdiff.ToUnified(decodedPath, decodedPath+"fixed", contentBefore, edits)) diff --git a/llm/options.go b/llm/options.go index b0dbbcd8..72d4b704 100644 --- a/llm/options.go +++ b/llm/options.go @@ -2,6 +2,7 @@ package llm import ( "github.com/rs/zerolog" + "github.com/snyk/code-client-go/http" "github.com/snyk/code-client-go/observability" ) diff --git a/scan.go b/scan.go index bf762b34..3b33e92d 100644 --- a/scan.go +++ b/scan.go @@ -300,11 +300,12 @@ func (c *codeScanner) analyzeLegacy( return nil, "", err } - if status.Message == analysis.StatusComplete { + switch status.Message { + case analysis.StatusComplete: c.logger.Trace().Msg("sending diagnostics...") statusChannel <- scan.NewLegacyScanDoneStatus("Analysis complete") return response, bundleHash, err - } else if status.Message == analysis.StatusAnalyzing { + case analysis.StatusAnalyzing: c.logger.Trace().Msg("\"Analyzing\" message received") } From 611087280592ed6102ea53896d5994b93202f21b Mon Sep 17 00:00:00 2001 From: Ben Durrans Date: Wed, 10 Sep 2025 17:42:23 +0100 Subject: [PATCH 2/3] fix: make pact install fails fail the make target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ef7567e6..bbf62406 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ $(GOCI_LINT_TARGETS): $(TOOLS_BIN) $(PACT_CLI_TARGETS): $(TOOLS_BIN) @rm -f $(TOOLS_BIN)/.pact_* - @cd $(TOOLS_BIN); curl -fsSL https://raw.githubusercontent.com/pact-foundation/pact-ruby-standalone/master/install.sh | PACT_CLI_VERSION=$(PACT_CLI_V) bash; cd ../ + @cd $(TOOLS_BIN) && curl -fsSL https://raw.githubusercontent.com/pact-foundation/pact-ruby-standalone/master/install.sh | PACT_CLI_VERSION=$(PACT_CLI_V) bash && cd ../ @touch $(TOOLS_BIN)/.pact_$(PACT_CLI_V) $(PACT_GO_LIB_TARGETS): From a6fd7bc2639343b0a5c6092bdae15761d2c37292 Mon Sep 17 00:00:00 2001 From: Ben Durrans Date: Fri, 26 Sep 2025 10:28:16 +0100 Subject: [PATCH 3/3] fix: don't check tool bin timestamp Previously a redownload would happen after the contents of the directory changed. --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index bbf62406..ba6e242b 100644 --- a/Makefile +++ b/Makefile @@ -21,12 +21,12 @@ tools: $(GOCI_LINT_TARGETS) $(PACT_CLI_TARGETS) $(PACT_GO_LIB_TARGETS) $(TOOLS_BIN): @mkdir -p $(TOOLS_BIN) -$(GOCI_LINT_TARGETS): $(TOOLS_BIN) +$(GOCI_LINT_TARGETS): | $(TOOLS_BIN) @rm -f $(TOOLS_BIN)/.golangci-lint_* @curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/$(GOCI_LINT_V)/install.sh | sh -s -- -b $(TOOLS_BIN) $(GOCI_LINT_V) @touch $(TOOLS_BIN)/.golangci-lint_$(GOCI_LINT_V) -$(PACT_CLI_TARGETS): $(TOOLS_BIN) +$(PACT_CLI_TARGETS): | $(TOOLS_BIN) @rm -f $(TOOLS_BIN)/.pact_* @cd $(TOOLS_BIN) && curl -fsSL https://raw.githubusercontent.com/pact-foundation/pact-ruby-standalone/master/install.sh | PACT_CLI_VERSION=$(PACT_CLI_V) bash && cd ../ @touch $(TOOLS_BIN)/.pact_$(PACT_CLI_V)