fixtures: acceptance tests for every gate One fixture per check, each pinning the specific defect or behaviour it exists to catch: descriptor and schema validation, kconfig hazards and effective-config resolution, kunit/kselftest adapters and their debug-verdict paths, kmemleak verdict classification, legacy-symbol scanning, kernel-doc and comment-audit checks, commit-wise and squash-equivalence proofs, provenance and mbox construction, stream integrity, and the negative-control baseline that keeps a known-clean tree known-clean. Signed-off-by: Konstantin Sinyuk <ksinyuk@kernel.org>
Qualification gates for a Linux kernel patch series, run before it is posted.
The harness takes a series descriptor, asks Git which paths each revision actually submits, classifies those paths, runs the checks that classification selects, and reports whether each check examined what the series really contains. It runs everything in a pinned container, boots guests for the tests that need one, and records enough about each run to re-derive the result later.
It is not a CI system and does not want to be one. It answers a narrower question: is this series ready to send?
Most of the design follows from one observation: a check that silently examines nothing passes.
So every check reports what it expected to examine and what it did, and those numbers have to agree. Expected counts come from a contract the revision names, never from a value written into a gate — a count inside a check is a count nobody can see is wrong. Exit codes carry the distinction:
| Code | Meaning |
|---|---|
| 0 | pass |
| 1 | a real defect |
| 2 | the gate did not run against its intended inputs |
A 2 is not a softer 1. It means the answer is unavailable, and it is reported that way rather than being rounded to either side.
Requirements: Linux, Python 3.11+, Git, Docker, and GNU tar. Everything else — sparse, smatch, checkpatch's dependencies, virtme-ng, QEMU — lives in the pinned image.
git clone https://git.kernel.org/pub/scm/linux/kernel/git/ksinyuk/release-harness.git cd release-harness export LAB_ROOT=$PWD/.. # workspace; defaults to the parent anyway export LAB_REPO=$LAB_ROOT/linux.git # One-time reference repository setup. This shallow fetch contains the base and # all twelve commits used by the configuration shipped with the harness. # # drm-fabric-next is a branch, not a tag: it moves as the series is revised, so # unlike drm-fabric-v1 there is no annotated ref freezing it. Re-run this fetch # to pick up a new revision, and see "The series it ships configured against" # below for the exact commit this tree was validated against. git init --bare "$LAB_REPO" git -C "$LAB_REPO" fetch --depth=13 \ https://git.kernel.org/pub/scm/linux/kernel/git/ksinyuk/linux.git \ refs/heads/drm-fabric-next:refs/heads/drm-fabric-next tools/gates/rfc-gate.py selfcheck # the harness against itself tools/gates/rfc-gate.py catalogue # every check it can run
Then build the container and the guest kernels once:
tools/gates/lab-tier.sh foundation --phase both \ --readonly-rev drm-fabric-next~6 --provision-rev drm-fabric-next
and thereafter, per change:
tools/gates/lab-tier.sh quick --phase both \ --readonly-rev drm-fabric-next~6 --provision-rev drm-fabric-next # ~1.25 min tools/gates/lab-tier.sh release --phase both # ~22 min
See doc/configuring.md for pointing it at your own series, and doc/tier-cost-and-parallelism.md for what each tier costs and why.
tools/gates/ rfc-gate.py policy-driven check runner rfcgate/ the check engine (checks.py holds the checks themselves) lab-tier.sh tier driver: foundation, quick, polish, release lab-env.sh single authority for paths and pins — source it, don't parse it lab-run run a command inside the pinned container lib/ shell libraries: control, telemetry, verdict, revsel, out-usage ref/ the series descriptor and its contracts fixtures/ self-tests, one per check, each naming the defect it pins guest/ workloads that run inside a booted guest tools/comment-audit/ the comment analyser and its calibration corpus tools/container/ the pinned toolchain image recipe doc/ see doc/README.md
The reference configuration describes a real, published series: the twelve commits on the drm-fabric-next branch in ksinyuk/linux.git, adding a vendor-neutral DRM fabric topology layer. That is deliberate — every check has something real to run on, and every expected count is a number that is actually true.
Unlike the drm-fabric-v1 tag it superseded, drm-fabric-next is a branch and moves as the series is revised. This tree was validated against base e3e05bddbe9fea67639d2a3551e7cf2d473b804c, readonly milestone tip 96973c7156905d3c58a313bdc750fed7f6221093, and provisioning tip b923b88277e0b1d979411e99b2e18c2b8dc694ce. If the branch has moved since, the counts in tools/gates/ref/runtime-contracts.yaml describe that commit, not necessarily the branch's current head — re-run foundation and quick and compare before trusting a verdict against a moved branch.
Revision ids are opaque to every executable here. Nothing tests for the string readonly, and fixtures/squash-equivalence.py is the standing proof: it derives a one-revision descriptor from the real one and requires identical classification. Your series can have one revision or five, named whatever you like.
It has qualified one series end to end: drm-fabric-v1, the tag the reference configuration pointed at until it was retargeted to the drm-fabric-next branch above. The tier costs quoted above are measured on that earlier run, on one machine; treat them as the right order of magnitude rather than a promise, and as not yet re-confirmed against drm-fabric-next.
The base image digest and the Sparse/Smatch source archives are pinned, and the built image is checked for the tool versions and runtime dependencies the gates consume. Distribution packages and transitive Python packages are not locked by content hash, so rebuilding is not bit-for-bit reproducible. Preserve the image ID and generated provenance record when comparing evidence across runs.
The historical comment-calibration source commit is not yet advertised by a public ref. The gate and fixtures run, but an independent reader cannot rerun that historical measurement until the commit is published or the calibration is redone against a named public Linux revision; see doc/comment-policy.md §6.
Some things are known-unfinished and say so where they are: the smoke tier exists as a design and a standalone script but is not wired into the tier driver (doc/tier-cost-and-parallelism.md §3), and the supervision layer's phased rollout is not complete (doc/design/supervised-gates.md).
GPL-2.0, with a small number of MIT-licensed files. Source files carry SPDX tags; data and documentation without an inline tag are covered by COPYING and any directory-level licensing note it names.