From 3b1ed2f4656ea216192f21ec3200ec079098d8aa Mon Sep 17 00:00:00 2001
From: Etienne <etienne@kogusenn.com>
Date: Wed, 14 Oct 2020 16:34:37 +0200
Subject: [PATCH] fix(kustomize): lookup Github dependency using HTTP (#7456)

Co-authored-by: Michael Kriese <michael.kriese@visualon.de>
---
 .../__snapshots__/extract.spec.ts.snap        | 34 +++++------
 lib/manager/kustomize/extract.spec.ts         | 57 ++++++++++++-------
 lib/manager/kustomize/extract.ts              | 51 ++++++-----------
 3 files changed, 69 insertions(+), 73 deletions(-)

diff --git a/lib/manager/kustomize/__snapshots__/extract.spec.ts.snap b/lib/manager/kustomize/__snapshots__/extract.spec.ts.snap
index dc1b88f0a5..0d5a444f22 100644
--- a/lib/manager/kustomize/__snapshots__/extract.spec.ts.snap
+++ b/lib/manager/kustomize/__snapshots__/extract.spec.ts.snap
@@ -4,15 +4,13 @@ exports[`manager/kustomize/extract extractPackageFile() extracts http dependency
 Array [
   Object {
     "currentValue": "v0.0.1",
-    "datasource": "git-tags",
-    "depName": "github.com/user/repo//deploy",
-    "lookupName": "github.com/user/repo",
+    "datasource": "github-tags",
+    "depName": "user/repo",
   },
   Object {
     "currentValue": "1.19.0",
     "datasource": "github-tags",
-    "depName": "fluxcd/flux/deploy",
-    "lookupName": "fluxcd/flux",
+    "depName": "fluxcd/flux",
   },
 ]
 `;
@@ -22,14 +20,16 @@ Array [
   Object {
     "currentValue": "v0.0.1",
     "datasource": "git-tags",
-    "depName": "https://moredhel/remote-kustomize.git",
+    "depName": "moredhel/remote-kustomize",
+    "depNameShort": "moredhel/remote-kustomize",
     "lookupName": "https://moredhel/remote-kustomize.git",
   },
   Object {
     "currentValue": "v0.0.1",
     "datasource": "git-tags",
-    "depName": "https://moredhel/remote-kustomize.git//deploy",
-    "lookupName": "https://moredhel/remote-kustomize.git//deploy",
+    "depName": "moredhel/remote-kustomize",
+    "depNameShort": "moredhel/remote-kustomize",
+    "lookupName": "https://moredhel/remote-kustomize.git",
   },
 ]
 `;
@@ -38,9 +38,8 @@ exports[`manager/kustomize/extract extractPackageFile() extracts ssh dependency
 Array [
   Object {
     "currentValue": "v0.0.1",
-    "datasource": "git-tags",
-    "depName": "git@github.com:moredhel/remote-kustomize.git",
-    "lookupName": "git@github.com:moredhel/remote-kustomize.git",
+    "datasource": "github-tags",
+    "depName": "moredhel/remote-kustomize",
   },
 ]
 `;
@@ -49,9 +48,8 @@ exports[`manager/kustomize/extract extractPackageFile() extracts ssh dependency
 Array [
   Object {
     "currentValue": "v2.0.0",
-    "datasource": "git-tags",
-    "depName": "git@github.com:kubernetes-sigs/kustomize.git//examples/helloWorld",
-    "lookupName": "git@github.com:kubernetes-sigs/kustomize.git",
+    "datasource": "github-tags",
+    "depName": "kubernetes-sigs/kustomize",
   },
 ]
 `;
@@ -60,15 +58,13 @@ exports[`manager/kustomize/extract extractPackageFile() should extract bases fro
 Array [
   Object {
     "currentValue": "v0.0.1",
-    "datasource": "git-tags",
-    "depName": "git@github.com:moredhel/remote-kustomize.git",
-    "lookupName": "git@github.com:moredhel/remote-kustomize.git",
+    "datasource": "github-tags",
+    "depName": "moredhel/remote-kustomize",
   },
   Object {
     "currentValue": "1.19.0",
     "datasource": "github-tags",
-    "depName": "fluxcd/flux/deploy",
-    "lookupName": "fluxcd/flux",
+    "depName": "fluxcd/flux",
   },
 ]
 `;
diff --git a/lib/manager/kustomize/extract.spec.ts b/lib/manager/kustomize/extract.spec.ts
index 5c6eb4ed4c..9e9dce489e 100644
--- a/lib/manager/kustomize/extract.spec.ts
+++ b/lib/manager/kustomize/extract.spec.ts
@@ -69,26 +69,47 @@ describe('manager/kustomize/extract', () => {
       const version = 'v1.0.0';
       const sample = {
         currentValue: version,
-        datasource: datasourceGitTags.id,
-        depName: base,
-        lookupName: base,
+        datasource: datasourceGitHubTags.id,
+        depName: 'user/test-repo',
       };
 
       const pkg = extractBase(`${base}?ref=${version}`);
       expect(pkg).toEqual(sample);
     });
-
+    it('should extract the version of a non http base', () => {
+      const pkg = extractBase(
+        'ssh://git@bitbucket.com/user/test-repo?ref=v1.2.3'
+      );
+      expect(pkg).toEqual({
+        currentValue: 'v1.2.3',
+        datasource: datasourceGitTags.id,
+        depName: 'bitbucket.com/user/test-repo',
+        depNameShort: 'user/test-repo',
+        lookupName: 'ssh://git@bitbucket.com/user/test-repo',
+      });
+    });
+    it('should extract the version of a non http base with subdir', () => {
+      const pkg = extractBase(
+        'ssh://git@bitbucket.com/user/test-repo/subdir?ref=v1.2.3'
+      );
+      expect(pkg).toEqual({
+        currentValue: 'v1.2.3',
+        datasource: datasourceGitTags.id,
+        depName: 'bitbucket.com/user/test-repo',
+        depNameShort: 'user/test-repo',
+        lookupName: 'ssh://git@bitbucket.com/user/test-repo',
+      });
+    });
     it('should extract out the version of an github base', () => {
-      const base = 'fluxcd/flux/deploy';
+      const base = 'github.com/fluxcd/flux/deploy';
       const version = 'v1.0.0';
       const sample = {
         currentValue: version,
         datasource: datasourceGitHubTags.id,
-        depName: base,
-        lookupName: 'fluxcd/flux',
+        depName: 'fluxcd/flux',
       };
 
-      const pkg = extractBase(`github.com/${base}?ref=${version}`);
+      const pkg = extractBase(`${base}?ref=${version}`);
       expect(pkg).toEqual(sample);
     });
     it('should extract out the version of a git base', () => {
@@ -96,25 +117,23 @@ describe('manager/kustomize/extract', () => {
       const version = 'v1.0.0';
       const sample = {
         currentValue: version,
-        datasource: datasourceGitTags.id,
-        depName: base,
-        lookupName: base,
+        datasource: datasourceGitHubTags.id,
+        depName: 'user/repo',
       };
 
       const pkg = extractBase(`${base}?ref=${version}`);
       expect(pkg).toEqual(sample);
     });
     it('should extract out the version of a git base with subdir', () => {
-      const base = 'git@github.com:user/repo.git';
+      const base = 'git@github.com:user/repo.git/subdir';
       const version = 'v1.0.0';
       const sample = {
         currentValue: version,
-        datasource: datasourceGitTags.id,
-        depName: `${base}//subdir`,
-        lookupName: base,
+        datasource: datasourceGitHubTags.id,
+        depName: 'user/repo',
       };
 
-      const pkg = extractBase(`${sample.depName}?ref=${version}`);
+      const pkg = extractBase(`${base}?ref=${version}`);
       expect(pkg).toEqual(sample);
     });
   });
@@ -217,8 +236,7 @@ describe('manager/kustomize/extract', () => {
       expect(res.deps).toHaveLength(2);
       expect(res.deps[0].currentValue).toEqual('v0.0.1');
       expect(res.deps[1].currentValue).toEqual('1.19.0');
-      expect(res.deps[1].depName).toEqual('fluxcd/flux/deploy');
-      expect(res.deps[1].lookupName).toEqual('fluxcd/flux');
+      expect(res.deps[1].depName).toEqual('fluxcd/flux');
     });
     it('should extract out image versions', () => {
       const res = extractPackageFile(gitImages);
@@ -240,8 +258,7 @@ describe('manager/kustomize/extract', () => {
       expect(res.deps).toHaveLength(2);
       expect(res.deps[0].currentValue).toEqual('v0.0.1');
       expect(res.deps[1].currentValue).toEqual('1.19.0');
-      expect(res.deps[1].depName).toEqual('fluxcd/flux/deploy');
-      expect(res.deps[1].lookupName).toEqual('fluxcd/flux');
+      expect(res.deps[1].depName).toEqual('fluxcd/flux');
     });
   });
 });
diff --git a/lib/manager/kustomize/extract.ts b/lib/manager/kustomize/extract.ts
index 0468db0a28..00c73bec4a 100644
--- a/lib/manager/kustomize/extract.ts
+++ b/lib/manager/kustomize/extract.ts
@@ -18,49 +18,32 @@ interface Kustomize {
   images: Image[];
 }
 
-// extract the version from the url
-const versionMatch = /(?<basename>.*)\?ref=(?<version>.*)\s*$/;
-
-// extract the url from the base of a url with a subdir
-const extractUrl = /^(?<url>.*)(?:\/\/.*)$/;
-
-const githubUrl = /^github\.com\/(?<depName>(?<lookupName>[^/]+?\/[^/]+?)(?:\/[^/]+?)*)\?ref=(?<currentValue>.+)$/;
+// URL specifications should follow the hashicorp URL format
+// https://github.com/hashicorp/go-getter#url-format
+const gitUrl = /^(?:git::)?(?<url>(?:(?:(?:http|https|ssh):\/\/)?(?:.*@)?)?(?<path>(?:[^:/]+[:/])?(?<project>[^/]+\/[^/]+)))(?<subdir>[^?]*)\?ref=(?<currentValue>.+)$/;
 
 export function extractBase(base: string): PackageDependency | null {
-  const githubMatch = githubUrl.exec(base);
-
-  if (githubMatch?.groups) {
-    const { currentValue, depName, lookupName } = githubMatch.groups;
+  const match = gitUrl.exec(base);
 
-    return {
-      datasource: datasourceGitHubTags.id,
-      depName,
-      lookupName,
-      currentValue,
-    };
+  if (!match) {
+    return null;
   }
 
-  const basenameVersion = versionMatch.exec(base);
-  if (basenameVersion) {
-    const currentValue = basenameVersion.groups.version;
-    const root = basenameVersion.groups.basename;
-
-    const urlResult = extractUrl.exec(root);
-    let url = root;
-    // if a match, then there was a subdir, update
-    if (urlResult && !url.startsWith('http')) {
-      url = urlResult.groups.url;
-    }
-
+  if (match?.groups.path.startsWith('github.com')) {
     return {
-      datasource: datasourceGitTags.id,
-      depName: root,
-      lookupName: url,
-      currentValue,
+      currentValue: match.groups.currentValue,
+      datasource: datasourceGitHubTags.id,
+      depName: match.groups.project.replace('.git', ''),
     };
   }
 
-  return null;
+  return {
+    datasource: datasourceGitTags.id,
+    depName: match.groups.path.replace('.git', ''),
+    depNameShort: match.groups.project.replace('.git', ''),
+    lookupName: match.groups.url,
+    currentValue: match.groups.currentValue,
+  };
 }
 
 export function extractImage(image: Image): PackageDependency | null {
-- 
GitLab