Add workload upgrade detection package#5407
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.
CLI and API users have no way to discover when a newer version of a registry-sourced MCP server is available; only Studio implements drift detection, in its frontend. Introduce a backend package that all clients can consume. Add pkg/workloads/upgrade with a Checker that compares a running workload's image tag against its registry entry (semver-aware, with a string fallback) and reports environment-variable and configuration (transport / permission-profile / network-isolation) drift. Comparison degrades safely to "unknown" for :latest, digest refs, repository changes, and non-registry-sourced workloads, so only a strictly-newer tag on the same repository yields "upgrade-available". This is the read-only detection core (RFC THV-0068, phase A); the apply path, API endpoints, and CLI follow in later changes. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
b1361f7 to
3350917
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #5407 +/- ##
==========================================
+ Coverage 68.77% 68.83% +0.06%
==========================================
Files 629 632 +3
Lines 63937 64085 +148
==========================================
+ Hits 43970 44111 +141
- Misses 16713 16718 +5
- Partials 3254 3256 +2 ☔ 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. |
jhrozek
left a comment
There was a problem hiding this comment.
Detection logic looks solid and the tests are thorough. A few comments from a focused review of the comparison/drift logic — one correctness item on semver normalization, plus two defensive/semantic notes. Nothing blocking.
- Lowercase an uppercase "V" tag prefix so semver comparison works; "V1.2.0" vs "V1.3.0" no longer falls through to undecidable and hides a real upgrade. - Drop the raw provider error from CheckResult.Reason (it is serialized into the API response and can leak internal addressing); log it at DEBUG and return a fixed string. Same for the CheckAll path. - Add a defensive default to the comparison switch so an unexpected value yields StatusUnknown rather than the least-safe StatusUpToDate. - Stop reporting network-isolation drift: the registry has no network-isolation field, so it fired for every isolated workload regardless of the candidate version. Remove the ConfigDrift field and the now-unused BoolChange type. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
0431342 to
6cb9506
Compare
Summary
CLI and API users have no way to discover when a registry-sourced MCP server has a newer version available. Today only ToolHive Studio detects image-tag drift, and it does so in its frontend — so CLI users are blind to updates and every new client would have to reimplement the same logic. This is the first slice of RFC THV-0068 (Workload Upgrade), moving detection into the backend where all clients can consume it. Local experience only (Kubernetes is out of scope for this RFC).
pkg/workloads/upgradepackage with aCheckerthat compares a running workload's image tag against its current registry entry.golang.org/x/mod/semver) with a string-equality fallback; it degrades safely tounknownfor:latest, digest references, repository changes (host-normalized), and non-registry-sourced workloads, so only a strictly-newer tag on the same repository yieldsupgrade-available.Type of change
Test plan
task test) — table-driven coverage of tag comparison (incl. double-digit-minor and prerelease ordering), env/config drift, and status gating; registry provider mocked.task lint-fix)Changes
pkg/workloads/upgrade/doc.gopkg/workloads/upgrade/types.goCheckResult,EnvVarDrift,ConfigDrift,UpgradeStatus,ApplyOptionspkg/workloads/upgrade/version.gopkg/workloads/upgrade/checker.goChecker+Check/CheckAllpkg/workloads/upgrade/*_test.goDoes this introduce a user-facing change?
No — this PR adds an internal package only. The
thv upgradecommands and REST endpoints that consume it land in later PRs of this stack.Large PR Justification
This PR is ~1,158 lines, but 627 of those are unit tests (
*_test.go) and only 531 are source across one cohesive new package (doc.go+types.go+version.go+checker.go).Checkerdepends on its result types (types.go) and the tag-comparison helper (version.go); separating them yields a package that does not build. This is one self-contained unit, the smallest reviewable slice of the feature.Special notes for reviewers
This is PR 1 of 6 in a stack implementing RFC THV-0068 (split to stay within the repo's PR-size limit). Each PR is one logical phase; later PRs are based on this branch:
GET .../upgrade-check)thv upgrade check+thv list --check-upgradesupgrade.Applierthv upgrade apply,POST .../upgrade)🤖 Generated with Claude Code