Repository: helm/helm (go)

Issue:
Flag --repository-cache used for finding helm-manager-* ‘ad hoc’ repository indexes, but not for creating them
Output of `helm version`:
```text
version.BuildInfo{Version:"v3.9.4", GitCommit:"dbc6d8e20fe1d58d50e6ed30f09a04a77e4c68db", GitTreeState:"clean", GoVersion:"go1.19"}
```
But this bug applies to older versions of Helm 3 equally, also on Linux.

Output of `kubectl version`: `Client Version: v1.23.5`

Cloud Provider/Platform (AKS, GKE, Minikube etc.): Any and all (N/A)


When using the `--repository-cache` flag in conjunction with a `helm dependency update` command while the Helm chart affected has a dependency for which there is no repo ‘alias’ defined (i.e. its URL has not been added with a `helm repo add (…)` command; often called an ‘unmanaged’ repo), an ‘ad hoc’ repository index file, named `helm-manager-*-index.yaml` (along with a file with the same base name, but ends with `-charts.txt`), will be created in the default repository cache directory, but a later step tries to find it in the directory that was set via the flag.

Example of the error message (this was on _macOS_):
>Update Complete. ⎈Happy Helming!⎈
Error: no cached repository for helm-manager-0199bcabd1392eb1d12164d7fc1f56a975ac01570d110f202cb3a78614ce224b found. (try 'helm repo update'): open /Users/someone/tmp/x/helm-manager-0199bcabd1392eb1d12164d7fc1f56a975ac01570d110f202cb3a78614ce224b-index.yaml: no such file or directory

## How to reproduce

The default directories mentioned in the instructions are the ones for Linux.

### Setup and check the ‘standard’ usage

- Remove all files from the default repo index cache dir: `rm -f ~/.cache/helm/repository/*`
- Create a new Helm chart in a temporary directory: `helm create test`
- Change the current working directory to that chart: `cd test`
- Add a (can be fake) dependency to the `Chart.yaml` file, referring to a repository you don’t have registered with Helm yet, e.g.:
```yaml
dependencies:
- name: test
  repository: https://cetic.github.io/helm-charts
  version: "1.0.0"
```
- Run `helm dependency update` (that works, but if you have a fake dependency it’ll tell you that it can’t be found in the repo)
- List the default repo cache dir: `ls -lat ~/.cache/helm/repository`; you’ll find indexes for all ‘managed’ repos, e.g. for Bitnami, SonarQube, etc.; there’s an ‘ad hoc’ index for that ‘unmanaged’ repo we added as a dependency as well, named `helm-manager-<some-hash>-charts.txt` and `helm-manager-<some-hash>-index.yaml`
- To start with a clean slate, remove the indexes again: `rm -f ~/.cache/helm/repository/*`

### Reproduce the bug with the flag
- Not needed, but to make the scenario more realistic and to prove this doesn’t make a difference, explicitly update the repo indexes, but in the alternative cache dir: `helm --repository-cache /tmp/helm-cache repo update`
- Check that the default repo cache dir is still empty: `ls -lat ~/.cache/helm/repository`
- Check that the repo indexes have been created in the specified alternative dir: `ls -lat /tmp/helm-cache`; obviously, no index files were created for the ‘unmanaged’ repo
- Wait at least a minute (because of the minimal delta between file time stamps)
- Run `helm --repository-cache /tmp/helm-cache dependency update` (it will fail with a message complaining that it can’t find a `helm-manager-*-index.yaml` file in directory `/tmp/helm-cache`)
- List the contents of the default repo index cache dir: `ls -lat ~/.cache/helm/repository`; you’ll notice the file mentioned in the error message is present there (along with newly created indexes for the ‘managed’ repos)
- List the contents of the alternative repo cache dir that was specified: `ls -lat /tmp/helm-cache`; notice that the (specific) `helm-manager-*-index.yaml` is not present and that the indexes for the ‘managed’ repos were not updated (touched)



Pull request:
#11369 Fix custom repo index cache directory for unmanaged dependency updates
Closes #11369 

**What this PR does / why we need it**:

Using the `--repository-cache` flag for a chart with unmanaged dependencies consistently fails with:

>Error: no cached repository for helm-manager-[some-hash] found. (try 'helm repo update'): open /tmp/helm-cache/helm-manager-[some-hash]-index.yaml: no such file or directory

This PR fixes that.

**Special notes for your reviewer**:

The unit test case could probably be a bit cleaner, but this is my first attempt at writing Go code 👼 

**If applicable**:
- [ ] this PR contains documentation
- [x] this PR contains unit tests
- [x] this PR has been tested for backwards compatibility


Patch:
diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go
index 18b28dde1..5f1f4f514 100644
--- a/pkg/downloader/manager.go
+++ b/pkg/downloader/manager.go
@@ -668,6 +668,7 @@ func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error {
 		if err != nil {
 			return err
 		}
+		r.CachePath = m.RepositoryCache
 		wg.Add(1)
 		go func(r *repo.ChartRepository) {
 			if _, err := r.DownloadIndexFile(); err != nil {


Test patch:
diff --git a/cmd/helm/dependency_update_test.go b/cmd/helm/dependency_update_test.go
index 491f6a856..ec21f902e 100644
--- a/cmd/helm/dependency_update_test.go
+++ b/cmd/helm/dependency_update_test.go
@@ -206,6 +206,61 @@ func TestDependencyUpdateCmd_DoNotDeleteOldChartsOnError(t *testing.T) {
 	}
 }
 
+func TestDependencyUpdateCmd_WithRepoThatWasNotAdded(t *testing.T) {
+	srv := setupMockRepoServer(t)
+	srvForUnmanagedRepo := setupMockRepoServer(t)
+	defer srv.Stop()
+	defer srvForUnmanagedRepo.Stop()
+
+	dir := func(p ...string) string {
+		return filepath.Join(append([]string{srv.Root()}, p...)...)
+	}
+
+	chartname := "depup"
+	ch := createTestingMetadata(chartname, srv.URL())
+	chartDependency := &chart.Dependency{
+		Name:       "signtest",
+		Version:    "0.1.0",
+		Repository: srvForUnmanagedRepo.URL(),
+	}
+	ch.Metadata.Dependencies = append(ch.Metadata.Dependencies, chartDependency)
+
+	if err := chartutil.SaveDir(ch, dir()); err != nil {
+		t.Fatal(err)
+	}
+
+	_, out, err := executeActionCommand(
+		fmt.Sprintf("dependency update '%s' --repository-config %s --repository-cache %s", dir(chartname),
+			dir("repositories.yaml"), dir()),
+	)
+
+	if err != nil {
+		t.Logf("Output: %s", out)
+		t.Fatal(err)
+	}
+
+	// This is written directly to stdout, so we have to capture as is
+	if !strings.Contains(out, `Getting updates for unmanaged Helm repositories...`) {
+		t.Errorf("No ‘unmanaged’ Helm repo used in test chartdependency or it doesn’t cause the creation "+
+			"of an ‘ad hoc’ repo index cache file\n%s", out)
+	}
+}
+
+func setupMockRepoServer(t *testing.T) *repotest.Server {
+	srv, err := repotest.NewTempServerWithCleanup(t, "testdata/testcharts/*.tgz")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	t.Logf("Listening on directory %s", srv.Root())
+
+	if err := srv.LinkIndices(); err != nil {
+		t.Fatal(err)
+	}
+
+	return srv
+}
+
 // createTestingMetadata creates a basic chart that depends on reqtest-0.1.0
 //
 // The baseURL can be used to point to a particular repository server.