Skip to content

fix(kubernetes): keep tenant addon CRDs when a release is uninstalled - #3586

Merged
Aleksei Sviridkin (lexfrei) merged 4 commits into
mainfrom
fix/tenant-crd-addons-resource-policy-keep
Aug 7, 2026
Merged

Aleksei Sviridkin (lexfrei) merged 4 commits into
mainfrom
fix/tenant-crd-addons-resource-policy-keep

Conversation

@lexfrei

@lexfrei Aleksei Sviridkin (lexfrei) commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

What this PR does

Four tenant addon HelmReleases render their CRDs from a chart's templates/ directory and remediate a failed install by uninstalling the release. An uninstall deletes what the chart rendered, and deleting a CRD makes the API server garbage-collect every custom resource of that kind, so a failed reinstall takes every Gateway, VerticalPodAutoscaler, ServiceMonitor or VolumeSnapshot in the tenant cluster with it. This annotates the CRDs of the four packages behind them, gateway-api-crds, vertical-pod-autoscaler-crds, prometheus-operator-crds and vsnap-crd (that last one is declared by helmreleases/volumesnapshot-crd.yaml), with helm.sh/resource-policy: keep, which is what cert-manager-crds and etcd-operator-crds already carry in this tree.

Three of the four regenerate templates/ from upstream on make update: two delete the directory outright and the third overwrites its file. So the annotation is written into the vendored files and reapplied by a step in each update: target. Without that second half the next regeneration drops it silently, with nothing reporting the loss. I ran make update for real to check the pair holds: gateway-api-crds and vsnap-crd come back byte-identical to what is committed here, and vertical-pod-autoscaler-crds reproduces the annotation on both of its CRDs. The rest of the VPA diff is upstream drift, because that package's update: tracks a branch rather than a pinned ref; the bump itself is not in this PR. The step is idempotent, so running it twice does not stack a second annotation into the same mapping.

prometheus-operator-crds ships its CRDs in a vendored subchart that make update re-pulls, so nothing under charts/ is edited. The upstream template already renders .Values.annotations onto every CRD it emits, and the annotation is set through the package's values.yaml.

The Gateway API kustomization also emits a ValidatingAdmissionPolicy and its binding. Those hold no user data, so the stamping step selects on kind: CustomResourceDefinition and leaves them alone.

Each package gains a helm-unittest suite and the test: target that hack/helm-unit-tests.sh requires before it will run a suite at all. Every suite asserts the annotation across all CRDs its chart renders, not only the ones listed by name, so a CRD arriving in a later upstream bump is covered without editing the test.

The annotation has a cost worth stating plainly: uninstalling one of these releases on purpose now leaves the CRDs behind, to be removed by hand. That is the same trade-off cert-manager-crds already carries.

This covers the first of the two directions in #3555. The second one, setting install.strategy.name: RetryOnFailure on these releases, is a separate decision with a different blast radius and is not part of this PR.

Screenshots

Not a UI change.

Downstream repositories

I walked the trigger map in docs/agents/contributing.md against the file list of this diff. It touches four packages under packages/system/ and nothing else: no hack/package.mk, no app values.schema.json, no platform values, no ApplicationDefinition, no release asset names. The one line that looked close is the website's "developer tooling (the package Makefiles)" trigger, so I read content/en/docs/next/development.md in the website repo: it documents make update and make test in general terms, and neither goes stale from this change.

Release note

fix(kubernetes): tenant addon CRDs for Gateway API, VerticalPodAutoscaler, Prometheus Operator and VolumeSnapshot now carry `helm.sh/resource-policy: keep`. A failed install that remediates by uninstalling the release no longer deletes those CRDs and, with them, every custom resource of those kinds in the tenant cluster. In exchange, uninstalling one of these releases on purpose now leaves the CRDs in the cluster to be removed by hand.

Summary by CodeRabbit

  • Bug Fixes
    • Custom Resource Definitions for Gateway API, Prometheus Operator, Vertical Pod Autoscaler, and VolumeSnapshot are now retained when their Helm charts are uninstalled.
    • Prevents loss of custom resources and related configuration during chart lifecycle operations.
  • Tests
    • Added automated validation confirming all included CRDs receive the retention policy.
    • Added chart test commands to simplify verification of CRD updates.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Four Helm CRD charts now add helm.sh/resource-policy: keep. Their Makefiles support Helm unit tests and update-time annotation processing. New test suites validate rendered CRD counts, names, and retention annotations.

Changes

CRD retention

Layer / File(s) Summary
Gateway API CRD retention
packages/system/gateway-api-crds/*
Experimental Gateway API CRDs receive the retention annotation. The update workflow removes duplicates and inserts the annotation. Helm tests validate 14 rendered documents and named CRDs.
Prometheus Operator CRD retention
packages/system/prometheus-operator-crds/*
Prometheus Operator CRD configuration includes the retention annotation. Helm tests validate all rendered CRDs, names, counts, and annotations.
VPA CRD retention
packages/system/vertical-pod-autoscaler-crds/*
Both VPA CRDs receive the retention annotation. The update workflow and Helm tests cover annotation handling and both resources.
VolumeSnapshot CRD retention
packages/system/vsnap-crd/*
All three VolumeSnapshot CRDs receive the retention annotation. The update workflow and Helm tests validate the rendered resources.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related issues

  • cozystack/cozystack#3555 — Addresses the same objective of adding helm.sh/resource-policy: keep to unprotected CRD templates.

Suggested labels: kind/bug, size/L, area/kubernetes, area/testing, area/build

Suggested reviewers: ivanhunters

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: retaining tenant addon CRDs after Helm release uninstallation.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/tenant-crd-addons-resource-policy-keep

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/system/vertical-pod-autoscaler-crds/Makefile`:
- Around line 12-19: Update the awk transformation in the Makefile’s update
target to guarantee that each CustomResourceDefinition receives the
helm.sh/resource-policy annotation even when metadata.annotations is absent.
Create the annotations block before adding the policy, or fail before replacing
the generated file if it cannot be inserted; do not allow update to finish with
an unannotated CRD.
- Line 16: Update the curl invocation in the Makefile download target to include
the --fail option, ensuring HTTP 4xx and 5xx responses stop the command before
the generated template is modified by the subsequent awk step.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3d02055f-18c6-495e-90e3-c128aad23a94

📥 Commits

Reviewing files that changed from the base of the PR and between b4e2031 and 5f646c8.

📒 Files selected for processing (14)
  • packages/system/gateway-api-crds/Makefile
  • packages/system/gateway-api-crds/templates/crds-experimental.yaml
  • packages/system/gateway-api-crds/tests/resource_policy_test.yaml
  • packages/system/prometheus-operator-crds/Makefile
  • packages/system/prometheus-operator-crds/tests/resource_policy_test.yaml
  • packages/system/prometheus-operator-crds/values.yaml
  • packages/system/vertical-pod-autoscaler-crds/Makefile
  • packages/system/vertical-pod-autoscaler-crds/templates/vpa-v1-crd-gen.yaml
  • packages/system/vertical-pod-autoscaler-crds/tests/resource_policy_test.yaml
  • packages/system/vsnap-crd/Makefile
  • packages/system/vsnap-crd/templates/volumesnapshotclasses.yaml
  • packages/system/vsnap-crd/templates/volumesnapshotcontents.yaml
  • packages/system/vsnap-crd/templates/volumesnapshots.yaml
  • packages/system/vsnap-crd/tests/resource_policy_test.yaml

Comment on lines +12 to +19
# The stamp goes into the CRD's existing metadata.annotations block; a CRD that
# arrives without one is skipped, and the chart's helm-unittest suite is what
# catches that.
update:
curl -o ./templates/vpa-v1-crd-gen.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/refs/heads/master/vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml
@set -e; f=./templates/vpa-v1-crd-gen.yaml; tmp=$$(mktemp); \
awk '/^ helm.sh\/resource-policy: keep$$/{next} /^kind: /{kind=$$2} /^ annotations:$$/ && kind=="CustomResourceDefinition"{print; print " helm.sh/resource-policy: keep"; next} {print}' "$$f" > "$$tmp"; \
cat "$$tmp" > "$$f"; rm -f "$$tmp"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Handle CRDs that have no metadata.annotations block.

The awk rule adds the policy only when it finds ^ annotations:$. If upstream removes that block, make update completes with an unannotated CRD. Create the annotations block when absent, or fail the update before replacing the generated file. The separate test target does not run from update.

🧰 Tools
🪛 checkmake (0.3.2)

[warning] 15-15: Required target "all" is missing from the Makefile.

(minphony)


[warning] 15-15: Required target "clean" is missing from the Makefile.

(minphony)


[warning] 15-15: Required target "test" must be declared PHONY.

(minphony)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/vertical-pod-autoscaler-crds/Makefile` around lines 12 - 19,
Update the awk transformation in the Makefile’s update target to guarantee that
each CustomResourceDefinition receives the helm.sh/resource-policy annotation
even when metadata.annotations is absent. Create the annotations block before
adding the policy, or fail before replacing the generated file if it cannot be
inserted; do not allow update to finish with an unannotated CRD.

# arrives without one is skipped, and the chart's helm-unittest suite is what
# catches that.
update:
curl -o ./templates/vpa-v1-crd-gen.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/refs/heads/master/vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fail on an HTTP error before changing the generated template.

curl accepts HTTP 4xx and 5xx responses without --fail. The following awk command can then replace vpa-v1-crd-gen.yaml with an error page. Add --fail to prevent a failed download from corrupting the tracked template.

Proposed fix
-	curl -o ./templates/vpa-v1-crd-gen.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/refs/heads/master/vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml
+	curl --fail -o ./templates/vpa-v1-crd-gen.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/refs/heads/master/vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
curl -o ./templates/vpa-v1-crd-gen.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/refs/heads/master/vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml
curl --fail -o ./templates/vpa-v1-crd-gen.yaml https://raw.githubusercontent.com/kubernetes/autoscaler/refs/heads/master/vertical-pod-autoscaler/deploy/vpa-v1-crd-gen.yaml
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/system/vertical-pod-autoscaler-crds/Makefile` at line 16, Update the
curl invocation in the Makefile download target to include the --fail option,
ensuring HTTP 4xx and 5xx responses stop the command before the generated
template is modified by the subsequent awk step.

@github-actions github-actions Bot added area/kubernetes Issues or PRs related to the tenant Kubernetes app kind/bug Categorizes issue or PR as related to a bug size/L This PR changes 100-499 lines, ignoring generated files labels Aug 6, 2026
@lexfrei

Copy link
Copy Markdown
Contributor Author

Reopening to pick up the multus fix on main.

@kvaps Andrei Kvapil (kvaps) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verified the mechanics end to end and they hold. Rendering all four charts, every
CRD carries helm.sh/resource-policy: keep (12 / 2 / 10 / 3) and nothing else
does — the Gateway API ValidatingAdmissionPolicy pair is correctly left out. I
re-ran the stamping awk over the five committed files and it is a no-op, and I ran
the real update: fetch for gateway-api-crds (kubectl kustomize ... ?ref=v1.5.1)
and vsnap-crd: both come back byte-identical to what is committed here.

The tests are not self-asserting. Dropping the annotation from one vsnap CRD turns
two cases red; appending an unannotated CRD to the Gateway API file turns the
wildcard case and the document-count pin red. hack/helm-unit-tests.sh is green
across the whole repo.

On the trade-off: reinstall after a keep-uninstall is safe. Helm excludes kept
resources from the delete set without touching their metadata, so
meta.helm.sh/release-name and -namespace survive; release name and
storageNamespace are fixed in these HelmReleases, so the retry install passes the
ownership check and adopts the CRDs rather than failing on "exists and cannot be
imported". Existing clusters need no migration either — the platform upgrade runs
helm upgrade on these releases and patches the annotation onto the CRDs already in
place. Coverage looks complete for the stated scope: every tenant addon that renders
CRDs from templates/ is now annotated, and the ones that ship CRDs under crds/
(velero, gpu-operator) were never at risk since Helm does not delete those.

Two things worth resolving, both about consistency inside this block of PRs rather
than correctness here.

The stamping step is copy-pasted three times, and #3595 is hardening the fourth
copy in the opposite direction.
The same awk one-liner appears verbatim in
gateway-api-crds/Makefile:22, vertical-pod-autoscaler-crds/Makefile:18 and
vsnap-crd/Makefile:23, alongside a fourth, differently-shaped and non-idempotent
variant already in etcd-operator-crds/Makefile:20. #3595 gives that fourth one a
count guard — one annotation per CRD or the update fails — and defers writing
templates/ until after the check. The three added here have neither. A CRD that
arrives without a metadata.annotations block, or with annotations: {} in flow
style, is skipped silently, the step exits 0, and since rm -rf templates has
already run there is nothing to fall back to. The suite in this PR does catch it in
CI, which the description says, but #3595 has decided the guard belongs at the point
of failure. A shared hack/stamp-crd-keep.sh — the kind-aware idempotent matcher
from this PR plus the count guard from #3595 — would leave one implementation
instead of four.

The suites are much heavier than the equivalent in #3590. 387 of the 456 added
lines are tests, and most of that is repetition:
gateway-api-crds/tests/resource_policy_test.yaml:35-141 is twelve near-identical
cases that each re-check what the matchMany case at :18 already covers, and
prometheus-operator-crds/tests/resource_policy_test.yaml:24-142 is ten more. #3590
gets the same guarantee for cert-manager-crds in a single wildcard case. Worth
converging on one shape across the block.

Smaller points:

  • The description says a CRD from a later upstream bump is "covered without editing
    the test", but hasDocuments: count: 14 at :32 (and count: 2 in the VPA suite)
    is exactly what will need editing on such a bump. Both properties are worth having;
    the sentence just reads as if the pin were not there.
  • Three of the four suites scope to no template and assert
    kind == CustomResourceDefinition on every document. That is stricter than
    intended: a non-CRD resource appearing upstream would fail them for the wrong
    reason. The Gateway API suite gets this right with documentSelector + matchMany.
    Conversely it is the only one with a suite-level templates: (:15), so a second
    file under templates/ would go untested — moot today, since update: writes
    exactly one.
  • renders twelve CRDs and the admission policy pair (:30) bakes the count into the
    case name as well as the assertion; the name will go stale first.
  • vsnap-crd/Makefile:22 creates tmp outside the loop, so a mid-loop awk failure
    leaves it behind.

Out of scope, but the same class exists on the management cluster: kamaji-crds
(tenantcontrolplanes), piraeus-operator-crds, kubevirt-operator,
kubevirt-cdi-operator, metallb, objectstorage-controller,
mariadb-operator-crds, kubeovn and external-secrets all render CRDs from
templates/ without the annotation. Not urgent — those HelmReleases set no
install.remediation, and the default there is to perform no action — but the same
protection would cost the same.

CI is red on "Unit & controller tests" for an unrelated reason: the EXIT-trap freeze
guard in hack/cozyreport.bats:2553 does not list
hack/run-kubernetes-talos-diagnostics_test.bats, which landed on main with #3548.
This PR touches no .bats file.

Approving — none of the above blocks the fix.

The tenant addon HelmRelease remediates a failed install by uninstalling
the release, and an uninstall deletes whatever the chart rendered.
Deleting a CRD makes the API server garbage-collect every custom
resource of that kind, so a failed reinstall takes every Gateway,
HTTPRoute and ReferenceGrant in the tenant cluster with it.

Stamp helm.sh/resource-policy: keep on each CustomResourceDefinition and
teach `make update` to reapply it, since that target rebuilds templates/
from upstream and would otherwise drop the annotation silently. The
ValidatingAdmissionPolicy pair the experimental kustomization also emits
holds no user data and stays unannotated.

Removing the release on purpose now leaves the definitions behind to be
deleted by hand.

Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
The tenant addon HelmRelease remediates a failed install by uninstalling
the release, and an uninstall deletes whatever the chart rendered.
Deleting a CRD makes the API server garbage-collect every custom
resource of that kind, so a failed reinstall takes every
VerticalPodAutoscaler in the tenant cluster with it, along with the
recommendation history held in the checkpoints.

Stamp helm.sh/resource-policy: keep on each CustomResourceDefinition and
teach `make update` to reapply it, since that target refetches the
manifest from upstream and would otherwise drop the annotation silently.

Removing the release on purpose now leaves the definitions behind to be
deleted by hand.

Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
The tenant addon HelmRelease remediates a failed install by uninstalling
the release, and an uninstall deletes whatever the chart rendered.
Deleting a CRD makes the API server garbage-collect every custom
resource of that kind, so a failed reinstall takes every VolumeSnapshot
and VolumeSnapshotContent in the tenant cluster with it — the objects
that carry the only reference to a snapshot on the storage backend.

Stamp helm.sh/resource-policy: keep on each CustomResourceDefinition and
teach `make update` to reapply it, since that target rebuilds templates/
from upstream and would otherwise drop the annotation silently.

Removing the release on purpose now leaves the definitions behind to be
deleted by hand.

Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
The tenant addon HelmRelease remediates a failed install by uninstalling
the release, and an uninstall deletes whatever the chart rendered.
Deleting a CRD makes the API server garbage-collect every custom
resource of that kind, so a failed reinstall takes every ServiceMonitor,
PodMonitor, PrometheusRule and ScrapeConfig in the tenant cluster with
it.

The CRDs ship inside a vendored subchart that `make update` re-pulls, so
the annotation is set through the chart values the subchart already
renders rather than by editing templates that would be overwritten.

Removing the release on purpose now leaves the definitions behind to be
deleted by hand.

Assisted-By: Claude <[email protected]>
Signed-off-by: Aleksei Sviridkin <[email protected]>
@lexfrei
Aleksei Sviridkin (lexfrei) force-pushed the fix/tenant-crd-addons-resource-policy-keep branch from 5f646c8 to d90a6a5 Compare August 7, 2026 11:38
Aleksei Sviridkin (lexfrei) added a commit that referenced this pull request Aug 7, 2026
## What this PR does

`make update` in `packages/system/etcd-operator-crds` vendors three CRDs
and stamps `helm.sh/resource-policy: keep` onto each with an awk step
anchored on the `controller-gen.kubebuilder.io/version:` line. That line
is upstream's to emit. If a future controller-gen stops writing it, the
awk matches nothing, writes the CRD out unstamped and exits zero, so the
regeneration reports success and the CRDs land without the annotation
that keeps a chart uninstall from deleting them, and with them every
EtcdCluster, EtcdMember and EtcdSnapshot in the cluster.

The step now counts what it produced and requires exactly one annotation
per CRD. Zero means the anchor is gone; more than one means it matched
somewhere unintended. Every CRD is staged in a temporary directory and
`templates/` is replaced only after all of them have been counted, so a
failure on any one leaves the vendored files exactly as they were rather
than wiping the directory and refilling part of the set.

I checked it by substituting the upstream response, so what ran was the
recipe that ships rather than a copy of its logic: a CRD with no
controller-gen line fails with `stamped 0 keep annotations, expected 1`,
a CRD carrying that line twice fails with 2, a failure on the second of
the three leaves all three committed files untouched, and the real
upstream still vendors byte-identical output, with `make update` leaving
`git status` showing nothing but this Makefile.

On `main` today this is the only thing guarding those three CRDs. A
helm-unittest suite that fails when one of them renders without the
annotation is in #3590, which is open and not merged. Once that lands
the two catch the same loss at different moments: the suite on a test
run, this step in front of whoever ran the regeneration.

The same stamping shape exists in three more packages, but only on the
branch of #3586, which adds it to `gateway-api-crds`, `vsnap-crd` and
`vertical-pod-autoscaler-crds`. There is nothing to guard there on
`main` yet, so they are deliberately out of this change and need the
same step once #3586 merges.

### Screenshots

Not a UI change.

### Downstream repositories

- [x] No downstream repository is affected by this change
- [ ] [cozystack/website](https://github.com/cozystack/website) -
follow-up:
- [ ]
[cozystack/terraform-provider-cozystack](https://github.com/cozystack/terraform-provider-cozystack)
- follow-up:
- [ ]
[cozystack/ansible-cozystack](https://github.com/cozystack/ansible-cozystack)
- follow-up:
- [ ] [cozystack/ccp](https://github.com/cozystack/ccp) - follow-up:
- [ ] [cozystack/talm](https://github.com/cozystack/talm) - follow-up:
- [ ] [cozystack/cozyhr](https://github.com/cozystack/cozyhr) -
follow-up:
- [ ] [cozystack/cozy-proxy](https://github.com/cozystack/cozy-proxy) -
follow-up:
- [ ]
[cozystack/cozystack-telemetry-server](https://github.com/cozystack/cozystack-telemetry-server)
- follow-up:
- [ ]
[cozystack/external-apps-example](https://github.com/cozystack/external-apps-example)
- follow-up:
- [ ] [cozystack/examples](https://github.com/cozystack/examples) -
follow-up:

I walked the trigger map in `docs/agents/contributing.md` against the
file list of this diff, which is one package Makefile and nothing else.
`hack/package.mk` is untouched, so the `ccp` and `external-apps-example`
triggers that key on it do not fire, and the website's "developer
tooling (the package Makefiles)" line is the only near miss:
`content/en/docs/next/development.md` describes `make update` in general
terms and does not go stale from a package validating its own output.

### Release note

```release-note
NONE
```


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved CRD update validation to ensure generated definitions include
the required preservation annotation.
* Prevented incomplete or invalid updates from replacing existing CRD
templates.
  * Added automatic cleanup of temporary update files.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
@lexfrei
Aleksei Sviridkin (lexfrei) merged commit 177da78 into main Aug 7, 2026
14 of 15 checks passed
@lexfrei
Aleksei Sviridkin (lexfrei) deleted the fix/tenant-crd-addons-resource-policy-keep branch August 7, 2026 14:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/kubernetes Issues or PRs related to the tenant Kubernetes app kind/bug Categorizes issue or PR as related to a bug size/L This PR changes 100-499 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants