From fcd5b188c7fb732d1ce19f83e8c7ecd256a3df07 Mon Sep 17 00:00:00 2001
From: Michael Kriese <michael.kriese@visualon.de>
Date: Wed, 14 Jun 2023 16:26:57 +0200
Subject: [PATCH] fix(terraform): support more local path modules (#22758)

---
 .../manager/terraform/__fixtures__/modules.tf |  4 +++
 lib/modules/manager/terraform/extract.spec.ts | 16 +++++++++--
 .../terraform/extractors/others/modules.ts    | 28 +++++++++----------
 3 files changed, 32 insertions(+), 16 deletions(-)

diff --git a/lib/modules/manager/terraform/__fixtures__/modules.tf b/lib/modules/manager/terraform/__fixtures__/modules.tf
index 78bbe42af1..bbe27a63c0 100644
--- a/lib/modules/manager/terraform/__fixtures__/modules.tf
+++ b/lib/modules/manager/terraform/__fixtures__/modules.tf
@@ -132,6 +132,10 @@ module "relative" {
   source = "../../modules/fe"
 }
 
+module "relative" {
+  source = "./relative"
+}
+
 module "nosauce" {
   foo = "bar"
 }
diff --git a/lib/modules/manager/terraform/extract.spec.ts b/lib/modules/manager/terraform/extract.spec.ts
index 9d9a546a45..f2f59d12a8 100644
--- a/lib/modules/manager/terraform/extract.spec.ts
+++ b/lib/modules/manager/terraform/extract.spec.ts
@@ -53,8 +53,8 @@ describe('modules/manager/terraform/extract', () => {
 
     it('extracts  modules', async () => {
       const res = await extractPackageFile(modules, 'modules.tf', {});
-      expect(res?.deps).toHaveLength(18);
-      expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(2);
+      expect(res?.deps).toHaveLength(19);
+      expect(res?.deps.filter((dep) => dep.skipReason)).toHaveLength(3);
       expect(res?.deps).toIncludeAllPartialMembers([
         {
           packageName: 'hashicorp/example',
@@ -170,9 +170,21 @@ describe('modules/manager/terraform/extract', () => {
           datasource: 'terraform-module',
         },
         {
+          depName: 'relative',
+          depType: 'module',
+          currentValue: undefined,
           skipReason: 'local',
         },
         {
+          depName: 'relative',
+          depType: 'module',
+          currentValue: undefined,
+          skipReason: 'local',
+        },
+        {
+          depName: 'nosauce',
+          depType: 'module',
+          currentValue: undefined,
           skipReason: 'no-source',
         },
       ]);
diff --git a/lib/modules/manager/terraform/extractors/others/modules.ts b/lib/modules/manager/terraform/extractors/others/modules.ts
index 2c135d995d..a80351f126 100644
--- a/lib/modules/manager/terraform/extractors/others/modules.ts
+++ b/lib/modules/manager/terraform/extractors/others/modules.ts
@@ -41,15 +41,20 @@ export class ModuleExtractor extends DependencyExtractor {
     }
 
     const dependencies = [];
-    for (const moduleElement of Object.values(modules).flat()) {
-      const dep = {
-        currentValue: moduleElement.version,
-        managerData: {
-          source: moduleElement.source,
-        },
-      };
-      dependencies.push(this.analyseTerraformModule(dep));
+    for (const [depName, moduleElements] of Object.entries(modules)) {
+      for (const moduleElement of moduleElements) {
+        const dep = {
+          depName,
+          depType: 'module',
+          currentValue: moduleElement.version,
+          managerData: {
+            source: moduleElement.source,
+          },
+        };
+        dependencies.push(this.analyseTerraformModule(dep));
+      }
     }
+
     return dependencies;
   }
 
@@ -66,12 +71,10 @@ export class ModuleExtractor extends DependencyExtractor {
         regEx(/\.git$/),
         ''
       );
-      dep.depType = 'module';
       dep.depName = 'github.com/' + dep.packageName;
       dep.currentValue = githubRefMatch.groups.tag;
       dep.datasource = GithubTagsDatasource.id;
     } else if (bitbucketRefMatch?.groups) {
-      dep.depType = 'module';
       dep.depName =
         bitbucketRefMatch.groups.workspace +
         '/' +
@@ -80,13 +83,11 @@ export class ModuleExtractor extends DependencyExtractor {
       dep.currentValue = bitbucketRefMatch.groups.tag;
       dep.datasource = BitbucketTagsDatasource.id;
     } else if (azureDevOpsSshRefMatch?.groups) {
-      dep.depType = 'module';
       dep.depName = `${azureDevOpsSshRefMatch.groups.organization}/${azureDevOpsSshRefMatch.groups.project}/${azureDevOpsSshRefMatch.groups.repository}${azureDevOpsSshRefMatch.groups.modulepath}`;
       dep.packageName = azureDevOpsSshRefMatch.groups.url;
       dep.currentValue = azureDevOpsSshRefMatch.groups.tag;
       dep.datasource = GitTagsDatasource.id;
     } else if (gitTagsRefMatch?.groups) {
-      dep.depType = 'module';
       if (gitTagsRefMatch.groups.path.includes('//')) {
         logger.debug('Terraform module contains subdirectory');
         dep.depName = gitTagsRefMatch.groups.path.split('//')[0];
@@ -100,14 +101,13 @@ export class ModuleExtractor extends DependencyExtractor {
       dep.datasource = GitTagsDatasource.id;
     } else if (source) {
       const moduleParts = source.split('//')[0].split('/');
-      if (moduleParts[0] === '..') {
+      if (moduleParts[0] === '.' || moduleParts[0] === '..') {
         dep.skipReason = 'local';
       } else if (moduleParts.length >= 3) {
         const hostnameMatch = hostnameMatchRegex.exec(source);
         if (hostnameMatch?.groups) {
           dep.registryUrls = [`https://${hostnameMatch.groups.hostname}`];
         }
-        dep.depType = 'module';
         dep.depName = moduleParts.join('/');
         dep.datasource = TerraformModuleDatasource.id;
       }
-- 
GitLab