From 0e330ea7650f85b4edd9cbb9b39d931cb9425648 Mon Sep 17 00:00:00 2001
From: Philip <42116482+PhilipAbed@users.noreply.github.com>
Date: Sun, 21 Jul 2024 15:14:54 +0300
Subject: [PATCH] fix(helmfile): support case with oci repository in different
 document (#30215)

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
---
 lib/modules/manager/helmfile/extract.spec.ts | 31 ++++++++++++++++++++
 lib/modules/manager/helmfile/extract.ts      | 28 ++++++++++--------
 2 files changed, 46 insertions(+), 13 deletions(-)

diff --git a/lib/modules/manager/helmfile/extract.spec.ts b/lib/modules/manager/helmfile/extract.spec.ts
index e2378baf3c..c3b1a7be23 100644
--- a/lib/modules/manager/helmfile/extract.spec.ts
+++ b/lib/modules/manager/helmfile/extract.spec.ts
@@ -363,6 +363,37 @@ describe('modules/manager/helmfile/extract', () => {
       });
     });
 
+    it('parses a chart with an oci repository with ---', async () => {
+      const content = codeBlock`
+      repositories:
+        - name: oci-repo
+          url: ghcr.io/example/oci-repo
+          oci: true
+      ---
+      releases:
+        - name: example
+          version: 0.1.0
+          chart: oci-repo/example
+      `;
+      const fileName = 'helmfile.yaml';
+      const result = await extractPackageFile(content, fileName, {
+        registryAliases: {
+          stable: 'https://charts.helm.sh/stable',
+        },
+      });
+      expect(result).toMatchObject({
+        datasource: 'helm',
+        deps: [
+          {
+            currentValue: '0.1.0',
+            depName: 'example',
+            datasource: 'docker',
+            packageName: 'ghcr.io/example/oci-repo/example',
+          },
+        ],
+      });
+    });
+
     it('parses and replaces templating strings', async () => {
       const filename = 'helmfile.yaml';
       fs.localPathExists.mockReturnValue(Promise.resolve(true));
diff --git a/lib/modules/manager/helmfile/extract.ts b/lib/modules/manager/helmfile/extract.ts
index 83878a2023..f20ed1d61f 100644
--- a/lib/modules/manager/helmfile/extract.ts
+++ b/lib/modules/manager/helmfile/extract.ts
@@ -2,6 +2,7 @@ import is from '@sindresorhus/is';
 import { logger } from '../../../logger';
 import { coerceArray } from '../../../util/array';
 import { regEx } from '../../../util/regex';
+import { joinUrlParts } from '../../../util/url';
 import { parseYaml } from '../../../util/yaml';
 import { DockerDatasource } from '../../datasource/docker';
 import { HelmDatasource } from '../../datasource/helm';
@@ -11,7 +12,7 @@ import type {
   PackageDependency,
   PackageFileContent,
 } from '../types';
-import type { Doc } from './schema';
+import type { Doc, HelmRepository } from './schema';
 import { Doc as documentSchema } from './schema';
 import {
   kustomizationsKeysUsed,
@@ -34,7 +35,7 @@ export async function extractPackageFile(
 ): Promise<PackageFileContent | null> {
   const deps: PackageDependency[] = [];
   let docs: Doc[];
-  let registryAliases: Record<string, string> = {};
+  let registryData: Record<string, HelmRepository> = {};
   // Record kustomization usage for all deps, since updating artifacts is run on the helmfile.yaml as a whole.
   let needKustomize = false;
   try {
@@ -51,15 +52,16 @@ export async function extractPackageFile(
     );
     return null;
   }
+
   for (const doc of docs) {
     // Always check for repositories in the current document and override the existing ones if any (as YAML does)
     if (doc.repositories) {
-      registryAliases = {};
+      registryData = {};
       for (let i = 0; i < doc.repositories.length; i += 1) {
-        registryAliases[doc.repositories[i].name] = doc.repositories[i].url;
+        registryData[doc.repositories[i].name] = doc.repositories[i];
       }
       logger.debug(
-        { registryAliases, packageFile },
+        { registryAliases: registryData, packageFile },
         `repositories discovered.`,
       );
     }
@@ -106,23 +108,23 @@ export async function extractPackageFile(
       const res: PackageDependency = {
         depName,
         currentValue: dep.version,
-        registryUrls: [registryAliases[repoName]]
+        registryUrls: [registryData[repoName]?.url]
           .concat([config.registryAliases?.[repoName]] as string[])
           .filter(is.string),
       };
       if (kustomizationsKeysUsed(dep)) {
         needKustomize = true;
       }
-      // in case of OCI repository, we need a PackageDependency with a DockerDatasource and a packageName
-      const repository = doc.repositories?.find(
-        (repo) => repo.name === repoName,
-      );
+
       if (isOCIRegistry(dep.chart)) {
         res.datasource = DockerDatasource.id;
-        res.packageName = repoName + '/' + depName;
-      } else if (repository?.oci) {
+        res.packageName = joinUrlParts(repoName, depName);
+      } else if (registryData[repoName]?.oci) {
         res.datasource = DockerDatasource.id;
-        res.packageName = registryAliases[repoName] + '/' + depName;
+        const alias = registryData[repoName]?.url;
+        if (alias) {
+          res.packageName = joinUrlParts(alias, depName);
+        }
       }
 
       // By definition on helm the chart name should be lowercase letter + number + -
-- 
GitLab