Repository navigation
Fail the deploy when the Cilium rollout gate outruns its intended window #2972
Description
🤖 Generated by the Agentic Engineer
Evidence
The gated Cilium rollout has now been active for 10 days and has stepped zero nodes, and the
whole time every prod deploy has been green while silently skipping its only Talos machine-config
sync and its only ksail cluster update. Re-verified live today (read-only, admin@prod):
daemonset/cilium updateStrategy=OnDelete desired=9 ready=9 updatedNumberScheduled=0
all 9 agent pods on controller-revision-hash 7f7c864994 (revision 19)
The suppression is real and ongoing — see the parent #2963 for the full consequence list — but the
reason it survived 10 days is narrower and separable: nothing makes an over-running gate visible as
failure. A green deploy that quietly skipped its config sync looks exactly like a green deploy that
did not need one.
Scope of this child
Only the parent's fifth acceptance criterion:
A gate that stays active past its intended window fails a deploy rather than warning inside a green
one.
Deliberately not in scope: stepping the 9 agents, or rolling the component back. Those are
operator actions against prod networking that the parent keeps unautomated on purpose, and no
forcing function can perform them.
Expected behaviour
scripts/guard-cilium-homogeneous-device-rollout.sh records when the gate first went active and
fails the deploy once the gate has been active longer than its intended window.
- Activation time is stored as epoch seconds in a companion annotation on the same Cluster
Autoscaler deployment that already carries the guard's ownership markers, so the check is integer
arithmetic with no date parsing. (date -j -fon BSD anddate -don GNU disagree about what an
unspecified time-of-day means, so a parsed-date comparison is platform-dependent and cannot be
ablated locally against the Linux runner.) - The gate suspends the autoscaler first and checks the window second, so a stalled rollout stays
fenced rather than trading one safety property for the new one. - The window is exceeded ⇒ the guard fails, naming the elapsed time and the two legitimate
resolutions (complete the rollout, or roll the component back). Raising the window is explicitly
not one of them. - The gate already active with no recorded activation time (exactly today's prod state) ⇒ the
clock is backfilled to now and the deploy stays green. This is the honest bound: the guard cannot
know retroactively when a gate it never timestamped went active, and reddening every prod deploy
the moment this merges would freeze the merge queue on a change whose whole point is to make a
stall visible in an orderly way. The backfill is announced in the deploy log, and the window then
applies normally. - Releasing the gate clears the annotation alongside the existing ownership markers, so a later
rollout starts a fresh clock.
Acceptance criteria
- The guard records gate activation time and clears it on release.
- An active gate inside its window succeeds; an active gate past its window fails the deploy.
- Both states are covered by
scripts/tests/test-cilium-homogeneous-devices-autoscaler-gate.sh,
including the missing-annotation backfill path. - The window default is stated in the script and overridable for tests.
Size
Small — one script, its test, no manifest change.
Part of #2963.
Metadata
Metadata
Assignees
Labels
Type
Fields
Projects
- StatusShow more project fields✅ Done
Activity
coderabbitai commentedon Aug 5, 2026
🔗 Related PRs
#2793 - feat(cilium): activate homogeneous device selection [merged]
#2927 - fix(deploy): await pre-handoff kustomize-controller pod termination [merged]
#2930 - feat(ci): verify published evidence before promoting the prod digest [merged]
#2947 - fix(ci): refuse to promote a prod digest whose evidence cannot be verified [merged]
#2962 - fix(deploy): make rollout-gate suppression of machine-config sync visible and bounded [merged]
📝 Issue Planner
Check the box below or use the
@coderabbitai plancommand to generate an implementation plan and prompts that you can use with your favorite coding assistant.🧪 Issue enrichment is currently in open beta.
You can configure auto-planning by selecting labels in the issue_enrichment configuration.
To disable automatic issue enrichment, add the following to your
.coderabbit.yaml:💬 Have feedback or questions? Drop into our discord!
chore: agent-claim #2972 nonce=615f16112bb938e74a8b20fc05fc45d4
devantler commentedon Aug 21, 2026
Closing as already delivered. This shipped on the day the issue was filed, and the issue was
simply never closed behind it.
fix(ci): fail the deploy when the Cilium rollout gate outruns its window(#2973,97d41324,2026-08-05) — the same title as this issue — added the hard bound to
scripts/report-cilium-rollout-gate-suppression.sh, whose own reporting half had landed the daybefore in #2962 (
a312e62b).Acceptance criteria against
main(a0537f33)platform.devantler.tech/rollout-gate-activated: <YYYY-MM-DD>marker declared beside thecomponent reference in
k8s/providers/hetzner/infrastructure/controllers/kustomization.yaml;releasing the gate removes the component reference and its marker in the same diff. An active
gate with no marker, a duplicated marker, an unparseable date, or a future date each fail
closed.
warn_after_days=7emits a::warning::;fail_after_days=14callsfail, which emits::error::and exits 1. Thestep is wired at
.github/actions/deploy-prod/action.yml:330underalways() && steps.cilium_rollout_gate.outputs.active == 'true'with nocontinue-on-error,so the non-zero exit reddens the deploy rather than warning inside a green one.
scripts/tests/test-cilium-rollout-gate-suppression-signal.sh—including the exact
>=boundary on both thresholds, the future-date and one-day-ahead cases(where integer division would otherwise hide the skew as
0 days), the duplicated-markercase, and the override.
readonly fail_after_days="${CILIUM_ROLLOUT_FAIL_AFTER_DAYS_OVERRIDE:-14}".One deviation from the issue's design, and it is an improvement
This issue specified an epoch-seconds annotation on the Cluster Autoscaler Deployment, guarded in
scripts/guard-cilium-homogeneous-device-rollout.shand covered intest-cilium-homogeneous-devices-autoscaler-gate.sh. What shipped instead dates the gate from areviewed marker in Git. That is the stronger choice on the axis that matters here: a cluster
annotation is operator-writable, so the same
kubectl annotatecommand a refusal hands out is alsothe way to silence it — a far-future value would make the gate immortal, and a zero-padded value
would abort in shell arithmetic before the guard's own message. The Git marker cannot be moved
without a reviewed diff, so completing or rolling back the rollout is the only way to clear it. The
coverage living in the suppression-signal test rather than the autoscaler-gate test follows from
that design, and is not a gap.
The issue's own framing still holds exactly as written — "a green deploy that quietly skipped its
config sync looks exactly like a green deploy that did not need one". That is now false in the
deploy, which is what this asked for.