Summary
The flux deployer's OCI output (aicr bundle --deployer flux --output oci://...) is not consumable by Flux for local-chart components — recipes that include manifestFiles, preManifestFiles, or vendored Helm wrappers. Discovered during PR #956 while adding the flux-oci KWOK lane.
Symptom
When the bundle is consumed via an outer OCIRepository + Kustomization, the per-component HelmRelease CRs for local-chart components reference:
spec:
chart:
spec:
chart: ./<component-name>
sourceRef:
kind: GitRepository
name: github-com-your-org-your-repo
The GitRepository resource inside the bundle points at the bundler placeholder URL https://github.com/YOUR_ORG/YOUR_REPO.git, which Flux's source-controller cannot fetch. helm-controller observes:
release is in a failed state
terminal error: exceeded maximum retries: cannot remediate failed release
Because Flux components are chained via dependsOn, the entire HelmRelease graph downstream of any local-chart component stalls on "dependency not ready".
Why this PR doesn't fix it
Two attempts to point the inner HelmReleases at the outer OCIRepository both fail against Flux's API:
HelmRelease.spec.chart.spec.sourceRef.kind: OCIRepository — rejected by the validating webhook with "supported values: HelmRepository, GitRepository, Bucket". The legacy chart-fetch path goes through a HelmChart resource whose sourceRef only accepts those three kinds.
HelmRelease.spec.chartRef — accepts OCIRepository, but points at the entire OCI artifact as a single chart. There is no path support; a multi-chart bundle cannot be addressed this way.
So a single wrapper OCIRepository cannot serve sub-paths to inner local charts. The fix has to come from the bundler's side: either eliminate the local-chart HelmReleases or publish each one as its own OCI artifact.
Mitigation in PR #956
The flux-oci KWOK lane validates that the bundle artifact can be pulled (OCIRepository Ready=True), applied (Kustomization Ready=True), and produces the expected GitOps shape (per-component HelmRelease CRs created). It does NOT wait for HelmReleases to reach terminal state — that wait would always fail under the current placeholder-URL behavior.
This covers the most common bundle-format regression vector (pull, parse, schema correctness) for the flux deployer's OCI output, at the cost of deferring reconciliation validation.
Proposed fix options
Option A: Render local-chart manifests at bundle time
For local-chart components (those that today emit Chart.yaml + templates/ inside the bundle), run helm template at aicr bundle time and write the rendered manifests into the bundle. The root kustomization.yaml lists them directly; no per-component HelmRelease is emitted for these.
External-chart components (cert-manager, gpu-operator from upstream Helm repos) keep their HelmRelease + HelmRepository source CRs.
- Pros: single OCI artifact, no per-chart push, mirrors what the
helm deployer already does on its local-chart path.
- Cons: changes the bundle layout for the
flux + OCI case (manifests at component root, not under templates/); partially duplicates the helm deployer's rendering.
Option B: Push each local chart as its own OCI helm artifact
For each local-chart component, push the chart with helm.config.v1+json config + helm.chart.content.v1.tar+gzip layer (the same flow we added for argocd-helm-oci in this PR — see pkg/oci.PackageAndPushHelmChart). The bundle then contains one OCIRepository per local chart, plus a HelmRelease with spec.chartRef pointing at it.
- Pros: native Flux pattern; uses
chartRef (the post-v2.1 API).
- Cons: N+1 OCI pushes per bundle (one outer wrapper + one per local chart); more registry traffic; more cleanup.
Option C: Both
Option A as the default; Option B behind a flag for users who want strict GitOps separation per chart.
Acceptance criteria
Related
Summary
The
fluxdeployer's OCI output (aicr bundle --deployer flux --output oci://...) is not consumable by Flux for local-chart components — recipes that includemanifestFiles,preManifestFiles, or vendored Helm wrappers. Discovered during PR #956 while adding theflux-ociKWOK lane.Symptom
When the bundle is consumed via an outer
OCIRepository+Kustomization, the per-componentHelmReleaseCRs for local-chart components reference:The
GitRepositoryresource inside the bundle points at the bundler placeholder URLhttps://github.com/YOUR_ORG/YOUR_REPO.git, which Flux's source-controller cannot fetch. helm-controller observes:Because Flux components are chained via
dependsOn, the entire HelmRelease graph downstream of any local-chart component stalls on "dependency not ready".Why this PR doesn't fix it
Two attempts to point the inner HelmReleases at the outer OCIRepository both fail against Flux's API:
HelmRelease.spec.chart.spec.sourceRef.kind: OCIRepository— rejected by the validating webhook with"supported values: HelmRepository, GitRepository, Bucket". The legacy chart-fetch path goes through aHelmChartresource whosesourceRefonly accepts those three kinds.HelmRelease.spec.chartRef— acceptsOCIRepository, but points at the entire OCI artifact as a single chart. There is no path support; a multi-chart bundle cannot be addressed this way.So a single wrapper OCIRepository cannot serve sub-paths to inner local charts. The fix has to come from the bundler's side: either eliminate the local-chart HelmReleases or publish each one as its own OCI artifact.
Mitigation in PR #956
The
flux-ociKWOK lane validates that the bundle artifact can be pulled (OCIRepository Ready=True), applied (Kustomization Ready=True), and produces the expected GitOps shape (per-component HelmRelease CRs created). It does NOT wait for HelmReleases to reach terminal state — that wait would always fail under the current placeholder-URL behavior.This covers the most common bundle-format regression vector (pull, parse, schema correctness) for the
fluxdeployer's OCI output, at the cost of deferring reconciliation validation.Proposed fix options
Option A: Render local-chart manifests at bundle time
For local-chart components (those that today emit
Chart.yaml + templates/inside the bundle), runhelm templateataicr bundletime and write the rendered manifests into the bundle. The rootkustomization.yamllists them directly; no per-componentHelmReleaseis emitted for these.External-chart components (cert-manager, gpu-operator from upstream Helm repos) keep their
HelmRelease+HelmRepositorysource CRs.helmdeployer already does on its local-chart path.flux + OCIcase (manifests at component root, not undertemplates/); partially duplicates thehelmdeployer's rendering.Option B: Push each local chart as its own OCI helm artifact
For each local-chart component, push the chart with
helm.config.v1+jsonconfig +helm.chart.content.v1.tar+gziplayer (the same flow we added forargocd-helm-ociin this PR — seepkg/oci.PackageAndPushHelmChart). The bundle then contains oneOCIRepositoryper local chart, plus aHelmReleasewithspec.chartRefpointing at it.chartRef(the post-v2.1 API).Option C: Both
Option A as the default; Option B behind a flag for users who want strict GitOps separation per chart.
Acceptance criteria
aicr bundle --deployer flux --output oci://...produces a bundle whose local-chart components reconcile successfully under Flux without external Git access.flux-ociKWOK lane is updated to wait for HelmRelease terminal state (Ready=True OR Released+history=deployed), restoring the same depth of validationargocd-ocihas today.docs/contributor/kwok-testing.md"Local-chart skip" note is removed.Related
flux-ocilane with this gap deferred)