Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 106 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

version: "2"

run:
timeout: 5m
# Lint everything by default. The tools modules under hack/tools/ have their
# own go.mod files and are not part of `./...` of the root module, so they
# are naturally excluded from this run.

linters:
# The "standard" preset enables errcheck, govet, ineffassign, staticcheck,
# and unused. This is the conservative set; new linters can be added once
# the codebase is clean for the basics.
default: standard

settings:
errcheck:
# Functions where ignoring the return is idiomatic in this codebase.
# Note: errcheck's exclude-functions matches on the static receiver
# type, not the resolved interface. Patterns for the common
# concrete-type cases (X.Close on *os.File, *grpc.ClientConn, etc.)
# are handled below as message-pattern rules in exclusions.rules.
exclude-functions:
- fmt.Fprintf
- fmt.Fprintln
- fmt.Fprint
# net/http handler writes: surfacing a write error from a handler
# has no recovery path; the connection is already failing.
- (net/http.ResponseWriter).Write
# cobra flag-required bindings: only fail if the flag name itself is
# wrong, which is a programming error caught at startup.
- (*github.com/spf13/cobra.Command).MarkFlagRequired
# k8s informer event-handler / indexer registrations: failures here
# mean the controller is fundamentally misconfigured at startup.
- (k8s.io/client-go/tools/cache.SharedIndexInformer).AddEventHandler
- (k8s.io/client-go/tools/cache.SharedIndexInformer).AddIndexers

exclusions:
# Built-in presets that suppress the most common idiomatic false
# positives across the standard linters.
presets:
- common-false-positives
- legacy

paths:
# Tool modules have their own go.mod and dependency trees.
- hack/tools
# Third-party license bundles vendored under LICENSES/.
- LICENSES

rules:
# Generated code: ignore findings entirely.
- path: '\.pb\.go$'
linters: [errcheck, govet, ineffassign, staticcheck, unused]
- path: '\.pb\.gw\.go$'
linters: [errcheck, govet, ineffassign, staticcheck, unused]
- path: 'zz_generated.*\.go$'
linters: [errcheck, govet, ineffassign, staticcheck, unused]
# Kubernetes client-gen / informer-gen / lister-gen output.
- path: '^pkg/client/'
linters: [errcheck, govet, ineffassign, staticcheck, unused]
# Tests routinely discard error returns from setup helpers.
- path: '_test\.go'
linters:
- errcheck
# Suppress staticcheck QF* (quickfix) recommendations. They are
# stylistic rewrites rather than bug detectors and would generate a
# large amount of churn if applied indiscriminately. Run
# `make lint-fix` if you want to apply them in a dedicated cleanup.
- linters: [staticcheck]
text: '^QF[0-9]+'
# Deferred Close() returns are idiomatic in this codebase across many
# concrete types (*os.File, *grpc.ClientConn, *storage.Client,
# *gzip.Writer, *io.PipeReader, etc.). Suppress via message pattern
# rather than enumerating every receiver type.
- linters: [errcheck]
text: 'Error return value of `[^`]+\.Close` is not checked'
# os.Remove in defer cleanup paths is similarly idiomatic.
- linters: [errcheck]
text: 'Error return value of `os\.Remove` is not checked'
# json.Encoder.Encode in HTTP-handler write paths is fire-and-forget.
- linters: [errcheck]
text: 'Error return value of `\(\*encoding/json\.Encoder\)\.Encode` is not checked'
# ST1019: duplicate import aliases in extproc_out.go are pending a
# separate cleanup that will collide with an in-flight PR; suppress
# in this file for now.
- path: '^cmd/servers/atenet/app/router/extproc_out\.go$'
linters: [staticcheck]
text: '^ST1019'

issues:
max-issues-per-linter: 0
max-same-issues: 0
10 changes: 10 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ fmt:
verify-fmt:
@./hack/verify/gofmt.sh

.PHONY: lint lint-fix

# Runs golangci-lint and fails on any reported issues.
lint:
@./hack/verify/golangci-lint.sh

# Runs golangci-lint with --fix, applying auto-fixes in place.
lint-fix:
@./hack/update/golangci-lint.sh

.PHONY: verify
verify: test
$(GO) vet ./...
Expand Down
2 changes: 1 addition & 1 deletion api/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ var (
SchemeGroupVersion = GroupVersion

// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} //nolint:staticcheck // SA1019: scheme.Builder is the conventional kubebuilder pattern for api packages.

// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
Expand Down
2 changes: 1 addition & 1 deletion cmd/kubectl-ate/cmd/logs_actors.go
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ func filterAndDisplayLogLine(line, targetActorID string, w io.Writer, raw bool)

labelsAny, ok := m["logging.googleapis.com/labels"]
if !ok {
labelsAny, ok = m["labels"]
labelsAny = m["labels"]
}
var actorID string
if labelsAny != nil {
Expand Down
5 changes: 1 addition & 4 deletions cmd/servers/ateapi/controlapi/syncer.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,5 @@ func (s *WorkerPoolSyncer) syncWorkerToStore(ctx context.Context, pod *corev1.Po
}

func isWorkerEligible(pod *corev1.Pod) bool {
if pod.Status.PodIP == "" {
return false
}
return true
return pod.Status.PodIP != ""
}
2 changes: 1 addition & 1 deletion cmd/servers/ateapi/controlapi/workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,6 @@ func (w *ActorWorkflow) acquireActorLock(ctx context.Context, id string, ttl tim
return workflowCtx, func() {
cancel()
// Use context.Background() to ensure the lock is released even if the workflow context was canceled.
w.store.ReleaseLock(context.Background(), lockKey, lockValue)
w.store.ReleaseLock(context.Background(), lockKey, lockValue) //nolint:errcheck // best-effort release; the lock TTL is the safety net.
}, nil
}
2 changes: 1 addition & 1 deletion cmd/servers/atenet/app/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ func (s *RouterServer) Run(ctx context.Context) error {
g.Go(func() error {
go func() {
if err := httpServer.Serve(listener); err != nil && !errors.Is(err, http.ErrServerClosed) {
// silent shutdown
slog.WarnContext(ctx, "status HTTP server exited unexpectedly", slog.Any("err", err))
}
}()
<-ctx.Done()
Expand Down
2 changes: 1 addition & 1 deletion cmd/servers/atenet/app/router/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func TestStatuszEndpoint(t *testing.T) {
go func() {
close(statusReady)
if runErr := srv.Run(ctx); runErr != nil && !strings.Contains(runErr.Error(), "context canceled") {
// ignore task cancellation shutdowns
t.Logf("status server Run returned unexpected error: %v", runErr)
}
}()

Expand Down
20 changes: 0 additions & 20 deletions cmd/servers/ateom-gvisor/runsc.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,23 +212,3 @@ func (r *runsc) cmdState(ctx context.Context, containerName string) error {
}
return nil
}

func (r *runsc) cmdList(ctx context.Context) error {
reapLock.RLock()
defer reapLock.RUnlock()

cmd := exec.CommandContext(
ctx,
r.path,
"-log-format", "json",
"--alsologtostderr",
"-root", ateompath.RunSCStateDir(r.actorTemplateNamespace, r.actorTemplateName, r.actorID),
"list",
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
return fmt.Errorf("while running `runsc list`: %w", err)
}
return nil
}
2 changes: 1 addition & 1 deletion demos/agent-secret/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func suspendSelf(id string) {
}

creds := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true})
conn, err := grpc.Dial(apiAddr, grpc.WithTransportCredentials(creds))
conn, err := grpc.Dial(apiAddr, grpc.WithTransportCredentials(creds)) //nolint:staticcheck // SA1019: TODO migrate to grpc.NewClient.
if err != nil {
log.Printf("Failed to connect to ATE API: %v", err)
return
Expand Down
2 changes: 1 addition & 1 deletion demos/claude-code-multiplex/ui/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,7 @@ func handleGiveTask(w http.ResponseWriter, r *http.Request) {
}

func main() {
rand.Seed(time.Now().UnixNano())
rand.Seed(time.Now().UnixNano()) //nolint:staticcheck // SA1019: TODO remove; seeding is a no-op since Go 1.20.

port := envOr("PORT", defaultPort)

Expand Down
20 changes: 20 additions & 0 deletions hack/golangci-lint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/usr/bin/env bash

# Copyright 2026 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -o errexit -o nounset -o pipefail

ROOT=$(git rev-parse --show-toplevel)
"${ROOT}"/hack/run-tool.sh golangci-lint "$@"
Loading
Loading