[quality] check:links is configured and guarded by a test, but no workflow ever runs it
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 72/100
- Issue type
- Feature
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- github-actions, markdown, yaml
- Domain
- ci-cd, documentation
Research direction
Start at .github/workflows/ci.yml lines 101-105, where check:format, check:spelling and check:markdown are invoked, and copy that job's steps verbatim (checkout ref, setup-node node-version-file, npm ci) into a new top-level link-check job guarded by if: github.event_name == 'schedule'; add a schedule/cron trigger to the on: block if none exists. Then correct the stale claim in tests/root-docs-links.test.mjs:10 that check:links delegates to a nonexistent Makefile. Done means a scheduled job runs npm run check:links, no existing job or line is modified, and the test header matches reality; note that pushing to .github/workflows/** needs a token with workflow-write access.
Written by the indexing model from the issue text.
Description
Finding
npm run check:links is maintained with unusual care and executed by nothing.
The repository ships .markdown-link-check.json and a dedicated guard test
for it, tests/markdown-link-check-config.test.mjs, whose own header explains
why the guard is needed:
It fails silently by construction. markdown-link-check does not pass the
parsed config object through to the checker: its CLI copies a fixed list of
keys ontooptsand drops everything else, with no warning and no non-zero
exit.
—tests/markdown-link-check-config.test.mjs:4-8
That guard derives the accepted key set from the installed CLI source so a
devDependency bump cannot quietly disable a setting. It is real, careful work
defending a command that CI never runs.
.github/workflows/ci.yml runs the other three check:* targets one at a time
and omits this one:
run: npm run check:format # ci.yml:101
run: npm run check:spelling # ci.yml:103
run: npm run check:markdown # ci.yml:105
No workflow runs the aggregate npm run check or npm test either, so nothing
reaches check:links indirectly.
Evidence and provenance
main=7ab301e, checked 2026-10-06.grep -rn 'check:links\|npm test\|npm run check\b' .github/workflows/returns
onlyci.yml:101,ci.yml:103,ci.yml:105— the format, spelling and
markdown targets. Across all nine workflow files
(architecture-submission,ci,codeql,create-milestones,
deploy-gh-pages,import-architectures,pr-queue-hygiene,
refresh-community-people,refresh-radar-reports) there is no invocation
ofcheck:links,npm run check, ornpm test.- What is not affected, measured rather than assumed:
- Relative links in root
*.mdare covered offline by
tests/root-docs-links.test.mjs, which runs undernpm run test:unitin
CI. - Relative links between ADR files are covered by
tests/adr-contract.test.mjs:172. - Links inside
docs/**andblog/**are gated by the production build.
Verified empirically at7ab301e: appending
[Broken probe link](./no-such-page.md)todocs/community/index.mdmakes
npm run buildexit 1 withDocusaurus found broken links! ... Broken link on source page path = /community/.onBrokenMarkdownLinksiswarn
(docusaurus.config.js:125), but the unresolved link falls through to
onBrokenLinks: 'throw'(docusaurus.config.js:124), and
npm run build:productionruns in CI atci.yml:79. The probe edit was
reverted.
- Relative links in root
- The actual hole: external
http(s)links. Nothing in the repository
verifies them, in any file.tests/root-docs-links.test.mjsresolves paths
on disk and never issues a request; Docusaurus does not check outbound URLs.
check:linksis the only mechanism that would, and it never runs.
This is a missing-workflow finding, not a coverage gap — no source path is
under-tested — so it carries no coverage-gap priority.
Recommendation
Run it on a schedule rather than on pull_request. markdown-link-check issues
live network requests, so a required per-PR check would make unrelated PRs red
when a third-party host rate-limits or 503s; the config already carries
retryOn429, retryCount: 3 and a 20s timeout for exactly that reason, which
mitigates but does not eliminate it.
Add to .github/workflows/ci.yml, as a new top-level job (it is additive; no
existing job or line changes):
link-check:
name: Link check
# Scheduled only: markdown-link-check issues live network requests, so a
# third-party outage must not turn unrelated pull requests red. The config
# it reads is guarded by tests/markdown-link-check-config.test.mjs.
if: github.event_name == 'schedule'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v4
with:
node-version-file: .nvmrc
cache: npm
- name: Install dependencies
run: npm ci
- name: Check markdown links
run: npm run check:links
and give the workflow a schedule trigger if it has none:
on:
schedule:
- cron: '0 6 * * 1'
Pin the action refs and the node-version-file to whatever the repository's
other jobs already use — match ci.yml's existing steps verbatim rather than
the sketch above where they differ.
- a workflow job runs
npm run check:links, on a schedule rather than on
pull_request -
tests/root-docs-links.test.mjs:10no longer states thatcheck:links
"delegates to a Makefile that does not exist"
Deliberately out of scope
Widening _check:links-md (package.json:10) beyond root *.md is not
part of this issue and should not be bundled into it. Measured at 7ab301e:
$ npx markdown-link-check --config .markdown-link-check.json -p -v docs/community/index.md
21 links checked.
ERROR: 3 dead links found!
[✖] /community/user-groups → Status: 400
[✖] /community/technical-community-groups → Status: 400
[✖] /architectures/ → Status: 400
Every one of those is a live site route that Docusaurus already resolves and
already gates; markdown-link-check reports them dead because it resolves a
leading / against the filesystem. Covering docs/** would therefore need
replacementPatterns mapping site-absolute routes onto the build output —
real design work, and redundant with the onBrokenLinks: 'throw' gate proved
above. Root *.md files are outside the route tree and carry no such links,
which is why they are the right and sufficient scope here.
Why only the second box has a PR
The first box edits .github/workflows/**, which is unreachable from this
agent's token tier: GitHub rejects a push whose diff touches that directory
without the workflows permission, which the contributor tier does not carry.
It needs a human or an agent with workflow-write access to land. That is a
token ceiling, not a judgement that the change is unready — the YAML above is
complete.
The second box is a correction this agent can push, and the PR below lands it.
Priority
- Impact: medium (every external link in the repository's contributor-facing
documentation is unverified; a maintained config and a bespoke guard test
defend a command nothing executes) - Effort: low
🐝 Hive Agent: quality | Instance: hosted-available-lke648397-260827-5n31 | SHA: 7ab301e
— hive: agent=quality backend=copilot model=claude-opus-5 copilot=1.0.88
- Dominant language
- JavaScript
- Stars
- 0
- Forks
- 2
- Avg merge
- 21h 59m
- Merged PRs (30d)
- 431
Getting set up
Starts the project's dev container in your browser, under your own GitHub account.
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from cncf/endusers
-
agent/scanner hive/hosted-available-lke648397-260827-5n31 quality testing
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
Maintainers usually reply within 1 day
-
enhancement security
Difficulty 5/5 Over a week Newbie friendliness 35/100
Maintainers usually reply within 1 day
-
agent/quality hive/hosted-available-lke648397-260827-5n31 quality testing
Difficulty 4/5 3-5 days Newbie friendliness 42/100
Maintainers usually reply within 1 day
-
quality testing
Difficulty 4/5 3-5 days Newbie friendliness 52/100
cncf/endusers#1187 · 1 comment ·
Maintainers usually reply within 1 day
-
agent/quality hive/hosted-available-lke648397-260827-5n31 hive/verified-open needs-human quality testing
Difficulty 4/5 3-5 days Newbie friendliness 35/100
cncf/endusers#1079 · 13 comments ·
Maintainers usually reply within 1 day
Similar issues
-
Engineering
Difficulty 2/5 1-3 hours Newbie friendliness 66/100
techmatters/terraso-web-client#3095 ·
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Service process inherits the caller's cwd at first use, holding that folder open on Windows (EBUSY)Open
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
nextcloud/viewer#3424 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
Maintainers usually reply within 1 day