From 290463747fd26960a2f9abddd422ee90d411a2a8 Mon Sep 17 00:00:00 2001
From: Spencer Williams <s@spencerenglish.com>
Date: Thu, 18 May 2023 00:41:03 -0700
Subject: [PATCH] feat(manager/terragrunt): support lockFileMaintenance
 (#20833)

Co-authored-by: Rhys Arkins <rhys@arkins.net>
Co-authored-by: Sebastian Poxhofer <secustor@users.noreply.github.com>
---
 .../manager/terragrunt/artifacts.spec.ts      | 71 +++++++++++++++++++
 lib/modules/manager/terragrunt/artifacts.ts   | 18 +++++
 lib/modules/manager/terragrunt/index.ts       |  2 +
 lib/modules/manager/terragrunt/readme.md      |  5 ++
 4 files changed, 96 insertions(+)
 create mode 100644 lib/modules/manager/terragrunt/artifacts.spec.ts
 create mode 100644 lib/modules/manager/terragrunt/artifacts.ts

diff --git a/lib/modules/manager/terragrunt/artifacts.spec.ts b/lib/modules/manager/terragrunt/artifacts.spec.ts
new file mode 100644
index 0000000000..d69cc1ba35
--- /dev/null
+++ b/lib/modules/manager/terragrunt/artifacts.spec.ts
@@ -0,0 +1,71 @@
+import { join } from 'upath';
+import { GlobalConfig } from '../../../config/global';
+import type { UpdateType } from '../../../config/types';
+import * as terraformLockfile from '../terraform/lockfile';
+import type { UpdateArtifactsConfig } from '../types';
+import { updateArtifacts } from './artifacts';
+
+jest.mock('../terraform/lockfile');
+
+const config = {
+  constraints: {},
+};
+
+const adminConfig = {
+  // `join` fixes Windows CI
+  localDir: join('/tmp/github/some/repo'),
+  cacheDir: join('/tmp/renovate/cache'),
+  containerbaseDir: join('/tmp/renovate/cache/containerbase'),
+};
+
+describe('modules/manager/terragrunt/artifacts', () => {
+  const updateTypes: UpdateType[] = [
+    'digest',
+    'pin',
+    'rollback',
+    'patch',
+    'minor',
+    'major',
+    'replacement',
+    'pinDigest',
+    'lockfileUpdate',
+    'bump',
+  ];
+
+  beforeEach(() => {
+    GlobalConfig.set(adminConfig);
+  });
+
+  it('calls terraform updateArtifacts if the update type is lockfileMaintenance', async () => {
+    const localConfig: UpdateArtifactsConfig = {
+      updateType: 'lockFileMaintenance',
+      ...config,
+    };
+
+    await updateArtifacts({
+      packageFileName: '',
+      updatedDeps: [],
+      newPackageFileContent: '',
+      config: localConfig,
+    });
+    expect(terraformLockfile.updateArtifacts).toHaveBeenCalledOnce();
+  });
+
+  it.each(updateTypes)(
+    'does not call terraform updateArtifacts if the update type is %s',
+    async (updateType) => {
+      const localConfig: UpdateArtifactsConfig = {
+        updateType,
+        ...config,
+      };
+
+      await updateArtifacts({
+        packageFileName: '',
+        updatedDeps: [],
+        newPackageFileContent: '',
+        config: localConfig,
+      });
+      expect(terraformLockfile.updateArtifacts).not.toHaveBeenCalled();
+    }
+  );
+});
diff --git a/lib/modules/manager/terragrunt/artifacts.ts b/lib/modules/manager/terragrunt/artifacts.ts
new file mode 100644
index 0000000000..865ee1195d
--- /dev/null
+++ b/lib/modules/manager/terragrunt/artifacts.ts
@@ -0,0 +1,18 @@
+import { logger } from '../../../logger';
+import { updateArtifacts as updateTerraformArtifacts } from '../terraform/lockfile/index';
+import type { UpdateArtifact, UpdateArtifactsResult } from '../types';
+
+export async function updateArtifacts(
+  artifact: UpdateArtifact
+): Promise<UpdateArtifactsResult[] | null> {
+  if (artifact.config.updateType !== 'lockFileMaintenance') {
+    logger.debug(
+      `UpdateType ${
+        artifact.config.updateType as string
+      } is not supported for terragrunt`
+    );
+    return null;
+  }
+
+  return await updateTerraformArtifacts(artifact);
+}
diff --git a/lib/modules/manager/terragrunt/index.ts b/lib/modules/manager/terragrunt/index.ts
index 78eb46b346..39d6faf56e 100644
--- a/lib/modules/manager/terragrunt/index.ts
+++ b/lib/modules/manager/terragrunt/index.ts
@@ -2,6 +2,7 @@ import { GitTagsDatasource } from '../../datasource/git-tags';
 import { GithubTagsDatasource } from '../../datasource/github-tags';
 import { TerraformModuleDatasource } from '../../datasource/terraform-module';
 
+export { updateArtifacts } from './artifacts';
 export { extractPackageFile } from './extract';
 
 export const supportedDatasources = [
@@ -10,6 +11,7 @@ export const supportedDatasources = [
   TerraformModuleDatasource.id,
 ];
 
+export const supportsLockFileMaintenance = true;
 export const defaultConfig = {
   commitMessageTopic: 'Terragrunt dependency {{depName}}',
   fileMatch: ['(^|/)terragrunt\\.hcl$'],
diff --git a/lib/modules/manager/terragrunt/readme.md b/lib/modules/manager/terragrunt/readme.md
index 0e36ffe155..e2484bcfae 100644
--- a/lib/modules/manager/terragrunt/readme.md
+++ b/lib/modules/manager/terragrunt/readme.md
@@ -18,3 +18,8 @@ terraform {
   source = "github.com/hashicorp/example?ref=v1.0.0"
 }
 ```
+
+### Terraform lockfiles
+
+The Terragrunt manager supports [lock file maintenance](https://docs.renovatebot.com/configuration-options/#lockfilemaintenance) for `.terraform.lock.hcl` artifacts.
+These artifacts will be updated if and only if the update type is `lockFileMaintenance`.
-- 
GitLab