Skip to content

fix(ci): make the link check actually check links - #12397

Open
sileht wants to merge 1 commit into
devs/sileht/api-eventlogs-404/point-activity-log-sidebar-entry-real-page--400be775from
devs/sileht/api-eventlogs-404/make-link-check-actually-check-links--8f9a56dc
Open

fix(ci): make the link check actually check links#12397
sileht wants to merge 1 commit into
devs/sileht/api-eventlogs-404/point-activity-log-sidebar-entry-real-page--400be775from
devs/sileht/api-eventlogs-404/make-link-check-actually-check-links--8f9a56dc

Conversation

@sileht

@sileht sileht commented Aug 15, 2026

Copy link
Copy Markdown
Member

check:links passed --skip 'https?://' to drop off-site links. linkinator
applies skip rules to the absolute URL of everything it fetches, and when it
is pointed at a directory it serves the build over HTTP and crawls it — so
that unanchored rule matched its own crawl root. The command exited 0 having
scanned zero links, and had been doing so on every pull request: the sidebar
link to the deleted /api/eventlogs page shipped through a green link check
that never requested a single URL.

Anchor the rule and exclude the local server. Both of its hostnames have to
be excluded, not just one: linkinator binds to 127.0.0.1 but builds its
trailing-slash redirects against localhost, so covering only the bind
address still skips nearly every page at the redirect hop.

The check now crawls 1355 links. It finds no pre-existing breakage — with the
previous commit in place the site is clean — and it fails on a reintroduced
/api/eventlogs.

Three supporting changes:

  • Move the settings into linkinator.config.mjs. The .json linkinator loads
    by default was already dead (CLI flags replace config wholesale, so its
    skip list, ^/api included, never applied). .mjs also lets the rule
    carry the comment explaining the trap and be asserted in a unit test — the
    failure mode here is a check that silently stops checking, which no amount
    of green CI would reveal.
  • Crawl /enterprise/ as a second entry point. Nothing outside that section
    links into it — it renders its own nav tree and is filtered out of the
    sitemap — so recursing from / alone reaches none of its eight pages and a
    broken link there would pass forever.
  • Lower the concurrency and enable retryErrors. Now that pages are actually
    fetched, linkinator's own static server drops an occasional connection,
    surfacing as a status-0 failure on a different file each run. retryErrors
    covers status 0, 5xx and 429 only — a 404 is never retried, so this costs
    nothing in strictness. Its count and jitter are left on the built-in
    defaults on purpose: meow declares defaults for both, so a value set in the
    config file would be silently overridden — the same class of dead config as
    the .json this replaces.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

Depends-On: #12396

`check:links` passed `--skip 'https?://'` to drop off-site links. linkinator
applies skip rules to the absolute URL of everything it fetches, and when it
is pointed at a directory it serves the build over HTTP and crawls it — so
that unanchored rule matched its own crawl root. The command exited 0 having
scanned zero links, and had been doing so on every pull request: the sidebar
link to the deleted `/api/eventlogs` page shipped through a green link check
that never requested a single URL.

Anchor the rule and exclude the local server. Both of its hostnames have to
be excluded, not just one: linkinator binds to `127.0.0.1` but builds its
trailing-slash redirects against `localhost`, so covering only the bind
address still skips nearly every page at the redirect hop.

The check now crawls 1355 links. It finds no pre-existing breakage — with the
previous commit in place the site is clean — and it fails on a reintroduced
`/api/eventlogs`.

Three supporting changes:

- Move the settings into `linkinator.config.mjs`. The `.json` linkinator loads
  by default was already dead (CLI flags replace config wholesale, so its
  `skip` list, `^/api` included, never applied). `.mjs` also lets the rule
  carry the comment explaining the trap and be asserted in a unit test — the
  failure mode here is a check that silently stops checking, which no amount
  of green CI would reveal.
- Crawl `/enterprise/` as a second entry point. Nothing outside that section
  links into it — it renders its own nav tree and is filtered out of the
  sitemap — so recursing from `/` alone reaches none of its eight pages and a
  broken link there would pass forever.
- Lower the concurrency and enable `retryErrors`. Now that pages are actually
  fetched, linkinator's own static server drops an occasional connection,
  surfacing as a status-0 failure on a different file each run. `retryErrors`
  covers status 0, 5xx and 429 only — a 404 is never retried, so this costs
  nothing in strictness. Its count and jitter are left on the built-in
  defaults on purpose: meow declares defaults for both, so a value set in the
  config file would be silently overridden — the same class of dead config as
  the `.json` this replaces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Change-Id: I8f9a56dc53b23c7a340b51b471c734298600fd7d
@mergify
mergify Bot had a problem deploying to Mergify Merge Protections August 15, 2026 20:18 Failure
@sileht

sileht commented Aug 15, 2026

Copy link
Copy Markdown
Member Author

This pull request is part of a Mergify stack:

# Pull Request Link
1 fix(api): point the Activity Log sidebar entry at its real page #12396
2 fix(ci): make the link check actually check links #12397 👈
3 feat(ci): fail the build on a sidebar link to a deleted /api page #12398

@mergify

mergify Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Merge Protections

🔴 3 of 7 protections blocking · waiting on 👀 reviews and ⛓️ dependency

Protection Waiting on
🔴 ⛓️ Depends-On Requirements ⛓️ dependency
🔴 👀 Review Requirements 👀 reviews
🔴 🔎 Reviews 👀 reviews
🟢 🤖 Continuous Integration
🟢 Enforce conventional commit
🟢 📕 PR description
🟢 🚦 Auto-queue

🔴 ⛓️ Depends-On Requirements

Waiting for

This rule is failing.

Requirement based on the presence of Depends-On in the body of the pull request

🔴 👀 Review Requirements

Waiting for

  • #approved-reviews-by >= 2
This rule is failing.
  • any of:
    • #approved-reviews-by >= 2
    • author = dependabot[bot]
    • all of:
      • author = mergify-ci-bot
      • -head ~= ^docs-agent/

🔴 🔎 Reviews

Waiting for

  • #review-requested = 0
This rule is failing.
  • #review-requested = 0
  • #changes-requested-reviews-by = 0
  • #review-threads-unresolved = 0

Show 4 satisfied protections

🟢 🤖 Continuous Integration

  • all of:
    • check-success = build
    • check-success = lint
    • check-success = test
    • any of:
      • check-success = test-broken-links
      • label = ignore-broken-links
    • any of:
      • check-success=Cloudflare Pages
      • -head-repo-full-name~=^Mergifyio/

🟢 Enforce conventional commit

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|internal|docs|style|refactor|perf|test|build|ci|chore|revert|ui)(?:\(.+\))?!?:

🟢 📕 PR description

  • body ~= (?ms:.{48,})

🟢 🚦 Auto-queue

When all merge protections are satisfied, this pull request will be queued automatically.

@mergify
mergify Bot requested a review from a team August 15, 2026 20:21
@sileht
sileht marked this pull request as ready for review August 15, 2026 20:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant