Skip to content

ci: add linkspector link checking for blog content, fixes #470 - #695

Merged
stasadev merged 3 commits into
mainfrom
20260726_link_check
Jul 27, 2026
Merged

ci: add linkspector link checking for blog content, fixes #470#695
stasadev merged 3 commits into
mainfrom
20260726_link_check

Conversation

@rfay

@rfay rfay commented Jul 26, 2026

Copy link
Copy Markdown
Member

Summary

Adds automated link checking for blog content, mirroring the approach ddev/ddev already uses for its docs (.github/workflows/docs-check.yml + umbrelladocs/action-linkspector).

  • .linkspector.yml scopes the check to src/content/blog and ignores a short list of known-noisy patterns (see below).
  • .github/workflows/link-check.yml runs linkspector on push to main (full check) and on pull requests (added lines only), same split ddev/ddev uses.

Fixing the internal-link-checker-for-Astro half of #470 (item 1 in the issue, replacing MkDocs strict-build checking) is left for later; root-relative internal links (/contact, /img/...) are intentionally excluded here since Astro has no build-time equivalent yet.

Why the ignore patterns

Running the checker against all 141 existing posts turned up two different kinds of noise that are not actually broken links:

  • *.ddev.site example URLs in tutorials always resolve to 127.0.0.1 and never have a real server behind them in CI.
  • LinkedIn, Medium, npmjs.com, packtpub.com, private Buildkite build permalinks, and tag1consulting.com all returned errors (403/999) to linkspector headless-browser requests while loading fine in a normal browser, so they are excluded the same way ddev/ddev excludes mailpit.axllent.org and similar in its own config.

Content fixes (26 posts)

Running the checker also surfaced real, pre-existing broken links across the blog archive. Fixed here so the checker starts green on merge instead of red:

  • Deleted contributor-training.md (8 posts): that post was removed a while back with a redirect from /blog/contributor-training/ to /blog/category/training/, but the markdown-filename links (contributor-training.md) in these posts still pointed at the deleted file. Repointed to /blog/category/training.
  • Broken internal reference / anchor (2 posts): docker-providers.md had a malformed relative link to the ARM64 post; ddev-add-on-maintenance-guide.md linked to a mistyped anchor (#mutagen-problemreport instead of #mutagen-problem-report).
  • Renamed/moved targets (4 posts): github.com/ddev/community -> github.com/ddev/.github (the actual community-health repo); two docs.ddev.com pages that were restructured (install/ddev/ -> install/ddev-installation/, alternate-uses/#casual-... -> topics/hosting/); a malformed github.com/.../README URL.
  • Dead external pages, archived via Wayback Machine (4 posts): an Ironstar developer survey page (referenced twice), a Florida DrupalCamp session page, and a HelloTech guide page had all been taken down. Replaced with web.archive.org snapshots so the content stays reachable.
  • Dead external page, no archive found, de-linked (2 posts): a deleted GitHub Discussion and a personal blog post whose slug changed (fixed to the new slug instead, once I found it).
  • Wrong/defunct service (2 posts): xip.io has shut down, replaced with its direct successor sslip.io; frankenphp.org was a wrong TLD, corrected to frankenphp.dev (used correctly elsewhere on the site).
  • Malformed URL (1 post): an Unsplash photo-credit link used a broken old-style search URL; replaced with the generic Unsplash referral link used elsewhere for the same purpose.
  • Markdown escaping bugs (2 posts): in two places, escaped or missing backticks caused example/loopback URLs (127.0.0.1, an autolinked <http://...>) to be parsed as real hyperlinks instead of inline code. Fixed the markdown so they render as code again.
  • Reference to a nonexistent repo (1 post): xdebugctl was linked to a github.com/xdebug/xdebugctl repo that does not exist (it is a script bundled inside DDEV itself, not a separate project); removed that link and kept the working xdebug.org documentation link in the same sentence.

How to test

Since this branch was pushed directly to ddev/ddev.com (not a fork), the new pull_request trigger in link-check.yml should run for this PR itself, not just after merging to main. A separate test repo like ddev-test/ddev.com is not needed: GitHub Actions resolves workflow files for pull_request events from the PR head branch as long as the PR is same-repo, so a brand-new workflow file added in a PR still executes for that PR. Check the "Checks" tab on this PR for a "Link check" run.

To reproduce locally instead:

npm install -g @umbrelladocs/linkspector
linkspector check -c .linkspector.yml -s

That should report 0 failed links (the local run before this PR was opened found 1: a gnu.org navigation timeout that reproduced only in my sandbox and loads fine in an actual browser — worth watching in case it is flaky on CI too, but not treated as broken here).

Fixes #470

🤖 Generated with Claude Code

rfay and others added 2 commits July 26, 2026 13:04
Adds a GitHub Actions job (mirroring ddev/ddevs docs-check.yml) that
runs linkspector against src/content/blog on push and PRs, checking
added lines only for PRs and everything on push to main.

Also fixes the ~20 broken/stale links this surfaced across 26 blog
posts (dead docs pages, renamed repos, expired campaign/session links
replaced with Wayback Machine snapshots, a defunct xip.io reference,
and a couple of markdown escaping bugs that turned example URLs into
real links) so the checker starts green instead of red on merge.

Developed with assistance from Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
…ners

The PR check for #695 failed on the Unsplash referral link added in
eight-more-ways-to-get-the-most-out-of-ddev-local.md: Unsplash returned
its anti-bot challenge (401) to the GitHub Actions runner even though
the same URL format works fine elsewhere on the site and loads fine in
a normal browser. Same class of issue as the existing LinkedIn/Medium/
npmjs/packtpub ignores.

Developed with assistance from Claude Code (https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jul 26, 2026

Copy link
Copy Markdown

Deploying ddev-com-front-end with  Cloudflare Pages  Cloudflare Pages

Latest commit: 8929115
Status: ✅  Deploy successful!
Preview URL: https://bc64cdb8.ddev-com-front-end.pages.dev
Branch Preview URL: https://20260726-link-check.ddev-com-front-end.pages.dev

View logs

@stasadev stasadev left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thank you!

I tested it locally with:

~/.ddev-dev-tools/node/bin/linkspector check

There's one more 404 page:
https://staatzstreich.de/blog/wie-ein-kaputter-installer-reload-zu-zwei-open-source-patche-2 (I fixed it).

The check itself is pretty heavy - it checks more than 2,000 links on main. If it becomes too annoying, we could remove it from the main push workflow and run it manually from time to time.

@stasadev
stasadev merged commit 981faab into main Jul 27, 2026
5 checks passed
@stasadev
stasadev deleted the 20260726_link_check branch July 27, 2026 16:13
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.

Add link checker

2 participants