diff --git a/docs/index.md b/docs/index.md index 7e3699b..8dcc204 100644 --- a/docs/index.md +++ b/docs/index.md @@ -240,11 +240,12 @@ graph LR -## Trusted by developers worldwide +## Used by
-**Used by developers and organizations worldwide in their production workflows.** +**Commit Check runs in repositories across these organizations, and in +[many more](https://github.com/commit-check/commit-check-action/network/dependents).**
@@ -323,8 +324,6 @@ graph LR
-And [many more](https://github.com/commit-check/commit-check-action/network/dependents). - ---
diff --git a/tests/docs_sync_test.py b/tests/docs_sync_test.py index 4eac633..de9abf0 100644 --- a/tests/docs_sync_test.py +++ b/tests/docs_sync_test.py @@ -32,6 +32,10 @@ def _read_doc(name: str) -> str: #: A pasted failure line, e.g. ``CC003 subject-imperative check failed ==> ...`` _SAMPLE_FAILURE = re.compile(r"(CC\d{3}) (\S+) check failed ==>") +#: A pasted ``--compact`` line, e.g. ``[FAIL] CC003 subject_imperative: ...``. +#: Indented, because these samples sit inside content tabs. +_COMPACT_FAILURE = re.compile(r"^\s*\[FAIL\] (CC\d{3}) ([^:\s]+):", re.M) + def _rule_section(content: str, rule_id: str) -> str: """Return just the part of the rules page belonging to one rule.""" @@ -39,6 +43,33 @@ def _rule_section(content: str, rule_id: str) -> str: return re.split(r"\{ #cc\d{3} \}", after)[0] +def _stale_samples(pattern: re.Pattern, attribute: str, printer: str) -> list[str]: + """Find pasted samples that name a rule differently from the tool. + + ``attribute`` is the field of the catalog entry the format prints, and + ``printer`` names that format in the failure message. + + An unrecognised rule ID is reported rather than skipped. Skipping it would + mean a typo, or an ID retired upstream, could sit in a sample with every + test still passing — which is the exact failure these guards exist to + catch, so it must not be the one they wave through. + """ + by_id = {entry.rule_id: entry for entry in ALL_RULES} + stale = [] + for page in DOCS.rglob("*.md"): + for rule_id, printed in pattern.findall(page.read_text("utf-8")): + where = page.relative_to(DOCS) + entry = by_id.get(rule_id) + if entry is None: + stale.append(f"{where}: {rule_id} is not a rule the package defines") + elif printed != getattr(entry, attribute): + stale.append( + f"{where}: {rule_id} shown as '{printed}', " + f"{printer} prints '{getattr(entry, attribute)}'" + ) + return stale + + class TestRulesDocumentation: """Every rule the package defines stays documented here.""" @@ -71,18 +102,27 @@ def test_sample_output_matches_what_the_tool_prints(self): to its kebab-case form, six samples across four pages kept showing the old one and every test still passed. """ - by_id = {entry.rule_id: entry for entry in ALL_RULES} - stale = [] - for page in DOCS.rglob("*.md"): - for rule_id, printed in _SAMPLE_FAILURE.findall(page.read_text("utf-8")): - entry = by_id.get(rule_id) - if entry and printed != entry.name: - stale.append( - f"{page.relative_to(DOCS)}: {rule_id} shown as " - f"'{printed}', the tool prints '{entry.name}'" - ) + stale = _stale_samples(_SAMPLE_FAILURE, "name", "the tool") assert not stale, "sample output is out of date:\n " + "\n ".join(stale) + def test_compact_sample_output_matches_what_the_tool_prints(self): + """Pasted ``--compact`` output names rules the way that format does. + + The two text formats spell a check differently: the default output + prints the kebab-case name, and ``--compact`` prints the config key. + A sample of one therefore cannot be validated against the other, and + the guard above only matches the default format — so the compact + samples were checked by nothing at all. That is the blind spot that + let a pre-2.13 sample sit unnoticed in the troubleshooting page. + + If the two formats are ever reconciled (see commit-check#528), this + is what will point at the samples that need rewriting. + """ + stale = _stale_samples(_COMPACT_FAILURE, "check", "--compact") + assert not stale, ( + "compact sample output is out of date:\n " + "\n ".join(stale) + ) + def test_every_rule_explains_itself(self): """Each rule section must answer what it does and why it matters.""" content = _read_doc("rules.md")