Skip to content

Commit 45a0784

Browse files
committed
lint & modernize
1 parent a131a44 commit 45a0784

18 files changed

Lines changed: 955 additions & 427 deletions

File tree

.golangci.yml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,12 @@ linters:
122122
struct-method: false
123123

124124
gocognit:
125-
min-complexity: 65
125+
min-complexity: 55
126126

127127
gocritic:
128128
enable-all: true
129129
disabled-checks:
130130
- paramTypeCombine
131-
- rangeValCopy # PRSummary struct (152 bytes) copies are acceptable for code clarity
132131
# The list of supported checkers can be found at https://go-critic.com/overview.
133132
settings:
134133
captLocal:
@@ -144,11 +143,6 @@ linters:
144143
govet:
145144
enable-all: true
146145

147-
maintidx:
148-
# Maintainability Index threshold (default: 20)
149-
# ExtrapolateFromSamples is a straightforward calculation with clear linear logic
150-
under: 16
151-
152146
godot:
153147
scope: toplevel
154148

@@ -183,7 +177,7 @@ linters:
183177
- name: cyclomatic
184178
disabled: true # prefer maintidx
185179
- name: function-length
186-
arguments: [150, 300]
180+
arguments: [150, 225]
187181
- name: line-length-limit
188182
arguments: [150]
189183
- name: nested-structs
@@ -192,8 +186,8 @@ linters:
192186
arguments: [10]
193187
- name: flag-parameter # fixes are difficult
194188
disabled: true
195-
- name: use-waitgroup-go
196-
disabled: true # wg.Add/Done pattern is idiomatic Go
189+
- name: bare-return
190+
disabled: true
197191

198192
rowserrcheck:
199193
# database/sql is always checked.

Makefile

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,28 @@ endif
3131
LINTERS :=
3232
FIXERS :=
3333

34+
SHELLCHECK_VERSION ?= v0.11.0
35+
SHELLCHECK_BIN := $(LINT_ROOT)/out/linters/shellcheck-$(SHELLCHECK_VERSION)-$(LINT_ARCH)
36+
$(SHELLCHECK_BIN):
37+
mkdir -p $(LINT_ROOT)/out/linters
38+
curl -sSfL -o $@.tar.xz https://github.com/koalaman/shellcheck/releases/download/$(SHELLCHECK_VERSION)/shellcheck-$(SHELLCHECK_VERSION).$(LINT_OS_LOWER).$(LINT_ARCH).tar.xz \
39+
|| echo "Unable to fetch shellcheck for $(LINT_OS)/$(LINT_ARCH): falling back to locally install"
40+
test -f $@.tar.xz \
41+
&& tar -C $(LINT_ROOT)/out/linters -xJf $@.tar.xz \
42+
&& mv $(LINT_ROOT)/out/linters/shellcheck-$(SHELLCHECK_VERSION)/shellcheck $@ \
43+
|| printf "#!/usr/bin/env shellcheck\n" > $@
44+
chmod u+x $@
45+
46+
LINTERS += shellcheck-lint
47+
shellcheck-lint: $(SHELLCHECK_BIN)
48+
$(SHELLCHECK_BIN) $(shell find . -name "*.sh")
49+
50+
FIXERS += shellcheck-fix
51+
shellcheck-fix: $(SHELLCHECK_BIN)
52+
$(SHELLCHECK_BIN) $(shell find . -name "*.sh") -f diff | { read -t 1 line || exit 0; { echo "$$line" && cat; } | git apply -p2; }
53+
3454
GOLANGCI_LINT_CONFIG := $(LINT_ROOT)/.golangci.yml
35-
GOLANGCI_LINT_VERSION ?= v2.5.0
55+
GOLANGCI_LINT_VERSION ?= v2.7.2
3656
GOLANGCI_LINT_BIN := $(LINT_ROOT)/out/linters/golangci-lint-$(GOLANGCI_LINT_VERSION)-$(LINT_ARCH)
3757
$(GOLANGCI_LINT_BIN):
3858
mkdir -p $(LINT_ROOT)/out/linters
@@ -61,6 +81,32 @@ LINTERS += yamllint-lint
6181
yamllint-lint: $(YAMLLINT_BIN)
6282
PYTHONPATH=$(YAMLLINT_ROOT)/dist $(YAMLLINT_ROOT)/dist/bin/yamllint .
6383

84+
BIOME_VERSION ?= 2.3.8
85+
BIOME_BIN := $(LINT_ROOT)/out/linters/biome-$(BIOME_VERSION)-$(LINT_ARCH)
86+
BIOME_CONFIG := $(LINT_ROOT)/biome.json
87+
88+
# Map architecture names for Biome downloads
89+
BIOME_ARCH := $(LINT_ARCH)
90+
ifeq ($(LINT_ARCH),x86_64)
91+
BIOME_ARCH := x64
92+
endif
93+
94+
$(BIOME_BIN):
95+
mkdir -p $(LINT_ROOT)/out/linters
96+
rm -rf $(LINT_ROOT)/out/linters/biome-*
97+
curl -sSfL -o $@ https://github.com/biomejs/biome/releases/download/%40biomejs%2Fbiome%40$(BIOME_VERSION)/biome-$(LINT_OS_LOWER)-$(BIOME_ARCH) \
98+
|| echo "Unable to fetch biome for $(LINT_OS_LOWER)/$(BIOME_ARCH), falling back to local install"
99+
test -f $@ || printf "#!/usr/bin/env biome\n" > $@
100+
chmod u+x $@
101+
102+
LINTERS += biome-lint
103+
biome-lint: $(BIOME_BIN)
104+
$(BIOME_BIN) check --config-path=$(BIOME_CONFIG) .
105+
106+
FIXERS += biome-fix
107+
biome-fix: $(BIOME_BIN)
108+
$(BIOME_BIN) check --write --config-path=$(BIOME_CONFIG) .
109+
64110
.PHONY: _lint $(LINTERS)
65111
_lint:
66112
@exit_code=0; \
@@ -79,6 +125,7 @@ fix:
79125

80126
# END: lint-install .
81127

128+
82129
.PHONY: deploy
83130
deploy:
84131
./hacks/deploy.sh cmd/server/

cmd/prcost/main.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -590,19 +590,13 @@ func printEfficiency(breakdown *cost.Breakdown) {
590590

591591
fmt.Println(" ┌─────────────────────────────────────────────────────────────┐")
592592
headerText := fmt.Sprintf("DEVELOPMENT EFFICIENCY: %s (%.1f%%) - %s", grade, efficiencyPct, message)
593-
padding := 60 - len(headerText)
594-
if padding < 0 {
595-
padding = 0
596-
}
593+
padding := max(60-len(headerText), 0)
597594
fmt.Printf(" │ %s%*s│\n", headerText, padding, "")
598595
fmt.Println(" └─────────────────────────────────────────────────────────────┘")
599596

600597
fmt.Println(" ┌─────────────────────────────────────────────────────────────┐")
601598
velocityHeader := fmt.Sprintf("MERGE VELOCITY: %s (%s) - %s", velocityGrade, formatTimeUnit(breakdown.PRDuration), velocityMessage)
602-
velPadding := 60 - len(velocityHeader)
603-
if velPadding < 0 {
604-
velPadding = 0
605-
}
599+
velPadding := max(60-len(velocityHeader), 0)
606600
fmt.Printf(" │ %s%*s│\n", velocityHeader, velPadding, "")
607601
fmt.Println(" └─────────────────────────────────────────────────────────────┘")
608602

cmd/prcost/repository.go

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,14 @@ func analyzeRepository(ctx context.Context, owner, repo string, sampleSize, days
6262
}
6363

6464
// Convert samples to PRSummaryInfo format
65-
var summaries []cost.PRSummaryInfo
66-
for _, pr := range samples {
67-
summaries = append(summaries, cost.PRSummaryInfo{
68-
Owner: pr.Owner,
69-
Repo: pr.Repo,
70-
Number: pr.Number,
71-
UpdatedAt: pr.UpdatedAt,
72-
})
65+
summaries := make([]cost.PRSummaryInfo, len(samples))
66+
for i := range samples {
67+
summaries[i] = cost.PRSummaryInfo{
68+
Owner: samples[i].Owner,
69+
Repo: samples[i].Repo,
70+
Number: samples[i].Number,
71+
UpdatedAt: samples[i].UpdatedAt,
72+
}
7373
}
7474

7575
// Create fetcher
@@ -104,17 +104,17 @@ func analyzeRepository(ctx context.Context, owner, repo string, sampleSize, days
104104

105105
// Convert PRSummary to PRSummaryInfo for extrapolation
106106
prSummaryInfos := make([]cost.PRSummaryInfo, len(prs))
107-
for i, pr := range prs {
107+
for i := range prs {
108108
prSummaryInfos[i] = cost.PRSummaryInfo{
109-
Owner: pr.Owner,
110-
Repo: pr.Repo,
111-
Author: pr.Author,
112-
AuthorType: pr.AuthorType,
113-
CreatedAt: pr.CreatedAt,
114-
UpdatedAt: pr.UpdatedAt,
115-
ClosedAt: pr.ClosedAt,
116-
Merged: pr.Merged,
117-
State: pr.State,
109+
Owner: prs[i].Owner,
110+
Repo: prs[i].Repo,
111+
Author: prs[i].Author,
112+
AuthorType: prs[i].AuthorType,
113+
CreatedAt: prs[i].CreatedAt,
114+
UpdatedAt: prs[i].UpdatedAt,
115+
ClosedAt: prs[i].ClosedAt,
116+
Merged: prs[i].Merged,
117+
State: prs[i].State,
118118
}
119119
}
120120

@@ -180,14 +180,14 @@ func analyzeOrganization(ctx context.Context, org string, sampleSize, days int,
180180
}
181181

182182
// Convert samples to PRSummaryInfo format
183-
var summaries []cost.PRSummaryInfo
184-
for _, pr := range samples {
185-
summaries = append(summaries, cost.PRSummaryInfo{
186-
Owner: pr.Owner,
187-
Repo: pr.Repo,
188-
Number: pr.Number,
189-
UpdatedAt: pr.UpdatedAt,
190-
})
183+
summaries := make([]cost.PRSummaryInfo, len(samples))
184+
for i := range samples {
185+
summaries[i] = cost.PRSummaryInfo{
186+
Owner: samples[i].Owner,
187+
Repo: samples[i].Repo,
188+
Number: samples[i].Number,
189+
UpdatedAt: samples[i].UpdatedAt,
190+
}
191191
}
192192

193193
// Create fetcher
@@ -223,17 +223,17 @@ func analyzeOrganization(ctx context.Context, org string, sampleSize, days int,
223223

224224
// Convert PRSummary to PRSummaryInfo for extrapolation
225225
prSummaryInfos := make([]cost.PRSummaryInfo, len(prs))
226-
for i, pr := range prs {
226+
for i := range prs {
227227
prSummaryInfos[i] = cost.PRSummaryInfo{
228-
Owner: pr.Owner,
229-
Repo: pr.Repo,
230-
Author: pr.Author,
231-
AuthorType: pr.AuthorType,
232-
CreatedAt: pr.CreatedAt,
233-
UpdatedAt: pr.UpdatedAt,
234-
ClosedAt: pr.ClosedAt,
235-
Merged: pr.Merged,
236-
State: pr.State,
228+
Owner: prs[i].Owner,
229+
Repo: prs[i].Repo,
230+
Author: prs[i].Author,
231+
AuthorType: prs[i].AuthorType,
232+
CreatedAt: prs[i].CreatedAt,
233+
UpdatedAt: prs[i].UpdatedAt,
234+
ClosedAt: prs[i].ClosedAt,
235+
Merged: prs[i].Merged,
236+
State: prs[i].State,
237237
}
238238
}
239239

hacks/debug-sessions/main.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func main() {
6464
events := make([]cost.ParticipantEvent, len(authorEvents))
6565
copy(events, authorEvents)
6666
// Sort manually
67-
for i := 0; i < len(events); i++ {
67+
for i := range events {
6868
for j := i + 1; j < len(events); j++ {
6969
if events[j].Timestamp.Before(events[i].Timestamp) {
7070
events[i], events[j] = events[j], events[i]
@@ -105,10 +105,7 @@ func main() {
105105
// Gaps between events
106106
for j := start; j < end; j++ {
107107
gap := events[j+1].Timestamp.Sub(events[j].Timestamp)
108-
counted := gap
109-
if gap > eventDur {
110-
counted = eventDur
111-
}
108+
counted := min(gap, eventDur)
112109
totalGitHub += counted
113110
fmt.Printf(" Gap %d->%d: %v (actual: %v)\n", j-start, j-start+1, counted, gap)
114111
}

hacks/test-sessions/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ func main() {
4040
copy(sorted, authorEvents)
4141

4242
// Simple sort
43-
for i := 0; i < len(sorted); i++ {
43+
for i := range sorted {
4444
for j := i + 1; j < len(sorted); j++ {
4545
if sorted[j].Timestamp.Before(sorted[i].Timestamp) {
4646
sorted[i], sorted[j] = sorted[j], sorted[i]

internal/server/integration_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ func TestOrgSampleStreamIntegration(t *testing.T) {
7474
for scanner.Scan() {
7575
line := scanner.Text()
7676

77-
if strings.HasPrefix(line, "data: ") {
78-
currentData = strings.TrimPrefix(line, "data: ")
77+
if after, ok := strings.CutPrefix(line, "data: "); ok {
78+
currentData = after
7979
} else if line == "" && currentData != "" {
8080
// Empty line marks end of SSE event
8181
var event ProgressUpdate

0 commit comments

Comments
 (0)