-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlefthook.yml
More file actions
138 lines (138 loc) · 7.38 KB
/
Copy pathlefthook.yml
File metadata and controls
138 lines (138 loc) · 7.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# Mirrors .github/workflows/ci.yml's checks locally, so a broken commit
# never lands in the first place. Requires frontend/dist to exist for the
# Go jobs (main.go embeds it) -- run `npm run build` in frontend/ once
# after cloning, same prerequisite CI itself has.
pre-commit:
parallel: true
jobs:
- name: file-loc-limit
glob: "*.{go,ts,tsx}"
run: ./scripts/check-loc.sh
- name: workflow-yaml
glob: ".github/workflows/*.yml"
run: ./scripts/check-workflow-yaml.sh
- name: comment-hygiene
glob: "*.{go,ts,tsx}"
run: ./scripts/check-comment-hygiene.sh
- name: ui-copy
glob: "frontend/src/locales/**/*.json"
run: ./scripts/check-ui-copy.sh
- name: toolbar-action-testids
glob: "{frontend/src/atlas/AtlasToolbar.tsx,frontend/src/atlas/AtlasFolderImport.tsx,frontend/e2e/*.spec.ts,frontend/e2e/fixtures/toolbarActions.ts}"
run: ./scripts/check-toolbar-action-testids.sh
- name: docsgen-freshness
# A hand-edited userdocs page without a docsgen regeneration
# fails only in CI (TestUserDocs_MatchCommitted) -- run the same
# freshness test here so the fix is one local `go generate
# ./internal/docsgen` away, not a failed PR round trip.
glob: "{userdocs/**,internal/docsgen/**}"
run: go test ./internal/docsgen/
- name: doc-paths
# docs/ is a private nested checkout (absent on public clones):
# skip silently when missing; mill-docs' own CI is the enforcing
# caller there. No glob -- the cited paths live outside docs/,
# so any commit can invalidate them.
run: 'test ! -f docs/scripts/check-doc-paths.sh || { bash docs/scripts/check-doc-paths.sh && bash docs/scripts/gen-adr-readme.sh --check; }'
- name: rules-frontmatter
# Lefthook's `**` requires 1+ directories deep (non-standard --
# confirmed against its own docs, not gitignore-style zero-or-more),
# so `.claude/rules/**/*.md` never matches a file directly in
# rules/, only in a subdirectory of it. Every rule file today is
# flat (frontend.md, backend.md, ...), so this glob is what
# actually matches them; revisit if/when a nested rules/<topic>/
# directory is ever added (docs/SPEC.md §9.1 -- Claude Code
# supports it, Mill doesn't use it yet).
glob: ".claude/rules/*.md"
run: ./scripts/check-rules-frontmatter.sh
- name: root-file-naming
# No glob, deliberately: .ls-lint.yml now covers every file type
# at the repo root (its `.*` catch-all), not just .go, so this
# must run on every commit -- a stray .png/.txt staged at root
# would never match a "*.go" glob. ls_lint is near-instant, so
# unconditional is cheap. Mirrors CI's own root-file-naming job
# (also unconditional). Requires `go install
# github.com/loeffel-io/ls-lint/v2/cmd/ls_lint@v2.3.1` once locally
# (same one-time-setup shape as golangci-lint itself).
run: ls_lint
- name: go-vet
glob: "*.go"
run: go vet . ./internal/...
- name: golangci-lint
glob: "*.go"
# --build-tags=server matches ci.yml's own golangci-lint-action
# args exactly -- without it this job lints the DEFAULT (desktop)
# tag set, a strictly larger file set than CI's job ever compiles
# (`!server`-tagged files CI's own -tags=server run never sees),
# so a local pass here was checking something CI doesn't and a
# local fail could block a commit CI's real gate would accept.
# --allow-parallel-runners: this job and gocognit-new run
# concurrently under lefthook's parallel executor and share
# golangci-lint's lock file -- without the flag whichever starts
# second dies with "parallel golangci-lint is running" (hit
# repeatedly; previously worked around by re-running the commit).
# GOLANGCI_LINT_CACHE per-checkout (all three golangci jobs): the
# user-level cache (~/Library/Caches/golangci-lint) is shared
# across every worktree on the machine and retains absolute paths
# from deleted checkouts, producing spurious findings in files a
# commit never touched (twice-hit class). A cache under this
# checkout's own gitignored .task/ isolates each worktree; the
# cost is one cold lint per fresh worktree.
run: GOLANGCI_LINT_CACHE="$PWD/.task/golangci-cache" golangci-lint run . ./internal/... --build-tags=server --allow-parallel-runners
- name: gocognit-new
glob: "*.go"
# Cognitive complexity gates NEW/CHANGED code only (goal 0109,
# Sonar's clean-as-you-code posture): 25 legacy functions sit
# over the threshold (burn-down in the goal file), so the gate
# scopes to the merge-base diff instead of failing every build
# or inflating the threshold into meaninglessness. Threshold
# lives in .golangci.yml's gocognit settings; --tests=false is
# the goal file's own recorded verdict (seeded-example tests
# dominate the noise; production code is the gate's subject).
run: GOLANGCI_LINT_CACHE="$PWD/.task/golangci-cache" golangci-lint run . ./internal/... --build-tags=server --enable-only gocognit --new-from-merge-base=origin/main --tests=false --allow-parallel-runners
- name: depguard-new
glob: "*.go"
# Boundary-enforcement gate on NEW/CHANGED code only (goal 0168):
# 22 legacy direct imports of wails/v3/pkg/application sit outside
# internal/adapters/windowing, burning down as they migrate, so
# this scopes to the merge-base diff instead of failing every
# build. Threshold/rule lives in .golangci.yml's depguard
# settings; same --tests=false / --allow-parallel-runners
# reasoning as gocognit-new just above.
run: GOLANGCI_LINT_CACHE="$PWD/.task/golangci-cache" golangci-lint run . ./internal/... --build-tags=server --enable-only depguard --new-from-merge-base=origin/main --tests=false --allow-parallel-runners
- name: go-test
glob: "*.go"
# Root package (`.`) included alongside ./internal/... -- the
# service test files (now under internal/services/*) run via the
# ./internal/... half; the root package itself (main.go only) has
# no tests but stays listed so a future root test can't silently
# run nowhere. No new frontend/dist dependency: go-vet and
# go-build-desktop below already build the root package locally,
# so that requirement (this file's own header comment) already
# applied before this line did.
run: OUT="$(mktemp -t mill-cover)" && go test . ./internal/... -race -coverprofile="$OUT" && bash scripts/check-go-coverage.sh "$OUT"
- name: go-build-desktop
glob: "*.go"
run: go build -o /dev/null .
- name: go-build-server
glob: "*.go"
run: go build -tags server -o /dev/null .
- name: eslint
root: "frontend/"
glob: "frontend/**/*.{ts,tsx}"
run: npm run lint
- name: boundaries
# docs/adr/0012: dependency-cruiser enforces the bounded-context
# folder rules (src/app|views|composition|configure|shared) --
# mirrors CI's own frontend job, same "one check, two runners"
# discipline as file-loc-limit/rules-frontmatter.
root: "frontend/"
glob: "frontend/**/*.{ts,tsx}"
run: npm run boundaries
- name: vitest
root: "frontend/"
glob: "frontend/**/*.{ts,tsx}"
run: npm run test
- name: tsc
root: "frontend/"
glob: "frontend/**/*.{ts,tsx}"
run: npx tsc --noEmit