Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .github/workflows/build-explainers.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ name: Build Explainers
# explainer - not byte- or pixel-compared against this job's own fresh
# regeneration, since Pillow's bundled FreeType renders text with
# genuinely different pixels across platforms (see
# scripts/check_generated_files_current.py's docstring).
# scripts/check_generated_files_current.py's docstring). Also verifies the
# plain-prose "N explainers" mentions in README.md, CONTRIBUTORS.md,
# METRICS.md, and ROADMAP.md haven't drifted from the real count of
# explainers/*.md (scripts/check_explainer_count.py).
#
# main requires a PR (branch protection), and github-actions[bot] isn't in
# that ruleset's bypass list, so this can no longer auto-commit a fix by
Expand All @@ -27,6 +30,11 @@ on:
- "scripts/build_explainers.py"
- "scripts/generate_og_images.py"
- "scripts/check_generated_files_current.py"
- "scripts/check_explainer_count.py"
- "README.md"
- "CONTRIBUTORS.md"
- "METRICS.md"
- "ROADMAP.md"
pull_request:
paths:
- "explainers/**.md"
Expand All @@ -35,6 +43,11 @@ on:
- "scripts/build_explainers.py"
- "scripts/generate_og_images.py"
- "scripts/check_generated_files_current.py"
- "scripts/check_explainer_count.py"
- "README.md"
- "CONTRIBUTORS.md"
- "METRICS.md"
- "ROADMAP.md"

jobs:
check:
Expand Down Expand Up @@ -67,3 +80,6 @@ jobs:
# existence/size/dimensions instead, which is platform-independent.
# Text-based generated files still get an exact git diff.
run: python3 scripts/check_generated_files_current.py

- name: Fail if a "current explainer count" mention has drifted
run: python3 scripts/check_explainer_count.py
2 changes: 1 addition & 1 deletion CONTRIBUTORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ the [Git identity map](#git-identity-map) so `git shortlog -sne` can be reconcil

| | Who | Role |
|:--|-----|------|
| <a href="https://github.com/yakew7"><img src="https://github.com/yakew7.png" width="48" height="48" alt="yakew7"></a> | **Yash Kewlani** - [@yakew7](https://github.com/yakew7) | Creator and maintainer. Author of the seven audits, the `faircode` library and benchmark harness, the Open Dataset Profiler, the website, and the bulk of the 39 explainers. Code owner for `faircode/`, `paper/`, every `audit.yaml`, and project policy (`CLAUDE.md`, `CONTRIBUTING.md`); co-owner of `explainers/`. |
| <a href="https://github.com/yakew7"><img src="https://github.com/yakew7.png" width="48" height="48" alt="yakew7"></a> | **Yash Kewlani** - [@yakew7](https://github.com/yakew7) | Creator and maintainer. Author of the seven audits, the `faircode` library and benchmark harness, the Open Dataset Profiler, the website, and the bulk of the 53 explainers. Code owner for `faircode/`, `paper/`, every `audit.yaml`, and project policy (`CLAUDE.md`, `CONTRIBUTING.md`); co-owner of `explainers/`. |

Contact: [yashkewlani2020@gmail.com](mailto:yashkewlani2020@gmail.com) · [@thefaircodeproject](https://instagram.com/thefaircodeproject)

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1166,7 +1166,7 @@ The full public roadmap - with phases, completion status, and content schedule -
| Combined Social Reach (Instagram + LinkedIn) | 30K+ |
| Countries Reached (Website Visitors) | 18 |
| Code Audits Published | 7 |
| Explainers Published | 47 |
| Explainers Published | 53 |

Tracked weekly in [METRICS.md](METRICS.md).

Expand Down
61 changes: 61 additions & 0 deletions scripts/check_explainer_count.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env python3
"""Fails if a "current explainer count" mention in README.md, CONTRIBUTORS.md,
METRICS.md, or ROADMAP.md drifts from the real count of explainers/*.md.

CHECKS below is a small, explicit list of exact regexes, one per file - not a
fuzzy "N explainers" scan across the whole file. METRICS.md in particular is a
weekly log full of legitimate historical counts (e.g. "explainer count `39 ->
44`" from an old week); matching those against today's count would be a false
positive worse than the drift this script is meant to catch. Each regex below
targets the one line in its file that's meant to state the current, live
total.

Run locally: python3 scripts/check_explainer_count.py
Exit code: 0 = all mentions match, 1 = at least one is stale or missing.
"""
from __future__ import annotations

import re
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent
EXPLAINERS_DIR = ROOT / "explainers"

# (relative path, regex whose sole capture group is the claimed count)
CHECKS = [
("README.md", re.compile(r"Show all (\d+) explainers")),
("CONTRIBUTORS.md", re.compile(r"the bulk of the (\d+) explainers")),
("METRICS.md", re.compile(r"Explainers-(\d+)-blueviolet")),
("ROADMAP.md", re.compile(r"(\d+) explainers published")),
]


def main() -> int:
actual = len(list(EXPLAINERS_DIR.glob("*.md")))
stale = []

for rel_path, pattern in CHECKS:
path = ROOT / rel_path
text = path.read_text(encoding="utf-8")
match = pattern.search(text)
if match is None:
stale.append((rel_path, f"expected pattern not found: {pattern.pattern!r}"))
continue
claimed = int(match.group(1))
if claimed != actual:
stale.append((rel_path, f"says {claimed} explainers, but explainers/*.md has {actual}"))

if stale:
print(f"Explainer count drift found (explainers/*.md currently has {actual} files):",
file=sys.stderr)
for rel_path, reason in stale:
print(f" {rel_path}: {reason}", file=sys.stderr)
return 1

print(f"OK: all {len(CHECKS)} explainer-count mentions match explainers/*.md ({actual} files).")
return 0


if __name__ == "__main__":
sys.exit(main())