Skip to content

Commit 09e4d54

Browse files
committed
fix: upgrade golangci-lint to v2.8.0 and resolve all linting issues
- Upgrade golangci-lint from v1.64.8 to v2.8.0 for Go 1.24 support - Migrate .golangci.yml to v2 format with version declaration - Use official golangci-lint-action@v9 in CI for better performance - Fix linting issues in check-plugin-counts.go (unchecked error, formatting) - Fix error message capitalization in config.go (ST1005) - Apply De Morgan's law in cache.go for cleaner validation (QF1001) - Add pre-push checklist to CLAUDE.md with linting requirements All linting now passes with 0 issues. CI will no longer fail on lint step.
1 parent 49729e4 commit 09e4d54

6 files changed

Lines changed: 99 additions & 97 deletions

File tree

.github/workflows/ci.yml

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,19 +43,11 @@ jobs:
4343
with:
4444
go-version-file: go.mod
4545

46-
- name: Check formatting
47-
run: |
48-
if [ -n "$(gofmt -l .)" ]; then
49-
echo "Go files are not formatted. Run 'gofmt -w .'"
50-
gofmt -l .
51-
exit 1
52-
fi
53-
54-
- name: Install golangci-lint
55-
run: go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.64.8
56-
5746
- name: Run golangci-lint
58-
run: golangci-lint run --timeout=5m --out-format=colored-line-number
47+
uses: golangci/golangci-lint-action@v9
48+
with:
49+
version: v2.8.0
50+
args: --timeout=5m
5951

6052
vuln-check:
6153
name: Vulnerability Check

.golangci.yml

Lines changed: 53 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,60 @@
1+
version: "2"
12
run:
2-
timeout: 5m
3-
tests: true
43
modules-download-mode: readonly
5-
4+
tests: true
65
linters:
76
enable:
8-
- errcheck # Check for unchecked errors
9-
- gosimple # Simplify code
10-
- govet # Reports suspicious constructs
11-
- ineffassign # Detect ineffectual assignments
12-
- staticcheck # Static analysis
13-
- unused # Check for unused constants, variables, functions
14-
- gofmt # Check code formatting
15-
- goimports # Check import formatting
16-
- misspell # Check for misspelled English words
17-
- gosec # Security-focused linter
18-
- revive # Drop-in replacement for golint (style issues)
19-
- unconvert # Unnecessary type conversions
20-
# Disable unparam and prealloc - too strict for existing code
21-
# - unparam # Unused function parameters
22-
# - prealloc # Slice preallocation opportunities
23-
- gocyclo # Cyclomatic complexity
24-
- gocritic # Comprehensive Go linter (with disabled checks)
25-
26-
linters-settings:
27-
gosec:
28-
excludes:
29-
- G104 # We handle unhandled errors contextually
30-
- G304 # Allow file inclusion in tests with variables
31-
confidence: medium
32-
33-
errcheck:
34-
check-blank: false
35-
check-type-assertions: false
36-
37-
gocyclo:
38-
# We have known high-complexity functions (handleDetailKeys: 35, handleListKeys: 31)
39-
# Set threshold to 40 to catch regressions without failing on existing code
40-
# TODO: Refactor to <15 in Phase 4
41-
min-complexity: 40
42-
43-
revive:
44-
severity: warning
45-
rules:
46-
- name: exported
47-
severity: warning
48-
disabled: true # Disable to allow existing patterns
49-
- name: error-return
50-
- name: error-naming
51-
- name: if-return
52-
- name: var-naming
53-
- name: indent-error-flow
54-
disabled: true # Disable to allow existing else-after-return patterns
55-
56-
gocritic:
57-
enabled-tags:
58-
- diagnostic
59-
# Disable style and performance for now - too strict for existing code
60-
disabled-checks:
61-
- unnecessaryBlock # Sometimes explicit blocks improve readability
62-
- octalLiteral # Allow old octal syntax (0750 vs 0o750)
63-
- rangeValCopy # Allow range value copies for readability
64-
- hugeParam # Allow passing structs by value (existing pattern)
65-
- httpNoBody # Allow nil request bodies (existing pattern)
66-
- ifElseChain # Allow if-else chains (existing pattern)
67-
- emptyStringTest # Allow len(s) > 0 pattern (existing code)
68-
- singleCaseSwitch # Allow single-case switch statements
69-
7+
- gocritic
8+
- gocyclo
9+
- gosec
10+
- misspell
11+
- revive
12+
- unconvert
13+
settings:
14+
errcheck:
15+
check-type-assertions: false
16+
check-blank: false
17+
gocritic:
18+
enabled-tags:
19+
- diagnostic
20+
disabled-checks:
21+
- ifElseChain
22+
- singleCaseSwitch
23+
gocyclo:
24+
min-complexity: 40
25+
gosec:
26+
excludes:
27+
- G104
28+
- G304
29+
confidence: medium
30+
revive:
31+
severity: warning
32+
rules:
33+
- name: exported
34+
severity: warning
35+
disabled: true
36+
- name: error-return
37+
- name: error-naming
38+
- name: if-return
39+
- name: var-naming
40+
- name: indent-error-flow
41+
disabled: true
42+
exclusions:
43+
generated: lax
44+
paths:
45+
- third_party$
46+
- builtin$
47+
- examples$
7048
issues:
71-
exclude-use-default: false
7249
max-issues-per-linter: 0
7350
max-same-issues: 0
51+
formatters:
52+
enable:
53+
- gofmt
54+
- goimports
55+
exclusions:
56+
generated: lax
57+
paths:
58+
- third_party$
59+
- builtin$
60+
- examples$

CLAUDE.md

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,25 @@
11
# Plum Project Guide
22

3+
## Pre-Push Checklist
4+
5+
**ALWAYS run before pushing to main:**
6+
7+
```bash
8+
# 1. Run linter (must pass)
9+
golangci-lint run --timeout=5m
10+
11+
# 2. Run tests (must pass)
12+
go test ./...
13+
14+
# 3. Verify build succeeds
15+
go build -o ./plum ./cmd/plum
16+
```
17+
18+
**If linter is not installed:**
19+
```bash
20+
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@v2.8.0
21+
```
22+
323
## Routine Maintenance
424

525
**At the start of each session**, check marketplace data freshness:
@@ -16,8 +36,9 @@ go run scripts/check-plugin-counts.go
1636
- Update `internal/marketplace/discovery.go` with new stats and plugin counts
1737
- Update `README.md` marketplace table with accurate counts
1838
- Update total plugin count in README intro and features section
19-
- Run: `go test ./internal/marketplace && go build -o ./plum ./cmd/plum`
39+
- Run pre-push checklist above
2040

2141
## Why This Matters
2242

23-
The README is users' first impression - accurate plugin counts and GitHub stats help them make informed decisions about installation.
43+
- **Linting** - CI will fail if linting doesn't pass locally. Always lint before pushing.
44+
- **Accurate Data** - The README is users' first impression. Accurate plugin counts and GitHub stats help them make informed decisions about installation.

internal/config/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ func LoadKnownMarketplaces() (KnownMarketplaces, error) {
5555
data, err := os.ReadFile(path)
5656
if err != nil {
5757
if os.IsNotExist(err) {
58-
return nil, fmt.Errorf("Claude Code marketplaces not found at %s.\n\nPlease run Claude Code and configure at least one marketplace using the /plugin command.", path)
58+
return nil, fmt.Errorf("claude Code marketplaces not found at %s - please run Claude Code and configure at least one marketplace using the /plugin command", path)
5959
}
6060
return nil, err
6161
}

internal/marketplace/cache.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ func validateMarketplaceName(name string) error {
4343

4444
// Only allow safe characters: alphanumeric, dash, underscore, dot
4545
for _, r := range name {
46-
if !((r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') ||
47-
(r >= '0' && r <= '9') || r == '-' || r == '_' || r == '.') {
46+
if (r < 'a' || r > 'z') && (r < 'A' || r > 'Z') &&
47+
(r < '0' || r > '9') && r != '-' && r != '_' && r != '.' {
4848
return fmt.Errorf("marketplace name contains invalid character %q", r)
4949
}
5050
}

scripts/check-plugin-counts.go

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,23 +9,23 @@ import (
99
)
1010

1111
type MarketplaceManifest struct {
12-
Name string `json:"name"`
12+
Name string `json:"name"`
1313
Plugins []map[string]interface{} `json:"plugins"`
1414
}
1515

1616
var marketplaces = map[string]string{
17-
"claude-code-plugins-plus": "jeremylongshore/claude-code-plugins-plus-skills",
18-
"claude-code-marketplace": "ananddtyagi/cc-marketplace",
19-
"claude-code-plugins": "anthropics/claude-code",
20-
"mag-claude-plugins": "MadAppGang/claude-code",
21-
"dev-gom-plugins": "Dev-GOM/claude-code-marketplace",
22-
"feedmob-claude-plugins": "feed-mob/claude-code-marketplace",
23-
"claude-plugins-official": "anthropics/claude-plugins-official",
24-
"anthropic-agent-skills": "anthropics/skills",
25-
"wshobson-agents": "wshobson/agents",
26-
"docker-plugins": "docker/claude-plugins",
27-
"ccplugins-marketplace": "ccplugins/marketplace",
28-
"claude-mem": "thedotmack/claude-mem",
17+
"claude-code-plugins-plus": "jeremylongshore/claude-code-plugins-plus-skills",
18+
"claude-code-marketplace": "ananddtyagi/cc-marketplace",
19+
"claude-code-plugins": "anthropics/claude-code",
20+
"mag-claude-plugins": "MadAppGang/claude-code",
21+
"dev-gom-plugins": "Dev-GOM/claude-code-marketplace",
22+
"feedmob-claude-plugins": "feed-mob/claude-code-marketplace",
23+
"claude-plugins-official": "anthropics/claude-plugins-official",
24+
"anthropic-agent-skills": "anthropics/skills",
25+
"wshobson-agents": "wshobson/agents",
26+
"docker-plugins": "docker/claude-plugins",
27+
"ccplugins-marketplace": "ccplugins/marketplace",
28+
"claude-mem": "thedotmack/claude-mem",
2929
}
3030

3131
func fetchPluginCount(repo string) (int, error) {
@@ -36,7 +36,9 @@ func fetchPluginCount(repo string) (int, error) {
3636
if err != nil {
3737
return 0, err
3838
}
39-
defer resp.Body.Close()
39+
defer func() {
40+
_ = resp.Body.Close()
41+
}()
4042

4143
if resp.StatusCode != 200 {
4244
return 0, fmt.Errorf("HTTP %d", resp.StatusCode)

0 commit comments

Comments
 (0)