Add upgrade apply for the CLI and API#5411
Conversation
There was a problem hiding this comment.
Large PR Detected
This PR exceeds 1000 lines of changes and requires justification before it can be reviewed.
How to unblock this PR:
Add a section to your PR description with the following format:
## Large PR Justification
[Explain why this PR must be large, such as:]
- Generated code that cannot be split
- Large refactoring that must be atomic
- Multiple related changes that would break if separated
- Migration or data transformationAlternative:
Consider splitting this PR into smaller, focused changes (< 1000 lines each) for easier review and reduced risk.
See our Contributing Guidelines for more details.
This review will be automatically dismissed once you add the justification section.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5411 +/- ##
==========================================
- Coverage 68.84% 68.82% -0.02%
==========================================
Files 635 635
Lines 64331 64376 +45
==========================================
+ Hits 44286 44308 +22
- Misses 16771 16790 +19
- Partials 3274 3278 +4 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Large PR justification has been provided. Thank you!
|
✅ Large PR justification has been provided. The size review has been dismissed and this PR can now proceed with normal review. |
Detecting an available upgrade is only useful if users can apply it while keeping their configuration. Add the apply path that the CLI and API will drive. Add upgrade.Applier: it reloads the workload's saved config, re-runs the check on fresh state (so a stale result can never drive an apply), resolves the candidate from the registry, and rebuilds the run config preserving the full user configuration — auth, authz, audit, telemetry, tools filters, volumes, secrets, ports, permission profile, and more — changing only the image, merged env/secrets, and re-resolved registry URLs. New required env vars surface through the injected validator. Crucially, the candidate image is verified and pulled (and the policy gate runs) before the destructive stop/delete/start, so a missing or unverifiable image leaves the running workload untouched — there is no rollback once UpdateWorkload begins. Verification uses the same path as thv run. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
With the Applier in place, expose it to users. This lets CLI users and
API clients apply an upgrade while preserving their configuration,
instead of manually re-running a workload with a new image.
Add a thv upgrade apply <name> command. It runs the check, shows the
candidate image, new env vars, and any permission/transport/network
posture drift, then prompts for confirmation. --dry-run reports the plan
without applying; --env/--secret supply values for newly required
variables; --yes (or a non-interactive shell) skips the prompt and fails
loudly on missing required values; --image-verification mirrors thv run.
Add POST /api/v1beta/workloads/{name}/upgrade, delegating to the same
Applier so all clients share one apply path. The API path is always
non-interactive (detached validator) and sources image verification from
server config; the request body can only supply env/secret values, never
redirect the image or weaken verification. Apply failures return a
sanitized 422 with the detailed cause logged server-side, so secret
references in an error chain are never echoed to the caller.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
With the
Applierin place (PR #5410), expose it to users so they can apply an upgrade while preserving configuration, instead of manually re-running a workload with a new image. Part of RFC THV-0068, local scope.thv upgrade apply <name>: runs the check, shows the candidate image, new env vars, and any permission/transport/network posture drift, then prompts for confirmation.--dry-runreports the plan without applying;--env/--secretsupply values for newly required variables;--yes(or a non-interactive shell) skips the prompt and fails loudly on missing required values;--image-verificationmirrorsthv run.POST /api/v1beta/workloads/{name}/upgrade, delegating to the sameApplierso all clients share one apply path. The API path is always non-interactive (detached validator) and sources image verification from server config; the request body can only supply env/secret values — it cannot redirect the image or weaken verification. Apply failures return a sanitized 422 with the detailed cause logged server-side, so secret references in an error chain are never echoed to the caller.Type of change
Test plan
task test) — API: happy path, no-op, 404/400, no-secret-leak (asserts a secret reference in the request never appears in success or 422 responses), route ordering. CLI: output-formatting helper.task lint-fix)Changes
cmd/thv/app/upgrade.goapplysubcommand + flags + confirmationpkg/api/v1/workloads_upgrade.goPOST .../upgradehandlerpkg/api/v1/workloads.go,workload_types.godocs/cli/*,docs/server/*Does this introduce a user-facing change?
Yes —
thv upgrade applyandPOST /api/v1beta/workloads/{name}/upgrade. The command stops and replaces the existing workload (verifying and pulling the candidate image first); there is no automatic rollback, which the help text states.Large PR Justification
This PR is ~1,007 lines, but only 330 are hand-written source; the remainder is generated reference and tests:
docs/server/*) and CLI reference (docs/cli/*), produced bytask docs. They must be regenerated and committed together (CI verifies them) and cannot be split.applysubcommand and the APIPOSThandler — two thin callers of the sameApplierthat the user explicitly chose to ship together so all clients share one apply path. Splitting CLI from API here would duplicate the wiring and the "all clients benefit" goal of the RFC, and both are well under the threshold individually.Special notes for reviewers
PR 5 of 6 in the RFC THV-0068 stack; based on #5410. The API path hardcodes the detached env-var validator and sources the verify mode from server config — a client cannot weaken verification or redirect the image via the request body.
🤖 Generated with Claude Code