Commit 0578af6
Opt 12 v1beta1 CRDs into storage-version migration + CI guard (#5391)
* Label v1beta1 CRDs for auto storage version migration
Adds the kubebuilder marker
+kubebuilder:metadata:labels=toolhive.stacklok.dev/auto-migrate-storage-version=true
to every v1beta1 root type and regenerates the CRD manifests. The label
is the opt-in signal for an upcoming StorageVersionMigrator controller
that will reconcile each CRD's status.storedVersions down to the current
storage version. List types are intentionally not labelled — the label
applies to the CRD itself, which is keyed on the root type.
Part of #4969.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Add CI test enforcing migrate-label coverage on v1beta1 root types
Guards against the main footgun of the opt-in-label design for
storage-version migration: if a new CRD root type is added to
cmd/thv-operator/api/v1beta1/ without the migrate-marker, the
StorageVersionMigrator controller silently excludes it. The problem
surfaces only when a future release tries to drop a deprecated version
— at which point it is far too late to fix.
The test scans every root type (marker block contains both
+kubebuilder:object:root=true and +kubebuilder:storageversion) and
fails unless the block also contains either the migrate marker or an
explicit +thv:storage-version-migrator:exclude sibling marker.
Part of #4969.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Scan all api/v* directories, label MCPWebhookConfig
The marker-coverage test was only scanning cmd/thv-operator/api/v1beta1/
and filtering for files matching *_types.go. This had two gaps:
1. Future graduations (v1beta1 → v1beta2) would silently break the test:
when +kubebuilder:storageversion moves to v1beta2/, the v1beta1 root
types lose the storage marker and become invisible to the scanner.
The test would either pass vacuously (other version dirs unscanned)
or hard-fail on the "no roots found" guard with no clear path forward.
2. MCPWebhookConfig lives in api/v1alpha1/types.go (not _types.go) and
carries +kubebuilder:storageversion as the only never-graduated CRD.
The original PR-B commit skipped it entirely; the migrator could not
act on its CRs even when explicitly opted in.
Changes:
- Walk cmd/thv-operator/api/v*/ instead of hardcoding v1beta1.
- File filter accepts both exact "types.go" and "*_types.go" suffix.
- Rename TestV1beta1TypesMarkerCoverage → TestStorageVersionRootMarkerCoverage.
- Update failure message + docstring to reflect the broader scope.
- Add the migrate marker to MCPWebhookConfig in v1alpha1/types.go and
regenerate its two CRD YAML files under deploy/charts/operator-crds/.
Future-proof: when v1beta2 lands and +kubebuilder:storageversion moves
to its root types, the scanner picks them up without code changes here.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Drop the exclude marker — every storage root must opt in
The previous test accepted either the migrate marker or an explicit
+thv:storage-version-migrator:exclude sibling. That permissive
contract opens a graduation-time hole: a single-version CRD created
with exclude passes CI, but at v1→v2 graduation time the developer
has to remember to swap exclude→migrate. Forgetting the swap leaves
the CRD silently un-migrated — exactly the failure mode this test
is meant to prevent.
No CRD in the codebase uses the exclude marker today. Removing it
costs nothing and closes the hole. If a legitimate exclusion ever
comes up, handle it as a one-off PR conversation and a hardcoded
allowlist in this test — not a self-serve marker that future
contributors can misuse.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Tighten marker match to whole-token boundary + stub allowlist
Two defensive additions identified during stress-testing the
opt-in-label design:
1. Strict marker matching. containsMarker previously used
strings.Contains, which would accept "=truee" (or any extra
character) as a substring match for "=true". The CI test would
pass, the generated CRD YAML would carry label value "truee",
and the controller's runtime check (labels[key] == "true")
would silently exclude the CRD. The bug only surfaces at
version-drop time months later. containsMarker now requires
the marker to be followed by end-of-line or whitespace.
TestContainsMarkerStrictBoundary defends the contract against
future regressions to substring semantics.
2. excludedRootTypes allowlist stub. The previous commit removed
the self-serve +thv:storage-version-migrator:exclude marker.
This adds the documented alternative — a hardcoded allowlist
in the test file — as an empty map with an example entry and
a comment explaining the deliberate, reviewed-decision policy
for adding entries. If a future contributor needs to exclude a
CRD, the path is "add an entry, justify it in PR review";
they don't have to invent the mechanism from scratch.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* Address review nits: marker order + drop pre-1.22 loop shadow
- v1alpha1/types.go MCPWebhookConfig: move the migrate marker to
AFTER +kubebuilder:subresource:status, matching the v1beta1
convention. controller-gen ignores order so behaviour is
unchanged; this is purely consistency for greppability and
future readers.
- marker_coverage_test.go: drop `tc := tc` shadowing in
TestContainsMarkerStrictBoundary. go.mod is on go 1.26; loop
variables have been per-iteration since 1.22, so the shadow is
dead code from older-Go muscle memory.
go/ast or controller-tools/pkg/markers refactor (raised separately)
deliberately deferred: the bufio scanner is correct for every CRD
in the codebase today; switching to AST is a ~40-line restructure
better landed as a follow-up if/when we actually need generics or
grouped type decl support in a CRD.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 83aaf96 commit 0578af6
40 files changed
Lines changed: 325 additions & 0 deletions
File tree
- cmd/thv-operator
- api
- v1alpha1
- v1beta1
- controllers
- deploy/charts/operator-crds
- files/crds
- templates
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
281 | 281 | | |
282 | 282 | | |
283 | 283 | | |
| 284 | + | |
284 | 285 | | |
285 | 286 | | |
286 | 287 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
211 | 211 | | |
212 | 212 | | |
213 | 213 | | |
| 214 | + | |
214 | 215 | | |
215 | 216 | | |
216 | 217 | | |
| |||
Lines changed: 1 addition & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1117 | 1117 | | |
1118 | 1118 | | |
1119 | 1119 | | |
| 1120 | + | |
1120 | 1121 | | |
1121 | 1122 | | |
1122 | 1123 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
88 | 88 | | |
89 | 89 | | |
90 | 90 | | |
| 91 | + | |
91 | 92 | | |
92 | 93 | | |
93 | 94 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
200 | 200 | | |
201 | 201 | | |
202 | 202 | | |
| 203 | + | |
203 | 204 | | |
204 | 205 | | |
205 | 206 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
205 | 205 | | |
206 | 206 | | |
207 | 207 | | |
| 208 | + | |
208 | 209 | | |
209 | 210 | | |
210 | 211 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
356 | 356 | | |
357 | 357 | | |
358 | 358 | | |
| 359 | + | |
359 | 360 | | |
360 | 361 | | |
361 | 362 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
929 | 929 | | |
930 | 930 | | |
931 | 931 | | |
| 932 | + | |
932 | 933 | | |
933 | 934 | | |
934 | 935 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
164 | 164 | | |
165 | 165 | | |
166 | 166 | | |
| 167 | + | |
167 | 168 | | |
168 | 169 | | |
169 | 170 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
| 142 | + | |
142 | 143 | | |
143 | 144 | | |
144 | 145 | | |
| |||
0 commit comments