Skip to content

Commit ab39950

Browse files
authored
Enable v2 linters: modernize, gocritic, gosec, unconvert (#7447)
1 parent f91302c commit ab39950

File tree

15 files changed

+204
-56
lines changed

15 files changed

+204
-56
lines changed

.golangci.yml

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ linters:
55
enable:
66
- misspell
77
- revive
8+
- modernize # Modern Go patterns (NEW in v2.6.0)
9+
- gocritic # Comprehensive opinionated linter
10+
- gosec # Security-focused
11+
# godot linter disabled - too pedantic about comment punctuation
12+
- unconvert # Remove unnecessary conversions
813
settings:
914
errcheck:
1015
exclude-functions:
@@ -17,6 +22,24 @@ linters:
1722
- os.Remove
1823
- os.RemoveAll
1924
- os.WriteFile
25+
gocritic:
26+
disabled-checks:
27+
- ifElseChain # else-if chains are often clearer than switches
28+
- singleCaseSwitch # Single case switches can be intentional for consistency
29+
- appendAssign # Appending to different variable is often intentional
30+
- unlambda # Explicit lambdas can be clearer than direct function refs
31+
- elseif # else-if pattern is acceptable
32+
- assignOp # Long form assignment can be clearer
33+
- argOrder # False positives on string contains
34+
- dupBranchBody # Duplicate branches can be intentional for clarity
35+
gosec:
36+
excludes:
37+
- G101 # Ignore "Potential hardcoded credentials" - often false positives
38+
- G602 # Ignore "slice bounds check" - handled by runtime
39+
- G115 # Ignore "integer overflow conversion" - acceptable in most cases
40+
config:
41+
G204: "0644" # Allow common file permissions in tests
42+
G306: "0644" # Allow common file permissions
2043
exclusions:
2144
generated: lax
2245
presets:
@@ -46,6 +69,130 @@ linters:
4669
- linters:
4770
- revive
4871
text: exported
72+
- linters:
73+
- gosec
74+
text: "G204" # Allow exec.Command in controlled contexts
75+
path: pkg/awmg/gateway\.go
76+
- linters:
77+
- gosec
78+
text: "G204" # Allow docker commands in actionlint
79+
path: pkg/cli/actionlint\.go
80+
- linters:
81+
- gosec
82+
text: "G204" # Allow git commands in remote_fetch
83+
path: pkg/parser/remote_fetch\.go
84+
- linters:
85+
- gosec
86+
text: "G404" # Allow math/rand for non-crypto purposes
87+
path: pkg/cli/(add_command|update_git)\.go
88+
- linters:
89+
- gosec
90+
text: "G306" # Allow 0644 permissions in test files
91+
path: _test\.go
92+
- linters:
93+
- gosec
94+
text: "G305" # Allow file path operations in logs_download
95+
path: pkg/cli/logs_download\.go
96+
- linters:
97+
- gosec
98+
text: "G110" # Allow decompression in logs_download
99+
path: pkg/cli/logs_download\.go
100+
- linters:
101+
- gocritic
102+
text: "deprecatedComment" # Allow existing deprecated comment format
103+
- linters:
104+
- gocritic
105+
text: "commentFormatting" # Allow commented out code
106+
- linters:
107+
- gocritic
108+
text: "badCall" # filepath.Join with 1 arg is acceptable
109+
- linters:
110+
- godot
111+
path: _test\.go # Don't require periods in test comments
112+
- linters:
113+
- modernize
114+
text: "omitzero" # omitzero is acceptable for struct tags
115+
- linters:
116+
- modernize
117+
text: "mapsloop" # maps.Copy requires Go 1.21+, keep compatible
118+
- linters:
119+
- modernize
120+
text: "bloop" # b.Loop() is new, keep compatible with older Go
121+
- linters:
122+
- modernize
123+
text: "minmax" # min/max builtins are Go 1.21+, keep compatible
124+
- linters:
125+
- modernize
126+
text: "forvar" # Copying loop variable is sometimes clearer
127+
- linters:
128+
- modernize
129+
text: "plusbuild" # Keep build constraint for compatibility
130+
path: shell_backslash_integration_test\.go
131+
- linters:
132+
- modernize
133+
text: "any" # Keep interface{} for clarity in schema tests
134+
path: schema_strict_documentation_test\.go
135+
- linters:
136+
- modernize
137+
text: "any" # Keep interface{} for clarity in tests
138+
path: logs_awinfo_backward_compat_test\.go
139+
- linters:
140+
- modernize
141+
text: "rangeint" # Keep traditional loops for compatibility
142+
- linters:
143+
- modernize
144+
text: "stringsseq" # SplitSeq requires Go 1.23+, keep compatible
145+
- linters:
146+
- modernize
147+
text: "slicescontains" # slices.Contains requires Go 1.21+
148+
- linters:
149+
- modernize
150+
text: "stringscutprefix" # strings.Cut* requires Go 1.20+
151+
- linters:
152+
- modernize
153+
text: "stringsbuilder" # Minor optimization, acceptable pattern
154+
- linters:
155+
- modernize
156+
text: "reflecttypefor" # TypeFor requires Go 1.22+
157+
- linters:
158+
- unconvert
159+
path: _test\.go # Allow explicit conversions in tests for clarity
160+
- linters:
161+
- gosec
162+
text: "G204" # Allow git commands in download_workflow
163+
path: pkg/cli/download_workflow\.go
164+
- linters:
165+
- gosec
166+
text: "G204" # Allow exec.Command with config in mcp_inspect
167+
path: pkg/cli/mcp_inspect\.go
168+
- linters:
169+
- gosec
170+
text: "G204" # Allow exec.Command with config in mcp_inspect_mcp
171+
path: pkg/cli/mcp_inspect_mcp\.go
172+
- linters:
173+
- gosec
174+
text: "G306" # 0755 is correct permission for executable script
175+
path: pkg/cli/mcp_inspect\.go
176+
- linters:
177+
- gosec
178+
text: "G204" # Allow docker commands in poutine
179+
path: pkg/cli/poutine\.go
180+
- linters:
181+
- gosec
182+
text: "G204" # Allow node command in tests
183+
path: pkg/workflow/js_comments_test\.go
184+
- linters:
185+
- gosec
186+
text: "G204" # Allow npx command in integration tests
187+
path: pkg/workflow/playwright_mcp_integration_test\.go
188+
- linters:
189+
- gosec
190+
text: "G204" # Allow exec of binary in status tests
191+
path: pkg/cli/status_command_test\.go
192+
- linters:
193+
- gosec
194+
text: "G204" # Allow docker commands in zizmor
195+
path: pkg/cli/zizmor\.go
49196
paths:
50197
- third_party$
51198
- builtin$

cmd/awmg/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"github.com/githubnext/gh-aw/pkg/console"
99
)
1010

11-
// Build-time variables
11+
// Build-time variables.
1212
var (
1313
version = "dev"
1414
)

pkg/awmg/gateway.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,26 @@ import (
2020

2121
var gatewayLog = logger.New("awmg:gateway")
2222

23-
// version is set by the main package
23+
// version is set by the main package.
2424
var version = "dev"
2525

26-
// SetVersionInfo sets the version information for the awmg package
26+
// SetVersionInfo sets the version information for the awmg package.
2727
func SetVersionInfo(v string) {
2828
version = v
2929
}
3030

31-
// GetVersion returns the current version
31+
// GetVersion returns the current version.
3232
func GetVersion() string {
3333
return version
3434
}
3535

36-
// MCPGatewayConfig represents the configuration for the MCP gateway
36+
// MCPGatewayConfig represents the configuration for the MCP gateway.
3737
type MCPGatewayConfig struct {
3838
MCPServers map[string]MCPServerConfig `json:"mcpServers"`
3939
Gateway GatewaySettings `json:"gateway,omitempty"`
4040
}
4141

42-
// MCPServerConfig represents configuration for a single MCP server
42+
// MCPServerConfig represents configuration for a single MCP server.
4343
type MCPServerConfig struct {
4444
Command string `json:"command,omitempty"`
4545
Args []string `json:"args,omitempty"`
@@ -48,7 +48,7 @@ type MCPServerConfig struct {
4848
Container string `json:"container,omitempty"`
4949
}
5050

51-
// GatewaySettings represents gateway-specific settings
51+
// GatewaySettings represents gateway-specific settings.
5252
type GatewaySettings struct {
5353
Port int `json:"port,omitempty"`
5454
APIKey string `json:"apiKey,omitempty"`

pkg/campaign/template.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ var projectUpdateInstructionsTemplate string
2020
//go:embed prompts/closing_instructions.md
2121
var closingInstructionsTemplate string
2222

23-
// CampaignPromptData holds data for rendering campaign orchestrator prompts
23+
// CampaignPromptData holds data for rendering campaign orchestrator prompts.
2424
type CampaignPromptData struct {
2525
// ProjectURL is the GitHub Project URL
2626
ProjectURL string
@@ -38,7 +38,7 @@ type CampaignPromptData struct {
3838
MaxDiscoveryPagesPerRun int
3939
}
4040

41-
// renderTemplate renders a template string with the given data
41+
// renderTemplate renders a template string with the given data.
4242
func renderTemplate(tmplStr string, data CampaignPromptData) (string, error) {
4343
// Create custom template functions for Handlebars-style conditionals
4444
funcMap := template.FuncMap{
@@ -66,7 +66,7 @@ func renderTemplate(tmplStr string, data CampaignPromptData) (string, error) {
6666
return buf.String(), nil
6767
}
6868

69-
// RenderOrchestratorInstructions renders the orchestrator instructions with the given data
69+
// RenderOrchestratorInstructions renders the orchestrator instructions with the given data.
7070
func RenderOrchestratorInstructions(data CampaignPromptData) string {
7171
result, err := renderTemplate(orchestratorInstructionsTemplate, data)
7272
if err != nil {

pkg/cli/fileutil/fileutil.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"path/filepath"
77
)
88

9-
// FileExists checks if a file exists and is not a directory
9+
// FileExists checks if a file exists and is not a directory.
1010
func FileExists(path string) bool {
1111
info, err := os.Stat(path)
1212
if err != nil {
@@ -15,7 +15,7 @@ func FileExists(path string) bool {
1515
return !info.IsDir()
1616
}
1717

18-
// DirExists checks if a directory exists
18+
// DirExists checks if a directory exists.
1919
func DirExists(path string) bool {
2020
info, err := os.Stat(path)
2121
if os.IsNotExist(err) {
@@ -24,7 +24,7 @@ func DirExists(path string) bool {
2424
return info.IsDir()
2525
}
2626

27-
// IsDirEmpty checks if a directory is empty
27+
// IsDirEmpty checks if a directory is empty.
2828
func IsDirEmpty(path string) bool {
2929
files, err := os.ReadDir(path)
3030
if err != nil {
@@ -33,7 +33,7 @@ func IsDirEmpty(path string) bool {
3333
return len(files) == 0
3434
}
3535

36-
// CopyFile copies a file from src to dst using buffered IO
36+
// CopyFile copies a file from src to dst using buffered IO.
3737
func CopyFile(src, dst string) error {
3838
in, err := os.Open(src)
3939
if err != nil {
@@ -53,7 +53,7 @@ func CopyFile(src, dst string) error {
5353
return out.Sync()
5454
}
5555

56-
// CalculateDirectorySize recursively calculates the total size of files in a directory
56+
// CalculateDirectorySize recursively calculates the total size of files in a directory.
5757
func CalculateDirectorySize(dirPath string) int64 {
5858
var totalSize int64
5959

pkg/constants/constants.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import (
55
"time"
66
)
77

8-
// CLIExtensionPrefix is the prefix used in user-facing output to refer to the CLI extension
8+
// CLIExtensionPrefix is the prefix used in user-facing output to refer to the CLI extension.
99
const CLIExtensionPrefix = "gh aw"
1010

1111
// Semantic types for measurements and identifiers
@@ -44,23 +44,24 @@ type LineLength int
4444
// func InstallTool(name string, version Version) error { ... }
4545
type Version string
4646

47-
// FeatureFlag represents a feature flag identifier
47+
// FeatureFlag represents a feature flag identifier.
4848
type FeatureFlag string
4949

50-
// MaxExpressionLineLength is the maximum length for a single line expression before breaking into multiline
50+
// MaxExpressionLineLength is the maximum length for a single line expression before breaking into multiline.
5151
const MaxExpressionLineLength LineLength = 120
5252

53-
// ExpressionBreakThreshold is the threshold for breaking long lines at logical points
53+
// ExpressionBreakThreshold is the threshold for breaking long lines at logical points.
5454
const ExpressionBreakThreshold LineLength = 100
5555

56-
// DefaultMCPRegistryURL is the default MCP registry URL
56+
// DefaultMCPRegistryURL is the default MCP registry URL.
5757
const DefaultMCPRegistryURL = "https://api.mcp.github.com/v0"
5858

59-
// DefaultClaudeCodeVersion is the default version of the Claude Code CLI
59+
// DefaultClaudeCodeVersion is the default version of the Claude Code CLI.
6060
const DefaultClaudeCodeVersion Version = "2.0.75"
6161

62-
// DefaultCopilotVersion is the default version of the GitHub Copilot CLI
63-
// WARNING: UPGRADING COPILOT CLI REQUIRES A FULL INTEGRATION TEST RUN TO ENSURE COMPATIBILITY
62+
// DefaultCopilotVersion is the default version of the GitHub Copilot CLI.
63+
//
64+
// WARNING: UPGRADING COPILOT CLI REQUIRES A FULL INTEGRATION TEST RUN TO ENSURE COMPATIBILITY.
6465
const DefaultCopilotVersion Version = "0.0.372"
6566

6667
// DefaultCopilotDetectionModel is the default model for the Copilot engine when used in the detection job

pkg/gitutil/gitutil.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package gitutil
22

33
import "strings"
44

5-
// IsAuthError checks if an error message indicates an authentication issue
6-
// This is used to detect when GitHub API calls fail due to missing or invalid credentials
5+
// IsAuthError checks if an error message indicates an authentication issue.
6+
// This is used to detect when GitHub API calls fail due to missing or invalid credentials.
77
func IsAuthError(errMsg string) bool {
88
lowerMsg := strings.ToLower(errMsg)
99
return strings.Contains(lowerMsg, "gh_token") ||
@@ -15,8 +15,8 @@ func IsAuthError(errMsg string) bool {
1515
strings.Contains(lowerMsg, "permission denied")
1616
}
1717

18-
// IsHexString checks if a string contains only hexadecimal characters
19-
// This is used to validate Git commit SHAs and other hexadecimal identifiers
18+
// IsHexString checks if a string contains only hexadecimal characters.
19+
// This is used to validate Git commit SHAs and other hexadecimal identifiers.
2020
func IsHexString(s string) bool {
2121
if len(s) == 0 {
2222
return false

pkg/logger/error_formatting.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,19 @@ import (
55
"strings"
66
)
77

8-
// Pre-compiled regexes for performance (avoid recompiling in hot paths)
8+
// Pre-compiled regexes for performance (avoid recompiling in hot paths).
99
var (
1010
// Timestamp patterns for log cleanup
11-
// Pattern 1: ISO 8601 with T or space separator (e.g., "2024-01-01T12:00:00.123Z " or "2024-01-01 12:00:00 ")
11+
// Pattern 1: ISO 8601 with T or space separator (e.g., "2024-01-01T12:00:00.123Z " or "2024-01-01 12:00:00 ").
1212
timestampPattern1 = regexp.MustCompile(`^\d{4}-\d{2}-\d{2}[T\s]\d{2}:\d{2}:\d{2}(\.\d+)?([+-]\d{2}:\d{2}|Z)?\s*`)
13-
// Pattern 2: Bracketed date-time (e.g., "[2024-01-01 12:00:00] ")
13+
// Pattern 2: Bracketed date-time (e.g., "[2024-01-01 12:00:00] ").
1414
timestampPattern2 = regexp.MustCompile(`^\[\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\]\s*`)
15-
// Pattern 3: Bracketed time only (e.g., "[12:00:00] ")
15+
// Pattern 3: Bracketed time only (e.g., "[12:00:00] ").
1616
timestampPattern3 = regexp.MustCompile(`^\[\d{2}:\d{2}:\d{2}\]\s+`)
17-
// Pattern 4: Time only with optional milliseconds (e.g., "12:00:00.123 ")
17+
// Pattern 4: Time only with optional milliseconds (e.g., "12:00:00.123 ").
1818
timestampPattern4 = regexp.MustCompile(`^\d{2}:\d{2}:\d{2}(\.\d+)?\s+`)
1919

20-
// Log level pattern for message cleanup (case-insensitive)
20+
// Log level pattern for message cleanup (case-insensitive).
2121
logLevelPattern = regexp.MustCompile(`(?i)^\[?(ERROR|WARNING|WARN|INFO|DEBUG)\]?\s*[:-]?\s*`)
2222
)
2323

0 commit comments

Comments
 (0)