Skip to content

ci: auto-deploy Replicated releases to internal instances - #1123

Merged
dylan-openhands merged 6 commits into
mainfrom
dj/replicated-auto-deploy
Aug 20, 2026
Merged

dylan-openhands merged 6 commits into
mainfrom
dj/replicated-auto-deploy

Conversation

@dylan-openhands

@dylan-openhands dylan-openhands commented Aug 20, 2026 •

Copy link
Copy Markdown
Contributor

Description

Embedded Cluster has no supported auto-update path on V2 so we have to handroll it with KOTS (the underlying k8s admin layer)

This wires the deploy into the release workflows and reports it. When a release publishes, the instance tracking that channel gets it, and a failure turns the release run red.

The deploy drives the same upgrade-service API the admin console's own wizard uses. It is undocumented (😢 ), so every call below was verified by hand against replicated-unstable (0.45.0 → 0.48.0, then 0.49.0) before any of it was written down.

Why a needs: job and not workflow_run

The deploy has to be pinned to the release the caller just built, and workflow_run only ever executes the default-branch copy of a workflow — so the logic couldn't be iterated on a branch. Coupling it also means a deploy failure marks the release run red, which is the signal the PR check reads.

Pinning, and why it needs a Makefile target

Three different numbers identify a release, and the one we actually use to update is totally hidden

Number Example Scope
versionLabel 0.49.0 the build — not unique, Unstable republishes it on every push to main
release sequence 1451 app-global, what replicated release create prints
channelSequence / KOTS updateCursor 404 per channel — what KOTS actually selects on

So the release job resolves its own release sequence to a channelSequence and hands that to the deploy.

The channel comes from make print-channel rather than a hardcoded Unstable, because Makefile derives CHANNEL from the branch.

Helm Chart Checklist

Additional Notes

Files

  • scripts/replicated_deploy.sh — 100 lines, no retries or recovery by design. Takes KOTS_CURSOR, deploys exactly that release, or fails loudly with ::error::.
  • .github/workflows/deploy-replicated.yml — reusable (workflow_call + workflow_dispatch), concurrency: replicated-deploy-<instance>, cancel-in-progress: false.
  • release-replicated.yml / release-replicated-beta.yml — resolve the cursor, then call the deploy workflow as a needs: job.
  • deploy-gate.yml — non-blocking PR check, both lanes.
  • Makefile — adds print-channel. Purely additive; release, the guard, and local branch releases are untouched.
  • README.md — native GitHub Actions badges for both lanes.

The PR check is visibility only. It is deliberately not in the main ruleset's required_status_checks, so a red X never blocks a merge. Promoting it later means adding the check context last-deploy under Settings → Rules → Rulesets — the context is the job name with no workflow prefix, which the four existing publish-charts (…) entries confirm.

It asserts coverage rather than age, because a stale badge reads as green: GitHub renders the last real conclusion forever, so a workflow that silently stopped firing stays passing. Each lane finds what should have triggered a deploy and checks a run exists for it.

  • unstable — main's newest commit under release-replicated.yml's own on.push.paths, read at runtime with yq so there's no second copy of that path list to drift. (yq, not PyYAML: YAML 1.1 parses a bare on: key as the boolean True.)
  • beta — the newest openhands/* GitHub Release. Tag refs can't be used: git/matching-refs sorts alphabetically, so openhands/0.9.0 outranks openhands/0.49.0 and the check would pin to a months-old tag and pass forever.

@dylan-openhands dylan-openhands changed the title Auto-deploy Replicated releases to internal instances ci: auto-deploy Replicated releases to internal instances Aug 20, 2026
@github-actions github-actions Bot added the type: ci CI configuration changes label Aug 20, 2026

@aivong-openhands aivong-openhands left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bummer that replicated didn't have an API for embedded cluster V2 :( hopefully V3 will have an API driven way to do this without us having to handroll a solution

@dylan-openhands

Copy link
Copy Markdown
Contributor Author

Yep v3 supports headless upgrades from the CLI..so if we get to that point this gets much cleaner @aivong-openhands 🤞

@dylan-openhands
dylan-openhands force-pushed the dj/replicated-auto-deploy branch from 847885e to d330aef Compare August 20, 2026 22:13
@dylan-openhands
dylan-openhands merged commit d80c7af into main Aug 20, 2026
14 checks passed
@dylan-openhands
dylan-openhands deleted the dj/replicated-auto-deploy branch August 20, 2026 22:14
@openhands-release-bot

Copy link
Copy Markdown
Contributor

🚀 Released in openhands/0.50.0.

@openhands-release-bot openhands-release-bot Bot added the released: openhands/0.50.0 Shipped in openhands/0.50.0 label Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

released: openhands/0.50.0 Shipped in openhands/0.50.0 type: ci CI configuration changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants