ci: put a timeout on every job, cancel superseded PR runs, lint the protocol
Lane 3a of the testing arc --- the three cheap, deterministic items of `TEST_IMPROVEMENT.md` §5-6. The larger ones (nextest, the serial/parallel split, a parallel canary leg, the nightly cron, the macOS matrix trim) are deliberately NOT here: each changes what CI certifies or how it runs, and each deserves its own decision rather than riding in on a timeout patch. `timeout-minutes` on every job (§5.2). Measured before changing rather than assumed: SEVEN of eight jobs had none and inherited GitHub's 360-minute default; only `m6-perf-gates` had one, at 15. So a single hung test burnt six hours --- times four on the test matrix --- and reported nothing useful at the end of it. Set to 25 against a measured ~14.6 min critical path (macOS/luajit), which leaves ample headroom for a slow runner while catching a hang in under half an hour. This is the gate that has to exist before `PMACS_REQUIRE_PYRIGHT` can ever be set. Lane 2 left basedpyright unarmed *because* this did not exist; the two decisions are the same decision, half a lane apart. `concurrency` with `cancel-in-progress` (§6.1), scoped to pull requests. This project rebases heavily --- the ledger re-conflicts on nearly every merge --- so branches take several pushes while earlier runs are still going, and macOS minutes are both the expensive ones and the critical path. Pushes to `main` are deliberately exempt: `github.event.pull_request.number` is empty there, so the fallback keys those runs by SHA and none can cancel another. Cancelling a `main` run would leave the branch-protection record ambiguous about a commit that has already landed, which is the one place the saving is not worth having. `-p pmacs-protocol` clippy (§5.7). The root-package clippy never covered it --- the workspace default member is only `pmacs` --- so a warning introduced through a protocol-only change would reach `main` unseen. Verified passing locally BEFORE proposing it, so it cannot turn CI red on arrival. The timeout rationale is stated once above the job list rather than copied onto each job: the first draft duplicated a seven-line comment across seven jobs, which is the same degraded-copy shape this arc keeps removing elsewhere. Verified: YAML parses; all eight jobs carry a timeout (seven at 25, m6-perf-gates keeping its tighter 15); `cargo fmt --all --check`, `clippy -p pmacs-protocol` and `clippy -p pmacs-gpu` all exit 0; `git diff --check` clean. The diff touches `ci.yml` and the ledger and nothing else, so no code gate is affected.
This commit is contained in:
parent
b7bf2c6644
commit
708054e8d5
|
|
@ -9,10 +9,39 @@ env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
RUSTFLAGS: "-D warnings"
|
RUSTFLAGS: "-D warnings"
|
||||||
|
|
||||||
|
# Cancel a pull request's superseded runs instead of letting them burn
|
||||||
|
# to completion. This project rebases heavily — the ledger re-conflicts
|
||||||
|
# on nearly every merge — so a branch routinely takes several pushes
|
||||||
|
# while an earlier run is still going, and each of those runs is
|
||||||
|
# obsolete the moment the next push lands. macOS minutes are the
|
||||||
|
# expensive ones and the macOS leg is the critical path, so superseded
|
||||||
|
# runs are exactly where the waste concentrates.
|
||||||
|
#
|
||||||
|
# Scoped to pull requests deliberately. `github.event.pull_request.number`
|
||||||
|
# is empty for a push to `main`, so the fallback keys those runs by SHA:
|
||||||
|
# every `main` commit gets its own group and none can cancel another.
|
||||||
|
# Cancelling a `main` run would leave the branch-protection record
|
||||||
|
# ambiguous about a commit that has already landed — the one place this
|
||||||
|
# saving is not worth having.
|
||||||
|
concurrency:
|
||||||
|
group: ci-${{ github.event.pull_request.number || github.sha }}
|
||||||
|
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||||
|
|
||||||
|
# Every job carries `timeout-minutes`. Without one a job inherits
|
||||||
|
# GitHub's 360-minute default, so a single hung test burns six hours —
|
||||||
|
# times four on the test matrix — and reports nothing useful at the end
|
||||||
|
# of it. The measured critical path is ~14.6 min (macOS/luajit), so 25
|
||||||
|
# leaves ample headroom for a slow runner while catching a hang in
|
||||||
|
# under half an hour. `m6-perf-gates` keeps its tighter 15.
|
||||||
|
#
|
||||||
|
# This is also the gate that has to exist before the basedpyright-class
|
||||||
|
# hang can ever be armed — see `PMACS_REQUIRE_PYRIGHT`, deliberately
|
||||||
|
# never set, in the test job below.
|
||||||
jobs:
|
jobs:
|
||||||
fmt:
|
fmt:
|
||||||
name: Format
|
name: Format
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 25
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
@ -23,6 +52,7 @@ jobs:
|
||||||
clippy:
|
clippy:
|
||||||
name: Lint (${{ matrix.lua }})
|
name: Lint (${{ matrix.lua }})
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 25
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -40,10 +70,17 @@ jobs:
|
||||||
# not pmacs), so the root-package clippy above never lints it. Lint
|
# not pmacs), so the root-package clippy above never lints it. Lint
|
||||||
# it explicitly or its warnings slip through CI (audit F-001).
|
# it explicitly or its warnings slip through CI (audit F-001).
|
||||||
- run: cargo clippy -p pmacs-gpu --all-targets -- -D warnings
|
- run: cargo clippy -p pmacs-gpu --all-targets -- -D warnings
|
||||||
|
# pmacs-protocol is likewise never linted by the root-package
|
||||||
|
# clippy above: the workspace default member is only `pmacs`. The
|
||||||
|
# local `--workspace` gate covers it, so it passes today — CI has
|
||||||
|
# simply never checked, and a warning introduced through a
|
||||||
|
# protocol-only PR would reach `main` unseen.
|
||||||
|
- run: cargo clippy -p pmacs-protocol --all-targets -- -D warnings
|
||||||
|
|
||||||
gpu-render:
|
gpu-render:
|
||||||
name: GPU Render (headless)
|
name: GPU Render (headless)
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 25
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
@ -76,6 +113,7 @@ jobs:
|
||||||
test:
|
test:
|
||||||
name: Test (${{ matrix.os }} / ${{ matrix.lua }})
|
name: Test (${{ matrix.os }} / ${{ matrix.lua }})
|
||||||
runs-on: ${{ matrix.os }}
|
runs-on: ${{ matrix.os }}
|
||||||
|
timeout-minutes: 25
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
|
|
@ -160,6 +198,7 @@ jobs:
|
||||||
acceptance:
|
acceptance:
|
||||||
name: M1 Acceptance Gates
|
name: M1 Acceptance Gates
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 25
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
@ -170,6 +209,7 @@ jobs:
|
||||||
m4-perf-gates:
|
m4-perf-gates:
|
||||||
name: M4 Perf Gates
|
name: M4 Perf Gates
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 25
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
@ -188,6 +228,7 @@ jobs:
|
||||||
m5-perf-gates:
|
m5-perf-gates:
|
||||||
name: M5 Perf Gates
|
name: M5 Perf Gates
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 25
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: dtolnay/rust-toolchain@stable
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
|
|
||||||
|
|
@ -820,6 +820,45 @@ has **no branch and no framing yet**.
|
||||||
current documentation. The section said "whoever confirms the branch
|
current documentation. The section said "whoever confirms the branch
|
||||||
carries nothing unique removes the section"; this is that.
|
carries nothing unique removes the section"; this is that.
|
||||||
|
|
||||||
|
## Test-improvement arc, lane 3a — CI timeouts and concurrency
|
||||||
|
|
||||||
|
- Portable branch: `githubsucks/ci-timeouts-concurrency`, worktree
|
||||||
|
`../pmacs-ci3`. Workflow only — **no product code, no tests changed.**
|
||||||
|
- **Base, measured at write time:**
|
||||||
|
|
||||||
|
```
|
||||||
|
$ git log --oneline -1 githubsucks/main
|
||||||
|
b7bf2c6 Merge pull request #194 from levineuwirth/silent-skip-arming
|
||||||
|
```
|
||||||
|
|
||||||
|
- Ships the three cheap, deterministic items of `TEST_IMPROVEMENT.md`
|
||||||
|
§5-6. The larger ones — nextest (§6.3), the serial/parallel split
|
||||||
|
(§6.2), the parallel canary leg (§5.6), the nightly cron (§5.5), and
|
||||||
|
the macOS matrix trim (§6.4) — are **deliberately not here**: each
|
||||||
|
changes what CI certifies or how it runs, and each wants its own
|
||||||
|
decision rather than riding a timeout patch.
|
||||||
|
- **`timeout-minutes` on every job (§5.2).** Measured before changing:
|
||||||
|
**7 of 8 jobs had none** and inherited GitHub's 360-minute default;
|
||||||
|
only `m6-perf-gates` had one (15). A single hung test therefore burnt
|
||||||
|
six hours, times four on the test matrix. Set to 25 against a
|
||||||
|
measured ~14.6 min critical path (macOS/luajit).
|
||||||
|
**This is the gate that must land before `PMACS_REQUIRE_PYRIGHT` can
|
||||||
|
ever be set** — lane 2 left basedpyright unarmed precisely because
|
||||||
|
this did not exist.
|
||||||
|
- **`concurrency` with `cancel-in-progress` (§6.1)**, scoped to pull
|
||||||
|
requests. `github.event.pull_request.number` is empty on a push to
|
||||||
|
`main`, so the fallback keys those by SHA and no `main` run can
|
||||||
|
cancel another — cancelling one would leave the branch-protection
|
||||||
|
record ambiguous about a commit that already landed.
|
||||||
|
- **`-p pmacs-protocol` clippy (§5.7).** Verified passing locally
|
||||||
|
*before* proposing it, so adding it cannot turn CI red on arrival.
|
||||||
|
The root-package clippy never covered it: the workspace default
|
||||||
|
member is only `pmacs`.
|
||||||
|
- Recovery from a clean checkout:
|
||||||
|
`git fetch githubsucks && git worktree add ../pmacs-ci3
|
||||||
|
-b ci-timeouts-concurrency githubsucks/ci-timeouts-concurrency`.
|
||||||
|
|
||||||
|
|
||||||
## Parked lane: kill-ring browser + persistence
|
## Parked lane: kill-ring browser + persistence
|
||||||
|
|
||||||
- Portable branch: `githubsucks/kill-ring-browser`
|
- Portable branch: `githubsucks/kill-ring-browser`
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue