diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1b63629..f14b89c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,11 +55,20 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 + - uses: actions/setup-go@v6 + with: + go-version-file: go.mod - uses: azure/setup-helm@v5 - - name: Lint Helm chart - run: helm lint charts/drop - - name: Template Helm chart - run: helm template drop charts/drop + - name: Generate CRDs and sync into charts + run: make sync-crds + - name: Lint Helm charts + run: | + helm lint charts/drop + helm lint charts/drop-crds + - name: Template Helm charts + run: | + helm template drop charts/drop + helm template drop-crds charts/drop-crds docs-build: runs-on: ubuntu-latest @@ -103,7 +112,7 @@ jobs: - name: Install CRDs run: | make controller-gen - make manifests + make sync-crds kubectl apply -f config/crd/bases/ - name: Deploy E2E infrastructure (Prometheus + Registry) run: make e2e-infra diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 648bb6c..ab2e15e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -161,13 +161,23 @@ jobs: subject-digest: ${{ steps.build.outputs.digest }} push-to-registry: true - - name: Package and push Helm chart + - name: Package and push Helm charts if: steps.changes.outputs.skip != 'true' run: | VERSION=${{ steps.version.outputs.version }} echo "${{ secrets.GITHUB_TOKEN }}" | helm registry login ghcr.io -u ${{ github.actor }} --password-stdin + + # Sync CRDs from generated sources into chart templates + make sync-crds + + # Package and push main operator chart helm package charts/drop --version "${VERSION#v}" --app-version "${VERSION#v}" helm push drop-*.tgz oci://ghcr.io/$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')/charts + rm -f drop-*.tgz + + # Package and push CRDs chart + helm package charts/drop-crds --version "${VERSION#v}" --app-version "${VERSION#v}" + helm push drop-crds-*.tgz oci://ghcr.io/$(echo '${{ github.repository_owner }}' | tr '[:upper:]' '[:lower:]')/charts - name: Create GitHub Release if: steps.changes.outputs.skip != 'true' diff --git a/.gitignore b/.gitignore index 06989d0..94e121d 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,7 @@ docs/.hugo_build.lock # Generated docs-gen binary /gen-ai-docs .kubeconfig + +# Generated CRD chart templates (produced by make sync-crds in CI) +charts/drop-crds/templates/drop.corewire.io_*.yaml +charts/drop/templates/crds-drop.corewire.io_*.yaml diff --git a/Makefile b/Makefile index de99a67..c4ede01 100644 --- a/Makefile +++ b/Makefile @@ -57,8 +57,21 @@ generate: controller-gen ## Generate DeepCopy methods. manifests: controller-gen ## Generate CRD and RBAC manifests. $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases +.PHONY: sync-crds +sync-crds: manifests ## Sync generated CRDs into Helm chart templates. + @echo "Syncing CRDs into charts/drop-crds/templates/ and charts/drop/templates/" + @for f in config/crd/bases/*.yaml; do \ + base=$$(basename "$$f"); \ + { echo '{{- /* Generated from config/crd/bases — do not edit manually. Run make sync-crds */ -}}'; \ + echo '{{- if .Values.install }}'; cat "$$f"; echo '{{- end }}'; \ + } > "charts/drop-crds/templates/$$base"; \ + { echo '{{- /* Generated from config/crd/bases — do not edit manually. Run make sync-crds */ -}}'; \ + echo '{{- if .Values.crds.install }}'; cat "$$f"; echo '{{- end }}'; \ + } > "charts/drop/templates/crds-$$base"; \ + done + .PHONY: codegen -codegen: generate manifests docs-gen ## Run all code generation (deepcopy + CRDs + docs). +codegen: generate manifests sync-crds docs-gen ## Run all code generation (deepcopy + CRDs + docs). ##@ Testing diff --git a/charts/drop-crds/.helmignore b/charts/drop-crds/.helmignore new file mode 100644 index 0000000..414bb6e --- /dev/null +++ b/charts/drop-crds/.helmignore @@ -0,0 +1,18 @@ +# Patterns to ignore when building packages. +.DS_Store +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +*.swp +*.bak +*.tmp +*.orig +*~ +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/drop-crds/Chart.yaml b/charts/drop-crds/Chart.yaml new file mode 100644 index 0000000..5a3f207 --- /dev/null +++ b/charts/drop-crds/Chart.yaml @@ -0,0 +1,19 @@ +apiVersion: v2 +name: drop-crds +description: CRDs for the drop operator (install separately for reliable upgrades) +type: application +version: 0.1.0 +appVersion: "0.1.0" +kubeVersion: ">=1.28.0-0" +keywords: + - kubernetes + - operator + - image-caching + - pre-pull + - crds +home: https://github.com/Breee/drop +sources: + - https://github.com/Breee/drop +maintainers: + - name: Breee + url: https://github.com/Breee diff --git a/charts/drop-crds/values.yaml b/charts/drop-crds/values.yaml new file mode 100644 index 0000000..ba8a937 --- /dev/null +++ b/charts/drop-crds/values.yaml @@ -0,0 +1,5 @@ +# Default values for drop-crds. + +# Set to false to render the chart without actually creating CRDs +# (useful for dry-run or templating). +install: true diff --git a/charts/drop/values.yaml b/charts/drop/values.yaml index 19429a4..dca0847 100644 --- a/charts/drop/values.yaml +++ b/charts/drop/values.yaml @@ -40,6 +40,10 @@ certManager: name: selfsigned-issuer kind: ClusterIssuer +# CRD management. Set install to false when using the separate drop-crds chart. +crds: + install: true + nodeSelector: {} tolerations: [] affinity: {} diff --git a/config/crd/bases/drop.corewire.io_cachedimages.yaml b/config/crd/bases/drop.corewire.io_cachedimages.yaml index 1bce2fd..cc9d58f 100644 --- a/config/crd/bases/drop.corewire.io_cachedimages.yaml +++ b/config/crd/bases/drop.corewire.io_cachedimages.yaml @@ -52,7 +52,8 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: CachedImage is the Schema for the cachedimages API. + description: CachedImage ensures a single container image is pre-cached on + cluster nodes. properties: apiVersion: description: |- diff --git a/config/crd/bases/drop.corewire.io_cachedimagesets.yaml b/config/crd/bases/drop.corewire.io_cachedimagesets.yaml index 3372da6..0ea3cf7 100644 --- a/config/crd/bases/drop.corewire.io_cachedimagesets.yaml +++ b/config/crd/bases/drop.corewire.io_cachedimagesets.yaml @@ -39,7 +39,8 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: CachedImageSet is the Schema for the cachedimagesets API. + description: CachedImageSet manages a group of images to cache, optionally + backed by a DiscoveryPolicy. properties: apiVersion: description: |- diff --git a/config/crd/bases/drop.corewire.io_discoverypolicies.yaml b/config/crd/bases/drop.corewire.io_discoverypolicies.yaml index d4dad33..397fa38 100644 --- a/config/crd/bases/drop.corewire.io_discoverypolicies.yaml +++ b/config/crd/bases/drop.corewire.io_discoverypolicies.yaml @@ -39,7 +39,8 @@ spec: name: v1alpha1 schema: openAPIV3Schema: - description: DiscoveryPolicy is the Schema for the discoverypolicies API. + description: DiscoveryPolicy automatically discovers images from registries + or Prometheus metrics. properties: apiVersion: description: |- diff --git a/config/crd/bases/drop.corewire.io_pullpolicies.yaml b/config/crd/bases/drop.corewire.io_pullpolicies.yaml index 96cad10..2f2155e 100644 --- a/config/crd/bases/drop.corewire.io_pullpolicies.yaml +++ b/config/crd/bases/drop.corewire.io_pullpolicies.yaml @@ -33,7 +33,7 @@ spec: schema: openAPIV3Schema: description: |- - PullPolicy is the Schema for the pullpolicies API. + PullPolicy controls the pacing and retry behavior for image pulls across cluster nodes. It is a configuration-only resource with no status. properties: apiVersion: diff --git a/docs/content/docs/install.md b/docs/content/docs/install.md index 90182bb..2bdcf0f 100644 --- a/docs/content/docs/install.md +++ b/docs/content/docs/install.md @@ -8,6 +8,7 @@ llmsDescription: | Installation guide for the drop operator. Prerequisites: Kubernetes 1.28+, Helm 3.12+. Install via Helm chart from ghcr.io/breee/charts/drop. Optional: cert-manager for secure metrics, ServiceMonitor for Prometheus. + CRDs can be installed separately via the drop-crds chart for reliable upgrades. --- ## Prerequisites @@ -34,6 +35,62 @@ helm install drop oci://ghcr.io/breee/charts/drop \ --set certManager.enabled=true ``` +## CRD Management + +Helm does not update CRDs on `helm upgrade`. For reliable CRD lifecycle +management, install CRDs separately using the **drop-crds** chart: + +```bash +# Install CRDs independently +helm install drop-crds oci://ghcr.io/breee/charts/drop-crds + +# Install the operator with CRD installation disabled +helm install drop oci://ghcr.io/breee/charts/drop \ + --namespace drop-system \ + --create-namespace \ + --set crds.install=false +``` + +To upgrade CRDs later: + +```bash +helm upgrade drop-crds oci://ghcr.io/breee/charts/drop-crds +``` + +### ArgoCD + +When using ArgoCD, deploy CRDs and the operator as separate Applications so +that CRD updates are applied independently. See +[`examples/argocd/`](https://github.com/Breee/drop/tree/main/examples/argocd) +for ready-to-use Application manifests. + +Key points for ArgoCD CRD management: + +- Use `ServerSideApply=true` and `Replace=true` sync options on the CRDs Application. +- Set a negative sync-wave (`argocd.argoproj.io/sync-wave: "-1"`) so CRDs are synced before the operator. +- Disable `crds.install` in the operator chart values. + +### Renovate + +The repository includes Renovate custom managers that automatically detect new +chart versions in the ArgoCD example manifests. Add similar regex managers to +your own `renovate.json` to keep chart references up to date: + +```json +{ + "customManagers": [ + { + "customType": "regex", + "fileMatch": ["argocd/.*\\.yaml$"], + "matchStrings": ["chart: drop-crds\\n\\s+repoURL: oci://ghcr\\.io/breee/charts\\n\\s+targetRevision: (?\\S+)"], + "depNameTemplate": "drop-crds", + "datasourceTemplate": "docker", + "packageNameTemplate": "ghcr.io/breee/charts/drop-crds" + } + ] +} +``` + ## Verify ```bash diff --git a/examples/argocd/drop-crds.yaml b/examples/argocd/drop-crds.yaml new file mode 100644 index 0000000..a31d467 --- /dev/null +++ b/examples/argocd/drop-crds.yaml @@ -0,0 +1,28 @@ +# ArgoCD Application — drop CRDs (install first) +# +# Best practice: Install CRDs as a separate ArgoCD Application with +# Replace=true sync option so that ArgoCD can manage CRD lifecycle +# independently of the operator. +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: drop-crds + namespace: argocd + annotations: + argocd.argoproj.io/sync-wave: "-1" +spec: + project: default + source: + chart: drop-crds + repoURL: oci://ghcr.io/breee/charts + targetRevision: 0.1.0 + destination: + server: https://kubernetes.default.svc + syncPolicy: + automated: + prune: false + selfHeal: true + syncOptions: + - CreateNamespace=false + - ServerSideApply=true + - Replace=true diff --git a/examples/argocd/drop-operator.yaml b/examples/argocd/drop-operator.yaml new file mode 100644 index 0000000..edc0eb0 --- /dev/null +++ b/examples/argocd/drop-operator.yaml @@ -0,0 +1,30 @@ +# ArgoCD Application — drop operator +# +# When using the separate drop-crds chart, disable CRD installation in the +# operator chart by setting crds.install=false. +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: drop + namespace: argocd + annotations: + argocd.argoproj.io/sync-wave: "0" +spec: + project: default + source: + chart: drop + repoURL: oci://ghcr.io/breee/charts + targetRevision: 0.1.0 + helm: + valuesObject: + crds: + install: false + destination: + server: https://kubernetes.default.svc + namespace: drop-system + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true diff --git a/renovate.json b/renovate.json index 2534534..0a778ba 100644 --- a/renovate.json +++ b/renovate.json @@ -14,6 +14,31 @@ "description": "Major updates require manual approval", "matchUpdateTypes": ["major"], "automerge": false + }, + { + "description": "Group drop chart and drop-crds chart version bumps together", + "matchFileNames": ["charts/drop/Chart.yaml", "charts/drop-crds/Chart.yaml"], + "groupName": "drop-charts" + } + ], + "customManagers": [ + { + "customType": "regex", + "description": "Update drop-crds chart version in ArgoCD examples", + "fileMatch": ["examples/argocd/.*\\.yaml$"], + "matchStrings": ["chart: drop-crds\\n\\s+repoURL: oci://ghcr\\.io/breee/charts\\n\\s+targetRevision: (?\\S+)"], + "depNameTemplate": "drop-crds", + "datasourceTemplate": "docker", + "packageNameTemplate": "ghcr.io/breee/charts/drop-crds" + }, + { + "customType": "regex", + "description": "Update drop operator chart version in ArgoCD examples", + "fileMatch": ["examples/argocd/.*\\.yaml$"], + "matchStrings": ["chart: drop\\n\\s+repoURL: oci://ghcr\\.io/breee/charts\\n\\s+targetRevision: (?\\S+)"], + "depNameTemplate": "drop", + "datasourceTemplate": "docker", + "packageNameTemplate": "ghcr.io/breee/charts/drop" } ] }