Skip to content

Production deploys fail only for the change they deploy #4979

Open
8 of 25 issues completed
Open

Description

@devantler

🤖 Generated by the Agentic Engineer (interactive Claude Code session)

Evidence

Audience and problem

Everyone who changes the platform (the maintainer and both agent lanes) and every tenant waiting on a platform change. When a deploy gate fails for a reason the candidate did not cause, the candidate is evicted, the next candidate inherits the same fault, and a working change can take hours to land. When a gate passes something broken, production drifts from main unnoticed.

Hypothesis

If every deploy gate judges only the effect of the candidate it is deploying, and names the condition that failed, then evictions caused by something outside the evicted pull request become rare, and a gate never reports success for a step it could not complete.

Success signal

  • Signal: the share of failed_checks merge-queue evictions whose root cause lies outside the evicted pull request.
  • Baseline: not measured yet. The first child classifies the evictions from the last 30 days, so the baseline is a number, not an estimate.
  • Target: under 10% over a 30-day window after the fixes, with every eviction's cause named by the failing step's own output.
  • Guardrail: no gate is removed or made non-blocking, and a candidate that does break production is still evicted and healed. Fixes narrow what a gate looks at; they never stop it looking.

Smallest useful change

Measure first: classify the last 30 days of failed_checks evictions by root cause (candidate's own change, unrelated platform fault, infrastructure transient, timeout) and rank the unrelated causes by how many evictions each caused. Then fix the top cause.

Acceptance criteria

  • An eviction-cause baseline for the last 30 days is recorded on this issue.
  • The children above are fixed or closed with a reason, highest-ranked cause first.
  • A 30-day re-measurement meets the target without breaching the guardrail.

Size: large — about 8 child issues, each small to medium. Decompose further as the baseline names new causes.

Activity

  1. added theissue type on Oct 17, 2026
  2. moved this to 📥 Backlog in 🌊 Project Boardon Oct 17, 2026
  3. 1 remaining item

  4. devantler commented on Oct 17, 2026

    @devantler
    ContributorAuthor

    🤖 Generated by the Agentic Engineer (interactive Claude Code session)

    Eviction-cause baseline, 2026-09-17 to 2026-10-17 (from #4993)

    Source. Every CI (ci.yaml) run with event=merge_group created in the window: 871 runs fetched, matching the run list's total of 871. Conclusions: 699 success, 160 failure, 12 cancelled. All 160 failures are classified below; the 12 cancelled runs are not.

    Method. Each failed run's failing job and step were read from the Actions API. The deploy job runs one composite step, 🚀 Deploy to Production, so for deploy failures the cause comes from the script's own error annotation (43 runs) or the job log (43 logs read). About 42 runs were not read one by one and are grouped by time with runs that were: 39 in cause 1 and 3 in cause 5. A run is "own change" only when its log shows a failure in what the pull request changed and a fix was pushed before it merged (or it was closed). Where the run cannot show the cause, the class is unknown.

    Baseline for this issue's signal

    • Outside the candidate: 132 of 160 failed runs (82.5%): unrelated platform fault 105, infrastructure transient 14, timeout 13.
    • Unknown: 8 (5.0%). Candidate's own change: 20 (12.5%).
    • Counting only the 145 runs whose pull request was removed from the queue by a check result (141 failed_checks, 4 checks_timed_out): 121 of 145 (83.4%) outside the candidate, 4 unknown, 20 own change.
    • The 160 runs belong to 68 pull requests; 149 of them belong to pull requests that later merged, many with no new push.

    Causes, ranked by failed runs

    Run-minutes run from start to last update, so they include the heal job.

    # Cause Class Issue Runs Share Run-min
    1 GHCR credential step refuses a node drain because its pull-probe pod ran out of memory on a full node; heal on main failed the same way unrelated platform fault #5009 (new) 46 28.8% 1910
    2 Coroot baseline check refuses the deploy because a Coroot workload was already unready unrelated platform fault #4659 34 21.3% 486
    3 Flux image-verification policy handoff refuses (parent not quiescent, controller restart incomplete, fences changed, pods unproven) unrelated platform fault (12), unknown (2) #5010 (new) 14 8.8% 551
    4 Static validation fails on the candidate's own change own change — 9 5.6% 26
    5 Longhorn client-migration detach step holds on state left by an earlier run unrelated platform fault #5011 (new) 7 4.4% 207
    6 A validation step's external download fails (429, DNS timeout, reset, HTTP 500) infrastructure transient #5012 (new) 7 4.4% 100
    7 Flux or Helm reconcile fails for the component the candidate changed own change — 6 3.8% 242
    8 Talos image factory unreachable or slow during cluster update infrastructure transient #5013 (new) 6 3.8% 208
    9 Deployed-PR-still-queued check gives up after 60 minutes of reads timeout #5014 (new) 4 2.5% 513
    10 Queue preflight refuses an entry already removed by hand unknown #4937 4 2.5% 435
    11 GHCR node credential rollout: node identity or cordon state changed, or registry auth not accepted unrelated platform fault #5016 (new) 3 1.9% 150
    12 Go helper regression suite times out timeout #5015 (new) 3 1.9% 26
    13 Node drain times out on disruption budgets timeout #3388 3 1.9% 308
    14 ARC verification of the candidate's own ARC change fails own change — 2 1.3% 80
    15 Data product UI check exceeds its deadline timeout #4545 2 1.3% 107
    16 Ten causes with one run each various see below 10 6.3% 563

    The single-run causes: the data product rollout check changing mid-check (#4545); #4873's own message (#4873); an ARC transport test harness failure (unrelated, no issue); a KSail download HTTP 500 (transient); a Coroot admission rollout over 15 minutes (timeout); a Coroot check failing on a Coroot change (own change); a data product UI expected-state error (own change); a leftover route after a refused prune (own change, the case #4734 describes); the GHCR lease that could not be inspected (unknown, closest #3071); and required checks cancelled with no failing step (unknown).

    #4839 explains none of these runs: it is about the Release workflow, not merge-group CI.

    Decision: what to fix first

    1. fix(deploy): an unrelated Coroot fault must not refuse every production deploy #4659 first. It failed 34 runs, the most of any open child, and the mechanism is structural: any unready Coroot workload refuses every deploy and the heal deploy as well. All 34 came in one burst on 2026-10-08 that held delivery for about 15 hours, and while fix(deploy): an unrelated Coroot fault must not refuse every production deploy #4659 is open the next Coroot fault can do the same.
    2. The policy handoff family second: Deploy GHCR step can time out on the Flux policy pause without saying which condition never held #4873 (pull request fix(ghcr-auth): name which Flux parent check failed when the policy pause times out #5006, open as a draft) and Flux policy handoff refuses deploys for conditions other than the post-pause wait #5010. It is smaller per episode, but chronic: 15 runs across a month and 11 pull requests, including dependency bumps.
    3. Deploy GHCR step refuses node drains when its pull-probe pod runs out of memory #5009 needs a check before a fix. It is the costliest cause in the window (46 runs, about 1,910 run-minutes) but has not recurred since 2026-10-09, after the attempt in fix(deploy): let the credential probe run on a worker with almost no free memory #4666. Its first criterion is to confirm whether the trigger can still happen; if it can, it moves to the front.

    The remaining new issues are each small, and the transients (#5012, #5013) are cheap wins once the top three are done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Fields

    No fields configured for Epic.

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions