From 4c0ecc86fe3d7d0897e8bb95c977e7be0dce3e61 Mon Sep 17 00:00:00 2001
From: Flo Everett <73506550+flo-everett-xero@users.noreply.github.com>
Date: Tue, 1 Nov 2022 03:09:00 -0400
Subject: [PATCH] fix(git-refs): search hostRules by http url, not ssh.
 (#17868)

---
 lib/util/git/url.spec.ts | 39 +++++++++++++++++++++++++++++++++++++++
 lib/util/git/url.ts      | 18 +++++++++++++++++-
 2 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/lib/util/git/url.spec.ts b/lib/util/git/url.spec.ts
index 7dfee16cd9..cc05cc63e2 100644
--- a/lib/util/git/url.spec.ts
+++ b/lib/util/git/url.spec.ts
@@ -59,6 +59,18 @@ describe('util/git/url', () => {
         getHttpUrl('http://gitlab.com:8443/', 'gitlab-ci-token:token')
       ).toBe('http://gitlab-ci-token:token@gitlab.com:8443/');
     });
+
+    it('returns github url with token', () => {
+      expect(getHttpUrl('http://github.com/', 'token')).toBe(
+        'http://x-access-token:token@github.com/'
+      );
+      expect(getHttpUrl('http://github.com/', 'x-access-token:token')).toBe(
+        'http://x-access-token:token@github.com/'
+      );
+      expect(
+        getHttpUrl('http://github.com:8443/', 'x-access-token:token')
+      ).toBe('http://x-access-token:token@github.com:8443/');
+    });
   });
 
   describe('getRemoteUrlWithToken()', () => {
@@ -68,6 +80,24 @@ describe('util/git/url', () => {
       );
     });
 
+    it('transforms an ssh git url to https for the purpose of finding hostRules', () => {
+      getRemoteUrlWithToken('git@foo.bar:some/repo');
+      expect(hostRules.find).toHaveBeenLastCalledWith(
+        expect.objectContaining({
+          url: 'https://foo.bar/some/repo',
+        })
+      );
+    });
+
+    it('does not transform urls that are not parseable as git urls', () => {
+      getRemoteUrlWithToken('abcdefg');
+      expect(hostRules.find).toHaveBeenLastCalledWith(
+        expect.objectContaining({
+          url: 'abcdefg',
+        })
+      );
+    });
+
     it('returns http url with token', () => {
       hostRules.find.mockReturnValueOnce({ token: 'token' });
       expect(getRemoteUrlWithToken('http://foo.bar/')).toBe(
@@ -144,5 +174,14 @@ describe('util/git/url', () => {
         'https://gitlab-ci-token:token@gitlab.com/some/repo.git'
       );
     });
+
+    it('returns https url for ssh url with encoded github token', () => {
+      hostRules.find.mockReturnValueOnce({
+        token: 'token',
+      });
+      expect(getRemoteUrlWithToken('ssh://github.com/some/repo.git')).toBe(
+        'https://x-access-token:token@github.com/some/repo.git'
+      );
+    });
   });
 });
diff --git a/lib/util/git/url.ts b/lib/util/git/url.ts
index 7136246621..7857f66bd9 100644
--- a/lib/util/git/url.ts
+++ b/lib/util/git/url.ts
@@ -19,6 +19,12 @@ export function getHttpUrl(url: string, token?: string): string {
         parsedUrl.token = token.includes(':')
           ? token
           : `gitlab-ci-token:${token}`;
+        break;
+      case 'github':
+        parsedUrl.token = token.includes(':')
+          ? token
+          : `x-access-token:${token}`;
+        break;
     }
   }
 
@@ -29,7 +35,17 @@ export function getHttpUrl(url: string, token?: string): string {
 }
 
 export function getRemoteUrlWithToken(url: string, hostType?: string): string {
-  const hostRule = hostRules.find({ url, hostType });
+  let coercedUrl: string;
+
+  try {
+    coercedUrl = getHttpUrl(url);
+  } catch {
+    logger.warn(`Attempting to use non-git url '${url}' for git operations`);
+
+    coercedUrl = url;
+  }
+
+  const hostRule = hostRules.find({ url: coercedUrl, hostType });
 
   if (hostRule?.token) {
     logger.debug(`Found hostRules token for url ${url}`);
-- 
GitLab