Skip to content

Commit aac6a85

Browse files
authored
docs(standard): add CI9, the shared ADR check fetched from main (#121)
1 parent 3285af8 commit aac6a85

2 files changed

Lines changed: 34 additions & 0 deletions

File tree

‎docs/standard.md‎

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,37 @@ remapping this repo's `blob/main` URLs to the checkout.
257257

258258
A repo with a docs site MUST have a `docs` job running `just docs-build` (`mkdocs build --strict`).
259259

260+
### CI9 · Shared ADR check { #CI9 }
261+
262+
The `lint` job MUST run `just adr-check` after `just install lint-ci`. The recipe MUST be this,
263+
byte for byte, and a repo MUST NOT keep a copy of `tests/test_adr_citations.py`:
264+
265+
```just
266+
adr_check_source := "https://raw.githubusercontent.com/modern-python/.github/main/tests/test_adr_citations.py"
267+
268+
# Tracks main on purpose: the shared check is unpinned.
269+
adr-check:
270+
#!/usr/bin/env sh
271+
set -eu
272+
dir="$(mktemp -d .adr-check.XXXXXX)"
273+
trap 'rm -rf "$dir"' EXIT
274+
curl -fsSL "{{ adr_check_source }}" -o "$dir/test_adr_citations.py"
275+
uv run --no-sync pytest --rootdir=. --noconftest -o addopts= "$dir/test_adr_citations.py"
276+
```
277+
278+
The check asserts that every ADR cited anywhere in the repo, by `docs/adr/NNNN-slug.md` path or by
279+
bare `ADR-NNNN` number, exists in `docs/adr/` ([FL4](#FL4)).
280+
281+
*Why:* one rule, one file. Twenty-five byte-identical copies of this test drifted within a month
282+
of being written. The recipe tracks `main` unpinned on purpose: a change to the rule lands once,
283+
with no release and no bump across the org. The trade is that it reaches every repo's next run at
284+
once, so a change to the file in this repo is run against every repo's `main` before it merges,
285+
and a repo's own pull request sees the fix only once its branch carries it. `--rootdir=.` makes
286+
the repo the scanned root; `--noconftest` and `-o addopts=` keep the repo's conftests and
287+
coverage gate out of a one-file run; the temporary directory sits inside the repo because
288+
plugins such as `pytest-alembic` reject collected files outside the root. `adr_check_source` can
289+
be pointed at a `file://` path to run an unmerged version of the check.
290+
260291
## Release
261292

262293
### RL1 · Tags { #RL1 }

‎tests/test_adr_citations.py‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ def unresolved_citations(root: pathlib.Path) -> list[tuple[str, str]]:
5858
def test_every_adr_citation_in_the_repo_resolves(pytestconfig: pytest.Config) -> None:
5959
"""INVARIANT: every ADR named in this repo resolves, by full path or by bare `ADR-NNNN` number.
6060
61+
Every org repo fetches this file from `main` and runs it against its own tree (CI9), so a change
62+
here reaches all of them on their next run.
63+
6164
Broken by renaming, renumbering or pruning an ADR without following its citations. The offline
6265
link gate reads Markdown links only, so a path in a docstring, a comment, a guard message or a
6366
`pyproject.toml` dependency rationale is otherwise checked by nothing, and neither is the bare

0 commit comments

Comments
 (0)