Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

[quality] check:links is configured and guarded by a test, but no workflow ever runs it

Closed Beginner friendly
#1,137 0 comments 0 reactions 0 assignees View on GitHub

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

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

agent/quality hive/covered-by-pr hive/hosted-available-lke648397-260827-5n31 quality testing

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 onto opts and 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
    only ci.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
    of check:links, npm run check, or npm test.
  • What is not affected, measured rather than assumed:
    • Relative links in root *.md are covered offline by
      tests/root-docs-links.test.mjs, which runs under npm run test:unit in
      CI.
    • Relative links between ADR files are covered by
      tests/adr-contract.test.mjs:172.
    • Links inside docs/** and blog/** are gated by the production build.
      Verified empirically at 7ab301e: appending
      [Broken probe link](./no-such-page.md) to docs/community/index.md makes
      npm run build exit 1 with Docusaurus found broken links! ... Broken link on source page path = /community/. onBrokenMarkdownLinks is warn
      (docusaurus.config.js:125), but the unresolved link falls through to
      onBrokenLinks: 'throw' (docusaurus.config.js:124), and
      npm run build:production runs in CI at ci.yml:79. The probe edit was
      reverted.
  • The actual hole: external http(s) links. Nothing in the repository
    verifies them, in any file. tests/root-docs-links.test.mjs resolves paths
    on disk and never issues a request; Docusaurus does not check outbound URLs.
    check:links is 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:10 no longer states that check: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

Open in Codespaces

Starts the project's dev container in your browser, under your own GitHub account.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from cncf/endusers

All issues in cncf/endusers

Similar issues

More JavaScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.