Skip to content

ci: add PR build gate via reusable workflow - #171

Merged
Arthurvdv merged 2 commits into
mainfrom
ci/pr-build
Sep 5, 2026
Merged

Arthurvdv merged 2 commits into
mainfrom
ci/pr-build

Conversation

@Arthurvdv

Copy link
Copy Markdown
Member

What

Adds a pull-request build gate so broken builds, dead internal links, and lint regressions are caught before merge — without duplicating the deploy pipeline's build steps.

The build logic now lives in one reusable workflow (build.yaml, workflow_call) that both the PR gate and the release deploy call, so they can never drift.

ci.yaml ────────┐
                ├─► build.yaml (toolchain + strict build + htmltest + markdownlint)
hugo.yaml ──────┤        deploy adds: configure-pages + upload + deploy-pages
link-check.yaml ┘        link-check adds: lychee (external only)

Checks on every PR (and every deploy)

  • Strict Hugo build--gc --minify --panicOnWarning --printPathWarnings; broken ref/relref already fail via Hugo's default refLinksErrorLevel: ERROR. (Verified: the current tree builds warning-clean.)
  • htmltest — internal links, anchors, and image existence over the rendered public/. External checking is off here (deterministic gate).
  • markdownlint (markdownlint-cli2) — content/**/*.md.

Also pins what CI previously left implicit: Node 22 (setup-node + .nvmrc) and Go from go.mod (setup-go), plus a Hugo resource cache.

Off the gate: scheduled external-link check

link-check.yaml runs lychee weekly (and on demand) for external links only — internal is htmltest's job (.lycheeignore skips our own domain). Kept off PRs so a flaky/rate-limited third-party site never blocks a merge; opens a tracking issue on failure.

Fast-follow: pre-existing broken links (NOT fixed here)

htmltest surfaced real issues already live on the site. Per scope, this PR keeps to CI infra and temporarily allowlists them in .htmltest.yml with anchored, self-expiring patterns (they stop matching once each link is fixed, and they do not mask new breakage). To be fixed in a follow-up:

Broken internal cross-refs (bare xxxx/ resolves under the current page dir -> 404; correct form is ../xxxx/). The convention in CLAUDE.md / .claude/rules/rule-pages.md ([PC0034](pc0034/)) is itself the buggy form and should become ../pc0034/:

  • AC0024 -> ac0012/
  • LC0081 -> lc0082/, LC0082 -> lc0081/
  • PC0005 -> pc0006/, PC0017 -> pc0018/, PC0020 -> pc0021/, PC0021 -> pc0020/
  • downloading-analyzers -> getting-started/vscode/, getting-started/cicd/github/
  • getting-started/cicd/cli -> azure-devops/
  • lintercop-migration -> ../lintercop-migration-script (missing trailing slash)

{{< relref >}} inside a link destination renders as href="hahahugoshortcode…" (the render-link hook mangles it) — LC0007, LC0008, LC0010 -> Configuration. Use a plain lowercase path or fix the hook.

Missing image alt (10 images) — AC0003, AC0016, AC0017 (x2), LC0028 (x4), LC0090, getting-started/vscode. htmltest's IgnoreAltMissing is set until these get alt text.

Verification

All three gates confirmed green locally on the current tree (Hugo 0.165.0 extended, Go 1.26, Node): strict build ✓, htmltest ✓ (157 docs), markdownlint ✓ (148 files). This PR's own CI run exercises the new gate end-to-end.

Action for maintainer

Make build / build a required status check on main (Settings -> Branches -> branch protection). I'll confirm the exact check name once CI runs here.

🤖 Generated with Claude Code

Arthurvdv and others added 2 commits September 5, 2026 16:22
Add a pull_request CI check so breakage is caught before merge, without
duplicating the deploy pipeline's build logic.

- build.yaml: reusable (workflow_call) single source of truth — pinned Hugo
  extended, Node 22, Go (from go.mod), Dart Sass; strict build
  (--gc --minify --panicOnWarning --printPathWarnings); htmltest link/image
  check; markdownlint. Optional artifact uploads via inputs.
- ci.yaml: pull_request gate, calls build.yaml (build-only, no deploy).
- hugo.yaml: deploy now calls build.yaml instead of inlining the build, so
  PR and release stay identical.
- link-check.yaml: scheduled lychee check for EXTERNAL links only (off the PR
  gate to avoid third-party flakiness); opens a tracking issue on failure.
- .htmltest.yml / .markdownlint.jsonc / .lycheeignore: configs tuned so the
  current tree is green. Pre-existing broken internal links are temporarily
  allowlisted (anchored, self-expiring patterns) for a fast-follow fix.
- .nvmrc: pin local Node to 22 to match CI.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make .nvmrc the single source of truth for the Node version, shared by CI
(setup-node reads node-version-file) and local nvm, instead of hardcoding
node-version: 22 in the workflow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Arthurvdv
Arthurvdv merged commit f3d1834 into main Sep 5, 2026
1 check passed
@Arthurvdv
Arthurvdv deleted the ci/pr-build branch September 5, 2026 15:06
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.

1 participant