fix: support go-getter URLs in ad-hoc dependencies to fix #821 (#2670)

* fix: support go-getter URLs in ad-hoc dependencies to fix #821

Ad-hoc release dependencies (release.dependencies[].chart) that used
go-getter URLs like "git::https://host/repo.git@path?ref=tag" were passed
to chartify as-is. chartify then tried to resolve them via `helm repo
list`, which fails with "no helm list entry found for repository
\"git::https:\". please `helm repo add` it!".

The primary chart already fetched such URLs via downloadChartWithGoGetter,
but the ad-hoc dependency path in PrepareChartify only handled local
directories and OCI rewrites, so go-getter URLs fell through.

This adds a branch that detects remote go-getter URLs (remote.IsRemote)
and fetches them to a local cache directory via a new
downloadAdhocDepChartWithGoGetter helper, mirroring the primary-chart
fetch path. chartify then sees a local chart and takes its file:// branch.

Fixes #821

Signed-off-by: yxxhero <aiopsclub@163.com>

* test: add integration test for go-getter ad-hoc dependencies (#821)

Adds an integration test that commits a chart to a throwaway local git repo
and references it via a "git::file://..." go-getter URL as a release
ad-hoc dependency, then asserts `helmfile template` renders both the main
chart and the fetched dependency.

Using file:// (rather than https://) keeps the test deterministic and
network-free while exercising the exact fix path (remote.IsRemote +
downloadAdhocDepChartWithGoGetter in PrepareChartify). Verified to fail on
the unfixed code with the original "no helm list entry found for repository
\"git::file:\"" error and pass on the fixed code.

Signed-off-by: yxxhero <aiopsclub@163.com>

* test: surface helmfile error in issue #821 integration test

The integration runner (run.sh) enables `set -e`, so a non-zero helmfile
exit aborted the script before the captured output could be printed,
hiding the real failure in CI. Disable `set -e` around the helmfile
invocation and report the exit code plus full output on failure.

Signed-off-by: yxxhero <aiopsclub@163.com>

* test: fix issue-821 integration test chart path and errexit handling

Two issues caused the integration test to fail in CI (while passing in my
local smoke test, which used an absolute path):

1. The main chart path was relative to the integration CWD, but the
   helmfile.yaml is generated in a temp directory and helmfile resolves
   `chart:` relative to that directory (its basePath). The relative path
   was interpreted as a named-repo chart and failed instantly with
   `Error: repo test not found`. Resolve the case dir to an absolute path
   with `$(cd ... && pwd)`.

2. run.sh runs under `set -e`, so the unguarded helmfile invocation exited
   the whole script on failure before the captured output could be printed,
   hiding the real error. Capture the exit code via `cmd || rc=$?` so
   failures are reported.

Signed-off-by: yxxhero <aiopsclub@163.com>

---------

Signed-off-by: yxxhero <aiopsclub@163.com>
This commit is contained in:
yxxhero
2026-06-28 15:28:05 +08:00
committed by GitHub
parent e3f757d5ed
commit 8f1bb404d6
8 changed files with 268 additions and 0 deletions
+42
View File
@@ -914,6 +914,34 @@ func (st *HelmState) downloadChartWithGoGetter(r *ReleaseSpec) (string, error) {
return st.goGetterChart(r.Chart, r.Directory, cacheDir, r.ForceGoGetter)
}
// downloadAdhocDepChartWithGoGetter fetches a go-getter URL referenced by an
// ad-hoc release dependency (release.dependencies[].chart) to a local cache
// directory and returns the local path.
//
// Ad-hoc dependencies were previously passed to chartify as-is. chartify then
// tried to resolve non-local, non-OCI values via `helm repo list`, which fails
// for go-getter URLs like "git::https://host/repo.git@path?ref=tag" with
// "no helm list entry found for repository". This mirrors the primary-chart
// fetch path (downloadChartWithGoGetter) so go-getter URLs work uniformly.
// See issue #821.
func (st *HelmState) downloadAdhocDepChartWithGoGetter(release *ReleaseSpec, chart string) (string, error) {
var pathElems []string
if release.Namespace != "" {
pathElems = append(pathElems, release.Namespace)
}
if release.KubeContext != "" {
pathElems = append(pathElems, release.KubeContext)
}
pathElems = append(pathElems, release.Name, "deps")
cacheDir := filepath.Join(pathElems...)
return st.goGetterChart(chart, "", cacheDir, release.ForceGoGetter)
}
func (st *HelmState) goGetterChart(chart, dir, cacheDir string, force bool) (string, error) {
if dir != "" && chart == "" {
chart = dir
@@ -985,6 +1013,20 @@ func (st *HelmState) PrepareChartify(helm helmexec.Interface, release *ReleaseSp
} 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
} else if remote.IsRemote(chart) {
// Ad-hoc dependency uses a go-getter URL (e.g.
// "git::https://host/repo.git@path?ref=tag"). Fetch it to a local
// cache directory so chartify treats it as a local chart instead of
// trying to resolve it via `helm repo list`, which fails with
// "no helm list entry found for repository" for go-getter URLs.
// The primary chart already does this via downloadChartWithGoGetter;
// this mirrors that path for ad-hoc deps. See issue #821.
fetched, err := st.downloadAdhocDepChartWithGoGetter(release, chart)
if err != nil {
return nil, clean, fmt.Errorf("ad-hoc dependency %q: %w", d.Chart, err)
}
st.logger.Debugf("ad-hoc dependency %q fetched to %q via go-getter", d.Chart, fetched)
chart = fetched
}
c.Opts.AdhocChartDependencies = append(c.Opts.AdhocChartDependencies, chartify.ChartDependency{