CRD versioning and migration plan
Bloodraven's API is currently shipstream.io/v1alpha1. This page sets
the compatibility contract expected before promoting the API to
v1beta1 and then v1.
Current state: v1alpha1
v1alpha1 means the API is usable for pilots and early production
evaluation, but the schema is still allowed to change. Consumers should:
- Pin the operator and chart version.
- Commit generated manifests rather than relying on floating chart refs.
- Review release notes before applying CRD updates.
- Avoid depending on undocumented fields or status internals.
Bloodraven will preserve data-plane safety across upgrades, but it does not yet promise wire-compatible CRD evolution for every alpha field.
Promotion criteria for v1beta1
Move to v1beta1 only after these are true:
- A conversion webhook exists and is covered by envtest.
- All fields that may be renamed, reshaped, or removed from
v1alpha1have a documented migration path. - Defaults and validation rules are stable enough to support server-side dry-run in production pipelines.
- The chart installs webhook Service, Deployment flags, CA injection, and RBAC without manual post-install steps.
- Generated CRDs in
config/crd/bases/andcharts/bloodraven/crds/are checked for drift in CI. - Backward compatibility is tested against at least one real older CR fixture per managed resource.
Promotion criteria for v1
Move to v1 only after v1beta1 has survived real upgrades and the
following compatibility contract is acceptable:
- No breaking spec-field removals within
v1. - Additive spec fields are allowed.
- Status fields may grow additively; existing documented status fields keep their meaning.
- Enum values are not removed without a deprecation window.
- Defaults do not change in a way that causes existing manifests to reconcile into different data-plane behavior.
- Destructive operations remain gated by explicit confirmation fields or annotations.
Conversion strategy
Bloodraven should use hub-and-spoke conversion with the newest stable API as the hub.
Initial shape:
v1alpha1 <-> internal hub <-> v1beta1
After v1 exists:
v1alpha1 <-> internal hub <-> v1beta1 <-> v1
The webhook must be lossless for fields that still exist in the target version. If a field has no equivalent, conversion should preserve it via annotations only when there is a concrete rollback requirement; otherwise the release notes must call out the one-way migration.
Deprecation policy
Use this policy once v1beta1 exists:
| Change type | Policy |
|---|---|
| Add optional spec field | Allowed in any minor release. |
| Add status field | Allowed in any minor release. |
| Rename spec field | Add replacement first; support both through at least one minor release; remove only before v1 or in a new API version. |
| Remove enum value | Deprecate in docs and events first; reject new usage only after one minor release; keep conversion for old objects. |
| Change default | Treat as breaking unless old behavior is unsafe. Require release-note callout and migration guidance. |
| Change log/event contract | Update Log schema and release notes in the same PR. |
Storage-version migration
When introducing a new stored version:
- Serve both old and new versions in the CRD.
- Deploy the conversion webhook before changing
storage: true. - Mark the new version as storage.
- Run Kubernetes' storage-version migrator or force a safe read/write of all objects.
- Verify
status.storedVersionsno longer lists the retired storage version before removing it from the CRD.
Operational checks:
kubectl get crd mysqlfailovergroups.shipstream.io \
-o jsonpath='{.status.storedVersions}{"\n"}'
kubectl get mysqlfailovergroups -A -o yaml >/tmp/bloodraven-cr-backup.yaml
Always take an object backup before storage-version migration. This is a Kubernetes API safety net, not a MySQL data backup.
Release-note requirements
Every release that changes the CRD schema must include:
- A list of added, changed, deprecated, and removed fields.
- Whether
make manifestschangesconfig/crd/bases/and chart CRDs. - Whether a conversion webhook upgrade order is required.
- A
kubectl apply --server-side --dry-run=servercommand users can run against representative manifests. - Any data-plane behavior change caused by new defaults.
Compatibility tests
Before declaring v1beta1, add tests that:
- Decode old
v1alpha1YAML fixtures and convert them to the hub. - Convert hub objects back to
v1alpha1andv1beta1without losing preserved fields. - Install the CRD and webhook in envtest.
- Exercise status subresource writes across served versions.
- Validate that destructive fields still require confirmation after conversion.
What not to do
- Do not silently change field meaning while keeping the same name.
- Do not make the chart install a CRD version that the running operator cannot reconcile.
- Do not remove a served version until every supported upgrade path has a conversion route.
- Do not rely on Helm alone for storage-version migration; Helm updates CRD YAML but does not rewrite existing objects.