fix(replicated-deploy): Make the Replicated deploy job re-runnable and its failures more legible - #1243
Open
dylan-openhands wants to merge 1 commit into
Open
fix(replicated-deploy): Make the Replicated deploy job re-runnable and its failures more legible#1243dylan-openhands wants to merge 1 commit into
dylan-openhands wants to merge 1 commit into
Conversation
dylan-openhands
requested review from
aivong-openhands,
jlav and
mamoodi
as code owners
September 12, 2026 00:06
dylan-openhands
enabled auto-merge (squash)
September 12, 2026 00:13
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The unstable deploy job failed with
Error: deploy rejected: <empty response>and there was no way to act on it — the script never inspects HTTP status, so a bare 4xx from KOTS and a dropped connection produce byte-identical output. Re-running didn't help either: a cursor only appears under/updateswhile it's still an upstream update, so any re-run of a deploy that already got somewhere failed withcursor N never became an available update, which is not what happened.Two changes, plus first test coverage for this script.
scripts/replicated_deploy.shResolve the cursor's state once, up front, from a single
/appscall and give each state a path:never became an available updatesequence/$SEQ/deploynever became an available updateSo the job is now idempotent for a given cursor — run it fifty times and it converges instead of going red.
api()now captures the response code viacurl -w '%{stderr}…', sowhy()always has something to report:.error→ raw body →HTTP 404/curl: (7) … HTTP 000.<empty response>can't recur, and "KOTS refused" is now distinguishable from "never got a reply".Also guarded the new up-front
/appsread —jq '.apps[0].downstream'returnsnullwith exit 0 on an error body, so without it a transient 401 would skip all three branches and spin out the select loop for three minutes before reporting the wrong thing.Last,
preflight_gateno longer printspreflights okwhen KOTS recorded no results. It sayspreflights: none recorded, because on this fleet.preflightResult.resultis an empty string on every sequence, healthy ones included — the old message was claiming a check that never reported.scripts/test_replicated_deploy.py— new. Eight cases, each running the real script against a stub KOTS on localhost, so they cover the shell's control flow rather than a reimplementation of it. Runs in ~5s;test-scripts.ymlalready triggers onscripts/**.Helm Chart Checklist
N/A — no charts touched.
Additional Notes
Verified read-only against
unstablerather than reasoned about: the branching was replayed against the live/appspayload (489 → deployed, 491 → upstream, 480 → past), and the downstreamsequence/$SEQ/preflight/resultpath was confirmed to exist with the shape the script expects.Two things worth knowing:
POST sequence/$SEQ/deployresponse shape is the one thing I couldn't verify; it needs a real pending version to exercise and there wasn't one. If it answers 204 rather than{"success":true}, the run fails withdeploy of sequence N rejected: HTTP 204, naming the exact fix.