devantler-tech / devantler-tech/ksail
bug(ci): a transient 5xx on one link fails the whole lint job
- Dominant language
- Go
- Stars
- 165
- Forks
- 12
- Avg merge
- 5h 41m
- Merged PRs (30d)
- 337
Description
> 🤖 Generated by the Agentic Engineer
## Evidence
`🧹 Lint - mega-linter` failed on PR #6385 (run [30412333866](https://github.com/devantler-tech/ksail/actions/runs/30412333866), 2026-07-29T00:53:25Z) with a single lychee error:
```
Errors in README.md
[503] https://ksail.devantler.tech/resources/ (at 95:7) | Rejected status code: 503 Service Unavailable
```
Checked immediately afterwards from the agent host: **HTTP 200 on 3/3 attempts**. `main` was green on its recent runs, so the site is not persistently down — this was a transient 503 on **our own documentation host** during the CI window.
`lychee.toml` already retries (`max_retries = 3`, `retry_wait_time = 2`), and the whole lychee pass took 3.57s, so the retries did not span the outage.
## Why this matters
A single transient 5xx on one link fails the entire lint job, which then blocks a PR whose change is unrelated — here, Go changes in `pkg/cli/clusterapi`. The cost is a full CI cycle plus a manual re-run.
**The obvious remedy is the wrong one.** `lychee.toml`'s established pattern for hosts that 503 in CI is to exclude them (`starlight.astro.build`, `img.shields.io`, `git.k8s.io`). Excluding `ksail.devantler.tech` would suppress the one signal we genuinely want: our own docs site being unreachable is a real defect, not CI noise. Whatever we do here must keep a real outage of our own host visible.
## Hypothesis
Separating *link correctness* (gating) from *link reachability at this instant* (reporting) removes the flake without losing the signal — the same split `devantler-tech/platform#2789` proposes for the same class. A transient 5xx on a link that resolves correctly is an availability observation; a 404 or a malformed URL is a docs defect.
## Success signal
No CI failure attributable solely to a transient 5xx over a 4-week window, while a genuine 404 introduced into a doc still fails the job. Guardrail: an outage of `ksail.devantler.tech` lasting beyond one CI run must still surface somewhere a human sees.
## Smallest useful change
Decide the reporting-vs-gating split for 5xx specifically, and apply it consistently with whatever `platform#2789` settles on — this is the second product to hit it, so it likely belongs in shared CI configuration rather than being solved twice.
## Acceptance criteria
- [ ] 5xx-on-an-otherwise-valid-link no longer fails the lint job outright.
- [ ] A 404 or malformed link still fails it (proved by a deliberate negative case).
- [ ] An outage of a first-party host is still reported rather than silently swallowed.
- [ ] The approach is consistent with `devantler-tech/platform#2789`, or that issue is updated to match.
Rough size: S–M, mostly a configuration and policy decision.
Related: `devantler-tech/platform#2789` (same class, platform side); ksail#6272 (the shields.io 503 exclusion that set the current precedent).
Contributor guide
Research direction
Start with lychee.toml and the workflow that runs the “Lint - mega-linter” job, then compare the proposed behavior with devantler-tech/platform#2789. Verify that transient 5xx responses do not fail the job, while a deliberate 404 or malformed link does, and confirm that a sustained first-party outage is still reported.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- github-actions
- Domain
- ci-cd, devops
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 38/100