feat(ci): validate embed source_page references before build (Phase 4) - #641
Merged
Conversation
Add scripts/check_embed_sources.py, which verifies every content/embeds/* page's source_page resolves to an existing content/data page. A dangling reference makes the Hugo build abort via errorf (layouts/embeds/single.html, layouts/shortcodes/observatory-chart.html) — the failure mode behind issue #627. - Runs as a pytest (tests/test_embed_sources.py) in the required Python job, so a PR that adds an embed without its data page fails CI, not the deploy. - Runs as an explicit fast-fail step in the production-site job before the Hugo build, giving deploy-parity coverage. Implements Phase 4 (CI deploy-parity guard) of the deploy-hydration remediation plan.
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a deploy-parity CI guard to prevent Hugo builds from failing at deploy time due to content/embeds/* pages referencing missing content/data/* pages, addressing the failure mode from issue #627.
Changes:
- Introduces
scripts/check_embed_sources.pyto validate that each embed’ssource_pageresolves to an existing content page. - Adds
tests/test_embed_sources.pyto enforce the invariant in the Python test suite. - Wires the check into
.github/workflows/ci.ymlbefore the Hugo build for fast-fail parity with production.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
scripts/check_embed_sources.py |
New validator that scans embed bundles and reports missing/dangling source_page references. |
tests/test_embed_sources.py |
New unit tests covering missing, dangling, and resolving source_page cases plus a repo-wide invariant check. |
.github/workflows/ci.yml |
Adds a “Validate embed source pages” step prior to the Hugo build in CI. |
Contributor
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated no new comments.
Suppressed comments (2)
scripts/check_embed_sources.py:35
_resolvescurrently treats/data/(the section root) as a valid target becauserelative == "data"is allowed. That conflicts with this PR’s stated contract (“content/data//”) and can let an embed pass CI while rendering blank (the chart partial requires ranking params that section pages don’t have). Disallowdataitself and requiredata/<slug>.
relative = source_page.strip("/")
# NFR-012: an embed's source_page must be a data page under content/data/.
if relative != "data" and not relative.startswith("data/"):
return False
tests/test_embed_sources.py:60
- Add a regression test for the
/data/section-root case so the guard can’t accidentally accept it in the future (it should requirecontent/data/<slug>/, not the section index).
def test_non_data_source_page_is_reported() -> None:
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
_write(
root / "content/embeds/chart/index.md",
'+++\nsource_page = "/weekly/2026/w22/"\n+++\n',
)
# The referenced page exists, but it is not a content/data page.
_write(root / "content/weekly/2026/w22/index.md", '+++\ntitle = "W22"\n+++\n')
problems = check_embed_sources(root)
assert any("does not resolve to a content/data page" in problem for problem in problems)
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements Phase 4 (CI deploy-parity guard) of the deploy-hydration remediation plan.
Why
The #627 deploy failure was a
content/embeds/*page referencing acontent/datapage that wasn't present at build time, which aborts the Hugo build viaerrorf(layouts/embeds/single.html,layouts/shortcodes/observatory-chart.html). #637 made hydration safe so this can't be caused by hydration anymore, but a dangling embed reference authored in the repo would still only surface at deploy. This adds a guard so it fails in CI instead.What
scripts/check_embed_sources.py— verifies everycontent/embeds/*/index.mdsource_pageresolves to an existingcontent/data/<slug>/page.Wired in two places:
tests/test_embed_sources.pyruns in the required Python job → a PR that adds an embed without its data page fails CI.::error::message.Tests
test_repository_embed_sources_all_resolve— the real repo passes.source_pagecases covered.pytest tests/— 1385 passed, 19 skipped. zizmor: no new findings. YAML valid.Related