From 5c145796bd6a50e83549fe327ea6905f92b025ad Mon Sep 17 00:00:00 2001
From: lstoeferle <48953604+lstoeferle@users.noreply.github.com>
Date: Mon, 18 Mar 2024 09:40:09 +0100
Subject: [PATCH] feat(terragrunt): add support for gitlab-tags datasource
 (#27903)

---
 .../manager/terragrunt/__fixtures__/2.hcl     |  27 +++-
 .../manager/terragrunt/__fixtures__/3.hcl     |  28 +++-
 .../manager/terragrunt/__fixtures__/4.hcl     |  29 +++-
 .../manager/terragrunt/extract.spec.ts        | 141 +++++++++++++-----
 lib/modules/manager/terragrunt/index.ts       |   6 +
 lib/modules/manager/terragrunt/modules.ts     |  20 ++-
 6 files changed, 193 insertions(+), 58 deletions(-)

diff --git a/lib/modules/manager/terragrunt/__fixtures__/2.hcl b/lib/modules/manager/terragrunt/__fixtures__/2.hcl
index b99906d626..f38c392445 100644
--- a/lib/modules/manager/terragrunt/__fixtures__/2.hcl
+++ b/lib/modules/manager/terragrunt/__fixtures__/2.hcl
@@ -127,32 +127,32 @@ terraform {
 
 # foobar
 terraform {
-  source = "https://bitbucket.com/hashicorp/example?ref=v1.0.0"
+  source = "https://mygit.com/hashicorp/example?ref=v1.0.0"
 }
 
 # gittags
 terraform {
-  source = "git::https://bitbucket.com/hashicorp/example?ref=v1.0.0"
+  source = "git::https://mygit.com/hashicorp/example?ref=v1.0.0"
 }
 
 # gittags_badversion
 terraform {
-  source = "git::https://bitbucket.com/hashicorp/example?ref=next"
+  source = "git::https://mygit.com/hashicorp/example?ref=next"
 }
 
 # gittags_subdir
 terraform {
-  source = "git::https://bitbucket.com/hashicorp/example//subdir/test?ref=v1.0.1"
+  source = "git::https://mygit.com/hashicorp/example//subdir/test?ref=v1.0.1"
 }
 
 # gittags_http
 terraform {
-  source = "git::http://bitbucket.com/hashicorp/example?ref=v1.0.2"
+  source = "git::http://mygit.com/hashicorp/example?ref=v1.0.2"
 }
 
 # gittags_ssh
 terraform {
-  source = "git::ssh://git@bitbucket.com/hashicorp/example?ref=v1.0.3"
+  source = "git::ssh://git@mygit.com/hashicorp/example?ref=v1.0.3"
 }
 
 # invalid, ignored by test since it does not have source on the next line
@@ -164,3 +164,18 @@ terraform {
   name  = "foo"
   dummy = "true"
 }
+
+# bitbucket-tags
+terraform {
+  source = "git::https://bitbucket.com/hashicorp/example?ref=v1.0.0"
+}
+
+# gitlab-tags
+terraform {
+  source = "git::https://gitlab.com/hashicorp/example?ref=v1.0.0"
+}
+
+# gitea-tags
+terraform {
+  source = "git::https://gitea.com/hashicorp/example?ref=v1.0.0"
+}
diff --git a/lib/modules/manager/terragrunt/__fixtures__/3.hcl b/lib/modules/manager/terragrunt/__fixtures__/3.hcl
index bfb076653d..3cf9e16f8b 100644
--- a/lib/modules/manager/terragrunt/__fixtures__/3.hcl
+++ b/lib/modules/manager/terragrunt/__fixtures__/3.hcl
@@ -127,32 +127,32 @@ terraform {
 
 # foobar
 terraform {
-  source = "https://bitbucket.com/hashicorp/example?ref=v1.0.0&depth=1"
+  source = "https://mygit.com/hashicorp/example?ref=v1.0.0&depth=1"
 }
 
 # gittags
 terraform {
-  source = "git::https://bitbucket.com/hashicorp/example?ref=v1.0.0&depth=1"
+  source = "git::https://mygit.com/hashicorp/example?ref=v1.0.0&depth=1"
 }
 
 # gittags_badversion
 terraform {
-  source = "git::https://bitbucket.com/hashicorp/example?ref=next&depth=1"
+  source = "git::https://mygit.com/hashicorp/example?ref=next&depth=1"
 }
 
 # gittags_subdir
 terraform {
-  source = "git::https://bitbucket.com/hashicorp/example//subdir/test?ref=v1.0.1&depth=1"
+  source = "git::https://mygit.com/hashicorp/example//subdir/test?ref=v1.0.1&depth=1"
 }
 
 # gittags_http
 terraform {
-  source = "git::http://bitbucket.com/hashicorp/example?ref=v1.0.2&depth=1"
+  source = "git::http://mygit.com/hashicorp/example?ref=v1.0.2&depth=1"
 }
 
 # gittags_ssh
 terraform {
-  source = "git::ssh://git@bitbucket.com/hashicorp/example?ref=v1.0.3&depth=1"
+  source = "git::ssh://git@mygit.com/hashicorp/example?ref=v1.0.3&depth=1"
 }
 
 # invalid, ignored by test since it does not have source on the next line
@@ -164,3 +164,19 @@ terraform {
   name  = "foo"
   dummy = "true"
 }
+
+# bitbucket-tags
+terraform {
+  source = "git::https://bitbucket.com/hashicorp/example?ref=v1.0.0"
+}
+
+# gitlab-tags
+terraform {
+  source = "git::https://gitlab.com/hashicorp/example?ref=v1.0.0"
+}
+
+# gitea-tags
+terraform {
+  source = "git::https://gitea.com/hashicorp/example?ref=v1.0.0"
+}
+
diff --git a/lib/modules/manager/terragrunt/__fixtures__/4.hcl b/lib/modules/manager/terragrunt/__fixtures__/4.hcl
index 72889fb6ae..2eef263e14 100644
--- a/lib/modules/manager/terragrunt/__fixtures__/4.hcl
+++ b/lib/modules/manager/terragrunt/__fixtures__/4.hcl
@@ -127,32 +127,32 @@ terraform {
 
 # foobar
 terraform {
-  source = "https://bitbucket.com/hashicorp/example?depth=1&ref=v1.0.0"
+  source = "https://mygit.com/hashicorp/example?depth=1&ref=v1.0.0"
 }
 
 # gittags
 terraform {
-  source = "git::https://bitbucket.com/hashicorp/example?depth=1&ref=v1.0.0"
+  source = "git::https://mygit.com/hashicorp/example?depth=1&ref=v1.0.0"
 }
 
 # gittags_badversion
 terraform {
-  source = "git::https://bitbucket.com/hashicorp/example?depth=1&ref=next"
+  source = "git::https://mygit.com/hashicorp/example?depth=1&ref=next"
 }
 
 # gittags_subdir
 terraform {
-  source = "git::https://bitbucket.com/hashicorp/example//subdir/test?depth=1&ref=v1.0.1"
+  source = "git::https://mygit.com/hashicorp/example//subdir/test?depth=1&ref=v1.0.1"
 }
 
 # gittags_http
 terraform {
-  source = "git::http://bitbucket.com/hashicorp/example?depth=1&ref=v1.0.2"
+  source = "git::http://mygit.com/hashicorp/example?depth=1&ref=v1.0.2"
 }
 
 # gittags_ssh
 terraform {
-  source = "git::ssh://git@bitbucket.com/hashicorp/example?depth=1&ref=v1.0.3"
+  source = "git::ssh://git@mygit.com/hashicorp/example?depth=1&ref=v1.0.3"
 }
 
 # invalid, ignored by test since it does not have source on the next line
@@ -164,3 +164,20 @@ terraform {
   name  = "foo"
   dummy = "true"
 }
+
+
+# bitbucket-tags
+terraform {
+  source = "git::https://bitbucket.com/hashicorp/example?ref=v1.0.0"
+}
+
+# gitlab-tags
+terraform {
+  source = "git::https://gitlab.com/hashicorp/example?ref=v1.0.0"
+}
+
+# gitea-tags
+terraform {
+  source = "git::https://gitea.com/hashicorp/example?ref=v1.0.0"
+}
+
diff --git a/lib/modules/manager/terragrunt/extract.spec.ts b/lib/modules/manager/terragrunt/extract.spec.ts
index bcba2edcbf..bf997f1465 100644
--- a/lib/modules/manager/terragrunt/extract.spec.ts
+++ b/lib/modules/manager/terragrunt/extract.spec.ts
@@ -155,44 +155,44 @@ describe('modules/manager/terragrunt/extract', () => {
           {
             currentValue: 'v1.0.0',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.0',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'next',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.1',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.2',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'http://bitbucket.com/hashicorp/example',
+            packageName: 'http://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.3',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'ssh://git@bitbucket.com/hashicorp/example',
+            packageName: 'ssh://git@mygit.com/hashicorp/example',
           },
           {
             skipReason: 'no-source',
@@ -200,9 +200,30 @@ describe('modules/manager/terragrunt/extract', () => {
           {
             skipReason: 'no-source',
           },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'bitbucket-tags',
+            depName: 'bitbucket.com/hashicorp/example',
+            depType: 'gitTags',
+            packageName: 'https://bitbucket.com/hashicorp/example',
+          },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'gitlab-tags',
+            depName: 'gitlab.com/hashicorp/example',
+            depType: 'gitTags',
+            packageName: 'https://gitlab.com/hashicorp/example',
+          },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'gitea-tags',
+            depName: 'gitea.com/hashicorp/example',
+            depType: 'gitTags',
+            packageName: 'https://gitea.com/hashicorp/example',
+          },
         ],
       });
-      expect(res?.deps).toHaveLength(30);
+      expect(res?.deps).toHaveLength(33);
       expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(4);
     });
 
@@ -320,44 +341,44 @@ describe('modules/manager/terragrunt/extract', () => {
           {
             currentValue: 'v1.0.0',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.0',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'next',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.1',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.2',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'http://bitbucket.com/hashicorp/example',
+            packageName: 'http://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.3',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'ssh://git@bitbucket.com/hashicorp/example',
+            packageName: 'ssh://git@mygit.com/hashicorp/example',
           },
           {
             skipReason: 'no-source',
@@ -365,9 +386,30 @@ describe('modules/manager/terragrunt/extract', () => {
           {
             skipReason: 'no-source',
           },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'bitbucket-tags',
+            depName: 'bitbucket.com/hashicorp/example',
+            depType: 'gitTags',
+            packageName: 'https://bitbucket.com/hashicorp/example',
+          },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'gitlab-tags',
+            depName: 'gitlab.com/hashicorp/example',
+            depType: 'gitTags',
+            packageName: 'https://gitlab.com/hashicorp/example',
+          },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'gitea-tags',
+            depName: 'gitea.com/hashicorp/example',
+            depType: 'gitTags',
+            packageName: 'https://gitea.com/hashicorp/example',
+          },
         ],
       });
-      expect(res?.deps).toHaveLength(30);
+      expect(res?.deps).toHaveLength(33);
       expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(4);
     });
 
@@ -485,44 +527,44 @@ describe('modules/manager/terragrunt/extract', () => {
           {
             currentValue: 'v1.0.0',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.0',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'next',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.1',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'https://bitbucket.com/hashicorp/example',
+            packageName: 'https://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.2',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'http://bitbucket.com/hashicorp/example',
+            packageName: 'http://mygit.com/hashicorp/example',
           },
           {
             currentValue: 'v1.0.3',
             datasource: 'git-tags',
-            depName: 'bitbucket.com/hashicorp/example',
+            depName: 'mygit.com/hashicorp/example',
             depType: 'gitTags',
-            packageName: 'ssh://git@bitbucket.com/hashicorp/example',
+            packageName: 'ssh://git@mygit.com/hashicorp/example',
           },
           {
             skipReason: 'no-source',
@@ -530,9 +572,30 @@ describe('modules/manager/terragrunt/extract', () => {
           {
             skipReason: 'no-source',
           },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'bitbucket-tags',
+            depName: 'bitbucket.com/hashicorp/example',
+            depType: 'gitTags',
+            packageName: 'https://bitbucket.com/hashicorp/example',
+          },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'gitlab-tags',
+            depName: 'gitlab.com/hashicorp/example',
+            depType: 'gitTags',
+            packageName: 'https://gitlab.com/hashicorp/example',
+          },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'gitea-tags',
+            depName: 'gitea.com/hashicorp/example',
+            depType: 'gitTags',
+            packageName: 'https://gitea.com/hashicorp/example',
+          },
         ],
       });
-      expect(res?.deps).toHaveLength(30);
+      expect(res?.deps).toHaveLength(33);
       expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(4);
     });
 
diff --git a/lib/modules/manager/terragrunt/index.ts b/lib/modules/manager/terragrunt/index.ts
index 58864cf7f5..9343bcd0c5 100644
--- a/lib/modules/manager/terragrunt/index.ts
+++ b/lib/modules/manager/terragrunt/index.ts
@@ -1,6 +1,9 @@
 import type { Category } from '../../../constants';
+import { BitbucketTagsDatasource } from '../../datasource/bitbucket-tags';
 import { GitTagsDatasource } from '../../datasource/git-tags';
+import { GiteaTagsDatasource } from '../../datasource/gitea-tags';
 import { GithubTagsDatasource } from '../../datasource/github-tags';
+import { GitlabTagsDatasource } from '../../datasource/gitlab-tags';
 import { TerraformModuleDatasource } from '../../datasource/terraform-module';
 
 export { updateArtifacts } from './artifacts';
@@ -9,6 +12,9 @@ export { extractPackageFile } from './extract';
 export const supportedDatasources = [
   GitTagsDatasource.id,
   GithubTagsDatasource.id,
+  GitlabTagsDatasource.id,
+  BitbucketTagsDatasource.id,
+  GiteaTagsDatasource.id,
   TerraformModuleDatasource.id,
 ];
 
diff --git a/lib/modules/manager/terragrunt/modules.ts b/lib/modules/manager/terragrunt/modules.ts
index 01fc5b4356..f881a78a95 100644
--- a/lib/modules/manager/terragrunt/modules.ts
+++ b/lib/modules/manager/terragrunt/modules.ts
@@ -1,7 +1,11 @@
 import { logger } from '../../../logger';
+import { detectPlatform } from '../../../util/common';
 import { regEx } from '../../../util/regex';
+import { BitbucketTagsDatasource } from '../../datasource/bitbucket-tags';
 import { GitTagsDatasource } from '../../datasource/git-tags';
+import { GiteaTagsDatasource } from '../../datasource/gitea-tags';
 import { GithubTagsDatasource } from '../../datasource/github-tags';
+import { GitlabTagsDatasource } from '../../datasource/gitlab-tags';
 import { TerraformModuleDatasource } from '../../datasource/terraform-module';
 import type { PackageDependency } from '../types';
 import { extractTerragruntProvider } from './providers';
@@ -31,6 +35,20 @@ export function extractTerragruntModule(
   return result;
 }
 
+function detectGitTagDatasource(registryUrl: string): string {
+  const platform = detectPlatform(registryUrl);
+  switch (platform) {
+    case 'gitlab':
+      return GitlabTagsDatasource.id;
+    case 'bitbucket':
+      return BitbucketTagsDatasource.id;
+    case 'gitea':
+      return GiteaTagsDatasource.id;
+    default:
+      return GitTagsDatasource.id;
+  }
+}
+
 export function analyseTerragruntModule(
   dep: PackageDependency<TerraformManagerData>,
 ): void {
@@ -61,7 +79,7 @@ export function analyseTerragruntModule(
       dep.packageName = gitTagsRefMatch.groups.url;
     }
     dep.currentValue = gitTagsRefMatch.groups.tag;
-    dep.datasource = GitTagsDatasource.id;
+    dep.datasource = detectGitTagDatasource(gitTagsRefMatch.groups.url);
   } else if (tfrVersionMatch?.groups) {
     dep.depType = 'terragrunt';
     dep.depName =
-- 
GitLab