agent-platform release v3.18.0

Added

  • The chart brings its own Flux engine (roadmap#4348, PRD Q1/Q2/Q3/Q9): helm install of the meta-package on a cluster without Flux yields a running platform. The new flux-engine subchart (helm/agent-platform/charts/flux-engine, released with this chart, the only dependencies: entry of Chart.yaml, condition: components.flux.enabled, default true) carries the seven Flux CRDs of source-controller and helm-controller and the four Flux Operator CRDs in its crds/, and renders the Flux Operator (ghcr.io/controlplaneio-fluxcd/flux-operator 0.59.0 as a Renovate-managed pin, web UI off, no network policy — the upstream chart’s Deployment/ServiceAccount/cluster-admin binding/metrics Service, lifted verbatim) and one FluxInstance named flux in the release namespace (distribution.version: "2.x" from ghcr.io/fluxcd, components: [source-controller, helm-controller], cluster.multitenant: true with tenantDefaultServiceAccount: default, no network policy). The operator upgrades Flux — controllers, CRDs, stored objects — inside the range on its own. Its values live under flux-engine:. components.flux is a feature switch, not a component: an entry without a chart key takes part in the roster and the enablement logic but renders no release (templates/components.yaml). Measured on a fresh kind cluster: helm install --wait deployed in about two minutes, the FluxInstance Ready at Flux v2.9.5 in 15 s.
  • The tenant identity agent-platform-flux: a ServiceAccount in the release namespace bound to cluster-admin, rendered by the subchart; gitops.serviceAccountName defaults to it whenever the engine is on, so every platform HelmRelease names it (under the lockdown a HelmRelease without one runs as the rights-less default account and fails). The fleet keeps "" and its exempt namespace and renders none.
  • Render guards for the engine (agent-platform.validateEngine): with the engine on, a cluster that already runs Flux — a helm-controller Deployment (app.kubernetes.io/component=helm-controller) or a FluxInstance outside the release namespace, looked up live under the Helm CLI, --dry-run=server and helm-controller — fails the render with this cluster runs Flux; set components.flux.enabled=false or install the chart through it; gitops.namespace set to another namespace fails (the tenant identity lives in the release namespace); with the engine off, turning it off on an installation that runs it fails (an upgrade would delete the operator together with the FluxInstance it finalizes and hang). helm template sees no cluster and renders the engine.
  • The ordered teardown: pre-delete hook Jobs (templates/hooks/, rendered only with the engine on) — a hook ServiceAccount + ClusterRoleBinding <release>-hooks to cluster-admin at weight -10, <release>-teardown-releases at weight 0 deleting the platform HelmReleases by name in gitops.namespace and waiting, <release>-teardown-engine at weight 5 deleting the FluxInstance and waiting; one plain kubectl command each in the distroless registry.k8s.io/kubectl (gitops.hooks.image, a Renovate-managed pin), restricted pod security, --ignore-not-found, hook-delete-policy: before-hook-creation,hook-succeeded; weights -6/-5 are reserved for the self-management hooks. helm uninstall --wait returns clean in well under a minute; the operator removes Flux including its CRDs (every HelmRelease object with them, the agents’ included; workloads and Helm storage stay), the four operator CRDs remain, a reinstall is clean. Without the hooks Helm deletes the operator together with the FluxInstance and hangs for its timeout (measured).
  • A kind install smoke in the ATS (.ats/main.yaml runs the smoke step with app-tests-skip-app-deploy: true; tests/ats/test_smoke.py): the Gateway API CRDs, then helm install --wait of the candidate with tests/test-values.yaml (the kind shape: engine on, muster + dicebear + connectivity, valkey off, muster’s OAuth server and the network policies off — the auto knobs resolve the rest), asserting the release deployed, the FluxInstance Ready at a Flux 2.x, every component HelmRelease Ready as agent-platform-flux, one Helm revision, the operator as field manager of the Flux CRDs; then helm uninstall --wait in under a minute with no Flux CRD left and the operator CRDs kept, and a clean reinstall. execute-chart-tests runs it on every PR.
  • make verify-engine (tests/verify-engine.py, in CI with Helm 3.17.3): engine off renders no CRD, no hook, no operator, no FluxInstance, no identity and no serviceAccountName, the fleet shape stays clean; engine on renders exactly the eleven CRDs, the operator objects, the FluxInstance (two controllers, multitenant), the identities and the hooks at their weights, every HelmRelease names agent-platform-flux, the teardown Job names every rendered HelmRelease; the two shapes’ OCIRepository/HelmRelease documents are identical but for serviceAccountName and the roster; Chart.yaml’s only dependency is flux-engine, conditional, a local directory, its version and appVersion in step with the subchart. make verify-meta asserts the pure-renderer rule with the engine off and that the one dependency is not a component pin. README: a quick start (domain, identity, components — nothing about Flux), the engine, clusters that run Flux, uninstalling, Helm versions. Management clusters need not act: they carry components.flux.enabled: false already (management-cluster-bases#721), and the fleet render with it is byte-identical. Other installations that run their own Flux set the value before upgrading — see UPGRADE.md.