From 345a72829e1cffb916bba3d12f24ada1bf2cc9ea Mon Sep 17 00:00:00 2001 From: Jon Froehlich Date: Tue, 23 Jun 2026 04:37:03 -0700 Subject: [PATCH] Add CI gate enforcing per-page description: front matter Adds scripts/check_seo_frontmatter.py and a "Content lint" GitHub Actions workflow (runs on pull_request) that fails a PR if any published page is missing `description:`. Kept separate from the deploy workflow so a content miss blocks a merge but never the live site. Drafts (nav_exclude/search_exclude) and contributor docs are exempt; `image:` is advisory (reminds when an MP4-hero page has no poster). Documents the authoring template + enforcement in website-dev.md and adds the script to scripts/README.md. This makes the SEO convention self-sustaining for all new content and in-flight branches. Co-Authored-By: Claude Opus 4.8 --- .github/workflows/content-lint.yml | 29 +++++++ scripts/README.md | 14 ++++ scripts/check_seo_frontmatter.py | 120 +++++++++++++++++++++++++++++ website-dev.md | 28 +++++++ 4 files changed, 191 insertions(+) create mode 100644 .github/workflows/content-lint.yml create mode 100644 scripts/check_seo_frontmatter.py diff --git a/.github/workflows/content-lint.yml b/.github/workflows/content-lint.yml new file mode 100644 index 0000000..f77c1d6 --- /dev/null +++ b/.github/workflows/content-lint.yml @@ -0,0 +1,29 @@ +# Content lint: gate pull requests on textbook authoring conventions. +# +# Runs lightweight checks on the Markdown content. Separate from the deploy +# workflow (jekyll.yml) on purpose: a content-convention miss should block a +# MERGE, but never take down the live site. This is also the home for future +# content gates (e.g. the #99 code-block standardization lint). +name: Content lint + +on: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + seo-frontmatter: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Python + uses: actions/setup-python@v5 + with: + python-version: "3.x" + + - name: Check per-page SEO front matter (description:) + run: python scripts/check_seo_frontmatter.py diff --git a/scripts/README.md b/scripts/README.md index c2d12c2..12e2b79 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -22,6 +22,7 @@ Python utilities that bulk-edit or generate content across the textbook. They ar | Script | Purpose | Apply flag | |---|---|---| +| [`check_seo_frontmatter.py`](check_seo_frontmatter.py) | **CI gate** — fail if any published page is missing `description:` front matter (reminds about MP4-hero pages lacking a poster). Read-only. | _(none)_ | | [`generate_og_posters.py`](generate_og_posters.py) | Generate static OG/social-card poster images from a page's hero `