Skip to content

feat!: restore stranded HPA-managed Deployments after pre-deployment migrations#55

Merged
arthlr merged 4 commits into
mainfrom
chartreuse-restore
Jul 8, 2026
Merged

feat!: restore stranded HPA-managed Deployments after pre-deployment migrations#55
arthlr merged 4 commits into
mainfrom
chartreuse-restore

Conversation

@arthlr

@arthlr arthlr commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Problem

With CHARTREUSE_UPGRADE_BEFORE_DEPLOYMENT, chartreuse-upgrade skips start_pods() and relies on the deployment that follows to restore replicas. That never happens for HPA-managed Deployments: their chart omits spec.replicas (so ArgoCD/Helm applies never touch it), and an HPA whose target is at 0 replicas with minReplicas >= 1 is ScalingDisabled forever. Every migration leaves those workers stranded at 0 replicas — this hit pythie-cayzn-staging-demo on 2026-07-07 (3 worker deployments down for ~24h), and applies to every env with upgradeBeforeDeployment: true, including all pythie prods.

Fix

  • stop_pods() now marks every Deployment it scales down with the wiremind.io/stopped-by annotation. Live-only annotations survive ArgoCD sync/selfHeal (per-key field ownership), which is exactly the mechanism that orphaned spec.replicas in the first place.
  • New chartreuse-restore entrypoint, run as a post-deployment hook (ArgoCD PostSync — see companion chart PR): re-enables HPAs and scales back up annotated Deployments still at 0 — and only those, so a Deployment deliberately scaled to zero by a human is left alone. Any replicas >= 1 re-arms the HPA, which then enforces its own minReplicas.
  • A restore failure fails the Job (and thus the sync) instead of a log-and-continue: stranded workers must be visible.

BREAKING CHANGE

The wiremind-kubernetes dependency is dropped (library being decommissioned). The subset chartreuse used (deployment manager, kube config loading, run_command) now lives in chartreuse.kubernetes_helper / chartreuse.utils.command, depending only on the official kubernetes client. Version bumped to 7.0.0 (ensure_safe_run requires the chart's appVersion to match major.minor).

Companion PR: wiremind/wiremind-helm-charts (chartreuse chart 6.4.0)

🤖 Generated with Claude Code

…migrations

With CHARTREUSE_UPGRADE_BEFORE_DEPLOYMENT, chartreuse-upgrade skips start_pods()
and relies on the deployment that follows to restore replicas. That never happens
for HPA-managed Deployments: their chart omits spec.replicas, and an HPA whose
target is at 0 replicas with minReplicas >= 1 is ScalingDisabled forever. Every
migration left those workers stranded at 0 replicas (e.g. pythie-cayzn-staging-demo
on 2026-07-07).

stop_pods() now marks every Deployment it scales down with the
wiremind.io/stopped-by annotation, and the new chartreuse-restore entrypoint
(run as a post-deployment hook, e.g. ArgoCD PostSync) re-enables the HPAs and
scales back up the annotated Deployments still at 0 replicas - and only those,
so a Deployment deliberately scaled to zero is left alone. A restore failure
fails the Job, so the deployment is marked failed instead of stranding workers
silently.

BREAKING CHANGE: the wiremind-kubernetes dependency is dropped (library being
decommissioned). The subset chartreuse uses now lives in
chartreuse.kubernetes_helper and chartreuse.utils.command, and depends only on
the official kubernetes client.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
arthlr and others added 2 commits July 8, 2026 14:58
Allows validating a change on a canary environment before merging: tag any
branch commit with a PEP 440 dev version and the package is published. The
version is derived from the tag itself (never the VERSION file, so a dev tag
cannot accidentally publish a final version) and the workflow refuses any tag
that is not vX.Y.Z.devN. Stable releases keep going through a published
GitHub Release only.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The tag follows semantic versioning; the workflow translates it to the
PEP 440 equivalent (X.Y.Z.devN) for the PyPI package.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@arthlr arthlr requested a review from haoov July 8, 2026 13:42
Found during the staging-demo canary: the restore Job ran correctly but
logged nothing — main() never configured logging (the upgrade path gets
it via the Chartreuse class).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@arthlr arthlr self-assigned this Jul 8, 2026
@arthlr arthlr merged commit c4c0608 into main Jul 8, 2026
5 checks passed
@arthlr arthlr deleted the chartreuse-restore branch July 8, 2026 15:48
@arthlr

arthlr commented Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Canary validated on pythie-cayzn-staging-demo (chartreuse 7.0.0.dev1 + chart 6.4.0-dev.1): real alembic migration ran on the upgradeBeforeDeployment path — stop_pods stopped+annotated the workers at 15:04, PostSync chartreuse-restore brought the HPA-managed workers back at 15:07 and the HPAs re-armed and enforced their minimums. Without this fix those workers stayed at 0 forever (2026-07-07 incident). One fix found during the canary and already pushed here: configure logging in the restore entrypoint (a4ff120).

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants