Skip to content

argocd-helm OCI bundle: path-based child Applications miss .Chart.Name; Chart.yaml emits unquoted name #1034

Description

@yuanchen8911

Summary

Two correctness bugs in the argocd-helm bundler's OCI publishing path:

  1. P1 (regression from fix(bundler): derive argocd-helm chart name from OCI artifact path #1032) — Path-based child Applications resolve to a wrong artifact URL when the bundle is published to OCI.
  2. P2Chart.yaml emits an unquoted chart name; valid OCI artifact paths whose last segment is a YAML reserved scalar produce a chart Helm rejects.

Both reproduce against origin/main at HEAD 51eb4b5f.

P1 — Path-based child Applications miss .Chart.Name in repoURL

Where: pkg/bundler/deployer/argocdhelm/argocdhelm.go:699-704 in injectValuesIntoSingleSource.

What's wrong: #1032 changed the contract so users pass only the parent namespace (e.g., oci://reg/org) and the parent Application appends .Chart.Name to assemble the full artifact reference (e.g., oci://reg/org/my-bundle). The parent-App template at line 407-408 implements this correctly:

repoURL: {{ required "..." .Values.repoURL | quote }}
chart: {{ .Chart.Name | quote }}

But the path-based child-App template at line 703 only emits a repoURL, no chart field (path-based sources don't have one — Argo CD's generic OCI source uses repoURL directly as the full artifact). The template still emits just .Values.repoURL:

Value: ` + "`" + `{{ required "...do NOT include the chart name..." .Values.repoURL }}` + "`" + `,

So a bundle pushed as oci://reg/org/my-bundle:v1 with manifest-only or mixed-local-chart children (e.g., gpu-operator-post, nodewright-customizations raw manifests) installs with --set repoURL=oci://reg/org, the parent Application resolves correctly, but every path-based child Application resolves to oci://reg/org:v1 — an artifact that doesn't exist — and fails to sync. The instruction text in the required message and the template body are out of sync.

Severity: High — silently broken bundles for any recipe with raw manifests under the new (post-#1032) OCI contract.

Proposed fix: Assemble the full artifact reference in the path-based child template too, matching the parent-App pattern:

Value: ` + "`" + `{{ required "..." .Values.repoURL }}/{{ .Chart.Name }}` + "`" + `,

P2 — Unquoted name: in Chart.yaml mis-parses YAML reserved scalars

Where: pkg/bundler/deployer/argocdhelm/argocdhelm.go:944 in writeChartYAML.

What's wrong: (*Reference).ChartName() (pkg/oci/reference.go:152) returns path.Base(Repository). For valid OCI repository names like oci://reg/org/null:v1, oci://reg/org/false:v1, oci://reg/org/123:v1, or any other YAML reserved scalar (null, true, false, yes, no, on, off, ~, numeric-looking strings), path.Base returns the value verbatim. writeChartYAML then emits unquoted:

fmt.Fprintf(&buf, "name: %s\n", name)

Producing name: null (or name: 123, etc.). Helm's YAML parser interprets these as non-string scalars and chart.Metadata.Name becomes empty (or fails to unmarshal), so the subsequent helm package / helm push step rejects the chart with "chart.metadata.name is required" or a YAML type error.

Severity: Low — requires an unusual but valid OCI path. No known reports in the wild; defense-in-depth fix.

Proposed fix: Quote the value safely. %q produces a YAML-safe double-quoted scalar for all printable ASCII:

fmt.Fprintf(&buf, "name: %q\n", name)

Same defense should be applied to the version: line for symmetry (a version string like "1.0" would parse as a float and fail similarly).

Acceptance criteria

  • Path-based child Application template appends .Chart.Name so the rendered repoURL is the full OCI artifact reference (parent namespace + chart name).
  • writeChartYAML quotes both name and version so YAML reserved scalars round-trip as strings.
  • Unit test: path-based template renders {{ .Values.repoURL }}/{{ .Chart.Name }} (or a Helm-rendered fixture asserting the assembled URL).
  • Unit test: writeChartYAML produces YAML that unmarshals name back as a string for inputs like "null", "true", "123".

Related

Found via Codex review of the AICR codebase.

Metadata

Metadata

Assignees

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions