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..bec718e --- /dev/null +++ b/.golangci.yaml @@ -0,0 +1,29 @@ +# See https://golangci-lint.run/usage/configuration/ +version: "2" + +linters: + enable: + - govet + - errcheck + - staticcheck + - unused + - ineffassign + - misspell + - revive + settings: + govet: + enable-all: true + disable: + - fieldalignment + - shadow + misspell: + locale: US + revive: + rules: + - name: exported + arguments: + - "checkPrivateReceivers" + +formatters: + enable: + - goimports diff --git a/logger.go b/logger.go index 8d0775a..0e5c29f 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 { @@ -329,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) @@ -486,7 +491,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)