From 6b149db0a8ef05b0329e39d5371a65acf0c62b3d Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Wed, 10 Dec 2025 09:21:19 +0000 Subject: [PATCH 1/2] ci: add golangci-lint job - Add lint job to CI workflow using golangci-lint-action v7 with golangci-lint v2.1.6 - Create .golangci.yaml config with standard linters (govet, errcheck, staticcheck, unused, ineffassign, misspell, revive) and goimports formatter - Fix lint issues: - Add package comment to logger.go - Check error return values for Close() calls - Rename unused function parameters to _ - Update Go version to 1.24 to match go.mod --- .github/workflows/ci.yaml | 18 +++++++++++++++++- .golangci.yaml | 32 ++++++++++++++++++++++++++++++++ logger.go | 10 ++++++++-- logger_test.go | 8 +++++--- main.go | 6 ++++-- 5 files changed, 66 insertions(+), 8 deletions(-) create mode 100644 .golangci.yaml diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index eb8d845..6e4a1c3 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -33,7 +33,23 @@ jobs: - name: Setup Go uses: actions/setup-go@v5 with: - go-version: "~1.22" + go-version: "~1.24" - name: Test run: go test ./... -race + + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v5 + + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version: "~1.24" + + - name: golangci-lint + uses: golangci/golangci-lint-action@v7 + with: + version: v2.1.6 diff --git a/.golangci.yaml b/.golangci.yaml new file mode 100644 index 0000000..3e0992d --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,32 @@ +# See https://golangci-lint.run/usage/configuration/ +version: "2" + +linters: + enable: + - govet + - errcheck + - staticcheck + - unused + - ineffassign + - misspell + - revive + +formatters: + enable: + - goimports + +linters-settings: + govet: + enable-all: true + disable: + - fieldalignment + - shadow + + misspell: + locale: US + + revive: + rules: + - name: exported + arguments: + - "checkPrivateReceivers" diff --git a/logger.go b/logger.go index 8d0775a..92bbb59 100644 --- a/logger.go +++ b/logger.go @@ -1,3 +1,5 @@ +// Package main implements coder-logstream-kube, a Kubernetes controller +// that streams pod logs to the Coder agent API. package main import ( @@ -87,7 +89,9 @@ func newPodEventLogger(ctx context.Context, opts podEventLoggerOptions) (*podEve // If no namespaces are provided, we listen for events in all namespaces. if len(opts.namespaces) == 0 { - reporter.initNamespace("") + if err := reporter.initNamespace(""); err != nil { + return nil, fmt.Errorf("init namespace: %w", err) + } } else { for _, namespace := range opts.namespaces { if err := reporter.initNamespace(namespace); err != nil { @@ -486,7 +490,9 @@ func (l *logQueuer) newLogger(ctx context.Context, log agentLog) (agentLoggerLif lifecycle := agentLoggerLifecycle{ scriptLogger: sl, close: func() { - defer arpc.DRPCConn().Close() + defer func() { + _ = arpc.DRPCConn().Close() + }() defer client.SDK.HTTPClient.CloseIdleConnections() // We could be stopping for reasons other than the timeout. If // so, stop the timer. diff --git a/logger_test.go b/logger_test.go index 259be40..49a1836 100644 --- a/logger_test.go +++ b/logger_test.go @@ -989,7 +989,9 @@ func newFakeAgentAPI(t *testing.T) *fakeAgentAPI { } ctx, wsNetConn := codersdk.WebsocketNetConn(ctx, conn, websocket.MessageBinary) - defer wsNetConn.Close() + defer func() { + _ = wsNetConn.Close() + }() config := yamux.DefaultConfig() config.LogOutput = io.Discard @@ -1012,7 +1014,7 @@ func newFakeAgentAPI(t *testing.T) *fakeAgentAPI { return fakeAPI } -func newFailingAgentAPI(t *testing.T) *fakeAgentAPI { +func newFailingAgentAPI(_ *testing.T) *fakeAgentAPI { fakeAPI := &fakeAgentAPI{ disconnect: make(chan struct{}), logs: make(chan []*proto.Log), @@ -1020,7 +1022,7 @@ func newFailingAgentAPI(t *testing.T) *fakeAgentAPI { } // Create a server that always returns 401 Unauthorized errors - fakeAPI.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + fakeAPI.server = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { http.Error(w, "Unauthorized", http.StatusUnauthorized) })) diff --git a/main.go b/main.go index 4c65be5..ce425f8 100644 --- a/main.go +++ b/main.go @@ -34,7 +34,7 @@ func root() *cobra.Command { cmd := &cobra.Command{ Use: "coder-logstream-kube", Short: "Stream Kubernetes Pod events to the Coder startup logs.", - RunE: func(cmd *cobra.Command, args []string) error { + RunE: func(cmd *cobra.Command, _ []string) error { if coderURL == "" { return fmt.Errorf("--coder-url is required") } @@ -84,7 +84,9 @@ func root() *cobra.Command { if err != nil { return fmt.Errorf("create pod event reporter: %w", err) } - defer reporter.Close() + defer func() { + _ = reporter.Close() + }() select { case err := <-reporter.errChan: return fmt.Errorf("pod event reporter: %w", err) From 3976724f8a07d57b05ad13c66a5b211c70f6ca7e Mon Sep 17 00:00:00 2001 From: Kacper Sawicki Date: Wed, 10 Dec 2025 09:31:54 +0000 Subject: [PATCH 2/2] fix: use correct golangci-lint v2 config schema - Move linters-settings to linters.settings (v2 schema change) - Add comment to exported Close method --- .golangci.yaml | 29 +++++++++++++---------------- logger.go | 1 + 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/.golangci.yaml b/.golangci.yaml index 3e0992d..bec718e 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -10,23 +10,20 @@ linters: - ineffassign - misspell - revive + settings: + govet: + enable-all: true + disable: + - fieldalignment + - shadow + misspell: + locale: US + revive: + rules: + - name: exported + arguments: + - "checkPrivateReceivers" formatters: enable: - goimports - -linters-settings: - govet: - enable-all: true - disable: - - fieldalignment - - shadow - - misspell: - locale: US - - revive: - rules: - - name: exported - arguments: - - "checkPrivateReceivers" diff --git a/logger.go b/logger.go index 92bbb59..0e5c29f 100644 --- a/logger.go +++ b/logger.go @@ -333,6 +333,7 @@ func (p *podEventLogger) sendDelete(token string) { } } +// Close stops the pod event logger and releases all resources. func (p *podEventLogger) Close() error { p.cancelFunc() close(p.stopChan)