Skip to content

Manifest-driven validate(): the schema block is the spec, shared by the builders and a PR check #211

Manifest-driven validate(): the schema block is the spec, shared by the builders and a PR check

Manifest-driven validate(): the schema block is the spec, shared by the builders and a PR check #211

# 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
}