Comment only when a link we publish has actually rotted - #8
Conversation
The action was posting a link-check comment on every PR to this repo, reporting this-host-cannot-resolve.invalid from broken-links.html. That host is a fixture built to be unresolvable, so the comment said the same thing on every run and carried no information -- the same signal-to-noise problem #2 was about, pointed at our own PRs. The fixture scan now runs with fail-on-broken false, which stops the comment without losing the real-network smoke coverage. The comment path moves somewhere it can mean something. A new check-own-docs job renders this repository's Markdown to HTML and checks the links in it. A finding there is a link we actually publish that has rotted, and the comment names it. When the docs are clean there are no findings, broken-links-found stays false, and no comment is posted at all. Rendering does the filtering for free: the placeholder URLs in the usage examples live inside fenced code blocks and never become anchors, so 4 genuine links are checked rather than the 15 a grep over the raw Markdown would find. It found a real bug on its first run. The README's Marketplace badge linked to github.com/marketplace/actions/ai-link-checker, which returns 404 -- no release was ever published there, as the 1.1.0 notes already recorded. Badge removed. With it gone the job reports 0 broken and 0 redirects, so it posts nothing; adding a rotted link back makes it report 1 broken and post again. Both directions verified locally. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR reduces CI noise by ensuring link-check PR comments are only posted when the repository’s own published documentation has broken-link findings, rather than repeatedly reporting known fixture failures. It also removes an invalid README Marketplace badge link discovered by the new docs-check pathway.
Changes:
- Stop fixture-based link checks from posting PR comments by setting
fail-on-broken: 'false'for the fixture smoke scan. - Add a
check-own-docsCI job that renders this repo’s Markdown to HTML and scans only rendered anchor links, posting a PR comment only when broken links are found. - Remove the README GitHub Marketplace badge that pointed to a non-existent listing (404).
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
tests/README.md |
Documents that PR comments are reserved for the repo’s own docs checks (not fixtures). |
README.md |
Removes the broken GitHub Marketplace badge link. |
CHANGELOG.md |
Records the new docs-check job and the change to PR-comment behavior. |
.github/workflows/ci.yml |
Updates fixture scan to avoid PR comments and introduces the new check-own-docs job. |
Suppressed comments (1)
.github/workflows/ci.yml:378
- The new docs link-check job will treat transient transport failures (timeouts/DNS) as broken links (status 0) by default, which can trigger PR comments even when nothing has actually changed in our docs. If the intent is to comment only on actionable doc regressions, silence status 0 for this job while keeping the existing default silent codes (403,503).
with:
html-path: 'docs-html'
fail-on-broken: 'true'
timeout: 20
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| ## [Unreleased] | ||
|
|
||
| ### Added | ||
| - A `check-own-docs` CI job that renders this repository's Markdown and checks the links in it. It is the only job that posts a link-check comment on a pull request, and it posts one only when a link we publish has actually rotted |
There was a problem hiding this comment.
Agreed — fixed in e2ae392. The entry now says the comment is posted "only when a link we publish is reported broken", which is what the checker actually observes.
It also records the related change from your suppressed comment on ci.yml: the job runs with silent-codes: '0,403,503', so a transient timeout or DNS failure stays quiet and the comment is reserved for a real status such as a 404. That part matters for anyone reading the changelog to understand when this job will and will not speak up.
Copilot's suppressed comment was the substantive one of its four, and it holds. keepachangelog.com and semver.org are not on the built-in legitimate_domains allowance, so a transient timeout at either reported status 0 as broken and posted a comment about a link that is fine -- the same false positive this action shipped silent-codes '0' to prevent, unapplied to our own repo. The docs job now runs with silent-codes '0,403,503'. Verified both directions: a real 404 still posts a comment, so the class of finding that turned up the dead Marketplace badge is untouched, and a timeout at either bare domain is now quiet. The cost, recorded in both the workflow comment and tests/README.md, is that a domain which disappears outright is not reported here. Its three visible comments were all the same wording point, and also correct: a finding says a link came back broken, not that it rotted. The checker cannot distinguish the cause, so the four places that claimed it could now say what is actually observed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
You were right that the comment wasn't useful. This makes it useful rather than removing it.
The problem
Every PR to this repo got a comment reading 🚨 1 broken link(s) and 3 redirect(s). The broken one was
this-host-cannot-resolve.invalid— a fixture built specifically so it can never resolve. The comment said the same thing on every run, so it carried no information, and a contributor seeing 🚨 would reasonably think something was wrong. Six of them had accumulated across #3, #4 and #7.That is the signal-to-noise problem #2 was about, pointed at our own pull requests.
The fix
The fixture scan drops to
fail-on-broken: 'false', which stops the comment while keeping its real-network smoke coverage.The comment path moves to a new
check-own-docsjob that renders this repository's Markdown to HTML and checks the links in it. A finding there is a link we publish that has rotted, and the comment names it.The key property is what happens when nothing is wrong:
broken-links-foundfalsetrueSo the comment appears only when it has something to say.
Rendering does the filtering for free. A grep over the raw Markdown finds 15 URLs, but most are placeholders inside fenced code blocks —
github.com/user/repo,YOUR-USERNAME/REPO-NAME, thefred\.stlouisfed\.org/.*regex from a YAML sample. Those never become anchors, so the job checks the 4 genuine links and ignores the rest. No allowlist to maintain.It found a real bug immediately
The README's Marketplace badge linked to
https://github.com/marketplace/actions/ai-link-checker, which returns 404. The action was never published there — the v1.1.0 release notes already recorded that no GitHub Release existed before now, and Marketplace requires one. The badge has been advertising a listing that does not exist.Badge removed. If you would rather publish to Marketplace instead, restoring one line brings it back — but as things stand the link was false.
Verification
Both directions, run locally against the real renderer and the real checker:
broken-links-found=false→ no commentbroken-links-found=true→ comment posted, namingthis-doc-link-rotted.invalidI also extracted the render step from the YAML exactly as the runner would and ran it under
bash --noprofile --norc -e -o pipefail, confirming all six Markdown files render and the heredoc dedents correctly.No change to the action itself —
action.ymlandlink_checker.pyare untouched.