-
Notifications
You must be signed in to change notification settings - Fork 0
188 lines (181 loc) · 10.8 KB
/
Copy pathcommit-lint.yml
File metadata and controls
188 lines (181 loc) · 10.8 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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
name: commit-lint
# PRs land by fast-forward, so every commit reaches main unchanged. For
# conventional-commit-driven semver (release-plz) to be correct, EACH commit must
# be conventional — not just the PR title. This is a CI backstop to the local hk
# commit-msg hook; the rule lives once in mise.toml (`mise run commit-lint`).
#
# Runs only on NON-DRAFT PRs — same cost discipline as ci.yml.
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
# Supersede, don't accumulate — see the note in zizmor.yml. A lap rebases and
# pushes; without this the superseded SHA's lint runs to completion unread.
concurrency:
group: commit-lint-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
env:
# Restores locked installs, which `[settings] lockfile = false` turns off
# along with the install-time write it exists to deny (CLOUD-223). A runner
# should install locked, and its checkout is disposable, so a write here
# costs nothing; the clone being protected is a developer's.
MISE_LOCKFILE: "true"
# What makes the `install_args` list below BINDING rather than decorative
# (CLOUD-812). mise auto-installs a missing tool when a task runs or when
# `mise exec` needs one, both default true — so with these on, a narrowed list
# moves the cost into the work step instead of removing it. CLOUD-180 measured
# exactly that in `ci.yml`'s `cross` job: rust installed in 13s, then serena's
# 72 Python packages, node, zig and prettier rebuilt inside the work step,
# "invisible in the step being optimised, because that step does get faster."
# That fix stopped at `ci.yml`; this workflow was never in its scope.
#
# Off, a tool this job did not ask for is a hard "command not found" rather
# than a silent re-download. `mise run ci-tools-check` is what keeps the pair
# honest in both directions: the names resolve, and a PR workflow cannot run
# `mise-action` with no list at all.
MISE_TASK_RUN_AUTO_INSTALL: "false"
MISE_EXEC_AUTO_INSTALL: "false"
jobs:
commit-lint:
name: commit-lint
if: ${{ github.event.pull_request.draft == false }}
# ARM64, AS ONE SET WITH THE REST OF THE `ci-` FAMILY (CLOUD-1416). This job
# became a reader of that family in the step below, and rust-cache puts
# `runnerOS-runnerArch` inside the restore prefix (`config.ts:93`, before
# `:133`) — so moving it while `cache-warm-linux` stayed on x64 would hand it
# no warm entry at all, which is worse than the cold build it is replacing.
# `ci.yml`'s `ci` job carries the reasoning and the list of jobs that
# deliberately do NOT move.
runs-on: ubuntu-24.04-arm
timeout-minutes: 10 # budget: grandfathered measured=2026-08-10
# `actions: write` is here for one call and one only: cancelling THIS run
# when the landing lease does not authorise this branch (CLOUD-420). A job
# that could not cancel itself would have to fail instead, and a failed job
# makes the run conclude `failure` rather than `cancelled` — which reds
# `final` and makes `land` re-draft a healthy PR.
permissions:
contents: read
actions: write
steps:
# CLOUD-420: THE LANDING LEASE, ENFORCED WHERE THE MONEY IS SPENT.
# First step, before any checkout or toolchain install, because a run this
# branch is not authorised to make should cost the rounding rather than a
# matrix. The body runs `batten lease guard`, installed from `main` and
# pinned to trunk's version rather than to this head's, so a clone
# carrying stale rules cannot dodge the predicate by carrying a stale copy
# of it. Every justification lives on `run_lease_guard`. THREE DIFFERENT
# FAILURES FAIL OPEN below, one `|| exit 0` each: a binary that will not
# download, a policy that will not fetch, and a guard that will not run.
# That is the whole posture — waving one matrix through costs one matrix,
# while a precondition that cannot reach its own inputs would stop the
# fleet. What keeps those three from reading as *ran and allowed* is
# trunk's installer refusing a binary that does not carry the verb
# (`BATTEN_REQUIRE`); until that installer IS trunk's, this step is
# vacuous by construction rather than by accident.
#
# AND IT WAS VACUOUS FOR A SECOND REASON THE PARAGRAPH ABOVE HID (review of
# #848). `$RUNNER_TEMP/batten-bin` is not on PATH, and `install.sh`'s
# off-PATH refusal is a `die 1` that fires BEFORE the `BATTEN_REQUIRE`
# check — so the `|| exit 0` ended the step at the install and the guard
# never ran, at any of the sites, whatever the installer's provenance. The
# bootstrap above is real and was not the reason; it just described the
# same silence convincingly enough that nobody looked further.
#
# `BATTEN_ALLOW_OFF_PATH=1` is the opt-out for exactly this shape and the
# binary is invoked by absolute path two lines down, so nothing here
# resolves `batten` by name and the refusal is protecting a caller that
# does not exist. Installing onto PATH instead would put a trunk-pinned
# binary ahead of the checkout's own for every later step in the job.
- name: Landing lease precondition
env:
GH_TOKEN: ${{ github.token }}
GH_REPO: ${{ github.repository }}
LEASE_HEAD_REF: ${{ github.head_ref }}
# The HEAD sha, never `github.sha`: on a pull_request event that is the
# merge commit, whose tree is trunk's wherever this head did not touch
# it — and the staleness read asks about the head's own landing paths.
LEASE_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
LEASE_RUN_ID: ${{ github.run_id }}
run: |
# `|| exit 0` ON EVERY LINE, and the reason outlives the shell it was
# written for (CLOUD-420). A step that reds makes the RUN's conclusion
# `failure` rather than `cancelled`; `final` then runs under
# `!cancelled()`, fails its `needs:` assertion, and `land` re-drafts a
# healthy PR — fleet-wide, from one bad response. `batten lease guard`
# promises it never exits non-zero; these are what make that true at the
# call site too, for the cases the promise cannot cover: a binary that
# will not download and one that will not run are different failures
# from one that ran and decided.
#
# THE VERSION IS TRUNK'S, NEVER THIS HEAD'S. The installer comes from
# trunk and resolves the version from trunk's own manifest, which is the
# property the fetched-script design protected by reading its logic from
# trunk — a head cannot pin an older guard for itself.
installer=$(gh api -H "Accept: application/vnd.github.raw" \
"repos/$GH_REPO/contents/install.sh?ref=main") || exit 0
printf '%s\n' "$installer" | \
BATTEN_VERSION_FROM_REF=main BATTEN_INSTALL_DIR="$RUNNER_TEMP/batten-bin" \
BATTEN_ALLOW_OFF_PATH=1 BATTEN_REQUIRE="lease guard" sh || exit 0
# THE POLICY IS TRUNK'S TOO, AND IT HAD TO BE FETCHED. This step runs
# BEFORE any checkout, so the directory the guard stands in is empty and
# `config::load` found nothing — `[lease] landing_paths` read as *no
# paths declared* and the staleness half failed open on every run, which
# is the exact silence the row was written to end. Fetched from `main`
# for the installer's own reason, one line up: a head must not pin the
# policy it is judged by, and the only tree a checkout would offer here
# is the pull request's own.
mkdir -p "$RUNNER_TEMP/batten-config" || exit 0
gh api -H "Accept: application/vnd.github.raw" \
"repos/$GH_REPO/contents/batten.toml?ref=main" \
>"$RUNNER_TEMP/batten-config/batten.toml" || exit 0
"$RUNNER_TEMP/batten-bin/batten" --config-in "$RUNNER_TEMP/batten-config" \
lease guard \
"$LEASE_HEAD_SHA" "$LEASE_HEAD_REF" "$LEASE_RUN_ID" || exit 0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
with:
fetch-depth: 0
- uses: jdx/mise-action@3c2e0cf82a5b2e5249f0d3635a4d83d0ae861518 # v4.2.5 (CLOUD-404 retry fix, now a release)
with:
# Pinned to `batten.toml`'s `[[provision]]` version (CLOUD-1672). The
# digest above pins the ACTION; this pins the MISE it installs, which
# is a separate resolution the digest does not reach.
version: 2026.9.1
# `rust`, and nothing else. `commit-lint` depends on `commit-check` and
# `commit-attribution`, both of which are `cargo run --quiet -p batten`,
# and on `signing-posture`, which uses only git, gpg and ssh-keygen —
# none of them pinned here. The other 27 `[tools]` entries were being
# installed on every PR push to run a commit-subject predicate.
install_args: rust
# A REQUIRED CHECK THAT SPENDS ~340s COLD-BUILDING TO RUN A 758ms LINT
# (CLOUD-1408). This workflow declared no `Swatinem/rust-cache` at all, so
# its target directory was empty on every run: `commit-lint` depends on
# `commit-attribution` and `commit-check`, both `cargo run --quiet -p
# batten`, and job 100806281473 measured both at ~341.9s against a lint
# body of 758.6ms. Chronic rather than incidental — 468s, 399s, 370s, 297s
# across the 2026-09-03 window. CLOUD-812 narrowed this workflow's tool
# installs to `rust` and the cargo cache was simply never in anyone's
# scope since.
#
# `ci-`, WHICH IS `cache-warm-linux`'s, and a key of this job's own would
# relocate the cost rather than remove it: GitHub scopes a cache read to
# the run's own ref plus the base branch, so only an entry written from
# `main` is readable by every pull request, and nothing on `main` would
# ever write a `commit-lint-` key.
#
# `save-if: false` IS LOAD-BEARING AND NOT MERELY TIDY. This job builds ONE
# binary against a family whose warm entry is the whole workspace plus its
# test targets, and it finishes roughly eleven minutes before `ci` does. A
# cache entry is immutable once written, so on a fresh key this job would
# win the race to populate a shared family with the thinnest of the trees
# that read it, and every later reader would rebuild what the warm job had
# already paid for. A pure consumer cannot lose that race because it does
# not enter it.
- uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2
with:
shared-key: ci-
save-if: false
- run: mise run commit-lint
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}