fix(state): resolve OCI repo prefix in ad-hoc release dependencies (#2579)
When a release `dependencies[].chart` is given as `<repoName>/<chart>` and the matching `repositories:` entry has `oci: true`, helmfile now rewrites it to `oci://<repoURL>/<chart>` before passing it to chartify. Without this, chartify's lookup falls into its `helm repo list` branch, which never finds OCI repos because helm 3+ does not register OCI registries as named repos (they live in the `helm registry login` state instead). The user-visible failure was: failed reading adhoc dependencies: no helm list entry found for repository "<name>". please `helm repo add` it! Explicit `oci://` URLs already worked through chartify's OCI branch; this change makes the `<repoName>/<chart>` form behave the same way. Non-OCI repo prefixes, unknown prefixes, single-segment names, and explicit `oci://` URLs all pass through unchanged. A debug log records each rewrite at the call site for easier troubleshooting. Fixes #1756. Signed-off-by: Dominik Schmidt <dev@dominik-schmidt.de>
This commit is contained in:
parent
41d815aa5b
commit
c6d0310029
|
|
@ -427,6 +427,9 @@ func (st *HelmState) PrepareChartify(helm helmexec.Interface, release *ReleaseSp
|
|||
if err != nil {
|
||||
return nil, clean, err
|
||||
}
|
||||
} else if rewritten, ok := st.resolveOCIAdhocDepChart(d.Chart); ok {
|
||||
st.logger.Debugf("ad-hoc dependency %q rewritten to %q (matched OCI repo entry)", d.Chart, rewritten)
|
||||
chart = rewritten
|
||||
}
|
||||
|
||||
c.Opts.AdhocChartDependencies = append(c.Opts.AdhocChartDependencies, chartify.ChartDependency{
|
||||
|
|
|
|||
|
|
@ -1392,6 +1392,28 @@ func (st *HelmState) GetRepositoryAndNameFromChartName(chartName string) (*Repos
|
|||
return nil, chartName
|
||||
}
|
||||
|
||||
// resolveOCIAdhocDepChart rewrites a release `dependencies[].chart` value that
|
||||
// uses the named-repo prefix form ("repoName/chartName") into a full oci:// URL
|
||||
// when the prefix matches a `repositories:` entry with `oci: true`. It returns
|
||||
// (rewritten, true) on a hit and ("", false) otherwise.
|
||||
//
|
||||
// This avoids the chartify path that does `helm repo list` to look up the
|
||||
// repository URL: that lookup never finds OCI repos because helm 3+ does not
|
||||
// register OCI registries as named repos (it uses `helm registry login`
|
||||
// instead). By the time chartify sees an `oci://` URL it already takes the
|
||||
// correct branch, so rewriting here is enough to make the named-repo form
|
||||
// behave the same as the explicit URL form.
|
||||
func (st *HelmState) resolveOCIAdhocDepChart(chart string) (string, bool) {
|
||||
if strings.HasPrefix(chart, "oci://") {
|
||||
return "", false
|
||||
}
|
||||
repo, name := st.GetRepositoryAndNameFromChartName(chart)
|
||||
if repo == nil || !repo.OCI {
|
||||
return "", false
|
||||
}
|
||||
return "oci://" + strings.TrimSuffix(repo.URL, "/") + "/" + name, true
|
||||
}
|
||||
|
||||
var rwMutexMap sync.Map
|
||||
|
||||
// getNamedRWMutex retrieves or creates a sync.RWMutex for a given name.
|
||||
|
|
|
|||
|
|
@ -6039,3 +6039,74 @@ func TestHelmState_getKubeContext(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
// resolveOCIAdhocDepChart should rewrite a release `dependencies[].chart` value
|
||||
// that uses the named-repo prefix form into a full oci:// URL whenever the
|
||||
// matching `repositories:` entry has `oci: true`. All other inputs must pass
|
||||
// through unchanged so we never disturb existing behavior.
|
||||
func TestResolveOCIAdhocDepChart(t *testing.T) {
|
||||
state := &HelmState{
|
||||
ReleaseSetSpec: ReleaseSetSpec{
|
||||
Repositories: []RepositorySpec{
|
||||
{Name: "ociregistry", URL: "registry.example.com:5000/charts", OCI: true},
|
||||
{Name: "ociregistry-trailing", URL: "registry.example.com:5000/charts/", OCI: true},
|
||||
{Name: "stable", URL: "https://charts.helm.sh/stable"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
chart string
|
||||
wantOK bool
|
||||
wantChart string
|
||||
}{
|
||||
{
|
||||
name: "named OCI repo prefix is rewritten to oci:// URL",
|
||||
chart: "ociregistry/redis",
|
||||
wantOK: true,
|
||||
wantChart: "oci://registry.example.com:5000/charts/redis",
|
||||
},
|
||||
{
|
||||
name: "trailing slash on repo URL does not produce a double slash",
|
||||
chart: "ociregistry-trailing/redis",
|
||||
wantOK: true,
|
||||
wantChart: "oci://registry.example.com:5000/charts/redis",
|
||||
},
|
||||
{
|
||||
name: "non-OCI repo prefix is left alone for chartify's helm-repo-list path",
|
||||
chart: "stable/nginx",
|
||||
wantOK: false,
|
||||
},
|
||||
{
|
||||
name: "explicit oci:// URL is left alone (already in chartify's OCI branch)",
|
||||
chart: "oci://registry.example.com:5000/charts/redis",
|
||||
wantOK: false,
|
||||
},
|
||||
{
|
||||
name: "unknown repo prefix is left alone",
|
||||
chart: "unknownrepo/something",
|
||||
wantOK: false,
|
||||
},
|
||||
{
|
||||
name: "single-segment chart (no slash) is left alone",
|
||||
chart: "localchart",
|
||||
wantOK: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, ok := state.resolveOCIAdhocDepChart(tt.chart)
|
||||
if ok != tt.wantOK {
|
||||
t.Errorf("ok: want %v, got %v", tt.wantOK, ok)
|
||||
}
|
||||
if tt.wantOK && got != tt.wantChart {
|
||||
t.Errorf("rewritten chart: want %q, got %q", tt.wantChart, got)
|
||||
}
|
||||
if !tt.wantOK && got != "" {
|
||||
t.Errorf("expected empty rewrite when ok=false, got %q", got)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue