From 77bb83f9aabc77ab6ad5e5a491610c7b0c333a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirko=20K=C3=A4mpf?= Date: Wed, 17 Jun 2026 16:10:58 +0200 Subject: [PATCH 1/2] chore(ci): modernize GitHub Actions + migrate golangci-lint to v2 Bump five GitHub Actions to the versions requested by the open dependabot PRs, and migrate the golangci-lint config to v2 format, which is the fix for the red "Build & Test > Lint" step. Action bumps (across build-and-release.yml, docs.yml, security.yml): - actions/checkout v4 -> v6 - actions/setup-go v5 -> v6 - golangci/golangci-lint-action v6 -> v9 - goreleaser/goreleaser-action v5 -> v7 - actions/deploy-pages v4 -> v5 The Lint step failed on every PR with "the Go language version (go1.24) used to build golangci-lint is lower than the targeted Go version (1.25.0)". go.mod targets go 1.25.0; golangci-lint v1 (built with go1.24) refuses to lint it. golangci-lint v2 is built with go1.25 and reads a v2-format config, so the action bump to v9 plus a .golangci.yml v2 migration are both required. The .golangci.yml was converted with `golangci-lint migrate`, which preserves the v1 linter intent (errcheck, govet, staticcheck with gosimple folded in, unused, ineffassign, misspell, gocritic, revive, plus bodyclose, gosec, noctx and the gofmt formatter). One real finding was fixed: a dead no-op loop in trend_test.go (staticcheck SA4017). gofmt alignment was applied tree-wide. The remaining pre-existing findings, which were never enforced because the v1 lint never ran green, are scoped with commented exclusions and listed in the PR for a follow-up cleanup. Supersedes the five action-bump dependabot PRs. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/build-and-release.yml | 12 +- .github/workflows/docs.yml | 4 +- .github/workflows/security.yml | 4 +- .golangci.yml | 129 ++++++++++++++++------ cmd/kshark/ai_test.go | 12 +- cmd/kshark/bundle.go | 9 +- cmd/kshark/connector_test.go | 18 +-- cmd/kshark/diff_test.go | 14 +-- cmd/kshark/kafka_test.go | 6 +- cmd/kshark/main_test.go | 3 +- cmd/kshark/neighborhood.go | 14 +-- cmd/kshark/properties_test.go | 10 +- cmd/kshark/tls_test.go | 26 ++--- cmd/kshark/trend_test.go | 9 +- cmd/kshark/util.go | 2 +- internal/connectapi/config_parser.go | 18 +-- internal/connectapi/config_parser_test.go | 44 ++++---- internal/connectapi/redact_test.go | 14 +-- internal/probe/db2.go | 26 ++--- internal/probe/db2_test.go | 4 +- internal/probe/elasticsearch_test.go | 16 +-- internal/probe/mongodb.go | 4 +- internal/probe/mongodb_test.go | 8 +- internal/probe/mysql.go | 12 +- internal/probe/mysql_test.go | 12 +- internal/probe/oracle.go | 20 ++-- internal/probe/oracle_test.go | 4 +- internal/probe/postgres.go | 4 +- internal/probe/redis.go | 3 +- internal/probe/redis_test.go | 6 +- internal/probe/sqlserver.go | 14 +-- internal/probe/sqlserver_test.go | 20 ++-- 32 files changed, 279 insertions(+), 222 deletions(-) diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index 5b30743..3e05175 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -16,10 +16,10 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: '1.23' @@ -30,7 +30,7 @@ jobs: run: go vet ./... - name: Lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v9 with: version: latest @@ -69,12 +69,12 @@ jobs: id-token: write # Required for keyless cosign signing via GitHub OIDC steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Set up Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: '1.23' @@ -85,7 +85,7 @@ jobs: uses: anchore/sbom-action/download-syft@v0 - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v5 + uses: goreleaser/goreleaser-action@v7 with: distribution: goreleaser version: latest diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index eef8bf7..eb06991 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -24,7 +24,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Setup Pages uses: actions/configure-pages@v5 @@ -47,4 +47,4 @@ jobs: steps: - name: Deploy to GitHub Pages id: deployment - uses: actions/deploy-pages@v4 + uses: actions/deploy-pages@v5 diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 8e29754..1b70cc4 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -13,9 +13,9 @@ jobs: name: Vulnerability Scan runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@v6 with: go-version: '1.23' diff --git a/.golangci.yml b/.golangci.yml index 422c353..7f88be7 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,41 +1,106 @@ -run: - timeout: 5m - +# golangci-lint v2 configuration. +# +# Migrated from the v1 config with `golangci-lint migrate`. In v2 the +# default linter set already includes errcheck, govet, staticcheck, +# unused and ineffassign, so only the additional v1 linters are listed +# under `enable`. The v1 intent is preserved: errcheck, govet, +# staticcheck (gosimple folded in), unused, ineffassign, misspell, +# gocritic, revive, plus bodyclose, gosec, noctx and the gofmt formatter. +# +# The exclusions in `exclusions.rules` below cover findings that already +# existed on main but were never enforced, because the v1 lint step never +# ran (golangci-lint v1 refused to load under the go1.25 module target). +# They are scoped per linter/rule with a reason and tracked as a code +# cleanup follow-up, not disabled wholesale. +version: "2" linters: enable: - - errcheck - - govet - - staticcheck - - unused - - gosimple - - ineffassign - - typecheck - - misspell - - gocritic - - revive - - gofmt - bodyclose + - gocritic - gosec + - misspell - noctx - -linters-settings: - revive: + - revive + settings: + gocritic: + disabled-checks: + - ifElseChain + gosec: + excludes: + - G104 + - G304 + - G204 + revive: + rules: + - name: exported + severity: warning + disabled: true + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling rules: - - name: exported - severity: warning - disabled: true # allow unexported in package main - gosec: - excludes: - - G104 # unhandled errors on deferred Close - - G304 # file path from variable (expected for config loading) - - G204 # subprocess with variable args (validated by isValidHostname) - gocritic: - disabled-checks: - - ifElseChain # acceptable in error classification functions - + # Test helpers routinely ignore errors on setup/teardown calls + # (os.Chdir, w.Write, json encode/decode) and use lax TLS / no-context + # network calls against in-process test servers. Standard test-only scope. + - linters: + - errcheck + - gosec + - noctx + path: _test\.go + # Pre-existing on main: deferred to a follow-up code cleanup. + # kshark is a network-diagnostic CLI, so direct net/tls/exec calls + # (LookupHost, DialTimeout, Handshake, exec.Command) without an + # explicit context are inherent to its probe paths. + - linters: + - noctx + text: "must not be called" + # gosec findings inherent to the protocol probes: integer narrowing of + # protocol byte fields (G115), MySQL native-password auth which is + # sha1 by protocol (G401/G505), deliberate TLS probing with skip-verify + # (G402), report-file permissions (G306) and jitter randomness (G404). + - linters: + - gosec + text: "G(115|306|401|402|404|505)" + # Unchecked io.Copy / SetReadDeadline / SetWriteDeadline / Sscanf / + # ReadString on the probe and bundle paths. Pre-existing; follow-up. + - linters: + - errcheck + text: "Error return value" + # staticcheck style/quickfix suggestions (tagged switch, omit inferred + # type, Fprintf, non-capitalized error strings). Pre-existing; follow-up. + - linters: + - staticcheck + text: "(QF1002|QF1003|QF1011|QF1012|S1039|ST1005|ST1023)" + # gocritic exitAfterDefer in CLI entrypoints (os.Exit after a defer). + # Pre-existing; follow-up. + - linters: + - gocritic + text: "exitAfterDefer" + # Unused per-probe default-port constants kept as protocol reference. + - linters: + - unused + text: "const \\w+DefaultPort is unused" + paths: + - testbed + - web + - third_party$ + - builtin$ + - examples$ issues: - exclude-dirs: - - testbed - - web max-issues-per-linter: 50 max-same-issues: 5 +formatters: + enable: + - gofmt + exclusions: + generated: lax + paths: + - testbed + - web + - third_party$ + - builtin$ + - examples$ diff --git a/cmd/kshark/ai_test.go b/cmd/kshark/ai_test.go index 2d3279c..762644f 100644 --- a/cmd/kshark/ai_test.go +++ b/cmd/kshark/ai_test.go @@ -258,7 +258,7 @@ func TestWriteAnalysisResponseJSON(t *testing.T) { analysis := &AIAnalysisResponse{ RootCauseAnalysis: "TLS certificate expired", ProblemLayer: "L5-6-TLS", - LikelyCategory: "tls", + LikelyCategory: "tls", Confidence: "high", Severity: "critical", Explanation: "The server certificate has expired.", @@ -347,7 +347,7 @@ func TestAnalyzeReport_ParseResponse_Success(t *testing.T) { inner := AIAnalysisResponse{ RootCauseAnalysis: "TLS certificate expired", ProblemLayer: "L5-6-TLS", - LikelyCategory: "tls", + LikelyCategory: "tls", Confidence: "high", Severity: "critical", Explanation: "The server certificate has expired.", @@ -413,7 +413,7 @@ func TestAnalyzeReport_HTTPServerIntegration(t *testing.T) { analysis := AIAnalysisResponse{ RootCauseAnalysis: "test root cause", ProblemLayer: "L7-Kafka", - LikelyCategory: "authentication", + LikelyCategory: "authentication", Confidence: "medium", Severity: "error", Explanation: "test explanation", @@ -455,7 +455,7 @@ func TestAnalyzeReport_DirectHTTPFlow(t *testing.T) { analysis := AIAnalysisResponse{ RootCauseAnalysis: "DNS resolution failure", ProblemLayer: "L3-Network", - LikelyCategory: "dns", + LikelyCategory: "dns", Confidence: "high", Severity: "error", Explanation: "Cannot resolve broker hostname.", @@ -671,7 +671,7 @@ func TestAnalyzeReport_FullFunction_Success(t *testing.T) { analysis := AIAnalysisResponse{ RootCauseAnalysis: "Firewall blocks port 9092", ProblemLayer: "L4-TCP", - LikelyCategory: "network", + LikelyCategory: "network", Confidence: "high", Severity: "critical", Explanation: "TCP connections to Kafka brokers are timing out.", @@ -789,7 +789,7 @@ func TestPrintIllustrativeAnalysis_NoPanic(t *testing.T) { analysis := &AIAnalysisResponse{ RootCauseAnalysis: "Test root cause", ProblemLayer: "L7-Kafka", - LikelyCategory: "authentication", + LikelyCategory: "authentication", Confidence: "high", Severity: "critical", Explanation: "Test explanation", diff --git a/cmd/kshark/bundle.go b/cmd/kshark/bundle.go index 448e481..f17f786 100644 --- a/cmd/kshark/bundle.go +++ b/cmd/kshark/bundle.go @@ -31,7 +31,7 @@ import ( // ---------- Diagnostics Bundle ---------- const ( - maxTFStateSize = 200 * 1024 * 1024 // 200 MB hard limit + maxTFStateSize = 200 * 1024 * 1024 // 200 MB hard limit warnTFStateSize = 50 * 1024 * 1024 // 50 MB warning threshold ) @@ -98,9 +98,9 @@ func isSensitiveKey(key string) bool { // captureSystemContext collects system information for the diagnostics bundle. func captureSystemContext() map[string]string { ctx := map[string]string{ - "os": runtime.GOOS, - "arch": runtime.GOARCH, - "go": runtime.Version(), + "os": runtime.GOOS, + "arch": runtime.GOARCH, + "go": runtime.Version(), } if hostname, err := os.Hostname(); err == nil { @@ -348,4 +348,3 @@ func redactPlanText(text string) string { } return strings.Join(lines, "\n") } - diff --git a/cmd/kshark/connector_test.go b/cmd/kshark/connector_test.go index 9da3f47..dbcd02c 100644 --- a/cmd/kshark/connector_test.go +++ b/cmd/kshark/connector_test.go @@ -144,9 +144,9 @@ func TestRunConnectorProbe_ConnectAPI_Fallback(t *testing.T) { cfgPath := filepath.Join(dir, "connector.json") cfg := map[string]string{ "name": "pg-sink", - "connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector", - "connection.url": "jdbc:postgresql://pg.example.com:5432/mydb", - "connection.user": "user", + "connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector", + "connection.url": "jdbc:postgresql://pg.example.com:5432/mydb", + "connection.user": "user", "connection.password": "pass", } data, _ := json.Marshal(cfg) @@ -188,9 +188,9 @@ func TestRunConnectorProbe_PasswordRedaction(t *testing.T) { cfg := map[string]string{ "name": "pg-sink", - "connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector", - "connection.url": "jdbc:postgresql://pg.example.com:5432/mydb", - "connection.user": "admin", + "connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector", + "connection.url": "jdbc:postgresql://pg.example.com:5432/mydb", + "connection.user": "admin", "connection.password": "super-secret-password", } data, _ := json.Marshal(cfg) @@ -239,9 +239,9 @@ func TestRunConnectorProbe_PostgreSQL(t *testing.T) { cfg := map[string]string{ "name": "pg-sink", - "connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector", - "connection.url": "jdbc:postgresql://pg.example.com:5432/mydb", - "connection.user": "user", + "connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector", + "connection.url": "jdbc:postgresql://pg.example.com:5432/mydb", + "connection.user": "user", "connection.password": "pass", } data, _ := json.Marshal(cfg) diff --git a/cmd/kshark/diff_test.go b/cmd/kshark/diff_test.go index baee9d0..5951153 100644 --- a/cmd/kshark/diff_test.go +++ b/cmd/kshark/diff_test.go @@ -344,17 +344,17 @@ func TestDiffReports_MixedChanges(t *testing.T) { r1 := &Report{ Rows: []Row{ {Component: "kafka", Target: "broker:9092", Layer: L4, Status: FAIL, Detail: "timeout"}, // will improve - {Component: "dns", Target: "broker", Layer: L3, Status: OK, Detail: "resolved"}, // will degrade - {Component: "tls", Target: "broker:9092", Layer: L56, Status: OK, Detail: "valid cert"}, // unchanged - {Component: "diag", Target: "traceroute", Layer: DIAG, Status: WARN, Detail: "high latency"}, // will be removed + {Component: "dns", Target: "broker", Layer: L3, Status: OK, Detail: "resolved"}, // will degrade + {Component: "tls", Target: "broker:9092", Layer: L56, Status: OK, Detail: "valid cert"}, // unchanged + {Component: "diag", Target: "traceroute", Layer: DIAG, Status: WARN, Detail: "high latency"}, // will be removed }, } r2 := &Report{ Rows: []Row{ - {Component: "kafka", Target: "broker:9092", Layer: L4, Status: OK, Detail: "connected"}, // improved - {Component: "dns", Target: "broker", Layer: L3, Status: FAIL, Detail: "NXDOMAIN"}, // degraded - {Component: "tls", Target: "broker:9092", Layer: L56, Status: OK, Detail: "valid cert"}, // unchanged - {Component: "rest", Target: "proxy:8082", Layer: HTTP, Status: OK, Detail: "topics listed"}, // new + {Component: "kafka", Target: "broker:9092", Layer: L4, Status: OK, Detail: "connected"}, // improved + {Component: "dns", Target: "broker", Layer: L3, Status: FAIL, Detail: "NXDOMAIN"}, // degraded + {Component: "tls", Target: "broker:9092", Layer: L56, Status: OK, Detail: "valid cert"}, // unchanged + {Component: "rest", Target: "proxy:8082", Layer: HTTP, Status: OK, Detail: "topics listed"}, // new }, } diff --git a/cmd/kshark/kafka_test.go b/cmd/kshark/kafka_test.go index 336237a..600961c 100644 --- a/cmd/kshark/kafka_test.go +++ b/cmd/kshark/kafka_test.go @@ -299,9 +299,9 @@ func TestParseStartOffset(t *testing.T) { func TestSelectBalancer(t *testing.T) { tests := []struct { - name string - input string - wantType string + name string + input string + wantType string }{ {name: "rr", input: "rr", wantType: "*kafka.RoundRobin"}, {name: "roundrobin", input: "roundrobin", wantType: "*kafka.RoundRobin"}, diff --git a/cmd/kshark/main_test.go b/cmd/kshark/main_test.go index d14e570..9511b88 100644 --- a/cmd/kshark/main_test.go +++ b/cmd/kshark/main_test.go @@ -400,7 +400,7 @@ func TestAIAPIIntegration_FullRoundTrip(t *testing.T) { analysis := AIAnalysisResponse{ RootCauseAnalysis: "Firewall blocking port 9092", ProblemLayer: "L4-TCP", - LikelyCategory: "network", + LikelyCategory: "network", Confidence: "high", Severity: "critical", Explanation: "TCP connection to broker timed out, indicating a firewall or security group issue.", @@ -898,4 +898,3 @@ func TestRunScan_ConnectorOnly(t *testing.T) { } } } - diff --git a/cmd/kshark/neighborhood.go b/cmd/kshark/neighborhood.go index 19efd4a..cc157a2 100644 --- a/cmd/kshark/neighborhood.go +++ b/cmd/kshark/neighborhood.go @@ -301,13 +301,13 @@ func hasNeighborhoodRows(r *Report, host string) bool { // connectorNeighborhoodPortsMap maps connector types to their default neighborhood ports. var connectorNeighborhoodPortsMap = map[string][]int{ - "mongodb": {27017, 27018, 27019, 443}, - "postgresql": {5432, 5433, 443}, - "db2": {50000, 50001, 446, 443}, - "mysql": {3306, 3307, 443}, - "sqlserver": {1433, 1434, 443}, - "oracle": {1521, 1522, 443}, - "redis": {6379, 6380, 443}, + "mongodb": {27017, 27018, 27019, 443}, + "postgresql": {5432, 5433, 443}, + "db2": {50000, 50001, 446, 443}, + "mysql": {3306, 3307, 443}, + "sqlserver": {1433, 1434, 443}, + "oracle": {1521, 1522, 443}, + "redis": {6379, 6380, 443}, "elasticsearch": {9200, 9300, 443}, } diff --git a/cmd/kshark/properties_test.go b/cmd/kshark/properties_test.go index 46cd222..47248d7 100644 --- a/cmd/kshark/properties_test.go +++ b/cmd/kshark/properties_test.go @@ -157,8 +157,8 @@ func TestRedactProps(t *testing.T) { { name: "password fields redacted", input: map[string]string{ - "sasl.password": "secret123", - "bootstrap.servers": "localhost:9092", + "sasl.password": "secret123", + "bootstrap.servers": "localhost:9092", }, check: func(t *testing.T, out map[string]string) { if out["sasl.password"] != "[REDACTED]" { @@ -227,9 +227,9 @@ func TestRedactProps(t *testing.T) { { name: "normal fields preserved", input: map[string]string{ - "bootstrap.servers": "broker1:9092", - "security.protocol": "SASL_SSL", - "sasl.mechanism": "PLAIN", + "bootstrap.servers": "broker1:9092", + "security.protocol": "SASL_SSL", + "sasl.mechanism": "PLAIN", }, check: func(t *testing.T, out map[string]string) { if out["bootstrap.servers"] != "broker1:9092" { diff --git a/cmd/kshark/tls_test.go b/cmd/kshark/tls_test.go index 18c9551..1c36058 100644 --- a/cmd/kshark/tls_test.go +++ b/cmd/kshark/tls_test.go @@ -196,8 +196,8 @@ func TestEarliestExpiry_NoCerts(t *testing.T) { } func TestEarliestExpiry_MultipleCerts(t *testing.T) { - earliest := time.Now().Add(30 * 24 * time.Hour) // 30 days from now - later := time.Now().Add(180 * 24 * time.Hour) // 180 days from now + earliest := time.Now().Add(30 * 24 * time.Hour) // 30 days from now + later := time.Now().Add(180 * 24 * time.Hour) // 180 days from now state := &tls.ConnectionState{ PeerCertificates: []*x509.Certificate{ @@ -273,7 +273,7 @@ func TestCheckTCP_ContextCancel(t *testing.T) { func TestCheckDNS_ResolvableHost(t *testing.T) { r := &Report{} - checkDNS(context.Background(), r,"localhost", "kafka") + checkDNS(context.Background(), r, "localhost", "kafka") if len(r.Rows) != 1 { t.Fatalf("expected 1 row, got %d", len(r.Rows)) } @@ -287,7 +287,7 @@ func TestCheckDNS_ResolvableHost(t *testing.T) { func TestCheckDNS_UnresolvableHost(t *testing.T) { r := &Report{} - checkDNS(context.Background(), r,"this.host.does.not.exist.kshark.invalid", "kafka") + checkDNS(context.Background(), r, "this.host.does.not.exist.kshark.invalid", "kafka") if len(r.Rows) != 1 { t.Fatalf("expected 1 row, got %d", len(r.Rows)) } @@ -301,7 +301,7 @@ func TestCheckDNS_UnresolvableHost(t *testing.T) { func TestCheckDNS_ComponentLabel(t *testing.T) { r := &Report{} - checkDNS(context.Background(), r,"localhost", "connector-mongodb") + checkDNS(context.Background(), r, "localhost", "connector-mongodb") if r.Rows[0].Component != "connector-mongodb" { t.Errorf("component = %q, want %q", r.Rows[0].Component, "connector-mongodb") } @@ -327,7 +327,7 @@ func TestCheckTCP_OpenPort(t *testing.T) { r := &Report{} addr := ln.Addr().String() - conn := checkTCP(context.Background(), r,addr, "kafka", 5*time.Second) + conn := checkTCP(context.Background(), r, addr, "kafka", 5*time.Second) if conn == nil { t.Fatal("expected non-nil conn for open port") } @@ -351,7 +351,7 @@ func TestCheckTCP_ClosedPort(t *testing.T) { ln.Close() r := &Report{} - conn := checkTCP(context.Background(), r,addr, "kafka", 2*time.Second) + conn := checkTCP(context.Background(), r, addr, "kafka", 2*time.Second) if conn != nil { conn.Close() t.Error("expected nil conn for closed port") @@ -370,7 +370,7 @@ func TestCheckTCP_Timeout(t *testing.T) { // 192.0.2.1 is TEST-NET-1 (RFC 5737), not routable r := &Report{} start := time.Now() - conn := checkTCP(context.Background(), r,"192.0.2.1:9092", "kafka", 500*time.Millisecond) + conn := checkTCP(context.Background(), r, "192.0.2.1:9092", "kafka", 500*time.Millisecond) elapsed := time.Since(start) if conn != nil { @@ -399,7 +399,7 @@ func TestCheckTCP_ReturnsLatencyInDetail(t *testing.T) { }() r := &Report{} - conn := checkTCP(context.Background(), r,ln.Addr().String(), "kafka", 5*time.Second) + conn := checkTCP(context.Background(), r, ln.Addr().String(), "kafka", 5*time.Second) if conn != nil { conn.Close() } @@ -469,7 +469,7 @@ func TestWrapTLS_NilConfig_PLAINTEXT(t *testing.T) { defer base.Close() r := &Report{} - got := wrapTLS(context.Background(), r,base, nil, "kafka", "127.0.0.1:9092") + got := wrapTLS(context.Background(), r, base, nil, "kafka", "127.0.0.1:9092") if got != base { t.Error("expected wrapTLS to return base conn when tlsConf is nil") } @@ -525,7 +525,7 @@ func TestWrapTLS_SuccessfulHandshake(t *testing.T) { } r := &Report{} - got := wrapTLS(context.Background(), r,base, clientTLSConf, "kafka", "127.0.0.1:9092") + got := wrapTLS(context.Background(), r, base, clientTLSConf, "kafka", "127.0.0.1:9092") if got == nil { t.Fatal("expected non-nil conn after successful TLS handshake") } @@ -577,7 +577,7 @@ func TestWrapTLS_HandshakeFailure_WrongCA(t *testing.T) { } r := &Report{} - got := wrapTLS(context.Background(), r,base, clientTLSConf, "kafka", "127.0.0.1:9092") + got := wrapTLS(context.Background(), r, base, clientTLSConf, "kafka", "127.0.0.1:9092") if got != nil { got.Close() t.Error("expected nil conn for untrusted cert") @@ -630,7 +630,7 @@ func TestWrapTLS_CertExpiringSoon(t *testing.T) { } r := &Report{} - got := wrapTLS(context.Background(), r,base, clientTLSConf, "kafka", "127.0.0.1:9092") + got := wrapTLS(context.Background(), r, base, clientTLSConf, "kafka", "127.0.0.1:9092") if got == nil { t.Fatal("expected non-nil conn (cert expiring soon, but still valid)") } diff --git a/cmd/kshark/trend_test.go b/cmd/kshark/trend_test.go index 22d7e1a..15da946 100644 --- a/cmd/kshark/trend_test.go +++ b/cmd/kshark/trend_test.go @@ -241,13 +241,8 @@ func TestLoadReportsFromDir(t *testing.T) { t.Fatalf("loaded %d trend entries, want 3", len(trends)) } - // Verify they are in order by sorting (same as runTrend) - for i := 1; i < len(trends); i++ { - if trends[i].StartedAt.Before(trends[i-1].StartedAt) { - // They may not be sorted from ReadDir, but the data should be valid - // runTrend sorts them, so we just verify all entries loaded correctly - } - } + // Ordering is handled by runTrend, not by loadTrendEntries, so this test + // only verifies that all entries loaded with valid data. // Verify aggregate counts for _, te := range trends { diff --git a/cmd/kshark/util.go b/cmd/kshark/util.go index 2062ed7..66cd299 100644 --- a/cmd/kshark/util.go +++ b/cmd/kshark/util.go @@ -58,7 +58,7 @@ func initScanLog(path string, logFormat string) (*os.File, error) { // credential leakage in reports. Redacts values following known secret flags. func redactArgs(args []string) []string { secretFlags := map[string]bool{ - "-connect-basic-auth": true, + "-connect-basic-auth": true, "-connect-bearer-token": true, } out := make([]string, len(args)) diff --git a/internal/connectapi/config_parser.go b/internal/connectapi/config_parser.go index 3c5157e..f0189b9 100644 --- a/internal/connectapi/config_parser.go +++ b/internal/connectapi/config_parser.go @@ -16,15 +16,15 @@ import ( type ConnectorType string const ( - TypeMongoDB ConnectorType = "mongodb" - TypeDB2 ConnectorType = "db2" - TypePostgreSQL ConnectorType = "postgresql" - TypeMySQL ConnectorType = "mysql" - TypeSQLServer ConnectorType = "sqlserver" - TypeOracle ConnectorType = "oracle" - TypeRedis ConnectorType = "redis" - TypeElasticsearch ConnectorType = "elasticsearch" - TypeUnknown ConnectorType = "unknown" + TypeMongoDB ConnectorType = "mongodb" + TypeDB2 ConnectorType = "db2" + TypePostgreSQL ConnectorType = "postgresql" + TypeMySQL ConnectorType = "mysql" + TypeSQLServer ConnectorType = "sqlserver" + TypeOracle ConnectorType = "oracle" + TypeRedis ConnectorType = "redis" + TypeElasticsearch ConnectorType = "elasticsearch" + TypeUnknown ConnectorType = "unknown" ) // ParsedConnector holds the result of parsing a connector configuration. diff --git a/internal/connectapi/config_parser_test.go b/internal/connectapi/config_parser_test.go index 86ad69c..52d8e82 100644 --- a/internal/connectapi/config_parser_test.go +++ b/internal/connectapi/config_parser_test.go @@ -135,9 +135,9 @@ func TestParseConnectorConfig_MongoDB(t *testing.T) { func TestParseConnectorConfig_DB2(t *testing.T) { cfg := map[string]string{ - "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", - "connection.url": "jdbc:db2://db2host:50000/PRODDB:sslConnection=true;", - "connection.user": "db2admin", + "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", + "connection.url": "jdbc:db2://db2host:50000/PRODDB:sslConnection=true;", + "connection.user": "db2admin", "connection.password": "secret", } @@ -168,9 +168,9 @@ func TestParseConnectorConfig_DB2(t *testing.T) { func TestParseConnectorConfig_PostgreSQL(t *testing.T) { cfg := map[string]string{ - "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", - "connection.url": "jdbc:postgresql://pghost:5432/appdb?sslmode=require", - "connection.user": "pguser", + "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", + "connection.url": "jdbc:postgresql://pghost:5432/appdb?sslmode=require", + "connection.user": "pguser", "connection.password": "secret", } @@ -271,9 +271,9 @@ func TestLoadConnectorConfigFile_InvalidJSON(t *testing.T) { func TestExtractMySQLTarget(t *testing.T) { cfg := map[string]string{ - "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", - "connection.url": "jdbc:mysql://myhost:3306/testdb?useSSL=true", - "connection.user": "myuser", + "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", + "connection.url": "jdbc:mysql://myhost:3306/testdb?useSSL=true", + "connection.user": "myuser", "connection.password": "mypass", } @@ -307,9 +307,9 @@ func TestExtractMySQLTarget(t *testing.T) { func TestExtractSQLServerTarget(t *testing.T) { cfg := map[string]string{ - "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", - "connection.url": "jdbc:sqlserver://sqlhost:1433;databaseName=mydb;encrypt=true", - "connection.user": "sqluser", + "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", + "connection.url": "jdbc:sqlserver://sqlhost:1433;databaseName=mydb;encrypt=true", + "connection.user": "sqluser", "connection.password": "sqlpass", } @@ -343,9 +343,9 @@ func TestExtractSQLServerTarget(t *testing.T) { func TestExtractOracleTarget(t *testing.T) { cfg := map[string]string{ - "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", - "connection.url": "jdbc:oracle:thin:@orahost:1521/ORCL", - "connection.user": "orauser", + "connector.class": "io.confluent.connect.jdbc.JdbcSourceConnector", + "connection.url": "jdbc:oracle:thin:@orahost:1521/ORCL", + "connection.user": "orauser", "connection.password": "orapass", } @@ -463,7 +463,7 @@ func TestExtractElasticsearchTarget(t *testing.T) { wantHost string wantPort int wantTLS bool - wantUsername string + wantUsername string wantPassword string wantErr bool }{ @@ -480,7 +480,7 @@ func TestExtractElasticsearchTarget(t *testing.T) { { name: "HTTP elasticsearch.url", cfg: map[string]string{ - "connector.class": "io.confluent.connect.elasticsearch.ElasticsearchSinkConnector", + "connector.class": "io.confluent.connect.elasticsearch.ElasticsearchSinkConnector", "elasticsearch.url": "http://eshost:9200", }, wantHost: "eshost", @@ -490,15 +490,15 @@ func TestExtractElasticsearchTarget(t *testing.T) { { name: "with connection.user and password", cfg: map[string]string{ - "connector.class": "io.confluent.connect.elasticsearch.ElasticsearchSinkConnector", - "connection.url": "https://eshost:9200", - "connection.user": "esuser", + "connector.class": "io.confluent.connect.elasticsearch.ElasticsearchSinkConnector", + "connection.url": "https://eshost:9200", + "connection.user": "esuser", "connection.password": "espass", }, wantHost: "eshost", wantPort: 9200, wantTLS: true, - wantUsername: "esuser", + wantUsername: "esuser", wantPassword: "espass", }, { @@ -510,7 +510,7 @@ func TestExtractElasticsearchTarget(t *testing.T) { wantHost: "eshost", wantPort: 9200, wantTLS: true, - wantUsername: "user", + wantUsername: "user", wantPassword: "pass", }, { diff --git a/internal/connectapi/redact_test.go b/internal/connectapi/redact_test.go index 838c8a4..c38817f 100644 --- a/internal/connectapi/redact_test.go +++ b/internal/connectapi/redact_test.go @@ -7,12 +7,12 @@ import ( func TestRedactConnectorConfig(t *testing.T) { cfg := map[string]string{ - "connector.class": "com.mongodb.kafka.connect.MongoSinkConnector", - "connection.uri": "mongodb+srv://user:pass@host/db", + "connector.class": "com.mongodb.kafka.connect.MongoSinkConnector", + "connection.uri": "mongodb+srv://user:pass@host/db", "connection.password": "secret123", - "database": "analytics", - "api.key": "mykey", - "api.secret": "mysecret", + "database": "analytics", + "api.key": "mykey", + "api.secret": "mysecret", } redacted := RedactConnectorConfig(cfg) @@ -151,8 +151,8 @@ func TestRedactMongoURI_ContainsRedactedMarker(t *testing.T) { func TestRedactConnectorConfig_TokenField(t *testing.T) { cfg := map[string]string{ - "bearer.token": "secret-token-value", - "normal.field": "visible", + "bearer.token": "secret-token-value", + "normal.field": "visible", } redacted := RedactConnectorConfig(cfg) if redacted["bearer.token"] != "[REDACTED]" { diff --git a/internal/probe/db2.go b/internal/probe/db2.go index 3e0fbad..7264326 100644 --- a/internal/probe/db2.go +++ b/internal/probe/db2.go @@ -14,7 +14,7 @@ import ( // DB2Prober probes DB2 targets using the DRDA wire protocol. type DB2Prober struct{} -func NewDB2Prober() *DB2Prober { return &DB2Prober{} } +func NewDB2Prober() *DB2Prober { return &DB2Prober{} } func (p *DB2Prober) Type() string { return "db2" } // DRDA code points @@ -30,18 +30,18 @@ const ( cpRDBNFNRM uint16 = 0x2211 // RDB Not Found // Parameter code points - cpSRVNAM uint16 = 0x116D // Server Name - cpSRVRLSLV uint16 = 0x115A // Server Release Level - cpEXTNAM uint16 = 0x115E // External Name - cpMGRLVLLS uint16 = 0x1404 // Manager Level List - cpSECMEC uint16 = 0x11A2 // Security Mechanism - cpSECCHKCD uint16 = 0x11A4 // Security Check Code - cpUSRID uint16 = 0x11A0 // User ID - cpPASSWORD uint16 = 0x11A1 // Password - cpRDBNAM uint16 = 0x2110 // RDB Name - cpPRDID uint16 = 0x112E // Product ID + cpSRVNAM uint16 = 0x116D // Server Name + cpSRVRLSLV uint16 = 0x115A // Server Release Level + cpEXTNAM uint16 = 0x115E // External Name + cpMGRLVLLS uint16 = 0x1404 // Manager Level List + cpSECMEC uint16 = 0x11A2 // Security Mechanism + cpSECCHKCD uint16 = 0x11A4 // Security Check Code + cpUSRID uint16 = 0x11A0 // User ID + cpPASSWORD uint16 = 0x11A1 // Password + cpRDBNAM uint16 = 0x2110 // RDB Name + cpPRDID uint16 = 0x112E // Product ID cpTYPDEFNAM uint16 = 0x002F // Type Definition Name - cpCRRTKN uint16 = 0x2135 // Correlation Token + cpCRRTKN uint16 = 0x2135 // Correlation Token cpRDBACSCLS uint16 = 0x210F // RDB Access Manager Class secUSRIDPWD uint16 = 0x0003 // User ID + Password mechanism @@ -252,7 +252,7 @@ func (p *DB2Prober) Probe(ctx context.Context, target ProbeTarget) []ProbeStep { func buildDSSHeader(length uint16, chainBit bool, correlationID uint16) []byte { buf := make([]byte, 6) binary.BigEndian.PutUint16(buf[0:2], length) // total length including header - buf[2] = 0xD0 // magic byte + buf[2] = 0xD0 // magic byte if chainBit { buf[3] = 0x41 // request, chained } else { diff --git a/internal/probe/db2_test.go b/internal/probe/db2_test.go index 1c7d329..0a4020e 100644 --- a/internal/probe/db2_test.go +++ b/internal/probe/db2_test.go @@ -130,9 +130,9 @@ func TestEBCDICRoundTrip(t *testing.T) { func TestParseSecurityCheckCode(t *testing.T) { // Build a mock SECCHKRD response data with SECCHKCD = 0x0000 (success) data := make([]byte, 6) - binary.BigEndian.PutUint16(data[0:2], 6) // length + binary.BigEndian.PutUint16(data[0:2], 6) // length binary.BigEndian.PutUint16(data[2:4], cpSECCHKCD) // code point - binary.BigEndian.PutUint16(data[4:6], 0x0000) // success + binary.BigEndian.PutUint16(data[4:6], 0x0000) // success code, err := parseSecurityCheckCode(data) if err != nil { diff --git a/internal/probe/elasticsearch_test.go b/internal/probe/elasticsearch_test.go index b2bb892..b1a5608 100644 --- a/internal/probe/elasticsearch_test.go +++ b/internal/probe/elasticsearch_test.go @@ -425,10 +425,10 @@ func TestElasticsearchProber_ConcurrentProbes(t *testing.T) { func TestParseHTTPStatusCode(t *testing.T) { tests := []struct { - name string - line string - wantCode int - wantErr bool + name string + line string + wantCode int + wantErr bool }{ { name: "HTTP 200", @@ -479,10 +479,10 @@ func TestParseHTTPStatusCode(t *testing.T) { func TestParseESRootResponse(t *testing.T) { tests := []struct { - name string - body string - wantCluster string - wantVersion string + name string + body string + wantCluster string + wantVersion string }{ { name: "full response", diff --git a/internal/probe/mongodb.go b/internal/probe/mongodb.go index fe27da1..99a2632 100644 --- a/internal/probe/mongodb.go +++ b/internal/probe/mongodb.go @@ -15,8 +15,8 @@ import ( // MongoProber probes MongoDB/Atlas targets. type MongoProber struct{} -func NewMongoProber() *MongoProber { return &MongoProber{} } -func (p *MongoProber) Type() string { return "mongodb" } +func NewMongoProber() *MongoProber { return &MongoProber{} } +func (p *MongoProber) Type() string { return "mongodb" } func (p *MongoProber) Probe(ctx context.Context, target ProbeTarget) []ProbeStep { var steps []ProbeStep diff --git a/internal/probe/mongodb_test.go b/internal/probe/mongodb_test.go index cbedef8..e6c93d4 100644 --- a/internal/probe/mongodb_test.go +++ b/internal/probe/mongodb_test.go @@ -242,10 +242,10 @@ func TestClassifyMongoError(t *testing.T) { func TestBuildMongoURI(t *testing.T) { tests := []struct { - name string - target ProbeTarget - wantPfx string // expected URI prefix - wantParts []string // substrings that must appear + name string + target ProbeTarget + wantPfx string // expected URI prefix + wantParts []string // substrings that must appear wantAbsent []string // substrings that must not appear }{ { diff --git a/internal/probe/mysql.go b/internal/probe/mysql.go index 7c99fec..8232b8e 100644 --- a/internal/probe/mysql.go +++ b/internal/probe/mysql.go @@ -14,7 +14,7 @@ import ( // MySQLProber probes MySQL targets using the MySQL wire protocol handshake. type MySQLProber struct{} -func NewMySQLProber() *MySQLProber { return &MySQLProber{} } +func NewMySQLProber() *MySQLProber { return &MySQLProber{} } func (p *MySQLProber) Type() string { return "mysql" } // MySQL protocol constants. @@ -22,11 +22,11 @@ const ( mysqlDefaultPort = 3306 // Capability flags (selected) - mysqlClientProtocol41 uint32 = 0x00000200 - mysqlClientSecureConn uint32 = 0x00008000 - mysqlClientPluginAuth uint32 = 0x00080000 - mysqlClientConnectDB uint32 = 0x00000008 - mysqlClientSSL uint32 = 0x00000800 + mysqlClientProtocol41 uint32 = 0x00000200 + mysqlClientSecureConn uint32 = 0x00008000 + mysqlClientPluginAuth uint32 = 0x00080000 + mysqlClientConnectDB uint32 = 0x00000008 + mysqlClientSSL uint32 = 0x00000800 // Packet types mysqlPacketOK byte = 0x00 diff --git a/internal/probe/mysql_test.go b/internal/probe/mysql_test.go index a81eaf3..5992aed 100644 --- a/internal/probe/mysql_test.go +++ b/internal/probe/mysql_test.go @@ -91,8 +91,8 @@ func buildMockMySQLGreeting(serverVersion string, connID uint32) []byte { func buildMockMySQLOK() []byte { var payload bytes.Buffer payload.WriteByte(mysqlPacketOK) - payload.WriteByte(0) // affected rows - payload.WriteByte(0) // last insert id + payload.WriteByte(0) // affected rows + payload.WriteByte(0) // last insert id binary.Write(&payload, binary.LittleEndian, uint16(0x0002)) // status binary.Write(&payload, binary.LittleEndian, uint16(0)) // warnings return writeMySQLPacket(payload.Bytes(), 2) @@ -385,10 +385,10 @@ func TestClassifyMySQLAuthResponse(t *testing.T) { } tests := []struct { - name string - pkt []byte - wantStatus string - wantLayer string + name string + pkt []byte + wantStatus string + wantLayer string wantInDetail string }{ { diff --git a/internal/probe/oracle.go b/internal/probe/oracle.go index 180791b..fbf8da9 100644 --- a/internal/probe/oracle.go +++ b/internal/probe/oracle.go @@ -236,22 +236,22 @@ func buildTNSConnect(connectDescriptor string) []byte { // TNS Header (8 bytes) binary.Write(&buf, binary.BigEndian, uint16(totalLen)) // Packet length binary.Write(&buf, binary.BigEndian, uint16(0)) // Packet checksum - buf.WriteByte(tnsPacketConnect) // Packet type + buf.WriteByte(tnsPacketConnect) // Packet type buf.WriteByte(0) // Reserved binary.Write(&buf, binary.BigEndian, uint16(0)) // Header checksum // Connect Header (24 bytes) - binary.Write(&buf, binary.BigEndian, uint16(0x0139)) // Version (313) - binary.Write(&buf, binary.BigEndian, uint16(0x012C)) // Compatible version (300) - binary.Write(&buf, binary.BigEndian, uint16(0x0000)) // Service options - binary.Write(&buf, binary.BigEndian, uint16(0x2000)) // SDU size (8192) - binary.Write(&buf, binary.BigEndian, uint16(0x7FFF)) // TDU size (32767) - binary.Write(&buf, binary.BigEndian, uint16(0x7F08)) // NT protocol characteristics - binary.Write(&buf, binary.BigEndian, uint16(0x0000)) // Max packets before ACK - binary.Write(&buf, binary.BigEndian, uint16(0x0100)) // Byte order + binary.Write(&buf, binary.BigEndian, uint16(0x0139)) // Version (313) + binary.Write(&buf, binary.BigEndian, uint16(0x012C)) // Compatible version (300) + binary.Write(&buf, binary.BigEndian, uint16(0x0000)) // Service options + binary.Write(&buf, binary.BigEndian, uint16(0x2000)) // SDU size (8192) + binary.Write(&buf, binary.BigEndian, uint16(0x7FFF)) // TDU size (32767) + binary.Write(&buf, binary.BigEndian, uint16(0x7F08)) // NT protocol characteristics + binary.Write(&buf, binary.BigEndian, uint16(0x0000)) // Max packets before ACK + binary.Write(&buf, binary.BigEndian, uint16(0x0100)) // Byte order binary.Write(&buf, binary.BigEndian, uint16(len(connectData))) // Data length binary.Write(&buf, binary.BigEndian, dataOffset) // Data offset - binary.Write(&buf, binary.BigEndian, uint32(0)) // Max receivable data + binary.Write(&buf, binary.BigEndian, uint32(0)) // Max receivable data // Connect data buf.Write(connectData) diff --git a/internal/probe/oracle_test.go b/internal/probe/oracle_test.go index 58f804f..a0de6a7 100644 --- a/internal/probe/oracle_test.go +++ b/internal/probe/oracle_test.go @@ -65,8 +65,8 @@ func buildTNSPacket(pktType byte, payload []byte) []byte { // TNS Header (8 bytes) binary.Write(&buf, binary.BigEndian, uint16(totalLen)) // Packet length binary.Write(&buf, binary.BigEndian, uint16(0)) // Packet checksum - buf.WriteByte(pktType) // Packet type - buf.WriteByte(0) // Reserved + buf.WriteByte(pktType) // Packet type + buf.WriteByte(0) // Reserved binary.Write(&buf, binary.BigEndian, uint16(0)) // Header checksum if payload != nil { diff --git a/internal/probe/postgres.go b/internal/probe/postgres.go index 28942a4..1e7a20f 100644 --- a/internal/probe/postgres.go +++ b/internal/probe/postgres.go @@ -12,8 +12,8 @@ import ( // PostgresProber probes PostgreSQL targets. type PostgresProber struct{} -func NewPostgresProber() *PostgresProber { return &PostgresProber{} } -func (p *PostgresProber) Type() string { return "postgresql" } +func NewPostgresProber() *PostgresProber { return &PostgresProber{} } +func (p *PostgresProber) Type() string { return "postgresql" } func (p *PostgresProber) Probe(ctx context.Context, target ProbeTarget) []ProbeStep { var steps []ProbeStep diff --git a/internal/probe/redis.go b/internal/probe/redis.go index fd8709b..4b52247 100644 --- a/internal/probe/redis.go +++ b/internal/probe/redis.go @@ -12,7 +12,7 @@ import ( // RedisProber probes Redis targets using the RESP wire protocol. type RedisProber struct{} -func NewRedisProber() *RedisProber { return &RedisProber{} } +func NewRedisProber() *RedisProber { return &RedisProber{} } func (p *RedisProber) Type() string { return "redis" } const ( @@ -410,4 +410,3 @@ func parseRedisInfoVersion(info string) string { } return "" } - diff --git a/internal/probe/redis_test.go b/internal/probe/redis_test.go index 31d3ed4..66aa3c6 100644 --- a/internal/probe/redis_test.go +++ b/internal/probe/redis_test.go @@ -478,9 +478,9 @@ func TestClassifyRedisAuthResponse(t *testing.T) { func TestParseRedisInfoVersion(t *testing.T) { tests := []struct { - name string - info string - want string + name string + info string + want string }{ { name: "standard info", diff --git a/internal/probe/sqlserver.go b/internal/probe/sqlserver.go index 7e7460d..1eab7b4 100644 --- a/internal/probe/sqlserver.go +++ b/internal/probe/sqlserver.go @@ -21,9 +21,9 @@ const ( tdsDefaultPort = 1433 // TDS packet types - tdsPacketPreLogin byte = 0x12 - tdsPacketResponse byte = 0x04 - tdsPacketLogin7 byte = 0x10 + tdsPacketPreLogin byte = 0x12 + tdsPacketResponse byte = 0x04 + tdsPacketLogin7 byte = 0x10 // TDS packet status tdsStatusEOM byte = 0x01 // end of message @@ -37,10 +37,10 @@ const ( tdsPreLoginTerminator byte = 0xFF // Encryption values - tdsEncryptOff byte = 0x00 - tdsEncryptOn byte = 0x01 - tdsEncryptNotSup byte = 0x02 - tdsEncryptRequired byte = 0x03 + tdsEncryptOff byte = 0x00 + tdsEncryptOn byte = 0x01 + tdsEncryptNotSup byte = 0x02 + tdsEncryptRequired byte = 0x03 ) func (p *SQLServerProber) Probe(ctx context.Context, target ProbeTarget) (steps []ProbeStep) { diff --git a/internal/probe/sqlserver_test.go b/internal/probe/sqlserver_test.go index effbe44..7cbb003 100644 --- a/internal/probe/sqlserver_test.go +++ b/internal/probe/sqlserver_test.go @@ -307,8 +307,8 @@ func TestSQLServerProber_WrongResponseType(t *testing.T) { func TestSQLServerProber_EncryptionValues(t *testing.T) { tests := []struct { - name string - encryption byte + name string + encryption byte wantInDetail string }{ {name: "encrypt OFF", encryption: tdsEncryptOff, wantInDetail: "OFF"}, @@ -371,11 +371,11 @@ func TestTDSEncryptionString(t *testing.T) { func TestParseTDSPreLoginResponse(t *testing.T) { tests := []struct { - name string - data []byte - wantVer string - wantEnc byte - wantErr bool + name string + data []byte + wantVer string + wantEnc byte + wantErr bool }{ { name: "empty data", @@ -391,15 +391,15 @@ func TestParseTDSPreLoginResponse(t *testing.T) { wantErr: false, }, { - name: "truncated option header", - data: []byte{tdsPreLoginVersion, 0x00}, // only 2 bytes, need 5 + name: "truncated option header", + data: []byte{tdsPreLoginVersion, 0x00}, // only 2 bytes, need 5 wantErr: true, }, { name: "valid response", data: func() []byte { // Build a valid pre-login response with VERSION and ENCRYPTION - headerSize := 2*5 + 1 // 2 options * 5 + terminator + headerSize := 2*5 + 1 // 2 options * 5 + terminator versionData := []byte{15, 0, 0x10, 0x10, 0x00, 0x00} // 15.0.4112 encData := []byte{tdsEncryptOff} From cbcfe947a3633dc7f3be8ff50dd6de6775e575d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mirko=20K=C3=A4mpf?= Date: Wed, 17 Jun 2026 16:16:13 +0200 Subject: [PATCH 2/2] ci: pin setup-go to 1.25 to match go.mod (fixes the deps step) setup-go v6 sets GOTOOLCHAIN=local, so the pinned go-version 1.23 no longer auto-upgrades to the 1.25 the module requires, and the Download dependencies step fails with 'go.mod requires go >= 1.25.0 (running go 1.23.12; GOTOOLCHAIN=local)'. Pin the CI Go to 1.25 so build + lint run on the module's target version. Co-Authored-By: Claude Opus 4.8 (1M context) --- .github/workflows/build-and-release.yml | 4 ++-- .github/workflows/security.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index 3e05175..d5c3388 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -21,7 +21,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: '1.23' + go-version: '1.25' - name: Download dependencies run: go mod download @@ -76,7 +76,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v6 with: - go-version: '1.23' + go-version: '1.25' - name: Install cosign uses: sigstore/cosign-installer@v3 diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 1b70cc4..e94b778 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -17,7 +17,7 @@ jobs: - uses: actions/setup-go@v6 with: - go-version: '1.23' + go-version: '1.25' - name: Install govulncheck run: go install golang.org/x/vuln/cmd/govulncheck@latest