Repository navigation
fix(lychee): accept 429, 5xx and timeouts in the online link check - #834
Conversation
A throttled or erroring host, or a timeout, says nothing about whether a link is dead, so it no longer fails the online run. 404, 410 and every other 4xx still fail. accept restates the default 100..=103 and 200..=299 because setting it replaces the default. lychee 0.24.2 never retries a rejected 5xx; revisit when lycheeverse/lychee#2324 ships. The status-code test now asserts that rule: 429, 500, 503, 599 and a timeout pass, an accepted 429 is requested once, 404 and 410 fail, and a 200 still passes. Refs: melodic-software/claude-code-plugins#8730 Refs: melodic-software/ci-workflows#739 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Tje1j8KEYaYSxYe8RgJ3Lw
…lows v0.59.0 v0.59.0 (4aff993) carries ci-workflows#844, the report step that lists timeouts and accepted 429 and 5xx links in the job summary, so the caller moves in the same merge as the accept config it reports on. The runner-policy contract at 4aff993 is a verbatim copy of the v0.55.0 entry: the reusable's workflow_call inputs, secrets, outputs, top-level and job permissions and runs-on are structurally identical between 3a2c748 and 4aff993. The gate cannot auto-approve it because the GITHUB_TOKEN-bearing lychee-action step changed (format, output, args, an id), so the copy is registered by hand. Refs: melodic-software/claude-code-plugins#8730 Refs: melodic-software/ci-workflows#739 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
claude-review reviewed No findings on #834 at 1a3af3c. This review was read-only: I read the diff and the PR context, and ran no tests or builds myself.
|
|
claude-security-review reviewed No security findings in PR #834 at head 1a3af3c. I read the full diff. I did not read the ci-workflows v0.59.0 source, because the cross-repo
|
Refs: melodic-software/claude-code-plugins#8730
Refs: melodic-software/ci-workflows#739
Summary
The online link check failed on transient responses: a 429, a 5xx such as 502, 503 or 522, or a timeout says nothing about whether a link is dead. The owner decided on 2026-10-21 that these responses must not fail the run, and must still appear in a read-only report. Dead links (404, 410 and every other 4xx) keep failing. lychee stays on v0.24.2 and lychee-action stays on v2.9.0, the latest stable releases.
Fix
lychee.toml:accept = ["100..=103", "200..=299", "429", "500..=599"]andaccept_timeouts = true.components/lychee/lychee.test.sh: the status-code block now asserts the owner's rule.1 OK.Rejected status code.1 Timeouts, while the same request with--accept-timeouts=falsefails.components/lychee-online/README.md: the prose now matches the new behavior.Basis for each setting, all at lychee v0.24.2:
acceptreplaces the default, so100..=103and200..=299are restated. The--acceptdefault is in the README.Status::newin status.rs#L90-L97 returnsOkonly for a code in the accepted set. A local probe with--accept 429alone rejected a 200.A rejected 5xx is never retried, so accepting 5xx is the only way to tolerate it. The basis is retry.rs#L97-L100. In the probe, 502 and 503 each got one request with
--max-retries 2.An accepted 429 is a success whose fragment is not checked. The basis is the comment and the
response.status.is_success()guard in website.rs#L137-L142. In the probe, an accepted 429 got one request.accept_timeoutsexists from v0.24.0. Basis: the lychee-v0.24.0 release notes (#2063). check.rs#L113-L117 usesis_success_ignoring_timeoutswhen it is set.Repin, in the same merge. The claude-code-plugins caller (
components/lychee-online/targets/claude-code-plugins.yml) moves from v0.55.0 (3a2c748) to v0.59.0 (4aff99320ef484a7beac35ee3a7b7b854ec1e33f). That release carries ci-workflows#844, the report step. The README "Pin" procedure moves the pin and thepolicy.jsoncontract key together in one PR, so the config and the reusable that reports it land in one merge.components/runner-policy/policy.json: the contract at4aff993is a verbatim copy of the v0.55.0 entry.components/runner-policy/README.md: a v0.59.0 rollout line, signed off by hand on 2026-10-21. The owner approved the change on that date.components/runner-policy/runner-policy.test.mjs: a test that the4aff993entry equals the v0.55.0 entry and is the only key at that SHA.maintenance-check-links-online.yml. The other3a2c748pins arepr-review,pr-review-security,maintenance-sync-standardsandcheck-managed-files, which the repin cascade owns.Contract review basis
b2caebc3at3a2c748anded87540bat4aff993. The diff is 83 lines added and 6 removed.workflow-yaml.cjs. The contract surface hashes identically at both SHAs (sha2569d258d23...). That surface covers theonblock (theworkflow_callinputs, secrets and outputs), the top-levelpermissions: {}, and every job'spermissions(contents: read),runs-on(${{ inputs.runner }}) anduses.token: ${{ github.token }}as before, gainsid: lycheeand moves toformat: json, anoutputpath,--verbose, andfail,failIfEmptyandjobSummaryset tofalse.Write the reportstep uses onlyenvandjqand holds no credential.Consumers. Every target in
distribution/sync-manifest.ymltakes thelycheecomponent as managed; none holds it locally owned. The file is read by these lanes:lychee-offlineaction and this repo'slychee-fixtureslane. Both run--offline, so they make no HTTP requests and neither key changes them. The offline run over this repo's Markdown gives the same result under the old and the new config:959 Total, 402 OK, 0 Errors, 557 Excluded. The bad fixture fails with 2 errors under both.maintenance-check-links-online.yml, which the claude-code-plugins caller runs. Under this config, lychee's markdown job summary lists timeouts but not accepted 429 or 5xx responses. ci-workflows#844 adds that list.The api.github.com 403s are out of scope here. They are handled by exact-URL ignores in claude-code-plugins#8875 (standards#831).
Verification
npm run test:runner-policy: 325 pass, 0 fail, includingthe online link-check contract at the v0.59.0 tag copies its v0.55.0 entry forward verbatim.npm run lint:runner-policy:Runner policy passed..github/runner-policy.jsoninto a temp tree and ranrunner-policy.mjs --repository-visibility public.Runner policy passed.runner-target-contractfailure for the caller (auto-approval declined,credentialReferenceschanged), so the contract is needed.bash harness/shell/run-tests.sh components/lychee/lychee.test.shstill passes after merging main.bash harness/shell/run-tests.sh components/lychee/lychee.test.sh: pass. I also mutatedlychee.toml(added 404 toaccept, setaccept_timeouts = false), and the test failed on the 404 and timeout cases as expected. Then I restored the file.bash harness/shell/run-tests.sh components/lychee/private-repo-inventory.test.sh: pass.bash components/lychee/private-repo-inventory.sh check --config lychee.toml: OK.shellcheck,typos,markdownlint-cli2,editorconfigandgitleakspass through the lefthook pre-commit.Related
🤖 Generated with Claude Code
https://claude.ai/code/session_01Tje1j8KEYaYSxYe8RgJ3Lw