Skip to content

ci: migrate golangci-lint to v2 and re-enable disabled workflows#11

Merged
port8080 merged 2 commits into
mainfrom
ajit/lint-config-v2-and-ci
May 8, 2026
Merged

ci: migrate golangci-lint to v2 and re-enable disabled workflows#11
port8080 merged 2 commits into
mainfrom
ajit/lint-config-v2-and-ci

Conversation

@port8080

@port8080 port8080 commented May 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Migrate .golangci.yml v1 → v2 with errcheck exclusions matching the codebase's existing policy. make check now passes cleanly (1101 tests, 0 lint findings).
  • Re-enable ci.yml and release.yml (renamed from .disabled in the initial commit, so neither has ever run). Drop Go 1.22/1.23 from the CI matrix (go.mod requires 1.24). Bump golangci/golangci-lint-action v4 → v6 (v4 predates lint v2 config support).

Why

While prepping the v0.1.10 release, two stale test assertions surfaced that should have been caught long ago:

  • TestSupportedAgents was missing AgentTypeGasCity (added to SupportedAgents in v0.1.8).
  • TestAllAgents_Detect/Codex/AGENT_ENV non-codex still asserted false after v0.1.9's e907e81 made DetectRuntime strictly authoritative for Codex (the equivalent assertion in codex_test.go was updated; this one was missed).

Both slipped past local verification and CI. Investigation: CI was renamed .disabled in 3efd314 (initial commit) and never re-enabled, while .golangci.yml was a v1 config unreadable by the installed golangci-lint v2.11.4 — so make check errored out on config load before tests ran. Nothing was gating PRs.

What's in the new lint config

  • v2 format produced by golangci-lint migrate plus targeted exclusions:
    • Skip errcheck for _test.go files (test setup/cleanup routinely ignores errors that aren't actionable in tests).
    • Exclude (io.Closer).Close, (*os.File).Close, os.Chmod, os.MkdirAll, Registry.Register, Environment.Remove, fmt.Sscanf from errcheck — these match patterns already in production code that are deliberate ignores.
    • Exclude staticcheck QF1011 (it flags var _ Iface = impl interface-conformance assertions, but the explicit type is the whole point of the pattern).

Follow-up (not in this PR)

30 errcheck warnings exist in production paths (agent.go fmt.Sscanf, agents/register.go Register calls, sessions/claudecode.go deferred file.Close, etc.) that are now hidden by the exclusion patterns. A separate pass should audit each — for genuinely safe ones, replace with explicit _ = fn() at the call site; for unsafe ones, propagate or log the error. Tracking left as a known follow-up per maintainer preference.

Test plan

  • make check passes locally (1101 tests, 0 lint findings)
  • golangci-lint run ./... reports 0 issues.
  • CI runs green on this PR (the workflows are now active)
  • Next tag push triggers release.yml and produces a GitHub release from CHANGELOG.md

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • CI now runs tests only on Go 1.24.
    • Lint action upgraded to v9 and linter tool pinned to v2.12.2.
    • Linter configuration updated to v2 format with revised default linters, formatter settings, and targeted rule exclusions for common/noise cases.

Both .github/workflows/ci.yml and release.yml were renamed to
.disabled in the initial commit of this repo, so neither tests nor
lint have ever run on PRs. Combined with .golangci.yml being v1
format (incompatible with the installed golangci-lint v2.x), this
explained how stale assertions slipped past v0.1.8 (TestSupportedAgents
missing AgentTypeGasCity) and v0.1.9 (the AGENT_ENV non-codex Codex
case in agents_comprehensive_test.go) without anyone noticing locally
or in CI.

Changes:

- Migrate .golangci.yml to v2 format using `golangci-lint migrate`.
  Add explicit errcheck exclusions to match the codebase's existing
  policy: skip _test.go files, exclude common cleanup patterns
  ((io.Closer).Close, os.Chmod, os.MkdirAll, Registry.Register,
  Environment.Remove, fmt.Sscanf). Exclude staticcheck QF1011 since
  `var _ Iface = impl` interface-conformance assertions need the
  explicit type. With these exclusions, `make check` passes cleanly.

- Re-enable ci.yml: drop Go 1.22/1.23 from the matrix (go.mod requires
  1.24), bump golangci/golangci-lint-action to v6 (v4 predates
  golangci-lint v2 config support).

- Re-enable release.yml unchanged except for the same lint-action bump.

Follow-up: 30 errcheck warnings exist in production paths (e.g.
agent.go fmt.Sscanf, agents/register.go Register calls,
sessions/claudecode.go defer file.Close) that are now hidden by
exclusion patterns. A separate pass should review whether each is
genuinely safe to ignore or should be tightened.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 8, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

Golangci-lint configuration migrated to v2 format; CI lint jobs updated to golangci/golangci-lint-action@v9 and the tool pinned to v2.12.2; Go test matrix reduced to run only Go 1.24.

Changes

Go Linting Toolchain Upgrade

Layer / File(s) Summary
Golangci-lint v2 Configuration Migration
.golangci.yml
Configuration updated to golangci-lint v2 (version: "2"); gofmt/goimports moved to formatters; preserves goimports.local-prefixes; adds errcheck function exclusions and test-file _test\.go errcheck disablement; adds staticcheck exclusion QF1011; removes legacy v1 blocks.
CI Test Matrix
.github/workflows/ci.yml
test job Go matrix narrowed from 1.22, 1.23, 1.24 to 1.24 only.
CI Lint Action
.github/workflows/ci.yml
lint job updated to golangci/golangci-lint-action@v9; tool version pinned to v2.12.2 (was latest).
Release Workflow Lint Action
.github/workflows/release.yml
Release workflow step updated to golangci/golangci-lint-action@v9 and linter version pinned to v2.12.2.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through configs, keen and spry,

Swapped to v2 beneath the sky,
Pinned the action, trimmed the test,
Now CI runs its tidy quest.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: migrating golangci-lint to v2 and re-enabling CI workflows, which matches the primary objectives.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ajit/lint-config-v2-and-ci

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (1)
.golangci.yml (1)

24-28: ⚡ Quick win

Test-file errcheck blanket exclusion may hide legitimate test bugs.

Excluding all errcheck violations in _test.go files can mask real issues where setup/teardown errors would cause test failures or false positives. For instance, failing to check errors from os.MkdirAll in test setup could result in misleading test outcomes when subsequent writes fail.

Consider narrowing exclusions to specific functions known to be safe in tests (e.g., (*testing.T).Cleanup registration), rather than suppressing all error checks in test files.

♻️ Narrower test exclusion example
-      # Test files routinely use Close/Chmod/Register without error checks
-      # for setup and cleanup. Those errors aren't actionable in tests.
-      - path: _test\.go
-        linters:
-          - errcheck
+      # Allow specific helper calls to ignore errors in tests
+      # but catch genuine logic errors
+      # (If you must exclude, list specific functions above in exclude-functions)

Alternatively, rely on the function-level exclude-functions list (lines 9-16) which already covers Close/Chmod/Register, and remove this blanket test-file exclusion.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.golangci.yml around lines 24 - 28, The current rule that disables the
errcheck linter for all files matching the _test\.go path is too broad; replace
this blanket exclusion by removing the path: _test\.go block for errcheck and
instead rely on the existing function-level exclusions (the exclude-functions
list used for Close/Chmod/Register) or add specific safe test helper functions
(e.g., testing.T.Cleanup registration) to exclude-functions; update
.golangci.yml to delete the path-based errcheck exclusion and, if needed, add
only narrowly scoped function names to exclude-functions so test setup/teardown
errors remain checked.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Around line 31-34: Update the GitHub Actions step using golangci-lint to use
golangci-lint-action@v7 (replace golangci-lint-action@v6) so it supports
golangci-lint v2.x; ensure the existing "name: golangci-lint" step and "version:
latest" remain but point to the v7+ action to avoid the "v2 is not supported by
v6" failure.

In @.golangci.yml:
- Around line 7-16: The .golangci.yml excludes suppress error checks for
operations like (io.Closer).Close, (*os.File).Close, os.Chmod, os.MkdirAll,
(github.com/sageox/agentx.Registry).Register,
(*github.com/sageox/agentx.DefaultRegistryImpl).Register,
(github.com/sageox/agentx.Environment).Remove and fmt.Sscanf which can mask real
failures; remove these entries and audit each call site: for each use of
Close/Chmod/MkdirAll/Register/Remove/Sscanf either (a) propagate the error to
the caller, (b) handle and log the error where it occurs, or (c) explicitly
ignore it with `_ = ...` plus a short comment why ignoring is safe; after
changes run golangci-lint to confirm warnings are fixed and keep only deliberate
`_ =` ignores documented inline.
- Around line 1-48: The CI failure comes from using golangci-lint v2 config
(version: "2" in .golangci.yml) while workflows reference
golangci/golangci-lint-action@v6 which only supports v1; either update all
workflow job steps that reference golangci/golangci-lint-action@v6 to use
golangci/golangci-lint-action@v7 (or later) so the action supports v2 config, or
change the config version in .golangci.yml from "2" to the v1-compatible format
(version: "1") to match the existing `@v6` action—search for occurrences of
golangci/golangci-lint-action@v6 in your workflow files or the version: "2" key
in .golangci.yml to locate where to change.

---

Nitpick comments:
In @.golangci.yml:
- Around line 24-28: The current rule that disables the errcheck linter for all
files matching the _test\.go path is too broad; replace this blanket exclusion
by removing the path: _test\.go block for errcheck and instead rely on the
existing function-level exclusions (the exclude-functions list used for
Close/Chmod/Register) or add specific safe test helper functions (e.g.,
testing.T.Cleanup registration) to exclude-functions; update .golangci.yml to
delete the path-based errcheck exclusion and, if needed, add only narrowly
scoped function names to exclude-functions so test setup/teardown errors remain
checked.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 51f9a5fd-953c-4829-be44-fc4a5f0cbc66

📥 Commits

Reviewing files that changed from the base of the PR and between 69b4879 and d7ac926.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • .github/workflows/release.yml
  • .golangci.yml

Comment thread .github/workflows/release.yml Outdated
Comment thread .golangci.yml
Comment on lines +1 to +48
version: "2"

linters:
# Default v2 linter set: errcheck, govet, ineffassign, staticcheck, unused.
# gofmt and goimports moved to formatters in v2 (configured below).
settings:
errcheck:
exclude-functions:
- (io.Closer).Close
- (*os.File).Close
- os.Chmod
- os.MkdirAll
- (github.com/sageox/agentx.Registry).Register
- (*github.com/sageox/agentx.DefaultRegistryImpl).Register
- (github.com/sageox/agentx.Environment).Remove
- fmt.Sscanf
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
rules:
# Test files routinely use Close/Chmod/Register without error checks
# for setup and cleanup. Those errors aren't actionable in tests.
- path: _test\.go
linters:
- errcheck
# QF1011 flags `var _ Iface = impl` interface-conformance assertions,
# but the explicit type is the whole point of the pattern.
- text: "QF1011"
linters:
- staticcheck

formatters:
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
- gofmt
- goimports

linters-settings:
goimports:
local-prefixes: github.com/sageox/agentx

issues:
exclude-use-default: false
settings:
goimports:
local-prefixes:
- github.com/sageox/agentx
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify the v2 configuration against golangci-lint's schema

# Check if the config is valid by running golangci-lint with --version to see output
golangci-lint --version 2>/dev/null || echo "golangci-lint not installed in sandbox"

# Look for any example v2 configs or migration documentation in the repo
fd -e yml -e yaml golangci | head -20

Repository: sageox/agentx

Length of output: 148


🌐 Web query:

Is golangci-lint-action@v6 compatible with golangci-lint configuration version 2 format?

💡 Result:

No, golangci-lint-action@v6 is not compatible with golangci-lint configuration version 2 format. It is restricted to golangci-lint v1.x versions, which use config version 1.[1][2] Attempting to use golangci-lint v2 (which requires config version: "2"[3][4][5]) with v6 will throw an error: "golangci-lint v2 is not supported by golangci-lint-action v6, you must update to golangci-lint-action v7."[1] v7.0.0 and later support golangci-lint v2 only.[6] The action added JSONSchema verification (default true in later v6 releases), which fails on v2 configs with v1 tooling.[7][8]

Citations:


🌐 Web query:

golangci-lint version 2 configuration format syntax for linters.settings and formatters sections

💡 Result:

In golangci-lint version 2, the configuration uses YAML format (also supports TOML/JSON). The top-level sections are linters and formatters, each with a settings subsection for per-linter/formatter options [1][2][3]. linters.settings syntax: Nested map where keys are linter names (lowercase, matching golangci-lint linters output) and values are linter-specific options as maps or primitives. Example: linters: settings: asasalint: exclude: - Append - \.Wrapf use-builtin-exclusions: false depguard: rules: main: list-mode: lax files: - $all allow: - $gostd [2][1] formatters.settings syntax: Nested map where keys are formatter names (e.g., gci, gofmt, gofumpt, goimports, golines, swaggo) and values are formatter-specific options. Example: formatters: settings: gci: sections: - standard - default - prefix(github.com/org/project) no-inline-comments: true custom-order: true goimports: local-prefixes: - github.com/my/project golines: max-len: 120 [3][4][5] Full reference in https://github.com/golangci/golangci-lint/blob/master/.golangci.reference.yml [1][6]. Use golangci-lint linters or golangci-lint formatters for lists. Config starts with version: "2" [1].

Citations:


🏁 Script executed:

fd -e yml -e yaml | xargs grep -l "golangci-lint-action" 2>/dev/null | head -10

Repository: sageox/agentx

Length of output: 39


🏁 Script executed:

find .github/workflows -type f -name "*.yml" -o -name "*.yaml" 2>/dev/null | xargs cat 2>/dev/null | grep -A2 -B2 "golangci" 2>/dev/null || echo "No workflows found or no golangci references"

Repository: sageox/agentx

Length of output: 376


Incompatible action version for v2 configuration format.

The .golangci.yml file uses version: "2", but the workflow files reference golangci/golangci-lint-action@v6, which only supports golangci-lint v1.x configuration. This will cause CI failures with the error: "golangci-lint v2 is not supported by golangci-lint-action v6, you must update to golangci-lint-action v7."

Update the workflow files to use golangci/golangci-lint-action@v7 or later, or downgrade .golangci.yml to v1 configuration format.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.golangci.yml around lines 1 - 48, The CI failure comes from using
golangci-lint v2 config (version: "2" in .golangci.yml) while workflows
reference golangci/golangci-lint-action@v6 which only supports v1; either update
all workflow job steps that reference golangci/golangci-lint-action@v6 to use
golangci/golangci-lint-action@v7 (or later) so the action supports v2 config, or
change the config version in .golangci.yml from "2" to the v1-compatible format
(version: "1") to match the existing `@v6` action—search for occurrences of
golangci/golangci-lint-action@v6 in your workflow files or the version: "2" key
in .golangci.yml to locate where to change.

Comment thread .golangci.yml
Comment on lines +7 to +16
errcheck:
exclude-functions:
- (io.Closer).Close
- (*os.File).Close
- os.Chmod
- os.MkdirAll
- (github.com/sageox/agentx.Registry).Register
- (*github.com/sageox/agentx.DefaultRegistryImpl).Register
- (github.com/sageox/agentx.Environment).Remove
- fmt.Sscanf

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Excluding error checks creates technical debt and potential correctness risks.

The exclude-functions list suppresses error checking for operations that can fail in production:

  • os.Chmod, os.MkdirAll - filesystem permission/creation failures
  • (io.Closer).Close, (*os.File).Close - resource cleanup failures
  • Registry.Register - registration failures
  • fmt.Sscanf - parse failures

While the PR objectives acknowledge ~30 production-path errcheck warnings are hidden, these exclusions can mask real bugs. For example, unhandled MkdirAll failures could lead to subsequent file-write crashes, and ignored Register errors could result in missing agent registrations at runtime.

Consider auditing each suppressed case to either explicitly ignore (with inline _ = ... and comment), propagate errors, or log them. This addresses the technical debt before it compounds.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.golangci.yml around lines 7 - 16, The .golangci.yml excludes suppress error
checks for operations like (io.Closer).Close, (*os.File).Close, os.Chmod,
os.MkdirAll, (github.com/sageox/agentx.Registry).Register,
(*github.com/sageox/agentx.DefaultRegistryImpl).Register,
(github.com/sageox/agentx.Environment).Remove and fmt.Sscanf which can mask real
failures; remove these entries and audit each call site: for each use of
Close/Chmod/MkdirAll/Register/Remove/Sscanf either (a) propagate the error to
the caller, (b) handle and log the error where it occurs, or (c) explicitly
ignore it with `_ = ...` plus a short comment why ignoring is safe; after
changes run golangci-lint to confirm warnings are fixed and keep only deliberate
`_ =` ignores documented inline.

The first PR run installed golangci-lint v1.64.8 because action v6
with `version: latest` doesn't pick a v2 release. The v2 config then
fails schema verification on v1's binary. Action v7+ supports v2;
v9 is the current major. Pin lint to v2.12.2 (latest v2.x at the
time of writing) so future v3 releases don't quietly break CI.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@port8080 port8080 merged commit f633bf3 into main May 8, 2026
2 of 3 checks passed
@port8080 port8080 deleted the ajit/lint-config-v2-and-ci branch May 8, 2026 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant