CI: link checker silently succeeds when the checker is unavailable

Author: jharvieuxCreated Sep 7, 2026Updated Sep 8, 2026
LabelsACK_OBTAINED

Problem

At current master commit 1eacf6cb9bfcba006ca972a804c5faace8c2758a, the Markdown link-check job can exit successfully without checking any links.

package.json runs markdown-link-check, but that executable is not declared in devDependencies or the lockfile. The script invokes it through find -exec; an execution failure makes the expression false for that file but does not make find itself exit non-zero. The final condition only searches err for the literal text ERROR:, so “command not found” errors are ignored and the script prints All good.

Reproduction

From a clean checkout of the commit above:

bash
npm ci --ignore-scripts
npm run link-check

Observed:

  • exit status: 0
  • stdout ends with All good
  • stderr contains 121 instances of find: ‘markdown-link-check’: No such file or directory
  • no Markdown links were checked

The workflow .github/workflows/md-link-check.yml installs only the locked dependencies before running this command, so it inherits the same fail-open behavior.

There is a second consistency problem: scripts/Apply_Link_Check.sh and the contributor instructions use .markdownlinkcheck.json, which does not exist. The repository’s actual configuration file is markdown-link-check-config.json.

Impact

The required link-integrity check can report success when the checker is unavailable. Contributors and reviewers therefore cannot treat a green Markdown Link Check job as evidence that links were exercised.

Proposed resolution

  • Add markdown-link-check as a pinned direct development dependency and update the lockfile.
  • Make the link-check command fail immediately when the executable is unavailable or any per-file invocation exits non-zero.
  • Use one canonical configuration filename in package.json, the helper script, and CONTRIBUTING.md.
  • Preserve useful per-file failure output for the workflow’s PR comment step.
  • Add regression coverage for failure propagation rather than relying only on a successful live run.

Acceptance criteria

  • A clean npm ci --ignore-scripts provides the checker used by npm run link-check.
  • A valid fixture exits zero.
  • A fixture containing a deliberately broken link exits non-zero.
  • A missing or deliberately failing checker exits non-zero and cannot print All good.
  • The workflow still reports the affected file and link when a real broken-link failure occurs.
  • Every documented command names the configuration file that exists in the repository.

I am happy to implement this after maintainer acknowledgment and assignment.


Disclosure: I used OpenAI Codex (GPT-5) to help inspect the repository and draft this issue. I reproduced the command behavior in a clean checkout and verified the referenced files against the commit above.