Manifest-driven validate(): the schema block is the spec, shared by the builders and a PR check #211
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Go-live guardrail (PLAN Phase 5): a PR must not break a file a live lecture | |
| # consumes. This job is the byte-integrity (sha256) and catalog-freshness gate; | |
| # its sibling validate-datasets.yml (2026-09-07, #119) is the schema gate — | |
| # manifest conformance and per-dataset invariants. Together they are the "PR | |
| # validation" Phase 5 promised; neither subsumes the other. | |
| name: consumed-file-check | |
| on: | |
| pull_request: | |
| push: | |
| branches: [main] | |
| jobs: | |
| consumed-files: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| # `lfs: false` is the assertion, not a saving. A manifest records the | |
| # sha256 of the real bytes, so if a `lectures/` file is ever | |
| # LFS-tracked by mistake this job hashes the pointer, mismatches, and | |
| # goes red — which is exactly what a reader would get from | |
| # raw.githubusercontent.com. Fetching the real bytes would hash them | |
| # correctly and pass green while every consumer downloads ~130 bytes | |
| # of pointer text. LFS belongs to `sources/**` only (.gitattributes). | |
| # | |
| # This job DOES read `sources/` now, and `lfs: false` is right there | |
| # too, for the opposite reason: those files are meant to be LFS, so | |
| # the checkout hands us pointers — and a pointer's `oid` IS the | |
| # object's sha256, which is the value sources/README.md records. The | |
| # check verifies ~100 MiB of bytes without fetching one of them, and | |
| # the direction still holds: a `sources/` file committed as plain git | |
| # by mistake arrives as real bytes, hashes to something the README | |
| # does not record, and goes red. | |
| lfs: false | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.12" | |
| - run: pip install pyyaml | |
| - run: python .github/scripts/check_consumed_files.py | |
| # CATALOG.md is generated from the same manifests this job validates, and | |
| # `scripts/build_catalog.py` has claimed since it was written that CI | |
| # asserts its freshness. Nothing did: no workflow ran the generator at | |
| # all, so #69 could populate six manifests' `consumers` and leave the | |
| # committed catalog contradicting them — invisible until an unrelated PR | |
| # inherited the surprise diff (#71). This is that gate, put where the | |
| # manifests are already parsed and pyyaml is already installed. | |
| - name: CATALOG.md is current | |
| run: | | |
| python scripts/build_catalog.py | |
| git diff --exit-code -- CATALOG.md || { | |
| echo "::error file=CATALOG.md::CATALOG.md is stale. A manifest changed without regenerating the catalog — run 'python scripts/build_catalog.py' and commit the result." | |
| exit 1 | |
| } |