Skip to content

Commit 3dbbf5a

Browse files
authored
Graduate CRDs from v1alpha1 to v1beta1 (#4849)
* Graduate CRDs from v1alpha1 to v1beta1 Signal API stability by promoting all ToolHive CRDs to v1beta1 while preserving backwards compatibility — the CRDs serve both versions simultaneously so existing v1alpha1 resources survive the upgrade untouched and users migrate manifests at their own pace. v1alpha1 and v1beta1 are schema-identical. The new cmd/thv-operator/api/v1alpha1/ package defines only the root resource types (MCPServer, MCPGroup, ...) as thin wrappers whose Spec and Status fields reference the canonical types from v1beta1. controller-gen walks field types when building the OpenAPI schema, so both versions resolve to the same schema without any duplication of the actual model — I verified empirically that all 12 CRDs produce structurally identical schemas (modulo the legitimately-different root descriptions). The upgrade is orchestrated through the `served` and `storage` flags on each version entry: the new CRDs list both versions as served, mark v1beta1 as storage, and mark v1alpha1 as deprecated with a warning. No conversion webhook is configured, which defaults to strategy: None — safe because the schemas are identical. Kubernetes swaps the apiVersion string when serving an object at a different version than it was stored at. Users can upgrade the CRD chart without deleting anything, keep reading/writing at v1alpha1 indefinitely, and migrate to v1beta1 by re-applying manifests. Once status.storedVersions no longer contains v1alpha1, a future release can drop the v1alpha1 entry and remove the wrapper package. What changed: - Mechanical rename from v1alpha1 to v1beta1 across all Go imports, YAML apiVersion strings, Helm deploy manifests, chainsaw fixtures, examples, docs, and generated artifacts. - New cmd/thv-operator/api/v1alpha1/ package: 12 root types + 12 list types as thin wrappers over v1beta1 Spec/Status, plus scheme registration. Each root type carries a +kubebuilder:deprecatedversion warning so kubectl prints a migration hint on every access. - Register both schemes in cmd/thv-operator/main.go. - Regenerated CRD manifests list both versions (v1alpha1 deprecated and non-storage, v1beta1 storage) with conversion.strategy: None. - Removed the obsolete pre-upgrade Helm hook that blocked upgrades when v1alpha1 resources existed — no longer needed since those resources now survive the upgrade. - Drive-by: regenerate pkg/audit/zz_generated.deepcopy.go which had drifted after DetectApplicationErrors was added to Config without re-running controller-gen. Closes #2556 * Update test files to use v1beta1 after merge Two test files that came in via the merge from main still reference the v1alpha1 Go package, which no longer exists on this branch. The operator binaries compile fine, but CI lint/test fail on the missing mcpv1alpha1 symbol in the test package. - cmd/thv-operator/controllers/mcpremoteproxy_deployment_test.go - cmd/thv-operator/controllers/mcpserver_resource_overrides_test.go Applied the same mcpv1alpha1 → mcpv1beta1 rename that the rest of the branch uses. No behavioural change.
1 parent 117be04 commit 3dbbf5a

384 files changed

Lines changed: 27197 additions & 12094 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/implement-story/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ After changes that affect generated artifacts, run the appropriate tasks:
170170

171171
| Change Type | Regeneration Command |
172172
|-------------|---------------------|
173-
| CRD type definitions (`api/v1alpha1/*_types.go`) | `task operator-manifests operator-generate` |
173+
| CRD type definitions (`api/v1beta1/*_types.go`) | `task operator-manifests operator-generate` |
174174
| Mock interfaces | `task gen` |
175175
| CLI commands or API endpoints | `task docs` |
176176
| Helm chart values | `task helm-docs` |

PROJECT

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,6 @@ resources:
1111
domain: toolhive.stacklok.dev
1212
group: toolhive
1313
kind: MCPServer
14-
path: github.com/stacklok/toolhive/cmd/thv-operator/api/v1alpha1
15-
version: v1alpha1
14+
path: github.com/stacklok/toolhive/cmd/thv-operator/api/v1beta1
15+
version: v1beta1
1616
version: "3"

cmd/thv-operator/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ helm upgrade -i <release_name> oci://ghcr.io/stacklok/toolhive/toolhive-operator
136136
To create an MCP server, define an `MCPServer` resource and apply it to your cluster:
137137

138138
```yaml
139-
apiVersion: toolhive.stacklok.dev/v1alpha1
139+
apiVersion: toolhive.stacklok.dev/v1beta1
140140
kind: MCPServer
141141
metadata:
142142
name: fetch
@@ -165,7 +165,7 @@ kubectl apply -f your-mcpserver.yaml
165165
For MCP servers that require authentication tokens or other secrets:
166166

167167
```yaml
168-
apiVersion: toolhive.stacklok.dev/v1alpha1
168+
apiVersion: toolhive.stacklok.dev/v1beta1
169169
kind: MCPServer
170170
metadata:
171171
name: github
@@ -272,7 +272,7 @@ kubectl create configmap my-registry-data --from-file registry.json=/path/to/you
272272
Then create the MCPRegistry resource with `configYAML` and mount the ConfigMap:
273273

274274
```yaml
275-
apiVersion: toolhive.stacklok.dev/v1alpha1
275+
apiVersion: toolhive.stacklok.dev/v1beta1
276276
kind: MCPRegistry
277277
metadata:
278278
name: my-registry
@@ -350,7 +350,7 @@ This operator is scaffolded using Kubebuilder. If you want to make changes to th
350350
Generate CRD manifests:
351351

352352
```bash
353-
kubebuilder create api --group toolhive --version v1alpha1 --kind MCPServer
353+
kubebuilder create api --group toolhive --version v1beta1 --kind MCPServer
354354
```
355355

356356
Update CRD manifests after changing API types:
@@ -369,7 +369,7 @@ task operator-run
369369

370370
The Kubebuilder project structure is as follows:
371371

372-
- `api/v1alpha1/`: Contains the API definitions for the CRDs
372+
- `api/v1beta1/`: Contains the API definitions for the CRDs
373373
- `controllers/`: Contains the reconciliation logic for the controllers
374374
- `config/`: Contains the Kubernetes manifests for deploying the operator
375375
- `PROJECT`: Kubebuilder project configuration file

cmd/thv-operator/REGISTRY.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ data:
3333
}
3434
}
3535
---
36-
apiVersion: toolhive.stacklok.dev/v1alpha1
36+
apiVersion: toolhive.stacklok.dev/v1beta1
3737
kind: MCPRegistry
3838
metadata:
3939
name: my-registry
@@ -171,7 +171,7 @@ type: Opaque
171171
stringData:
172172
password: "ghp_your_github_token_here" # GitHub PAT, GitLab token, etc.
173173
---
174-
apiVersion: toolhive.stacklok.dev/v1alpha1
174+
apiVersion: toolhive.stacklok.dev/v1beta1
175175
kind: MCPRegistry
176176
metadata:
177177
name: private-registry
@@ -501,7 +501,7 @@ kubectl logs -n toolhive-system deployment/toolhive-operator | grep "my-registry
501501

502502
### Production Registry
503503
```yaml
504-
apiVersion: toolhive.stacklok.dev/v1alpha1
504+
apiVersion: toolhive.stacklok.dev/v1beta1
505505
kind: MCPRegistry
506506
metadata:
507507
name: production-registry
@@ -523,7 +523,7 @@ spec:
523523

524524
### Development Registry
525525
```yaml
526-
apiVersion: toolhive.stacklok.dev/v1alpha1
526+
apiVersion: toolhive.stacklok.dev/v1beta1
527527
kind: MCPRegistry
528528
metadata:
529529
name: dev-registry
@@ -554,7 +554,7 @@ type: Opaque
554554
stringData:
555555
token: "<github token>"
556556
---
557-
apiVersion: toolhive.stacklok.dev/v1alpha1
557+
apiVersion: toolhive.stacklok.dev/v1beta1
558558
kind: MCPRegistry
559559
metadata:
560560
name: private-registry
@@ -586,7 +586,7 @@ spec:
586586
You can configure multiple data sources in a single MCPRegistry and aggregate them into registry views:
587587

588588
```yaml
589-
apiVersion: toolhive.stacklok.dev/v1alpha1
589+
apiVersion: toolhive.stacklok.dev/v1beta1
590590
kind: MCPRegistry
591591
metadata:
592592
name: multi-source-registry
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
// Package v1alpha1 contains the deprecated v1alpha1 API types for the
5+
// toolhive.stacklok.dev group. These types exist solely to enable seamless
6+
// CRD graduation from v1alpha1 → v1beta1: the CRD serves both versions
7+
// (with conversion strategy "None"), so existing v1alpha1 resources continue
8+
// to work while users migrate their manifests to v1beta1.
9+
//
10+
// All Spec and Status types are imported from v1beta1 — the schemas are
11+
// identical. Only the root resource types and their List companions are
12+
// defined here so that controller-gen produces a multi-version CRD.
13+
//
14+
// This package will be removed in a future release once the v1alpha1
15+
// deprecation period ends.
16+
//
17+
// +kubebuilder:object:generate=true
18+
// +groupName=toolhive.stacklok.dev
19+
package v1alpha1

cmd/thv-operator/api/v1alpha1/groupversion_info.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
// SPDX-FileCopyrightText: Copyright 2025 Stacklok, Inc.
22
// SPDX-License-Identifier: Apache-2.0
33

4-
// Package v1alpha1 contains API Schema definitions for the toolhive v1alpha1 API group
5-
// +kubebuilder:object:generate=true
6-
// +groupName=toolhive.stacklok.dev
74
package v1alpha1
85

96
import (
@@ -12,10 +9,10 @@ import (
129
)
1310

1411
var (
15-
// GroupVersion is group version used to register these objects
12+
// GroupVersion is group version used to register these objects.
1613
GroupVersion = schema.GroupVersion{Group: "toolhive.stacklok.dev", Version: "v1alpha1"}
1714

18-
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
15+
// SchemeBuilder is used to add go types to the GroupVersionKind scheme.
1916
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
2017

2118
// AddToScheme adds the types in this group-version to the given scheme.

0 commit comments

Comments
 (0)