Skip to content

Add CI/CD checks to prevent docs/ build drift and broken asset links #42

Description

@leoncheng57

Background

PR #40 merged a new blog post (the Rocketship Flywheel article) that added source files under src/content/blog/ and SVG assets under public/blog/rocketship-flywheel/. However, the corresponding docs/ build output was never regenerated before merge.

Because GitHub Pages serves from main's docs/ folder, the two SVG diagrams in the new post 404'd on the deployed site. PR #41 fixes the immediate issue by committing the rebuilt docs/, but the same failure mode can happen again on any future content change.

This issue tracks adding CI checks to prevent the class of problem.

Root cause

docs/ is a checked-in build artifact that can silently drift from source. The repo convention is:

  1. Change source under src/ or public/.
  2. Run npm run build locally.
  3. Commit both the source changes and the regenerated docs/ in the same PR.

Nothing enforces step 2. If a contributor forgets, the PR still merges cleanly and the deploy breaks.

Proposed scope

Add a GitHub Actions workflow (e.g. .github/workflows/ci.yml) that runs on every pull request against main and performs three checks. If any fails, the PR cannot merge (once branch protection is configured).

1. docs/ matches source (primary fix)

Run npm ci && npm run build, then fail if git status --porcelain docs/ is non-empty. This forces contributors to commit an up-to-date docs/ as part of their PR and catches the exact failure mode from PR #40.

Note: vite.config.ts currently sets emptyOutDir: false, which is why stale assets have accumulated in docs/assets/. The CI check only verifies that rebuilding produces no new diffs — it does not clean up existing stale files. Separate hygiene issue, not in scope here.

2. Lint

Run npm run lint (already exists). Surfaces ESLint violations that currently only fail locally.

3. Blog asset link check

Custom script that:

  • Parses each src/content/blog/*.md file.
  • Extracts all local asset references (images like /blog/... or /upstyling.png, etc.).
  • Verifies that each referenced file exists under public/.
  • Fails the CI run if any reference is broken.

Would have caught the specific Rocketship Flywheel issue at PR-time (in addition to check #1), and prevents typos in asset paths in future posts.

Out of scope

  • Migrating away from checked-in docs/ to an auto-deploy workflow (actions/deploy-pages). That is a larger restructure; considered and deferred. Revisit if the verify-matches approach proves too annoying in practice.
  • Cleaning up stale entries in docs/assets/. Separate hygiene issue.
  • Running tests (npm run test:run) in CI. Can be added in a follow-up if useful.

Acceptance criteria

  • .github/workflows/ci.yml exists and runs on pull_request events targeting main.
  • A failing job on a PR that changes src/ or public/ without rebuilding docs/.
  • A failing job on a PR that introduces a broken asset reference in a blog markdown file.
  • A failing job on a PR with ESLint violations.
  • Documentation in AGENTS.md (or equivalent) describing the expected workflow.
  • Optional: branch protection rule on main that requires these checks to pass before merge (repo setting, not a file change).

Context

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions