From 1af05b72f16c90278697c4de76c13095bfd0042b Mon Sep 17 00:00:00 2001
From: Sergei Zharinov <zharinov@users.noreply.github.com>
Date: Thu, 16 Feb 2023 09:35:00 +0300
Subject: [PATCH] feat(bazel): Support GitLab-based http archives (#20393)

---
 lib/modules/manager/bazel/extract.spec.ts | 46 +++++++++++++++++++++++
 lib/modules/manager/bazel/rules/http.ts   | 27 +++++++++++++
 2 files changed, 73 insertions(+)

diff --git a/lib/modules/manager/bazel/extract.spec.ts b/lib/modules/manager/bazel/extract.spec.ts
index 2657dee280..b89b8bf01a 100644
--- a/lib/modules/manager/bazel/extract.spec.ts
+++ b/lib/modules/manager/bazel/extract.spec.ts
@@ -163,5 +163,51 @@ describe('modules/manager/bazel/extract', () => {
       expect(res?.deps).toHaveLength(2);
       expect(res?.deps).toMatchSnapshot();
     });
+
+    it('http_archive with GitLab url', () => {
+      // Sequential http_archive
+      // See https://github.com/aspect-build/rules_swc/commit/d4989f9dfed781dc0226421fb9373b45052e7bc8
+      const res = extractPackageFile(
+        codeBlock`
+          http_archive(
+            name = "eigen3",
+            url = "https://gitlab.com/libeigen/eigen/-/archive/3.3.5/eigen-3.3.5.zip",
+            strip_prefix = "eigen-3.3.5",
+            sha256 = "0e7aeece6c8874146c2a4addc437eebdf1ec4026680270f00e76705c8186f0b5",
+            build_file = "@//third_party:eigen3.BUILD",
+          )
+
+          http_archive(
+            name = "eigen",
+            build_file = "//third_party:eigen.BUILD",
+            sha256 = "d76992f1972e4ff270221c7ee8125610a8e02bb46708a7295ee646e99287083b",  # SHARED_EIGEN_SHA
+            strip_prefix = "eigen-90ee821c563fa20db4d64d6991ddca256d5c52f2",
+            urls = [
+                "https://storage.googleapis.com/mirror.tensorflow.org/gitlab.com/libeigen/eigen/-/archive/90ee821c563fa20db4d64d6991ddca256d5c52f2/eigen-90ee821c563fa20db4d64d6991ddca256d5c52f2.tar.gz",
+                "https://gitlab.com/foo/bar",
+                "https://gitlab.com/libeigen/eigen/-/archive/90ee821c563fa20db4d64d6991ddca256d5c52f2/eigen-90ee821c563fa20db4d64d6991ddca256d5c52f2.tar.gz",
+            ],
+          )
+        `
+      );
+
+      expect(res?.deps).toHaveLength(2);
+      expect(res?.deps).toMatchObject([
+        {
+          currentValue: '3.3.5',
+          datasource: 'gitlab-releases',
+          depName: 'eigen3',
+          depType: 'http_archive',
+          packageName: 'libeigen/eigen',
+        },
+        {
+          currentDigest: '90ee821c563fa20db4d64d6991ddca256d5c52f2',
+          datasource: 'gitlab-tags',
+          depName: 'eigen',
+          depType: 'http_archive',
+          packageName: 'libeigen/eigen',
+        },
+      ]);
+    });
   });
 });
diff --git a/lib/modules/manager/bazel/rules/http.ts b/lib/modules/manager/bazel/rules/http.ts
index f2dbc0f805..16c87fe5a6 100644
--- a/lib/modules/manager/bazel/rules/http.ts
+++ b/lib/modules/manager/bazel/rules/http.ts
@@ -4,6 +4,8 @@ import { escapeRegExp, regEx } from '../../../../util/regex';
 import { parseUrl } from '../../../../util/url';
 import { GithubReleasesDatasource } from '../../../datasource/github-releases';
 import { GithubTagsDatasource } from '../../../datasource/github-tags';
+import { GitlabReleasesDatasource } from '../../../datasource/gitlab-releases';
+import { GitlabTagsDatasource } from '../../../datasource/gitlab-tags';
 import type { PackageDependency } from '../../types';
 
 // Source: https://bazel.build/rules/lib/repo/http
@@ -76,6 +78,27 @@ export function parseGithubPath(
     : { datasource, packageName, currentValue: value };
 }
 
+function parseGitlabPath(pathname: string): Partial<PackageDependency> | null {
+  // https://gitlab.com/libeigen/eigen/-/archive/3.3.5/eigen-3.3.5.zip
+  // https://gitlab.com/libeigen/eigen/-/archive/90ee821c563fa20db4d64d6991ddca256d5c52f2/eigen-90ee821c563fa20db4d64d6991ddca256d5c52f2.tar.gz
+  const [p0, p1, p2, p3, p4] = pathname.split('/').slice(1);
+  const packageName = p0 + '/' + p1;
+  if (p2 === '-' && p3 === 'archive' && p4) {
+    return isHash(p4)
+      ? {
+          datasource: GitlabTagsDatasource.id,
+          packageName,
+          currentDigest: p4,
+        }
+      : {
+          datasource: GitlabReleasesDatasource.id,
+          packageName,
+          currentValue: p4,
+        };
+  }
+  return null;
+}
+
 export function parseArchiveUrl(
   urlString: string | undefined | null
 ): Partial<PackageDependency> | null {
@@ -89,6 +112,10 @@ export function parseArchiveUrl(
     return parseGithubPath(url.pathname);
   }
 
+  if (url?.host === 'gitlab.com') {
+    return parseGitlabPath(url.pathname);
+  }
+
   return null;
 }
 
-- 
GitLab