Skip to content

feat(ci): validate embed source_page references before build (Phase 4) - #641

Merged
jmservera merged 4 commits into
mainfrom
feat/ci-embed-source-guard
Aug 1, 2026
Merged

feat(ci): validate embed source_page references before build (Phase 4)#641
jmservera merged 4 commits into
mainfrom
feat/ci-embed-source-guard

Conversation

@jmservera

Copy link
Copy Markdown
Owner

Implements Phase 4 (CI deploy-parity guard) of the deploy-hydration remediation plan.

Why

The #627 deploy failure was a content/embeds/* page referencing a content/data page that wasn't present at build time, which aborts the Hugo build via errorf (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 every content/embeds/*/index.md source_page resolves to an existing content/data/<slug>/ page.

Wired in two places:

  1. tests/test_embed_sources.py runs in the required Python job → a PR that adds an embed without its data page fails CI.
  2. An explicit "Validate embed source pages" step in the production-site job, before the Hugo build → deploy-parity fast-fail with a clear ::error:: message.

Tests

  • test_repository_embed_sources_all_resolve — the real repo passes.
  • Missing / dangling / resolving source_page cases covered.
  • pytest tests/1385 passed, 19 skipped. zizmor: no new findings. YAML valid.

Related

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.
Copilot AI review requested due to automatic review settings August 1, 2026 17:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.py to validate that each embed’s source_page resolves to an existing content page.
  • Adds tests/test_embed_sources.py to enforce the invariant in the Python test suite.
  • Wires the check into .github/workflows/ci.yml before 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.

Comment thread .github/workflows/ci.yml
Comment thread scripts/check_embed_sources.py
Copilot AI review requested due to automatic review settings August 1, 2026 17:52

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Comment thread scripts/check_embed_sources.py
Copilot AI review requested due to automatic review settings August 1, 2026 18:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

  • _resolves currently treats /data/ (the section root) as a valid target because relative == "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). Disallow data itself and require data/<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 require content/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)

@jmservera
jmservera merged commit 5ab5212 into main Aug 1, 2026
14 checks passed
@jmservera
jmservera deleted the feat/ci-embed-source-guard branch August 1, 2026 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants