mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-09 14:02:56 +09:00
c1da673b085a845a014db5b4c2f0e30bb205bd8a
5255
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
c1da673b08 |
docs(security): align the reporting paragraph with the undocumented backport rule
The vulnerability-reporting paragraph named severity and upgrade impact as the basis for backporting to an older line, two paragraphs after the table says no rule is documented. Both sentences were added by this branch, so this is an internal inconsistency of its own making rather than inherited text. Point at the same absence instead of naming a basis. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io> |
||
|
|
f2a091083a |
docs(security): drop an invented backport rule and fix the nightly counts
The previous commit added a backport prioritisation policy to SECURITY.md — by severity, by reachability in a default configuration, and by adopter count, with a critical fix reaching every supported line. No such rule exists in any project document. Reachability appears only as a triage question, and adopter count appears nowhere. In an adopter-facing file that also lists seven supported lines, that sentence read as a guarantee no maintainer has made. Replaced with what is actually true: backporting is decided per fix and the rule is not documented. Nightly figures corrected. Counting only scheduled runs, the first run after the fix still failed, the streak that followed was three days rather than four, and six of the last twenty-four passed rather than seven. The earlier numbers folded in a workflow_dispatch success from a day whose scheduled run failed. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io> |
||
|
|
ea3d68493a |
docs(security): restore the triage admission and correct the nightly timeline
The previous commit narrowed a true statement into a false one. It said the scanner gap was remediation throughput and that triage ran on schedule; triage is also behind, and the backlog awaiting a triage decision includes findings at critical severity well past the one-business-day target. Both tracks are now stated as behind. Figures stay out of this repository for the disclosure reason the document already gives and belong in the private channel, so the admission is qualitative rather than rounded down. The nightly characterisation was also wrong. It read as fixed-then-regressed, which understates it: after the fix in #3332 the scheduled run passed for four days, went red for five, passed for three, and has failed every run since 2026-08-02 — seven of the last twenty-four passed. It is flapping, not newly broken, and the current failure is untriaged rather than provably unfiled. Carry the target-attainment caveat into SECURITY.md, which stated the triage SLAs with no indication they are not being met, and resync the self-assessment on the monthly report: it names findings individually and so is not publishable until reduced to counts by severity. Also note in SECURITY.md what the activity test actually classifies today — every 1.x line from 1.0 to 1.6 — and how backport effort is prioritised across that set, since supporting seven lines in parallel otherwise invites the question it does not answer. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io> |
||
|
|
a627788b81 |
docs(security): make the disclosure line and the support test checkable
A second internal pass found that the previous commit's disclosure argument did not hold together and that its support test could not be evaluated by a reader. The document had nominated the monthly aggregate summaries as safe-to-publish evidence on the grounds that they hold no vulnerability detail. They do: they name accepted-risk findings individually by CVE ID, severity and package, some of them critical, next to a count of confirmed findings awaiting a fix. State the line where it actually falls — aggregate counts by severity are publishable, naming an individual unfixed finding is not, because a CVE ID plus a package plus this project's public pinned component list locates unpatched exposure — and note that the monthly summary needs reducing to counts before it can be published. Present the resulting posture as a proposal rather than as a position the maintainers have taken. The scanner SLA paragraph said a triage backlog was running against the clock. The pipeline's own output says something more specific and worse: triage is keeping up, remediation is not, with the last monthly period closing on no confirmed findings fixed. Say that instead. The supported-versions table keyed support to having an active release branch. Release branches are never deleted, so every line back to the earliest has one and the test tells a reader nothing; read literally it also committed the project to every 1.x line. Key it to patch activity within a stated window instead, restore an end-of-life category the previous commit had removed entirely, and put the v0.41 cutoff back rather than extending discretionary backports across all of 0.x. Also: drop an unevidenced claim that the per-PR checks are healthy, correct the nightly attribution — the current red run is a regression after #3332 and is not tracked by an issue, unlike the older failure in #3278 — and qualify how zizmor gates, through the required pre-commit hook rather than through its own path-filtered workflow. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io> |
||
|
|
d30d638575 |
docs(security): correct scanner, Renovate and support-line claims after internal review
Two internal reviews of the previous commit found that it overstated several controls. Corrections, all verified against the tree and the GitHub API: CodeQL is not a required status check on main — the required checks are pre-commit and E2E Tests — so the questionnaire no longer says it gates merges. SECURITY.md and the security self-assessment already hedged this correctly and the GTR now matches them. Renovate does not cover Helm charts: helm-values is disabled repo-wide because many image refs are assembled by the cozy-lib.image helper rather than written literally in values.yaml. Say so, and say that the curated platform component images are bumped by maintainers per release rather than by a bot. The rewritten supported-versions table narrowed the support window to the latest two minors, which contradicts practice — several 1.x lines receive patch releases concurrently. Restate it as a description of what the project actually does, keyed to active release branches rather than to version numbers. The CVE-scanning pipeline is described more precisely: noise filters run before issue creation, discovery reads direct Go requirements with transitive coverage coming from the filesystem scan, and render-time image refs are a known blind spot. Its SLAs are labelled as targets rather than measured attainment, and the confidentiality claim is narrowed from the whole repository to per-CVE findings and triage state, since the policy documents and scripts hold no vulnerability data and are what actually evidences the control. SBOM and provenance are stated from the build tooling rather than from an issue title: provenance is explicitly disabled and SBOM generation is implemented but defaulted off. zizmor is added as a third gating scanner in both documents. Also close markers that repository evidence settles: the in-tree security self-assessment, threat model and incident-response documents; no default audit policy is shipped; and there is no top-level NOTICE file, which is stated as a compliance gap rather than deferred. Fix the phantom OWNERS reference at its source in CONTRIBUTOR_LADDER.md, and add current CI health next to the e2e workflow links so the red nightly run is disclosed rather than discovered. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io> |
||
|
|
be8c6e507f |
docs(security): address GTR review — rolling supported-versions policy, CODEOWNERS, SCA and CI links
Review feedback on the GTR questionnaire flagged two factual errors and a set of unresolved markers that the repository can in fact answer. The supported-versions table in SECURITY.md pinned concrete version numbers and had drifted five minor releases behind the latest release. Restate it as a rolling policy relative to the latest release so it cannot go stale, and cite the Releases page as the authoritative list instead of repeating numbers in prose. The contributor-ladder answer referenced a top-level OWNERS file, which the project does not have; promotions go through .github/CODEOWNERS for the area-scoped Reviewer role and MAINTAINERS.md for the Maintainer roster. Close the markers that repository evidence settles: e2e and CI workflow links, the Renovate configuration, the organization-wide Trivy CVE-scanning pipeline and its triage SLAs, and the real state of artifact signing, SBOM and SLSA provenance. Replace the vague item count in the draft banner with the seven substantive gaps that genuinely need measurement or a maintainer decision. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Timur Tukaev <timur.tukaev@aenix.io> |
||
|
|
2c22ebc7f7 |
docs: add CNCF General Technical Review (GTR) questionnaire
Fills the CNCF TOC project-reviews General Technical Review template for Cozystack for the Sandbox -> Incubation Due Diligence (tracks cncf/toc#1916). Co-Authored-By: Claude <noreply@anthropic.com> Signed-off-by: tym83 <6355522@gmail.com> |
||
|
|
df157da618 |
ci(workflows): open the E2E breakpoint for maintainer-authored PRs (#3158)
## What this PR does Decouples opening the E2E SSH breakpoint from the `debug` label. Today, the only way to open a breakpoint on a failed feature PR is to add the `debug` label. That same label also flips every job's `runs-on` onto self-hosted runners, so you cannot get a breakpoint on the normal ephemeral runner — debugging always drags the whole pipeline onto self-hosted infrastructure. This adds a maintainer-authorship path to the breakpoint's `if` condition: a failed PR whose author is an `OWNER`, `MEMBER`, or `COLLABORATOR` now opens the breakpoint automatically, with no label required and without moving the jobs onto self-hosted runners. The breakpoint simply holds the default `oracle-vm` ephemeral runner the job already runs on. The existing `debug` and `release` label paths are unchanged, and the `authorized-users` list still controls who may actually SSH into an open breakpoint (second defense layer). Workflow triggers are untouched — this is purely an `if`-condition change. ### Release note ```release-note ci(workflows): open the E2E SSH breakpoint automatically on failed maintainer-authored PRs, without requiring the `debug` label or moving the jobs onto self-hosted runners ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Updated E2E failure debugging so breakpoints can now open for pull requests authored by repository maintainers, not just when specific labels are applied. * Clarified the conditions and runner behavior for breakpoint access in the workflow documentation. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
ee26a50f0e |
fix(postgres-operator): align CNPG operator and CRDs to 1.28.2 for PVC resize-deadlock fix (#3510)
## What this PR does Raises the CloudNativePG operator image **and its CRDs together** to 1.28.2, which carries the PVC resize-deadlock fix (cloudnative-pg#9980 / cloudnative-pg#9981). Symptom: after a simultaneous `resources` + `size` change on a single-instance Postgres, the operator deletes the sole primary Pod, classifies the PVC as `resizing`, and never recreates the Pod — the cluster wedges with zero instances and the disk FS resize never completes. Upstream publishes a CloudNativePG chart only per minor (`.0`/`.1`), so there is no 1.28.2 chart on the 1.28 line. Following the pattern of #3526 / #3528, `patches/cloudnative-pg-1.28.2.patch` (applied by `make update`) raises the vendored chart's `appVersion` and CRDs from 1.28.1 to 1.28.2 in lockstep. The operator image follows `appVersion`, so there is no `image.tag` pin (keeping operator and CRDs aligned and avoiding #3479). Verified #3479-safe: there are no CRD `status` field changes between 1.28.1 and 1.28.2 — only the `extensions` spec grows. Backportable to release-1.6 as-is (same 0.27.1 base chart). ### Release note ```release-note fix(postgres-operator): align CloudNativePG operator and CRDs to 1.28.2, fixing the PVC resize-deadlock that wedged single-instance PostgreSQL clusters after a simultaneous resources+size change ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added support for PostgreSQL extension configuration in catalog and cluster schemas. - Made extension image settings optional where appropriate. - **Bug Fixes** - Updated CloudNativePG to version 1.28.2, including the PVC resize deadlock fix. - Kept the operator image and CRDs aligned at the same version. - **Documentation** - Clarified versioning and chart update guidance. - **Tests** - Added checks confirming operator image and CRD version alignment. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
bcb36262ef |
fix(postgres-operator): align CNPG operator and CRDs to 1.28.2 for PVC resize-deadlock fix
Raises the CloudNativePG operator image and its CRDs together to 1.28.2, which carries the PVC resize-deadlock fix (cloudnative-pg#9980 / #9981): after a simultaneous resources+size change the operator deletes the sole primary Pod, leaves the PVC in the resizing class, and never recreates the Pod, wedging the cluster. Upstream publishes a chart only per minor .0/.1, so there is no 1.28.2 chart on the 1.28 line. Following #3526/#3528, patches/cloudnative-pg-1.28.2.patch (applied by make update) raises the vendored chart's appVersion and CRDs from 1.28.1 to 1.28.2 in lockstep; the operator image follows appVersion, so no image.tag pin. Verified #3479-safe: no CRD status field changes between 1.28.1 and 1.28.2 (only the extensions spec grows). Backportable to release-1.6. Signed-off-by: Alexey Artamonov <aleksei.artamonov@aenix.io> |
||
|
|
7cef85f988 |
feat(release): cutting an rc freezes the line into release-X.Y (#3399)
## What this changes Cutting the first `vX.Y.0-rc.N` now creates `release-X.Y` at the tagged commit and closes the line. Every later cut for that line must be dispatched from the branch; a dispatch from `main` is refused. Before this, `release-X.Y` was created only when the stable promote PR merged. So `rc.2` and `rc.3` were cut from `main`'s tip and silently absorbed every feature merged since `rc.1` — the shipped release could contain code that no rc had ever validated. `main` now reopens for the next minor immediately, and fixes reach the release by cherry-pick. ## Commits | Commit | What | | --- | --- | | `feat(release)` | `cut-prerelease.yaml`: create `release-X.Y` after the tag push; refuse a frozen line from `main` | | `ci(backport)` | `backport.yaml`: target the newest existing `release-X.Y` branch | | `docs(release)` | Rewrite the RC/Regular/Patch sections, diagrams, and workflow reference | ## Behaviour changes worth a close look **The promote PR base flips from `main` to `release-X.Y` on its own.** No code change causes this — `promote-rc.yaml` already prefers `release-X.Y` whenever it exists, and after the freeze it always does. Consequence: the digest-vendored `Prepare release vX.Y.0` commit stays on the release line and no longer lands on `main`. This matches how patch releases already work, but it is a real change for `.0` releases and is easy to miss in review. **`finalize`'s `Ensure maintenance branch` becomes a no-op.** The merge commit is already the branch tip, so the fast-forward has nothing to do. No change was needed there. **Backport targeting changes during a freeze window.** `backport.yaml` derived its target from `getLatestRelease`, which returns the newest published *stable*. Since `release-X.Y` now exists before `vX.Y.0` ships, that name lagged by a full line for the whole freeze window — a `backport` on a fix for the release being stabilised would have landed on the previous line and missed the release it was written for. It now enumerates real `release-X.Y` branches and takes the newest. Outside a freeze window the result is unchanged. This also drops a latent bug: `previous` was computed as `min - 1`, which names a branch that does not exist whenever a minor is skipped. Sorting is now numeric, so `release-1.10` correctly outranks `release-1.9`. ## A note on image pins An earlier revision of this PR also replaced the committed `ghcr.io/cozystack/cozystack/*` digests on `main` with an unpullable sentinel tag, on the theory that they are a build leftover that nothing restores — and that the freeze makes this worse, since the promote PR no longer merges into `main` to refresh them. That was wrong and has been dropped. Per #3143, PR CI rebuilds only the packages a diff touches (`hack/build-matrix.sh` "emits only the units whose package dir changed") and the installer bundles the whole digest-patched tree, so **every untouched package deploys from its committed pin**. A sentinel would have made those unpullable across E2E. The staleness problem is real, though, and #3143 already tracks it as a systemic gap. Evidence gathered while investigating is posted there rather than acted on here. ## Testing - Full `hack/helm-unit-tests.sh` green - Branch-selection logic tested against the live 424-branch list, including double-digit minors (`1.10 > 1.9`) and skipped minors; outside a freeze window the result is unchanged (`release-1.5` / `release-1.4`) - `zizmor` clean on both workflows - No `values.yaml` or `images/*.tag` file is touched by this PR ## Release note ```release-note Cutting a release candidate now creates the `release-X.Y` branch and freezes the release line. Features merged to `main` after the first rc no longer ship in that release; fixes must be cherry-picked or backported onto `release-X.Y`. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Release branches are now created and frozen when the first release candidate is published. * Later pre-releases and patches use the frozen release branch while `main` advances independently. * Release-line package artifacts can be generated manually, including for recovery. * Backport targets are selected from existing release branches, with clearer failures when a prior line is unavailable. * **Documentation** * Updated release, patch-release, workflow, promotion, finalization, and cleanup guidance to reflect the new freeze model. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
a7149d11a3 |
chore(etcd-operator): bump etcd-operator to v0.5.4 (#3529)
## What this PR does Bumps the cozystack etcd-operator packages from **v0.5.3 to v0.5.4**. `v0.5.4` is a controller bug-fix release — no API, RBAC or values changes: - fix(controllers): derive `--initial-cluster-state` from phase, not from the seed ([cozystack/etcd-operator#355](https://github.com/cozystack/etcd-operator/pull/355)) - fix(controllers): stop exempting the bootstrap seed from self-heal ([cozystack/etcd-operator#354](https://github.com/cozystack/etcd-operator/pull/354)) - fix(controllers): extend crash-loop self-heal to memory members ([cozystack/etcd-operator#352](https://github.com/cozystack/etcd-operator/pull/352)) - fix(controllers): switch the PDB from `maxUnavailable` to `minAvailable` ([cozystack/etcd-operator#351](https://github.com/cozystack/etcd-operator/pull/351)) Changes in this repo: - `packages/system/etcd-operator/Chart.yaml` — `appVersion: v0.5.3 → v0.5.4`. The manager image tag defaults to `.Chart.AppVersion` (`values.yaml` keeps `tag: ""`), so this reimages the controller to `ghcr.io/cozystack/etcd-operator:v0.5.4`. - `packages/system/etcd-operator/Makefile`, `packages/system/etcd-operator-crds/Makefile` — `ETCD_OPERATOR_REF: v0.5.3 → v0.5.4`. - `packages/system/etcd-operator-crds/templates/etcdmembers.yaml` — re-vendored at v0.5.4 via `make update`. Description-only change to the `/scale` `replicas`/`selector` field docs, tracking the PDB `minAvailable` fix. `etcdclusters` and `etcdsnapshots` are byte-identical to v0.5.3. - `templates/rbac.yaml` intentionally left as-is: `manager-role-rules.yaml` is byte-identical between v0.5.3 and v0.5.4. **Upgrade path (PDB switch, cozystack/etcd-operator#351).** This is the one change that rewrites live objects: the operator moves each EtcdCluster's PodDisruptionBudget from `maxUnavailable` to `minAvailable`. Setting both fields is invalid, but upstream `reconcilePDB` handles the migration — it treats a surviving pre-migration `maxUnavailable` as divergence and explicitly clears it (`MaxUnavailable = nil`) before writing `MinAvailable`, so existing clusters are reconciled cleanly on upgrade rather than wedging their PDB. Verified locally: `helm lint` and `helm template` pass for both packages; rendered manager image resolves to `ghcr.io/cozystack/etcd-operator:v0.5.4`. These `packages/system/*` packages have no `generate:` target and no `values.schema.json`, so there is nothing for `make generate` to regenerate. ### Screenshots Not applicable — no UI changes. ### Downstream repositories Walked the trigger map in `docs/agents/contributing.md` file-by-file against the diff: - The diff touches only `packages/system/etcd-operator*` — no `packages/apps/**` or `packages/extra/**` add/rename/remove, no `packages/core/platform` or `installer` values, no Talos bump, no asset-name or dev-tooling change → **website / ansible-cozystack** not reached. - The CRD edit is description-only, inside etcd-operator's own `etcd-operator.cozystack.io` CRDs — not the provider's hand-typed `Package`/`Plan`/`RestoreJob` types, and no new managed app → **terraform-provider-cozystack** not reached. - No `hack/` change, no `packages/system/<name>-rd/cozyrds/**`, no `ApplicationDefinition` CRD / `chartRef.kind` enum change, no `cozyhr`/`package.mk` contract change, no telemetry-metric or proxy-label rename → **ccp / talm / cozyhr / cozy-proxy / telemetry-server / examples / external-apps-example** not reached. - [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: ### Release note ```release-note chore(etcd-operator): bump etcd-operator to v0.5.4 (controller bug-fixes: PDB switched to minAvailable, crash-loop self-heal extended to memory members, --initial-cluster-state derived from phase, seed no longer exempt from self-heal) ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Updates** - Updated the etcd operator to version v0.5.4. - Clarified scale-related resource descriptions, including replica counts, selectors, and disruption budget behavior. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2f8c953cf5 |
fix(kubernetes): render the talos-reconcile Job for the default md0 group (#3535)
## What this PR does Fixes #3504. The chart has two loops over worker node groups and they read different sources. `templates/cluster.yaml` iterates the effective set through the `kubernetes.nodeGroups` helper, whose else-branch supplies the built-in `md0` group when the user declares none — that is how #2936 made `md0` removable without a Helm values merge re-adding it. `templates/talos/talos-reconcile-job.yaml` iterated the raw `.Values.nodeGroups` map instead, which is empty in exactly that case. The consequence is a dangling reference. The chart cannot render the `TalosConfigTemplate` itself — it needs the apiserver Service ClusterIP, the Talos CA and the Kubernetes CA, none of which exist while Helm is executing the template — so `cluster.yaml` deliberately stopped rendering it and the Job became its only producer, while the `MachineDeployment` still names it in `spec.template.spec.bootstrap.configRef`. On a cluster with the default `nodeGroups`, `MachineDeployment/<release>-md0` renders and zero Jobs render, so `TalosConfigTemplate/<release>-md0` is never created and CAPI blocks every Machine that ever joins the group. The same Job also patches `KamajiControlPlane.spec.network.certSANs` with the live Service ClusterIP, so that is skipped too. Nothing fails at install time, because the built-in group carries `minReplicas: 0`. The failure waits for the first scale-up, which is the documented path rather than a corner: `values.yaml` tells operators that enabling the ingress-nginx addon on a cluster with default `nodeGroups` means waiting for the cluster-autoscaler to bring `md0` up in response to the controller Pods becoming Pending, and the autoscaler is deployed unconditionally whenever the tenant has an etcd DataStore. The fix is to range over the helper so the Job set tracks the MachineDeployment set exactly. A cluster that declares its own groups renders byte-identically — which is why the pinned content-hash fixtures in `tests/talos_templates_test.yaml` are untouched — and `md0` stays removable, because the fix defers to the helper rather than merging `md0` in unconditionally. On upgrade it is additive: the Job appears where there was none, applies the `TalosConfigTemplate` the MachineDeployment already expects, and the content-hash name suffix means Helm creates a fresh Job rather than attempting to patch an immutable one. ### How this survived Every helm-unittest fixture and every e2e suite declares `md0` explicitly. `tests/nodegroups_default_test.yaml` does render the empty-`nodeGroups` case, but lists only `templates/cluster.yaml`, so it never looked at a Job. The two OIDC chainsaw lanes do install with an empty map, but assert that the HelmRelease exists rather than that it becomes Ready, so a worker that never boots is invisible to them. Offline `helm template` cannot reach this path at all: `cluster.yaml`'s instanceType validator needs a live `lookup` for `u1.medium`. `tests/talos_reconcile_nodegroups_test.yaml` closes the gap and pins both halves of the helper contract — an empty map yields exactly one `md0` Job carrying `GROUP_NAME=md0`, and a two-group map yields exactly two Jobs with no `md0` among them, so a future fix that merges `md0` in unconditionally fails here. Reverting the template change fails the first case on the document count, so it guards the behaviour rather than restating it. ### Screenshots Not a UI change. ### Downstream repositories Walked the trigger map in `docs/agents/contributing.md` against the diff: it is one Helm template loop and one new helm-unittest suite inside `packages/apps/kubernetes`. No package is added, renamed or removed; no `values.yaml`, `values.schema.json`, `ApplicationDefinition`, version enum or default changes; nothing under `hack/`, no namespace, variant, label, annotation or metric renamed. The behaviour now matches what `values.yaml` already documents, so no reference page drifts. - [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: ### Release note ```release-note fix(kubernetes): a tenant Kubernetes cluster created without an explicit `nodeGroups` map now gets a talos-reconcile Job for the built-in `md0` node group. Previously that Job rendered only for explicitly declared groups, so the default `md0` MachineDeployment referenced a TalosConfigTemplate nothing ever created: every worker the cluster-autoscaler added to `md0` stayed stuck waiting for its bootstrap config, and the KamajiControlPlane certSANs patch the same Job performs never ran. Clusters that declare their own node groups were unaffected. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Ensured the built-in `md0` node group receives its Talos reconciliation Job when no node groups are configured. * Prevented duplicate reconciliation Jobs when custom node groups are specified. * Preserved correct group-specific settings and control-plane configuration in generated Jobs. * **Tests** * Added regression coverage for default and custom node-group scenarios. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
83fce03839 |
test(release): scope the freeze pins to their steps and cover the guard
Three assertions extracted a step block, checked it was non-empty, and then ran their grep over the whole workflow. An unrelated step carrying the same condition would keep them green after the protected step lost its own guard, which is precisely the slip they exist to catch. Each now greps its own block, and `id: freeze` moved into the freeze step's test where it belongs. The force-detection greps looked for `+refs/heads/` and `+refs/tags/`, which is not how git spells a forced refspec: the `+` leads the refspec, so `git push origin "+HEAD:refs/heads/$BRANCH"` force-moves the branch and passed both checks. Match a leading `+` on any push refspec instead. Adds a test for the new build-release dispatch guard: the pattern anchored at both ends, the ref_type comparison and not merely its env wiring, a hard failure rather than a skip, and the guard ordered before the checkout. Every pin mutation-tested — forcing either push with a `+` refspec, parking the freeze condition on another step, dropping `id: freeze`, removing or unanchoring the dispatch guard, demoting it to exit 0, and relocating it after the checkout all turn the suite red. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
dfb1a41f28 |
ci(release): refuse a build-release dispatch from a non-line ref
The workflow_dispatch trigger added for the freeze takes any ref, and the "Run workflow" ref selector preselects the default branch — which is exactly where this workflow's own recovery advice, and cut-prerelease's warning, send an operator. IMAGE_TAG is github.ref_name, so a dispatch from main spends a two-hour `make build` republishing cozystack-packages:main and every main image tag while build-main.yaml may be writing the same ones: the 409 tag-collision class #2711 fixed. Nothing is ever mislabeled, since the content really is that ref, so the cost is a wasted runner rather than a wrong artifact. Guard it anyway: it is five lines, and the mis-click is easy. Anchored at both ends so the per-release staging branches (release-1.6.1, release-1.6.0-rc.4) do not qualify — those are built by tags.yaml — and gated on ref_type so a tag named release-1.6 cannot pass the pattern on its own. Runs before the checkout and the OCIR login, so a refused dispatch never touches the credentials. Fails rather than skips: a skipped job reads in the run list like one that produced the artifact. The push trigger was already filtered to release-X.Y; this closes the dispatch path to the same set. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
e8675dd321 |
docs(release): reword the changelog-backstop comments for the freeze model
Three comments still described the changelog reaching main by default, with a release-X.Y-targeted promote PR as a patch-release corner case. After the freeze that is inverted: promote-rc.yaml bases the promote PR on release-X.Y whenever the branch exists, and cutting vX.Y.0-rc.1 creates it, so every release merges its changelog onto the maintenance line and none reach main on the way. The tags.yaml backstop is now the normal route, and its self-skip on `exists` is the exception. These comments are the first thing anyone debugging a missing changelog reads, so pointing at the wrong model of which path is normal costs real time. Reworded in place: the generate-changelog job header, the three-paths comment above check_changelog, its inline at_tag note, finalize's explanation of why update-releasenotes.yaml is not trusted with the release body, and the contract test that pins the porting behaviour. Prose only, no behaviour change. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
22c1df8b94 |
test(etcd-operator): pin deployment unittest to v0.5.4
The manager image tag derives from .Chart.AppVersion, so bumping appVersion to v0.5.4 without updating the two image literals in the deployment unittest broke the suite (helm-unittest gates the PR via `make unit-tests`). Update both asserts (manager container image and the agent OPERATOR_IMAGE env) to ghcr.io/cozystack/etcd-operator:v0.5.4. Suite is green again (18/18). Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrey Kolkov <androndo@gmail.com> |
||
|
|
19f969b2f8 |
chore(etcd-operator): bump etcd-operator to v0.5.4
Bump the cozystack etcd-operator packages from v0.5.3 to v0.5.4. The release is a controller bug-fix set with no API, RBAC or values changes: - fix(controllers): derive --initial-cluster-state from phase, not from the seed (cozystack/etcd-operator#355) - fix(controllers): stop exempting the bootstrap seed from self-heal (cozystack/etcd-operator#354) - fix(controllers): extend crash-loop self-heal to memory members (cozystack/etcd-operator#352) - fix(controllers): switch the PDB from maxUnavailable to minAvailable (cozystack/etcd-operator#351) Adaptations: - etcd-operator/Chart.yaml: appVersion v0.5.3 -> v0.5.4 (the manager image tag defaults to .Chart.AppVersion, so this reimages the controller). - etcd-operator/Makefile, etcd-operator-crds/Makefile: ETCD_OPERATOR_REF v0.5.3 -> v0.5.4. - etcd-operator-crds/templates/etcdmembers.yaml: re-vendored at v0.5.4 via `make update`; description-only change to the /scale replicas/selector fields tracking the PDB minAvailable fix. etcdclusters/etcdsnapshots unchanged. - templates/rbac.yaml left as-is: manager-role-rules.yaml is byte-identical between v0.5.3 and v0.5.4. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrey Kolkov <androndo@gmail.com> |
||
|
|
4e9c5ce8ca |
fix(kubernetes): render the talos-reconcile Job for the default md0 group
The Job in templates/talos/talos-reconcile-job.yaml is the only producer of the TalosConfigTemplate that each worker MachineDeployment names in spec.template.spec.bootstrap.configRef; cluster.yaml renders the reference but deliberately not the object. Its loop read .Values.nodeGroups directly, while the MachineDeployment loop reads the effective set through the kubernetes.nodeGroups helper. For a cluster that supplies no nodeGroups the two disagree: the helper's else-branch emits the built-in md0 group, so the md0 MachineDeployment renders, but the raw map is empty and no Job renders at all. Every Machine the cluster-autoscaler adds to md0 then blocks indefinitely on a TalosConfigTemplate that nothing will ever create, and the KamajiControlPlane spec.network.certSANs patch the same Job performs is skipped too. Range over the helper so the Job set tracks the MachineDeployment set exactly. No change for a cluster that declares its own groups, and md0 stays removable: the helper's if-branch keeps a user-supplied map authoritative. The gap survived because every helm-unittest fixture and e2e suite declares md0 explicitly. tests/nodegroups_default_test.yaml does render the empty-nodeGroups case but lists only templates/cluster.yaml, so it never looked at the Job. The new suite pins both halves of the helper contract and fails without this fix. Fixes #3504 Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
e532844007 |
test(release): pin the freeze and backport-target contracts
Neither cut-prerelease.yaml nor backport.yaml had any test coverage, and
neither can be exercised by a PR lane: the first runs only on
workflow_dispatch and its whole purpose is a one-way write-once side
effect, the second only on a merged main-targeted PR. Every invariant
here is one that would otherwise first report a slip at a real release.
Pinned, following promote-gate-contract.bats so a guard demoted to a
comment cannot satisfy a pin:
- the freeze is gated to kind == 'rc' && patch == '0'. Widening either
half re-opens a frozen line with no error surfacing.
- neither the branch create nor the tag push is forced, in any spelling
including a `+refs/` refspec. A force-push on the branch would drag
in everything merged since the freeze.
- an existing release-X.Y is left untouched rather than reused.
- the refuse gate is gated on a main dispatch and runs BEFORE the tag
push, so a mistaken dispatch cannot burn a write-once tag name; the
freeze runs after it, at the commit that was actually tagged.
- backport targets come from enumerated branches, with no
getLatestRelease and no min-1 arithmetic, and `previous` is the
second-newest existing line.
- the comparator sorts numerically descending, which is the only reason
release-1.10 outranks release-1.9. A slip to the default
lexicographic sort aims every backport at a stale line silently.
- freezing a line dispatches its first build-release run.
backport.yaml's logic is a github-script block whose comments name
getLatestRelease and min-1, so the assertions over it strip `//`
comments; the YAML `#` filter alone would let a comment satisfy a pin.
The Makefile discovers hack/*.bats, so this runs under `make unit-tests`
with no wiring.
Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
|
||
|
|
5ed6b2204a |
ci(release): build the packages artifact when a freeze creates a line
build-release.yaml publishes `cozystack-packages:<line>` on push to a release line, and pull-requests.yaml's overlay reads it so a release-line PR tests its own line's binaries instead of main's (#3471, #3437). It cannot fire for the push that creates the line. The freeze points release-X.Y at a commit that is already on main, so the push carries no new commits, and GitHub does not run a workflow whose paths/paths-ignore filter finds no changed files ("If there are no files changed, the workflow will not run"). The line would therefore have no artifact until its first cherry-pick merged, and in that window the overlay finds nothing to pull and leaves every package on its committed ref — at freeze time the previous release's, which is exactly the cross-generation mix #3437 fixed. The old flow had no such window: it branched at the promote merge commit, which carried real commits and its own release's refs. Add workflow_dispatch to build-release.yaml and have the freeze step dispatch it for the branch it just created, so the artifact exists from the moment the line does. The dispatch is non-fatal: without it the overlay no-ops and early cherry-pick PRs test their committed refs, which is where they were before #3471. The tag is pushed and the line is frozen by that point, so failing there would misreport both. The trigger also gives a line build a re-run button, which previously needed an empty commit pushed to the line. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
24e9c5396c |
docs(release): resync the release doc with the freeze model
The freeze changed three things the prose still described the old way. The backport table claimed `backport-previous` resolves to `release-X.(Y-1)` and that resolution runs through `getLatestRelease`. Neither is true any more: the job enumerates the real `release-X.Y` branches, sorts them numerically descending, and takes the newest and second-newest existing lines. The `Y-1` derivation is the min-1 bug this branch dropped. Line 155 already carried the correct description, so the file contradicted itself. The freeze window's effect on backport targets lived only in a code comment. During it `backport` aims at the line being stabilised and `backport-previous` at the last published stable, so the line one step further back has no label for the duration. Document the trade-off where the labels are described. The changelog backstop and Phase 6 both framed a promote PR targeting `release-X.Y` as "a patch release". After the freeze every promote PR targets the release line, minor and patch alike, which makes the backstop the only path a `.0` changelog takes to `main`. Also note that re-cutting a line after an unusable rc.1 means deleting `release-X.Y` by hand — the refuse step blocks every other route, by design. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
66ed32c6f9 |
ci(release): print the recovery command if the freeze push fails
Address review feedback from lexfrei on .github/workflows/cut-prerelease.yaml:293: the tag push and this branch push are independent, so a transient failure here leaves the line tagged but not frozen, and the write-once tag guard refuses a same-tag re-dispatch — recovery is manual. Fail with the exact push command rather than leaving the operator to reconstruct it. Deliberately not an atomic two-ref push: the tag push relies on being anchored to the branch tip for GitHub to populate the push event's base_ref, which tags.yaml requires, and whether a multi-ref atomic push preserves that is only observable on a live release cut. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
a59ad88eb5 |
ci(release): distinguish absent from broken in the freeze branch probe
Address review feedback from lexfrei on .github/workflows/cut-prerelease.yaml:286: the release-X.Y existence probe piped ls-remote straight into cut, so a transport or auth failure produced empty output and read as "branch not found", steering into the create path. The write-once tag guard, the stale-tip guard, and the refuse step above all make this distinction; match them here. Behaviour is unchanged on the happy path — pipefail already failed the step on a real error, and the non-forced push below fails closed on a conflict. This makes the intent explicit rather than incidental. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
b55e822eaf |
docs(release): align the patch-release diagrams with the freeze model
Address review feedback from coderabbitai on docs/release.md:150: the patch-release gitGraphs still branched release-1.2 off main after the v1.2.0 commit, depicting the branch as created at the stable release. Under the rc freeze the line forks at vX.Y.0-rc.1 and the release commit never lands on main, as the surrounding prose already states. Fork release-1.2 at the rc.1 commit and place 'Release v1.2.0' on the release line in all three patch-section diagrams. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
3f15229795 |
docs(release): fix the Backports link fragment
Address review feedback from lexfrei and coderabbitai on docs/release.md:39: the anchor pointed at #backporting, but the heading is '## Backports' (slug #backports), so the link resolved nowhere and tripped markdownlint MD051. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
e5428caaa6 |
docs(release): document the rc freeze
The Release Candidates section said the opposite of current behaviour — "new features and changes can still be added before the regular release" — so it is rewritten around the freeze, along with the Regular Release step list, both gitGraph diagrams, and the workflow reference sections. The promote PR now targets release-X.Y rather than main, so the diagrams show main forking away at the freeze and never receiving the release commit. Patch Releases collapses to "same as above, the branch already exists", since after the freeze both flows are identical. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
6ff5b98d56 |
ci(backport): target the newest existing release line
Determine the backport targets by enumerating real release-X.Y branches instead of deriving them from getLatestRelease. getLatestRelease returns the newest published stable. Now that cutting an rc creates release-X.Y before vX.Y.0 exists, that name lagged by a full line for the whole freeze window: a `backport` on a fix for the release being stabilised would have landed on the previous line and missed the release it was written for. The freeze window is when backports matter most, since the frozen branch is the only way in. Also drops the contiguous-minor assumption — `previous` was computed as min-1, naming a branch that does not exist whenever a minor is skipped. Sorting is numeric, so release-1.10 correctly outranks release-1.9. Outside a freeze window the result is unchanged: with release-1.0..1.5 present it still resolves to release-1.5 / release-1.4. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
53a7fc4dcd |
feat(release): cutting an rc freezes the line into release-X.Y
Cutting the first vX.Y.0-rc.N now creates release-X.Y at the tagged commit, and every later cut for that line must be dispatched from the branch — a dispatch from main is refused. Before this, only the stable promote-PR merge created release-X.Y, so rc.2 and rc.3 were cut from main's tip and silently picked up every feature merged since rc.1. The release therefore shipped content no rc had ever validated. Freezing at the rc closes that: main stays open for the next minor, and fixes reach the release by cherry-pick onto the branch. promote-rc.yaml needs no change — it already prefers release-X.Y as the promote PR base when that branch exists, so the stable release is now cut from the frozen tree. Gated to -rc (alpha/beta are pre-freeze builds off an open main) and to patch 0 (a patch-line rc is cut from a release-X.Y that already exists). The branch is create-only and never force-moved: moving it would re-open the freeze and drag in whatever the new tip holds. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
3f967ec7e0 |
fix(platform): restore the isp-hosted dependency closure (#3391)
## Problem Fixes #3376. The `isp-hosted` preset shipped `bundles.system.enabled: false` while `paas` and `naas` were enabled, so it enabled an app catalog whose dependency closure it simultaneously disabled. Every emitted Package sat in `DependenciesNotReady`, the `*-rd` HelmReleases failed with `no matches for kind "ApplicationDefinition" in version "cozystack.io/v1alpha1"`, and the `cozystack-platform` HelmRelease never went Ready. Rendering the preset at `origin/main` shows the scale: **24 emitted Packages, 24 of them blocked**, by 6 missing dependencies — two more than the issue lists (`cert-manager` and `prometheus-operator-crds` are also absent). `isp-full` renders 75 Packages with a fully satisfied closure, which is a clean control. ## Root cause `templates/bundles/system.yaml` is gated end to end on `bundles.system.enabled`, but it carries two separable things: a variant-selected **data-plane head** (kubeovn/cilium/linstor on `isp-full`, a noop networking Package on `isp-hosted`) and a variant-agnostic **control-plane body** — `cozystack-engine`, the sole source of the `application-definition-crd` component, plus `cert-manager`, `prometheus-operator-crds`, `postgres-operator` and `objectstorage-controller`. "Hosted" means the host already provides CNI, storage and virtualisation, so only the data-plane head should be dropped. Disabling the whole bundle also deleted the control-plane body that every variant needs. Three things show the disable was the mistake rather than the intent: the preset still sets `variant: "isp-hosted"`; `system.yaml` contains an `isp-hosted` branch (noop networking plus default scheduler) that could never render; and `iaas.yaml` already refuses to render on this variant, encoding the same "system bundle minus iaas" contract. The preset has never worked — it was born this way in `2d022e38e` (January 2026), the refactor that replaced `bundles/paas-hosted.yaml`, whose contents confirm hosted was always meant to ship the engine, `cert-manager` and `prometheus-operator-crds`. ## Changes 1. **`values-isp-hosted.yaml`** — enable the system bundle. Hosted now emits 53 Packages with every `dependsOn` satisfied, installing 59 components against the 60 of the pre-refactor `paas-hosted` bundle, with no LINSTOR, KubeVirt, CAPI or Kamaji leakage. 2. **Move `cozystack.bucket-application`** from the iaas bundle into the system bundle. Its own `dependsOn` closure is `networking` + `objectstorage-controller` + `cozystack-engine`, none of them iaas, while `cozystack.backupstrategy-controller` — a *default* package of the system bundle — hard-depends on it. Any system-on/iaas-off configuration therefore wedged `backupstrategy-controller`; both `isp-full` presets masked this by enabling iaas. This is a second, independent bug not reported in the issue. 3. **Guards** — `paas`, `naas` and `iaas` now also require `bundles.system.enabled`. The pre-existing checks looked only at `bundles.system.variant`, which keeps its value when the bundle is disabled, so they passed on exactly this configuration. `iaas` had the identical hole (12 Packages, 6 unsatisfied deps). This turns a silent multi-hour `DependenciesNotReady` hang into a render-time failure that names the remedy. 4. **Two helm-unittest suites** — one pinning the dependency closure the catalog needs, one pinning the guards. ## Verification - All four operator-registered variants render dependency-closed: `default` 0 Packages, `isp-hosted` 53, `isp-full` 75, `isp-full-generic` 75. The two `isp-full` variants are byte-identical before and after, so the bucket move is a no-op for them. - Hosted is a strict subset of full with zero data-plane leakage, and its exclusions match the pre-refactor hosted bundle. - 23 suites / 97 tests pass in `packages/core/platform`; repo-wide `hack/helm-unit-tests.sh` is green. - Every change was **mutation-tested** — reverting each one in turn makes the suite fail, so the tests are not vacuous. - The workaround documented in #3376 (`paas`/`naas` disabled) still renders cleanly; the new guards do not fire on it. - Hosted runtime spot-checks: `cozystack-api` is a Deployment with only a *preferred* control-plane affinity plus blanket tolerations, and `cozystack-scheduler` uses its `default` variant (plain Deployment, no LINSTOR extender) — both schedule fine on a cluster with no control-plane nodes. ## What this does not fix This restores the dependency closure. It is **not** by itself sufficient for a fully converged hosted install. Review surfaced further hosted-unaware defaults that the dead bundle had been masking, filed separately: - #3387 — `apps/tenant` renders 14 `cilium.io/v2` policies with no `.Capabilities` guard, so `tenant-root` fails on a non-Cilium cluster. This is the blocker for actual hosted convergence, and it needs a deliberate decision rather than a reflexive capability guard, because those policies implement tenant network isolation. - #3388 — `extra/monitoring` defaults `logsStorages` to the LINSTOR-only `replicated` StorageClass. - #3389 — `bundles.disabledPackages` can still break the closure with no render-time error; the guards here cover the bundle flags only. - #3390 — nothing in CI exercises `isp-hosted`, which is why all of the above accumulated undetected. ## Upgrade note Existing `*-application` Package CRs carry `helm.sh/resource-policy: keep`. An operator who applied the #3376 workaround but did not also delete the retained Package CRs (as that issue instructs) will find them install once this change makes their dependencies Ready, since the reconciler re-enqueues dependents on readiness. Deleting the unwanted Packages before upgrading avoids that. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added fail-fast validation that requires the **System bundle** when enabling **IaaS**, **NaaS**, or **PaaS** to prevent incomplete catalogs. * Updated bundle composition so the **bucket application** is provided by the **System bundle**. * Enabled the **System bundle** by default for the `isp-hosted` variant. * **Bug Fixes** * Improved error messaging to clearly indicate the required bundle/variant configuration. * **Tests** * Added Helm unittest coverage for rendering-gate failures, dependency/package expectations, and hosted data-plane exclusions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
f1f383626e |
fix(ci): overlay images from the PR base branch, and publish per-line artifacts (#3471)
## What this PR does
The PR finalize job overlays image refs for every package a PR did not
rebuild, so e2e and the installer do not test last-release images for
everything outside the PR's build matrix. It could only ever read
`cozystack-packages:main`, which meant a **release-line PR was handed
main's binaries to run against its own line's charts**.
cozystack/cozystack#3437 is the demonstration: a one-line change on
`release-1.6` deactivating an app failed install deterministically,
twice, with
```
helmrelease/backupstrategy-controller: Helm install failed …
error validating data: SchemaError(github.com/cozystack/cozystack/pkg/apis/core/v1alpha1.Option.spec):
unknown model in reference: "github.com~1cozystack~1cozystack~1pkg~1apis~1core~1v1alpha1.OptionSpec"
```
main's `cozystack-controller` served an aggregated OpenAPI that
`release-1.6`'s charts could not validate against. Nothing in that PR
was broken; the lane was. Both branches carry `option_types.go` and key
`OptionSpec` identically in the committed generated OpenAPI, so this is
a generation mismatch at runtime, not a codegen drift.
This PR fixes it by giving every base branch its own artifact to overlay
from, rather than by turning the overlay off.
### The change
1. **`pull-requests.yaml`** reads `cozystack-packages:${BASE_REF}`
(`github.base_ref`) instead of a hardcoded `:main`.
2. **`build-release.yaml`** (new) publishes that artifact for maintained
`release-<major>.<minor>` branches exactly as `build-main.yaml` does for
main: every image tagged with the branch, and the whole packages tree
pushed with each reference digest-pinned to what the run just built.
An earlier revision of this branch simply skipped the overlay for
non-main bases. That fixed the wrong-images problem but left
release-line PRs testing their line's *last release*: for any package
the PR did not rebuild, the committed ref is the released digest, so a
component changed by an earlier backport was still exercised as its
pre-backport binary until the next rc. Per-line artifacts remove that
gap too, which is why the guard was replaced rather than kept.
### Three deliberate choices
**The trigger matches line branches only** (`release-[0-9]+.[0-9]+`).
The per-release and rc staging branches `promote-rc.yaml` and
`tags.yaml` create — `release-1.6.1`, `release-1.6.0-rc.4` — must not
trigger a full rebuild; their images come from the tag build and
rebuilding them is waste.
**`WRITE_CACHE` stays `0`.** `CACHE_REGISTRY/<img>:buildcache` is a
single ref per image and `build-main.yaml` is deliberately its only,
serialized writer so concurrent builds cannot race on the cache manifest
— the 409 class #2711 fixed for image tags. A line build can overlap a
main build, so writing here would reintroduce that race. Line builds
read the cache.
**A missing artifact still degrades to committed refs, but says so.** On
a release line it emits a `::warning::` naming the branch. Silent
degradation is indistinguishable from a working overlay, which is how a
mis-specified branch filter could hide for a whole release cycle.
### Cost
One `make build` per push to a maintained line — in practice per merged
backport. That is the price of release-line PRs testing their line's tip
instead of its last release.
### Verification
`hack/overlay-main-images_test.bats` pins the artifact tag to the base
branch, rejects a hardcoded `:main` in either overlay step, and pins
`build-release.yaml`'s branch filter, image tag and `WRITE_CACHE: '0'`.
Mutation-checked: restoring `:main`, setting `WRITE_CACHE: '1'`, and
broadening the filter to `release-*` each fail a test. 13/13 green;
`actionlint` and `zizmor` clean.
Worth an explicit ack in review: the branch-filter pattern is the one
thing no local test can prove, since only GitHub evaluates it. If it
does not match, `build-release` never runs and the new `::warning::` is
what surfaces it on the next release-line PR.
### Backport
`release-1.6` needs this too — for `pull_request` events GitHub builds
the workflow from the merge ref, so a release-line PR only stops
receiving main's images once the change is on its base branch.
cozystack/cozystack#3472 carried the interim guard and is closed in
favour of backporting this instead.
### Release note
```release-note
NONE
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added a “Build release line” workflow that builds and publishes images
and the packages artifact for maintained `release-<major>.<minor>`
branches.
* **Bug Fixes**
* Updated PR workflow finalization to use base-branch–specific package
overlays, avoiding incorrect main-branch image references when targeting
release branches.
* Improved fallback behavior when the base-branch packages artifact is
unavailable.
* **Tests**
* Added workflow wiring tests to verify base-branch artifact usage and
that each maintained release line publishes its own packages artifact.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
04b7426706 |
chore(codeowners): don't gate per-app generated files on architect review (#3507)
## What this PR does `.github/CODEOWNERS` scopes `/api/` to the architects (`@kvaps @lllamnyp`), meant for hand-authored API surface: the aggregated apiserver, the registry, the core API types. But `api/apps/v1alpha1/<name>/types.go` and `api/apps/v1alpha1/<name>/zz_generated.deepcopy.go` are entirely produced by `make generate` from each app's own `values.yaml`/`values.schema.json` — 23 of the 32 packages under `packages/apps/` and `packages/extra/` wire this into their `generate` target. Since CODEOWNERS applies the last matching pattern and nothing more specific overrode `/api/` for these paths, any PR that edits an app's `values.yaml` documentation and reruns `make generate` (mandatory per the contributing guide) ends up requiring an architect review, no matter which area actually changed — even though the app's own reviewers already cover the source file that produced the diff. `packages/system/<name>-rd/cozyrds/<name>.yaml` has the same problem in a milder form: it isn't scoped by CODEOWNERS at all, so it falls through to the generic `/packages/` owners instead of the app's own team, again just because it's a generated mirror. This adds a CODEOWNERS entry with no owner for these three generated paths, so touching them alone does not pull in any codeowner requirement beyond what the source `values.yaml` already needs. This is intentional and safe: both are verified by the existing pre-commit CI (`run-make-generate` / `run-make-generate-root`), which reruns the generator and fails the check if the committed output does not match — a stronger, mechanical guarantee against drift or hand-tampering than a human skim of a generated diff would be. While in there: `api/.gitattributes` had a stale `linguist-generated` pattern (`zz_generated_deepcopy.go`) that has never matched any real file in this repo — the actual generated files are named `zz_generated.deepcopy.go` (dot, not underscore, matching the standard controller-gen output). Fixed the pattern and added the same treatment for the per-app `types.go` files and for `packages/system/*/cozyrds/*.yaml`, so all of them collapse in the PR diff view instead of just some. ### Screenshots Not applicable — no UI change. ### Downstream repositories - [x] No downstream repository is affected by this change This only touches `.github/CODEOWNERS` and `.gitattributes` files; it changes neither the `values.schema.json` contract, generated CRDs, version enums, nor anything else in the trigger map in `docs/agents/contributing.md`. ### Release note ```release-note chore(codeowners): per-app generated API type mirrors and cozyrds manifests no longer require architect review on their own — only the source values.yaml they're generated from does, with the existing make-generate CI check guarding against drift. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Chores** * Updated repository metadata to better identify generated API and application artifacts. * Added ownership exceptions for generated files and application-specific configuration directories. * Marked generated CozyRDS configuration files for improved repository classification. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e5d4940338 |
chore(codeowners): don't gate per-app generated files on architect review
api/apps/v1alpha1/*/types.go and packages/system/*/cozyrds/*.yaml are entirely produced by `make generate` from each app's own values.yaml, but the /api/ codeowner rule pulled every app's regenerated types.go into an architect-only review, regardless of which area actually changed. Correctness there is already enforced by the pre-commit make-generate CI hooks, not by human review, so list no owner for these generated paths and let that check carry the weight instead. Also fixes a stale api/.gitattributes pattern that never matched any real file (zz_generated_deepcopy.go vs the actual zz_generated.deepcopy.go), and adds a matching linguist-generated attribute for the cozyrds ApplicationDefinition manifests, so both collapse in the PR diff view like the Go files already do. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Timofei Larkin <lllamnyp@gmail.com> |
||
|
|
007d0b1a22 |
chore(ci): re-trigger CI after a label event produced a no-op run
The latest run on this head came from a `labeled` event carrying a label other than full-e2e. pull-requests.yaml discards those by design — `plan` skips, and checks, build, build-talos, finalize and e2e all skip behind it — so the run reported nothing. Two side effects made that worse than a wasted run: the required "E2E Tests" context was left SKIPPED, which branch protection counts as satisfied, and cancel-in-progress killed the in-flight api-review-gate run that was carrying the real signal. Empty commit to get a genuine run against this head. No content change. Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
10554f9dce |
[cozystack-scheduler] Publish SchedulingClass demo (#2252)
## What this PR does Publish the scripts used for running the Cozystack scheduler demo at the community meetup on 19.03.2026. ### Release note ```release-note [cozystack-scheduler] Add demo scripts to the cozystack-scheduler system packages. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a complete set of interactive Bash demo scripts covering scheduling classes: creating scheduling classes and tenants, colocating pods on a single node, spreading replicas evenly, enforcing one-pod-per-node anti-affinity, and pinning workloads to a specific node. * Included guided scaling steps plus cleanup and teardown scripts to remove demo resources. * **Documentation** * Introduced a shared demo helper with colored, step-by-step terminal logging and Kubernetes polling to wait for pods and Redis readiness, improving clarity and consistency across demos. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e16df56019 |
chore(codeowners): scope CODEOWNERS to per-area reviewers (#3228)
## What this PR does Replaces the single catch-all owner line in `.github/CODEOWNERS` with area-scoped reviewer ownership, so each part of the tree routes to the people who actually own it (per the Contributor Ladder), instead of requiring the whole roster on every change. Highlights: - Architects (`@kvaps @lllamnyp`) are the default owner and own the API surface (`/api/`) and the VPC app. - CI / automation → `@myasnikovdaniil @sircthulhu`; backups → `@androndo @lllamnyp`; virtualization (kubevirt, vm-instance/disk) → `@scooby87 @lllamnyp @kvaps @myasnikovdaniil`. - `cozystack-api` / controller / lineage webhook → `@IvanHunters @kvaps @lllamnyp`. - General packages / apps / CLI ownership → `@lexfrei @IvanHunters @myasnikovdaniil` (+ `@scooby87` for apps), with `kubernetes` and `extra` scoped separately. - Flux → `@kingdonb`; GPU (hami, gpu-operator, GPU dashboards) → `@lexfrei`; metrics-server and seaweedfs → `@nbykov0`. - Governance / licensing files → `@tym83 @kvaps`. Ordering follows "last match wins" (broad → specific). The API review gate block is kept last so it cannot be overridden. This is review-routing only — no runtime/functional change — and only binds once "Require review from Code Owners" is enabled in branch protection. This file is what the CNCF Incubation review reads as "code ownership", so it is paired with #3462, which documents the same people in `MAINTAINERS.md` and introduces the Reviewers table the ladder already defined. Merging one without the other leaves the two describing different projects, which is the gap both PRs exist to close. Three of the people named here — `@kingdonb`, `@matthieu-robin`, `@mattia-eleuteri` — hold only read access today, and a CODEOWNERS entry for someone without write is silently ignored by GitHub, so the org-side permission changes have to land alongside. ### Screenshots N/A — governance/config change, no user-facing or UI impact. ### 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: Walked the trigger map against the diff: no row matches. The change touches only `.github/CODEOWNERS` — no package, no `values.schema.json`, no `ApplicationDefinition`, no platform variant, no release asset, no node prerequisite. Every path named here was checked against current `main`; all 65 exist. ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Updated CODEOWNERS from a single catch-all to an ordered, path-scoped reviewer mapping. * Clarified “last matching pattern wins” behavior and ensured the API review gate rules remain last to avoid overrides. * Expanded explicit ownership coverage across dashboards/examples, packages and Go components, apps, platform/infrastructure modules, CI/automation, and governance/licensing documentation (including SECURITY). <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
337bb4933e |
[cozystack-scheduler] Publish SchedulingClass demo
## What this PR does Publish the scripts used for running the Cozystack scheduler demo at the community meetup on 19.03.2026. ### Release note ```release-note [cozystack-scheduler] Add demo scripts to the cozystack-scheduler system packages. ``` Signed-off-by: Timofei Larkin <lllamnyp@gmail.com> |
||
|
|
0f0204a6c2 |
fix(e2e): disable guest fsync on ephemeral CI VM disks (#3455)
## What this PR does The e2e QEMU guests are launched in `hack/e2e-prepare-cluster.bats` with three `-drive … if=virtio,format=raw` lines that carry no `cache=` option, so QEMU falls back to its `cache=writeback` default, which honors every guest fsync against the host-backed raw disk files. The management-cluster Talos etcd — which holds every operator's leader-election lease — fsyncs on each Raft commit. During the VM-heavy suites, containerd is simultaneously unpacking dozens of images and CDI is importing multi-GB VM disks onto the same host-backed raw files. The resulting fsync storm serializes etcd's writes into multi-second stalls, so the management apiserver returns `context deadline exceeded` on lease PUTs, and several operators (capk, etcd-operator, fdb-operator, cilium-operator, kamaji) lose leadership at the same moment. Whichever chainsaw suite is mid-flight then fails — a different one each run (vmcluster, kubernetes-latest, vmdisk), which is the fingerprint of shared-resource contention rather than a bug in any single suite. This adds `cache=unsafe` to each guest drive. That makes guest flushes no-ops against the host page cache, which removes the fsync-gated etcd stalls at the root of the flakiness. It is safe here precisely because these CI VMs are ephemeral and destroyed at the end of every run — a crash before writeback loses only throwaway state — and it must never be used for real data. The change is minimal and uniform across all three guest drives; no non-guest drive is touched (there are none in this file). Runner sizing alone (#3251) did not resolve this, because more CPU and memory do not change the I/O path: the guest fsyncs still propagate through `cache=writeback` to the host, and etcd still stalls behind the same fsync storm. This addresses the I/O path directly. `git log -S 'cache='` on this file is empty, so a cache mode has never previously been set here. ### Screenshots Not applicable — no UI changes. ### Downstream repositories I walked the trigger map in `docs/agents/contributing.md` against the actual diff. The only entries that reference `hack/e2e-prepare-cluster.bats` (ansible-cozystack and ccp) are scoped to node prerequisites — kernel modules, containerd settings, the LVM `global_filter`, and the cluster domain. This change touches none of those: it adds a QEMU host-side hypervisor flag (`cache=unsafe`) to the CI VM `-drive` options, which is invisible to the guest OS and to any real node. No downstream repository is affected. - [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: ### Release note ```release-note fix(e2e): boot e2e QEMU guests with cache=unsafe so ephemeral CI VM fsyncs no longer stall the management-cluster etcd, removing the cross-operator leader-election flakiness that failed a different chainsaw suite each run ``` --- This PR was prepared with the assistance of an AI agent (Claude). A human maintainer reviewed the diff and the reasoning before submission and remains responsible for the change. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Tests** * Updated end-to-end virtual machine startup testing to use optimized QEMU disk caching settings for improved reliability and performance. * Improved end-to-end Kubernetes cluster readiness checks under load by extending the deadline for reaching “at least 2 nodes Ready,” and aligned related messaging and failure diagnostics accordingly. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
3dc0f56477 |
feat(kube-ovn): build the chart and image in-tree, retiring the wrapper repo (#3460)
## What this PR does Brings the `kubeovn-chart` wrapper into the tree, so `cozystack/kubeovn-chart` can be archived. Until now `packages/system/kubeovn` pulled a chart tarball from the latest `cozystack/kubeovn-chart` tag at `make update` time, and that repository also built and pushed the `kubeovn` image. The wrapper existed only to cache the upstream chart; with the current caching approach that reason is gone, and the split cost a second repository, a second release step, and a package whose provenance a reader cannot follow without leaving the tree. The package is now shaped like `packages/system/cilium`: - `update` pulls the upstream `kubeovn/kube-ovn` chart directly and applies `patches/mtu.diff`, then syncs the version into the Dockerfile. The MTU patch already carried monorepo-relative paths, so it applies unchanged. - `image` builds `images/kubeovn` (carrying the existing `fix-keepvmip-portgroup` patch) and pins the digest into `values.yaml`, using the shared `image-tags` / `cache-args` helpers. It also carries `cozystack/kubeovn-chart#5`, which never got a tag: `OVN_IPSEC_KEY_DIR` is pinned under `/var/lib`. The kube-ovn default sits in `/etc/origin`, which a Talos node cannot create, so enabling IPsec left the node without ESP security associations. ### The nightly host rewrite had to be fixed first Moving the image build here activates a gap recorded in `docs/agents/image-refs.md`. The nightly host rewrite is a literal `<src-registry>/` substring replace, and kubeovn keeps its host in `global.registry.address` with the bare repository in a sibling key — no trailing slash, no match. While the image came from a separate repository the baked reference carried the public host and the ownership filter skipped it; once CI builds the image here it stamps the build-registry host into that key, and the result is an image mirrored to the public registry while the published tree keeps pointing at the private build registry. The second commit adds an end-of-line-anchored expression that fires only when the source registry is the complete scalar value, so a contiguous reference — which continues past the host — is still handled by the first expression and the two can never both fire on one reference. `keycloak-operator` splits at a different boundary and stays unfixed; that is documented, and dormant while no CI path rebuilds it. Verified: `hack/nightly-mirror_test.bats` passes with the new case and the case fails without the fix; `promote-retag` and `promote-rewrite-tags` suites unaffected; `helm template` and `helm unittest` on the package pass. The pre-existing `helm lint` complaint about a missing `kube-ovn` dependency reproduces on `main` and is left alone. ### Follow-ups this PR does not do - `cozystack/kubeovn-chart` should be archived once this merges, with a pointer here. Its open PR #5 is carried by this change and needs no separate landing. - `cozystack/website` links the Kube-OVN license at `cozystack/kubeovn-chart` in `operations/configuration/licenses.md` and `guides/platform-stack/_index.md` (all versions, including `next`). Archived repositories stay readable so nothing breaks, but the link should move upstream or in-tree. **No follow-up has been opened yet** — flagging rather than ticking the box. ### Screenshots N/A — build and packaging change, no user-facing or UI impact. ### 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: Walked the trigger map against the diff. The website row matches — not through the app-list or platform-component triggers, but because two of its pages link the repository being archived. Left unticked because no follow-up exists there yet; a human should decide whether the license link moves to `kubeovn/kube-ovn` or to this package. No other row matches: the change touches no `packages/apps/` or `packages/extra/` package, no `values.schema.json`, no `ApplicationDefinition`, no platform variant, and no node prerequisite. ### Release note ```release-note feat(kube-ovn): the Kube-OVN chart and image are now built in this repository instead of cozystack/kubeovn-chart. OVN_IPSEC_KEY_DIR now defaults to /var/lib/ovs_ipsec_keys, so enabling IPsec on Talos nodes no longer leaves them without ESP security associations. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Updated Kube-OVN image build to use upstream chart metadata and keep registry/version alignment during `update`. - Added conditional MTU support for the OVN CNI DS via chart values. - Introduced `OVN_IPSEC_KEY_DIR` to standardize the OVN IPsec keys directory. - **Bug Fixes** - Preserved VM networking port-group assignments during live migration when an alive virt-launcher sibling pod exists. - Improved nightly mirror host rewriting for split and standalone registry host formats. - **Tests** - Added coverage for the end-of-line “whole scalar value” host rewrite case. - **Documentation** - Refreshed “Known gaps” guidance for nightly mirror host rewriting behavior and limitations. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
2330d6f3ca |
fix(ci): overlay images from the PR base branch, and publish per-line artifacts
Supersedes the interim guard in this branch`s first commit, which skipped the overlay entirely for release-line PRs. Skipping fixed the wrong images but left those PRs testing their line`s last release: for any package the PR did not rebuild, the committed ref is the released digest, so a component changed by an earlier backport was exercised as its pre-backport binary until the next rc. The overlay now reads `cozystack-packages:<base branch>` instead of always `:main`, and build-release.yaml publishes that artifact for every maintained `release-<major>.<minor>` branch the way build-main.yaml does for main: images tagged with the branch, and the whole packages tree pushed with each reference digest-pinned to what the run just built. Each base branch therefore has its own generation to overlay from, which is what the original bug was really about — #3437 failed install because main`s cozystack-controller served an aggregated OpenAPI release-1.6`s charts could not validate against. Three deliberate choices: * The trigger matches line branches only (`release-[0-9]+.[0-9]+`). The per-release and rc staging branches promote-rc.yaml and tags.yaml create (release-1.6.1, release-1.6.0-rc.4) must not trigger a full rebuild — their images come from the tag build, and rebuilding them would be waste. * WRITE_CACHE stays 0. CACHE_REGISTRY/<img>:buildcache is a single ref per image and build-main.yaml is deliberately its only, serialized writer so concurrent builds cannot race on the cache manifest (the 409 class #2711 fixed for image tags). A line build can overlap a main build, so writing here would reintroduce that race. Line builds read the cache. * A missing artifact still degrades to committed refs, but on a release line it now emits a ::warning:: naming the branch. Silent degradation is indistinguishable from a working overlay, which is how a mis-specified branch filter would hide for a whole release cycle. Cost: one `make build` per push to a maintained line, i.e. per merged backport. hack/overlay-main-images_test.bats pins the artifact tag to the base branch, rejects a hardcoded :main in either overlay step, and pins build-release.yaml`s branch filter, image tag and WRITE_CACHE=0. Mutation-checked: restoring :main, setting WRITE_CACHE=1, and broadening the filter to release-* each fail a test. 13/13 green; actionlint and zizmor clean. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com> |
||
|
|
cc44f6c981 |
ci(release): move release validation to rc time — e2e lane, changelog button, promote gate, docs at promote (#3449)
## What this PR does Moves release validation from promote time to rc time, making promotion itself a pure retag operation. This is the follow-up to the v1.6.0 retrospective: the promote flow's checks ran on the promote PR (coupled to promotion, skippable by never promoting), the changelog and website docs were produced only after the release went public, and the finalize tag push silently failed to trigger `tags.yaml` at all (persisted-credential bug, root-caused below). The release lifecycle after this PR: 1. `cut-prerelease.yaml` cuts an rc; `tags.yaml` builds, drafts, pushes the staging branch — and now runs a **mandatory full e2e** for every `-rc.N` tag via the new reusable `e2e-tag.yaml` lane. Alpha/beta (and any published tag) get the same validation as a **manual button** (`workflow_dispatch`). 2. Optionally, a maintainer presses the **`changelog-rc.yaml` button**: the release changelog is generated from the rc tag (reusable `changelog-generate.yaml`) and committed to the rc staging branch, ready for review long before promotion. 3. `promote-rc.yaml` dispatch is **gated on green rc e2e** (evidence: the rc's `tags.yaml` run containing a successful `rc-e2e` job, or a successful manual `e2e-tag` dispatch for the tag; `skip_e2e_gate` input for emergencies, always surfaced in the PR body as ✅/⚠️). Promote stages the release, picks up the rc-time changelog (or generates one), and **opens the website docs PR** on cozystack/website from the staging branch — parked with an explicit DO-NOT-MERGE-until-finalize contract. 4. The promote PR **no longer gets `full-e2e` automatically** — its tree is the rc's already-validated digests with only tag strings rewritten; a maintainer can still add the label manually to force the suite. 5. Finalize performs the irreversible side effects (tag, publish, retag, chart) — and with `persist-credentials: false` its tag push now actually authenticates as the CI app, so the `tags.yaml` backstops (`generate-changelog`, `update-website-docs`) fire for promoted tags. This is the one-line fix for the v1.6.0 incident where the tag triggered nothing: the checkout's persisted `GITHUB_TOKEN` `http.extraheader` silently defeats the app token injected via `git remote set-url`, and `GITHUB_TOKEN` pushes create no workflow runs. Everything is pinned by executable contract tests (`hack/promote-gate-contract.bats`, extended `hack/release-changelog-contract.bats` / `release-changelog-behaviour.bats` — 48 tests total, including behaviour tests that execute the new `hack/parse-rc-tag.sh` and `hack/select-changelog-source.sh` for real), and `docs/release.md` is rewritten to describe the new lifecycle end-to-end. ### Commit map (review commit-by-commit) - `75b5192f1`…`dd308644c` + `6fc970851` — the pre-existing changelog-before-publication rework (changelog generated at promote, committed to the staging branch before the PR opens, finalize publishes it as the release body; tags.yaml job becomes a verbatim-port backstop), rebased onto main. - `5aec70b3a` — `e2e-tag.yaml`: reusable published-tag e2e lane (prerelease → staging branch, stable → tag; draft releases fail fast; dispatch-only SSH `debug` breakpoint; tag-suffixed artifacts). - `025564d96` — `tags.yaml::rc-e2e`: mandatory full e2e for freshly cut rc tags (also on `release_exists` re-runs); fixes the `cut-prerelease.yaml` comment that falsely claimed e2e already existed. - `2dfbeea77` — `changelog-generate.yaml` (reusable core) + `changelog-rc.yaml` (rc-time button committing to the staging branch); promote-rc gains a top-level `parse` job with a strict no-whitespace tag policy (`hack/parse-rc-tag.sh`); source selection is validate-then-fallthrough (`hack/select-changelog-source.sh`) so an invalid higher-priority changelog can never silently win. - `ff7ddd3c9` — the promote e2e gate + `skip_e2e_gate` override + removal of the automatic `full-e2e` label (pull-requests.yaml release-path e2e now requires an explicit label; a post-open label now actually starts the run). - `936190d4b` — `website-docs` job at promote time behind a FETCH_REF-support guard (see dependency below), with the DO-NOT-MERGE-until-finalize contract and a pin-freshness pass before `release-next`; `tags.yaml::update-website-docs` stays as the backstop. - `01e1e7188` — the `persist-credentials: false` finalize fix (v1.6.0 root cause). - `717c8860f` — `docs/release.md` coherence pass over the whole new lifecycle. ### Dependency The promote-time website docs job needs cozystack/website#631 (`FETCH_REF` + fail-loud fetch). Until that merges, the job's guard detects the missing support and degrades to a ⚠️ line in the promote PR body — promotion is unaffected and the tag-time backstop backfills, so this PR is safe to merge first. ### Merge instructions Please **merge-commit, do not squash**: the 13 commits are deliberately atomic (the credential root-cause fix is separable from the feature work) and squashing would collapse ~3k lines into one commit, hurting bisectability. ### First live run The e2e lane is verified by lint, contract tests and dry-traces, but has not yet executed against a real tag; the intended first live run is a manual `e2e-tag.yaml` dispatch against an existing published rc tag before the gate is relied on for a real promotion. ### Release note ```release-note NONE ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added reusable changelog generation with validation, “present” signaling, and safe artifact upload behavior (including RC-time support). * Added an E2E release-tag workflow with tag parsing, deterministic sandboxing, and comprehensive report collection. * Improved RC promotion with a stricter parse front-door, verified E2E green gate (optional bypass), and earlier parallel changelog/asset staging. * **Documentation** * Refreshed release-process docs to match the updated RC-to-stable, changelog, and website-docs timing rules. * **Bug Fixes** * Improved PR finalization to source release bodies from verified changelogs and warn/fallback on missing or empty content. * Tightened label gating so E2E runs only under the intended conditions. <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
5d420475f4 |
refactor(ci): drop the vestigial /tmp workspace from e2e (both workflows) (#3454)
## What this PR does
The E2E job's `if: always()` cleanup ran `rm -rf /tmp/$SANDBOX_NAME`
with no check that `SANDBOX_NAME` was ever set. `Set sandbox ID` carries
no condition, so it inherits the implicit `success()` every
unconditional step gets: any failure ahead of it — a conflicting
`pr.patch`, a `download-artifact` miss, `Checkout code`, the
release-path `curl` — or a cancellation that reaches the job after it
has started (the job condition is `!cancelled()`) skips it, and
`SANDBOX_NAME` is never written to `$GITHUB_ENV`. The `if: always()`
steps then run anyway and interpolate the empty value; `Remove
workspace` is the destructive one, expanding to `rm -rf /tmp/` and
failing the cleanup step against root-owned entries in the runner's
`/tmp`. This is not a "re-run skips the setup" bug: a re-run restarts
the job at step one and re-runs the unconditional `Set sandbox ID` — the
trigger is incomplete initialization, by any of the routes above.
The `/tmp/$SANDBOX_NAME` workspace is a vestige of the retired multi-job
self-hosted-runner design, where several `runs-on: [self-hosted]` jobs
shared no state and rendezvoused through a `sha256(REPO:WORKFLOW:REF)`
key, with a per-run `cp -r` of the checkout into `/tmp`. Since CI moved
onto the ephemeral pool (`runs-on: oracle-vm-32cpu-128gb-x86-64`) it is
a single job: there is no cross-job rendezvous and the checkout is never
reused across runs, so copying it into `/tmp` and removing it afterwards
is dead weight. (An earlier review justified the change by "wiping the
entire `/tmp` of the self-hosted runner" — that describes the topology
we retired; the hazard is real, but not for that reason.)
So this drops the workspace rather than guarding the `rm`. Both the PR
(`pull-requests.yaml`) and nightly (`nightly.yaml`) E2E jobs now run in
`$GITHUB_WORKSPACE`: the `Prepare workspace` and `Remove workspace`
steps are gone, the `cd /tmp/$SANDBOX_NAME` prefixes are dropped, and
the upload paths point at `_out/…` instead of
`/tmp/${SANDBOX_NAME}/_out/…`. That takes the empty-value expansion out
of the `cd`s, the stray `mkdir`, the upload paths and the destructive
`rm` in one move, across both workflows rather than one step of many.
`Set sandbox ID` stays: the job still reads `$SANDBOX_NAME` directly
(failure diagnostics, the chainsaw `docker cp`, teardown, and every
`make SANDBOX_NAME=…` argument) — the container needs a name, just not a
directory.
It also removes the dead code the single-runner retirement left in
`packages/core/testing/Makefile`: the world-writable `mkdir -p
/tmp/${SANDBOX_NAME}` + `chmod 777` in the `apply` target (they backed a
`-v /tmp/${SANDBOX_NAME}:/workspace/hosttmp` bind mount that was later
removed — nothing under `images/e2e-sandbox/` references
`/workspace/hosttmp`), and the `-e SANDBOX_NAME=${SANDBOX_NAME}` passed
into the container (nothing under `images/e2e-sandbox/` reads it). Every
other use of `SANDBOX_NAME` — the container name and the `make`
arguments — is kept.
Note this cannot make a job with an empty `SANDBOX_NAME` go green: such
a job already failed initialization or was cancelled, so its conclusion
is fixed before cleanup runs. It removes a second, destructive failure
the old cleanup piled on top, and it does not change whether re-runs
work in general — they do.
The diagnosis of the real trigger, the corrected blast radius, and the
scope across both workflows plus the Makefile are credited to the
maintainer review on this PR.
### Evidence
Run [30067779342 attempt
3](https://github.com/cozystack/cozystack/actions/runs/30067779342/attempts/3)
exhibits the mechanism: `Download Talos image (regular PR)` failed on
`GetSignedArtifactURL` with a 404, which skipped `Set sandbox ID`, and
the `always()` steps then ran on an empty value — `Collect chainsaw
report` created `/tmp/_out`, the uploads resolved to `/tmp//_out/…`, and
`Remove workspace` did:
```
rm: cannot remove '/tmp/systemd-private-…-systemd-timedated.service-1oADZP': Operation not permitted
rm: cannot remove '/tmp/.X11-unix': Operation not permitted
##[error]Process completed with exit code 1.
```
The step ran unprivileged in `/home/ubuntu/_work/…`, so all it could hit
was `Operation not permitted` on root-owned entries in the sticky `/tmp`
— it deleted nothing. That run is a later, independent occurrence (it
started well after this PR was opened), not this change's motivating
case. The 404 that triggered it is a separate, non-deterministic problem
— the artifact listing succeeded and only the signed-URL call failed
~190 ms in, `download-artifact` treats 404 as non-retryable, and attempt
2 of the same run fetched the artifact fine — and it deserves its own
issue rather than being folded in here.
### Screenshots
Not applicable — CI workflow change only.
### Downstream repositories
The change is confined to this repo's E2E CI
(`.github/workflows/pull-requests.yaml`,
`.github/workflows/nightly.yaml`) and its testing Makefile
(`packages/core/testing/Makefile`). No downstream repository consumes
it.
- [x] No downstream repository is affected by this change
### Release note
```release-note
refactor(ci): drop the vestigial /tmp/$SANDBOX_NAME workspace from the E2E PR and nightly jobs — they now run in $GITHUB_WORKSPACE, removing an unguarded `rm -rf /tmp/$SANDBOX_NAME` cleanup that failed the job on cleanup when SANDBOX_NAME was empty
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved end-to-end test environment setup and sandbox cleanup.
* Updated test reporting and artifact collection for more reliable
results.
* Ensured OpenAPI and full-suite tests run from the correct prepared
environment.
* **Chores**
* Simplified container and workflow configuration for sandbox-based
testing.
* Clarified checkout token handling in nightly workflows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
9ed5483260 |
feat(computeplane): provision a ComputePlane tenant module for untrusted-code apps (#3280)
## What this PR does Implements the ComputePlane per the merged design proposal ([cozystack/community design-proposals/compute-plane](https://github.com/cozystack/community/tree/main/design-proposals/compute-plane); supersedes the earlier #3150 which was built on the pre-revision surface and came from a fork): a managed, isolated environment for running code-executing (untrusted-code) catalog applications. ComputePlane is delivered as an operator-owned **tenant module**: - **`packages/extra/computeplane`** — the module chart. Provisions a single-tenant, Cozystack-managed cluster by deploying the ordinary `apps/kubernetes` chart (Kamaji control plane + KubeVirt-VM workers) with operator-fixed values: the Cozystack-enablement addons (`fluxcd` + pinned distribution artifact, `certManager`, `ingressNginx` with `exposeMethod: Proxied`) are inline `spec.values`, so nothing injected via `valuesFrom` can disable them. The tenant can set cluster *shape* (`nodeGroups`, schema-validated) and receives no admin kubeconfig. - **Release naming**: neither HelmRelease sets `spec.releaseName` — the aggregated API rebuilds HelmRelease specs without that field, so both releases derive names from their object names. The cluster HelmRelease object is `computeplane-cluster`, and Kamaji writes the admin kubeconfig to the derived Secret **`computeplane-cluster-admin-kubeconfig`** — the contract future `placement: ComputePlane` routing consumes. Tenant-visible secrets are an allowlist (`include: []` withholds everything), so the credential is withheld by construction. - **`packages/system/computeplane-rd`** — registers the `ComputePlane` module-kind (`ApplicationDefinition`, `dashboard.module: true`). - **`packages/core/platform/sources/computeplane-application.yaml`** — self-contained package source: re-declares `apps/kubernetes` as its own source-only component; `dependsOn` cozystack-engine (ApplicationDefinition CRD) and kubernetes-application (registration ordering). Ships in the `iaas` bundle (variant `kubevirt`). - **Tenant toggle** — `computeplane: false` bool. The tenant chart fails loudly when the module is toggled on without the iaas package. Note: automatic `placement: ComputePlane` routing is a deferred follow-up and is not part of this PR; until it lands, external catalogs target the cluster via its kubeconfig Secret. - **`apps/kubernetes` fix** — the Proxied ingress `Service` renders only when the ingress-nginx addon is enabled **and** the tenant has etcd (mirroring the addon HelmRelease gates), independent of the `hosts` list. Follow-ups tracked separately: `placement` routing in cozystack-api, scoped per-service egress, visibility/mutation access control, e2e (#3369), release-name guards for the remaining extra charts (#3371). Tests: helm-unittest suites pin the module contract (object names, no explicit releaseName, tamper-proof inline addons, nodeGroups validation + ingress-role guard, unlisted-field pass-through), the tenant toggle, the package-source/bundle wiring, and the ingress Service gates. ### Screenshots Not a UI change. ### Release note ```release-note feat(computeplane): ComputePlane tenant module — a single-tenant, Cozystack-managed cluster for untrusted-code applications, delivered as an operator-owned extra module wrapping the kubernetes app. Enable with `computeplane: true` on the Tenant; the tenant receives no admin kubeconfig for it, and the cluster's admin kubeconfig Secret is `computeplane-cluster-admin-kubeconfig`. Catalog routing (`placement: ComputePlane`) ships separately. ``` <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added a new **ComputePlane** tenant option (`computeplane`, default off) to provision an isolated single-tenant environment for untrusted-code applications, including cluster creation and configurable **node groups**. * **Bug Fixes** * Refined ingress-nginx proxied rendering rules to avoid emitting incomplete resources: Ingress/Services are now gated on addon enablement (and etcd-backed tenancy), with correct behavior when hosts aren’t provided. * **Documentation / Tests** * Updated tenant and ComputePlane documentation; added/extended rendering tests for the new ComputePlane module and ingress-nginx gating (including release-name and etcd-less cases). <!-- end of auto-generated comment: release notes by coderabbit.ai --> |
||
|
|
e6460dbefe |
docs(governance): document the Reviewer role and align the maintainer roster (#3462)
## What this PR does
Makes the documented roster match who actually holds write access, which
CNCF Incubation checks directly through the API ("Code and Doc ownership
in GitHub matches documented governance roles", Required).
The two lists currently describe different projects. Ten people hold
write or admin on this repository without appearing in `MAINTAINERS.md`;
three people listed there — `@kingdonb`, `@matthieu-robin`,
`@mattia-eleuteri` — hold only read, one of them while carrying "CSI,
Storage, Networking & Security" as a documented responsibility. There is
no in-between state a reviewer will accept: someone with write is either
a maintainer or a reviewer, and should be findable as one.
**Maintainers, +3.** `@lexfrei`, `@myasnikovdaniil` and `@IvanHunters`
work across the whole tree rather than in one area, and already review
other people's changes at maintainer volume.
**Reviewers, new table.** `@sircthulhu`, `@androndo` and `@scooby87` own
a specific area with write access, without the project-wide
responsibilities of a maintainer. The role is not invented here, and it
is not new in practice either: `CONTRIBUTOR_LADDER.md` defines a
Reviewer as someone named in the owners file for one or more
directories, and `.github/CODEOWNERS` has named people since August 2024
— these three among them since February and April. What was missing is
that `MAINTAINERS.md` never said so, which is why the roster and the
access rights read as unrelated. The authoritative area-to-owner mapping
stays in `.github/CODEOWNERS`; this table only names the people.
**Emeritus, +2.** `@gecube` and `@nbykov0` move to the emeritus section.
Neither is carrying the responsibilities the ladder attaches to the role
— reviewing at least 40 pull requests a year and taking part in the
project's technical direction — and the section exists to record exactly
that, as a note on past contribution rather than a withdrawal of it.
**Security contacts.** `SECURITY.md` already routes reports correctly;
this names the maintainers who triage them, so the Required "contact
information" item points at people.
### What this PR does not do, and depends on
- `.github/CODEOWNERS` on `main` is still a single wildcard line naming
seven people, five of whom are not in `MAINTAINERS.md`. Aligning it is
#3228, which already scopes ownership by area and has been in draft
since 7 July. **This PR should land with or after it** — until then the
Reviewers table points at a file that does not yet reflect it. The area
additions still missing from #3228 (`@kingdonb` on
`packages/system/fluxcd*`, GPU/HAMi, `metrics-server`/`seaweedfs`) are
prepared and not pushed, because that branch is not mine to force.
- Permission changes themselves are not in any PR: raising `@kingdonb`,
`@matthieu-robin` and `@mattia-eleuteri` to write, and dropping write
from the four contributors who are neither maintainers nor reviewers, is
done by hand in the org.
- Two cells need confirmation from the people involved: `@scooby87`
publishes no name or company, and `@androndo`'s "Independent" is
inferred rather than stated. Both are placeholders, not claims.
### Screenshots
N/A — documentation 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:
Walked the trigger map against the diff: no row matches. The change
touches no package, no schema, no `ApplicationDefinition`, no platform
variant, no release asset and no node prerequisite. The website carries
no page mirroring `MAINTAINERS.md` — only blog posts that mention
maintainers in passing, which are historical and not regenerated.
The CNCF `.project` metadata does mirror this file, and is being updated
in a companion PR in
[cozystack/.project](https://github.com/cozystack/.project):
`project_lead` there still points at an emeritus maintainer, and the
roster needs the same three additions plus the reviewers team. That
repository is not on this checklist because it is CNCF automation
metadata rather than a downstream consumer of the platform.
### Release note
```release-note
NONE
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Expanded maintainer and reviewer listings, including area ownership
guidance.
* Clarified vulnerability reporting instructions with specific private
contact options and security triage details.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
|
||
|
|
93338cc434 |
refactor(computeplane): drop the in-cluster Flux pin
The fluxcd addon pin was a holdover from the #3150-era model where app charts rendered nested HelmReleases into the target cluster and needed an in-cluster helm-controller. Consumers now keep their releases on the management cluster and remote-apply via spec.kubeConfig, so the management Flux resolves charts and applies manifests — nothing inside the ComputePlane reconciles HelmReleases. This also decouples the module from the FluxCD addon removal (#3379). certManager and ingressNginx stay pinned: Certificate and Ingress objects land inside the cluster and need their controllers there. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <andrei.kvapil@aenix.io> |
||
|
|
2ff9c30d04 |
docs(kubernetes): note the etcd gate in the Proxied Service comment
The Proxied ingress Service is gated on _namespace.etcd as well as the addon toggle and exposeMethod, but the comment above it still described only the addon+exposeMethod gate — comment drift from the etcd-gate change. State both gates so the comment matches the condition it sits on. Assisted-By: Claude Signed-off-by: Andrei Kvapil <andrei.kvapil@aenix.io> |
||
|
|
8fc8d23dfd |
fix(computeplane): address review round three
Gate the Proxied ingress Service on _namespace.etcd like the addon HelmRelease it fronts, so an etcd-less tenant with the addon pinned on does not get a selector-less Service (+ test). Correct the secrets framing: the tenant-visible surface is an allowlist (include: [] withholds everything), so drop the never-load-bearing exclude entry, the bats cross-check and the rename-coupling comments, and state the real mechanism. Fix the etcd prerequisite docs (an ancestor's etcd satisfies the wrapped chart; the awaiting-etcd beacon is the diagnostic), reword the tenant toggle to stop advertising the not-yet-shipped placement routing, require maxReplicas >= 1 on the ingress-role node group, and fix comment drift (Service name after the release rename, placement-hook label, package-guard lookup semantics). Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <andrei.kvapil@aenix.io> |
||
|
|
366268d9f5 |
test(kubernetes): pin that a disabled ingress addon renders nothing with hosts set
hosts with the addon disabled used to render the Ingress; the addon gate makes 'the addon is off' mean nothing renders. Pin the combination so the behaviour change reads as a decision. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <andrei.kvapil@aenix.io> |
||
|
|
5a3d25b8f5 |
docs(computeplane): document the etcd prerequisite and unlisted-field pass-through
The tenant Kubernetes machinery — including the cluster-autoscaler that brings up the default scale-from-zero md0 group — is backed by the tenant's etcd module, so a ComputePlane without it provisions no workers and gives no diagnostic; state the prerequisite in the README. Also state plainly that unlisted NodeGroup fields pass through to the wrapped chart unvalidated (the schema generator cannot close the object), with a test pinning that behaviour. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <andrei.kvapil@aenix.io> |
||
|
|
6dcf5373e7 |
fix(computeplane): let Flux derive both release names
The aggregated API cannot represent spec.releaseName: the conversion rebuilds HelmRelease specs without it, so the first tenant edit through the API dropped the module's explicit computeplane-module release name, let it default to the object name computeplane, and collided with the Helm storage record the cluster release owned — with the tenant chart writing the old name back every interval. Drop releaseName from both HelmReleases and derive names from object names, like every other tenant module. Kamaji now writes the admin kubeconfig to computeplane-cluster-admin-kubeconfig; the computeplane-rd secrets.exclude entry follows in the same change, and a bats test pins the exclusion to the name the cluster release actually produces so a future rename cannot silently re-expose the credential. Also add the check-release-name guard the other extra modules carry, and pin the fluxcd addon's distribution artifact to the flux-operator version vendored in system/fluxcd-operator instead of :latest. Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Andrei Kvapil <andrei.kvapil@aenix.io> |