Repository navigation
Expand file tree
/
Copy pathlefthook.yml
More file actions
146 lines (143 loc) · 7.76 KB
/
Copy pathlefthook.yml
File metadata and controls
146 lines (143 loc) · 7.76 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
139
140
141
142
143
144
145
146
# Glob patterns below mirror the `changes` job's dorny/paths-filter groups in
# .github/workflows/ci.yml — keep the two in sync. Each globbed pre-push lane
# also sets `files: git diff --name-only origin/main...HEAD` so its file set is
# the branch's merge-base diff against origin/main — the same semantics as CI's
# dorny/paths-filter and `scripts/check-file-sizes-core.mjs` `resolveBaseRef`.
# Without it lefthook derives files from `git diff HEAD @{push}`, which after a
# rebase or `git merge origin/main` includes everything main changed since the
# branch's last push (firing mobile/desktop/rust lanes on unrelated pushes), and
# on a brand-new branch falls back to a stale remote's tip (a full-suite run).
# The three-dot diff scopes every lane to what this branch actually changed.
# Both the three-dot diff and lefthook's stock discovery inspect the checked-out
# HEAD, so pushing a non-HEAD ref (explicit refspec, `--all`) validates HEAD's
# tree, not the pushed commit — the always-on `push-head-scope` lane warns when
# they diverge and CI remains the authoritative gate for that ref.
# Deliberate deviations:
# - The `.github/workflows/ci.yml` path CI adds to its `rust`/`desktop`/`mobile`
# filters, and `scripts/ci-apt-retry.sh` in `rust`/`desktop`, are omitted;
# a CI-plumbing-only edit doesn't need a local test run.
# - `desktop-test` doesn't trigger on `crates/**` changes, though CI's Desktop
# JS job does: a few node:test cases read relay/DB crate sources to pin shared
# constants. Running the full desktop suite on every crate push would be
# expensive locally, so CI is the authoritative check for that coupling.
# - The repository-wide `file-size-check` is deliberately unfiltered. Its own
# merge-base diff is the path filter; duplicating its governed roots here is
# the coverage drift this gate is intended to prevent.
# - Deletion-only surface changes do not trigger local hooks: lefthook 2.1.x
# drops deleted paths from push-file discovery (`extractFiles` existence
# check, repository.go). CI's dorny/paths-filter catches deletions.
# Deliberate — accepted, not worked around.
# - `commit-msg` has no glob: it rewrites the commit message, not files. Note
# Git only runs it for `git commit` and `git merge` — other flows need their own
# flag: `git rebase --signoff`, `git cherry-pick -s`.
#
# `rc` points `lefthook install` at `bin/.lefthookrc`, which the generated
# `.git/hooks/*` dispatchers source before their `$LEFTHOOK_BIN`-first lookup. It
# (1) sets `LEFTHOOK_BIN` to the Hermit-pinned `bin/lefthook` (2.1.3) so a push
# from any worktree runs the pinned binary even when a different lefthook is on
# PATH, and (2) prepends the repo's Hermit `bin/` to `PATH` so every lane
# subprocess (`just mobile-check` -> flutter/dart, etc.) resolves the pinned
# toolchain regardless of the invoking shell — the hook self-pins, so a Homebrew
# flutter/dart ahead on PATH can no longer cause false lane failures.
rc: bin/.lefthookrc
pre-commit:
parallel: true
commands:
rust-fmt:
glob: ["crates/**", "examples/countdown-bot/**"]
run: just fmt
stage_fixed: true
desktop-tauri-fmt:
glob: ["desktop/src-tauri/**"]
run: just desktop-tauri-fmt
stage_fixed: true
desktop-fix:
# A lockfile-only change has no desktop source for Biome to rewrite.
glob: ["desktop/**"]
exclude: ["desktop/src-tauri/**"]
run: just desktop-fix
stage_fixed: true
web-fix:
# A lockfile-only change has no web source for Biome to rewrite.
glob: ["web/**"]
run: just web-fix
stage_fixed: true
mobile-fmt:
glob: ["mobile/**"]
run: just mobile-fmt
stage_fixed: true
# Appends the DCO Signed-off-by trailer the required "DCO Check" enforces.
# `--if-exists doNothing` makes it idempotent and preserves an existing
# sign-off (including `git commit -s` and a different signer's trailer).
commit-msg:
commands:
signoff:
run: 'git interpret-trailers --if-exists doNothing --trailer "Signed-off-by: $(git var GIT_COMMITTER_IDENT | sed ''s/ [0-9]* [+-][0-9]*$//'')" --in-place {1}'
# Lanes below that run test suites or builds go through
# scripts/without-git-env.sh, which strips git's repository-local variables
# (per `git rev-parse --local-env-vars`) while preserving transport/credential
# settings. The branch-skew and push-head-scope guards run no test fixtures
# and need the caller's transport env, so they run unwrapped.
pre-push:
parallel: true
commands:
branch-skew:
run: ./scripts/check-branch-skew.sh
push-head-scope:
# Warn-only: the scoped lanes below validate the checked-out HEAD, so a
# non-HEAD ref push (explicit refspec, --all) relies on CI for its
# path-scoped checks. This lane reads the pushed refs from stdin and
# warns when any pushed commit is not HEAD. It never fails the push.
use_stdin: true
run: ./scripts/check-push-head-scope.sh
file-size-check:
# The ratchet computes its own merge-base diff, so path filtering here
# would only duplicate policy and create another place for coverage drift.
run: ./scripts/without-git-env.sh just file-size-check
rust-tests:
files: git diff --name-only origin/main...HEAD
glob: ["crates/**", "migrations/**", "schema/**", "Cargo.toml", "Cargo.lock", "rust-toolchain.toml", "deny.toml", "scripts/run-tests.sh", "Justfile"]
env:
# Lanes run under a pty; with agent shells' TERM=dumb, nextest's
# progress bar swallows every FAIL line, panic, and summary.
NEXTEST_SHOW_PROGRESS: counter
# An orphaned nextest otherwise spins on the dead pty's input.
NEXTEST_NO_INPUT_HANDLER: "1"
run: ./scripts/without-git-env.sh just test-unit
desktop-check:
files: git diff --name-only origin/main...HEAD
glob: ["desktop/**", "pnpm-lock.yaml", "Justfile"]
exclude: ["desktop/src-tauri/**"]
env: &pnpm-verify-deps
# Warn when node_modules looks stale against the workspace (pnpm uses
# recorded workspace state and manifest mtimes; not a complete
# lockfile-content check). `warn`, not `error`: `just
# bump-desktop-version` leaves the workspace flagged, and release prep
# pushes through this hook.
pnpm_config_verify_deps_before_run: warn
run: ./scripts/without-git-env.sh just desktop-check
desktop-typecheck:
files: git diff --name-only origin/main...HEAD
glob: ["desktop/**", "pnpm-lock.yaml", "Justfile"]
exclude: ["desktop/src-tauri/**"]
env: *pnpm-verify-deps
run: ./scripts/without-git-env.sh just desktop-typecheck
desktop-test:
files: git diff --name-only origin/main...HEAD
glob: ["desktop/**", "pnpm-lock.yaml", "Justfile"]
exclude: ["desktop/src-tauri/**"]
env: *pnpm-verify-deps
run: ./scripts/without-git-env.sh just desktop-test
desktop-tauri-checks:
# Keep local lint parity with Desktop Tauri CI for every path that can
# affect the Tauri crate or its path dependencies. Run clippy and tests
# serially so parallel pre-push hooks do not contend for Cargo's lock.
files: git diff --name-only origin/main...HEAD
glob: ["desktop/src-tauri/**", "crates/**", "migrations/**", "schema/**", "Cargo.toml", "Cargo.lock", "rust-toolchain.toml", "deny.toml", "scripts/run-tests.sh", "Justfile"]
run: ./scripts/without-git-env.sh sh -c 'just desktop-tauri-clippy && just desktop-tauri-test'
mobile-checks:
# Run analysis and tests serially so parallel pre-push hooks do not
# contend for shared Flutter state (.dart_tool, shader bundle).
files: git diff --name-only origin/main...HEAD
glob: ["mobile/**", "Justfile", "scripts/test-mobile-gateway-recipes.sh"]
run: ./scripts/without-git-env.sh sh -c 'just mobile-check && just mobile-test'