@pagopa/dx-cli 0.15.1 → 0.15.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/bin/index.js +8 -1280
  2. package/dist/adapters/azure/__tests__/cloud-account-repository.test.d.ts +1 -0
  3. package/dist/adapters/azure/__tests__/cloud-account-repository.test.js +95 -0
  4. package/dist/adapters/azure/__tests__/cloud-account-service.test.d.ts +1 -0
  5. package/dist/adapters/azure/__tests__/cloud-account-service.test.js +95 -0
  6. package/dist/adapters/azure/cloud-account-repository.d.ts +12 -0
  7. package/dist/adapters/azure/cloud-account-repository.js +23 -0
  8. package/dist/adapters/azure/cloud-account-service.d.ts +22 -0
  9. package/dist/adapters/azure/cloud-account-service.js +255 -0
  10. package/dist/adapters/azure/locations.d.ts +7 -0
  11. package/dist/adapters/azure/locations.js +21 -0
  12. package/dist/adapters/codemods/__tests__/registry.test.d.ts +1 -0
  13. package/dist/adapters/codemods/__tests__/registry.test.js +59 -0
  14. package/dist/adapters/codemods/__tests__/use-azure-appsvc.test.d.ts +1 -0
  15. package/dist/adapters/codemods/__tests__/use-azure-appsvc.test.js +77 -0
  16. package/dist/adapters/codemods/__tests__/use-pnpm.test.d.ts +1 -0
  17. package/dist/adapters/codemods/__tests__/use-pnpm.test.js +148 -0
  18. package/dist/adapters/codemods/git.d.ts +2 -0
  19. package/dist/adapters/codemods/git.js +18 -0
  20. package/dist/adapters/codemods/index.d.ts +3 -0
  21. package/dist/adapters/codemods/index.js +9 -0
  22. package/dist/adapters/codemods/registry.d.ts +8 -0
  23. package/dist/adapters/codemods/registry.js +16 -0
  24. package/dist/adapters/codemods/update-code-review.d.ts +3 -0
  25. package/dist/adapters/codemods/update-code-review.js +60 -0
  26. package/dist/adapters/codemods/use-azure-appsvc.d.ts +3 -0
  27. package/dist/adapters/codemods/use-azure-appsvc.js +84 -0
  28. package/dist/adapters/codemods/use-pnpm.d.ts +22 -0
  29. package/dist/adapters/codemods/use-pnpm.js +214 -0
  30. package/dist/adapters/codemods/yaml.d.ts +2 -0
  31. package/dist/adapters/codemods/yaml.js +8 -0
  32. package/dist/adapters/commander/commands/codemod.d.ts +8 -0
  33. package/dist/adapters/commander/commands/codemod.js +22 -0
  34. package/dist/adapters/commander/commands/doctor.d.ts +4 -0
  35. package/dist/adapters/commander/commands/doctor.js +12 -0
  36. package/dist/adapters/commander/commands/info.d.ts +3 -0
  37. package/dist/adapters/commander/commands/info.js +9 -0
  38. package/dist/adapters/commander/commands/init.d.ts +7 -0
  39. package/dist/adapters/commander/commands/init.js +126 -0
  40. package/dist/adapters/commander/commands/savemoney.d.ts +2 -0
  41. package/dist/adapters/commander/commands/savemoney.js +26 -0
  42. package/dist/adapters/commander/index.d.ts +7 -0
  43. package/dist/adapters/commander/index.js +19 -0
  44. package/dist/adapters/execa/terraform.d.ts +27 -0
  45. package/dist/adapters/execa/terraform.js +28 -0
  46. package/dist/adapters/github/__tests__/github-repo.spec.d.ts +1 -0
  47. package/dist/adapters/github/__tests__/github-repo.spec.js +67 -0
  48. package/dist/adapters/github/github-repo.d.ts +2 -0
  49. package/dist/adapters/github/github-repo.js +31 -0
  50. package/dist/adapters/logtape/validation-reporter.d.ts +2 -0
  51. package/dist/adapters/logtape/validation-reporter.js +14 -0
  52. package/dist/adapters/node/__tests__/data.d.ts +18 -0
  53. package/dist/adapters/node/__tests__/data.js +22 -0
  54. package/dist/adapters/node/__tests__/package-json.test.d.ts +1 -0
  55. package/dist/adapters/node/__tests__/package-json.test.js +86 -0
  56. package/dist/adapters/node/__tests__/repository.test.d.ts +1 -0
  57. package/dist/adapters/node/__tests__/repository.test.js +77 -0
  58. package/dist/adapters/node/fs/__tests__/file-reader.test.d.ts +1 -0
  59. package/dist/adapters/node/fs/__tests__/file-reader.test.js +80 -0
  60. package/dist/adapters/node/fs/file-reader.d.ts +24 -0
  61. package/dist/adapters/node/fs/file-reader.js +26 -0
  62. package/dist/adapters/node/json/__tests__/index.test.d.ts +1 -0
  63. package/dist/adapters/node/json/__tests__/index.test.js +14 -0
  64. package/dist/adapters/node/json/index.d.ts +2 -0
  65. package/dist/adapters/node/json/index.js +2 -0
  66. package/dist/adapters/node/package-json.d.ts +2 -0
  67. package/dist/adapters/node/package-json.js +22 -0
  68. package/dist/adapters/node/release.d.ts +2 -0
  69. package/dist/adapters/node/release.js +33 -0
  70. package/dist/adapters/node/repository.d.ts +2 -0
  71. package/dist/adapters/node/repository.js +47 -0
  72. package/dist/adapters/octokit/__tests__/index.test.d.ts +1 -0
  73. package/dist/adapters/octokit/__tests__/index.test.js +197 -0
  74. package/dist/adapters/octokit/index.d.ts +24 -0
  75. package/dist/adapters/octokit/index.js +65 -0
  76. package/dist/adapters/plop/actions/__tests__/init-cloud-accounts.test.d.ts +1 -0
  77. package/dist/adapters/plop/actions/__tests__/init-cloud-accounts.test.js +115 -0
  78. package/dist/adapters/plop/actions/__tests__/provision-terraform-backend.test.d.ts +1 -0
  79. package/dist/adapters/plop/actions/__tests__/provision-terraform-backend.test.js +116 -0
  80. package/dist/adapters/plop/actions/fetch-github-release.d.ts +12 -0
  81. package/dist/adapters/plop/actions/fetch-github-release.js +20 -0
  82. package/dist/adapters/plop/actions/get-node-version.d.ts +2 -0
  83. package/dist/adapters/plop/actions/get-node-version.js +9 -0
  84. package/dist/adapters/plop/actions/get-terraform-backend.d.ts +3 -0
  85. package/dist/adapters/plop/actions/get-terraform-backend.js +17 -0
  86. package/dist/adapters/plop/actions/init-cloud-accounts.d.ts +5 -0
  87. package/dist/adapters/plop/actions/init-cloud-accounts.js +13 -0
  88. package/dist/adapters/plop/actions/provision-terraform-backend.d.ts +10 -0
  89. package/dist/adapters/plop/actions/provision-terraform-backend.js +16 -0
  90. package/dist/adapters/plop/actions/semver.d.ts +19 -0
  91. package/dist/adapters/plop/actions/semver.js +27 -0
  92. package/dist/adapters/plop/actions/setup-pnpm.d.ts +2 -0
  93. package/dist/adapters/plop/actions/setup-pnpm.js +26 -0
  94. package/dist/adapters/plop/generators/environment/__tests__/actions.test.d.ts +2 -0
  95. package/dist/adapters/plop/generators/environment/__tests__/actions.test.js +55 -0
  96. package/dist/adapters/plop/generators/environment/actions.d.ts +2 -0
  97. package/dist/adapters/plop/generators/environment/actions.js +54 -0
  98. package/dist/adapters/plop/generators/environment/index.d.ts +3 -0
  99. package/dist/adapters/plop/generators/environment/index.js +19 -0
  100. package/dist/adapters/plop/generators/environment/prompts.d.ts +66 -0
  101. package/dist/adapters/plop/generators/environment/prompts.js +166 -0
  102. package/dist/adapters/plop/generators/monorepo/actions.d.ts +51 -0
  103. package/dist/adapters/plop/generators/monorepo/actions.js +35 -0
  104. package/dist/adapters/plop/generators/monorepo/index.d.ts +6 -0
  105. package/dist/adapters/plop/generators/monorepo/index.js +17 -0
  106. package/dist/adapters/plop/generators/monorepo/prompts.d.ts +10 -0
  107. package/dist/adapters/plop/generators/monorepo/prompts.js +31 -0
  108. package/dist/adapters/plop/helpers/__tests__/resource-prefix.test.d.ts +1 -0
  109. package/dist/adapters/plop/helpers/__tests__/resource-prefix.test.js +113 -0
  110. package/dist/adapters/plop/helpers/env-short.d.ts +3 -0
  111. package/dist/adapters/plop/helpers/env-short.js +9 -0
  112. package/dist/adapters/plop/helpers/resource-prefix.d.ts +5 -0
  113. package/dist/adapters/plop/helpers/resource-prefix.js +18 -0
  114. package/dist/adapters/plop/index.d.ts +8 -0
  115. package/dist/adapters/plop/index.js +24 -0
  116. package/dist/adapters/terraform/fmt.d.ts +1 -0
  117. package/dist/adapters/terraform/fmt.js +17 -0
  118. package/dist/adapters/yaml/__tests__/index.test.d.ts +1 -0
  119. package/dist/adapters/yaml/__tests__/index.test.js +53 -0
  120. package/dist/adapters/yaml/index.d.ts +8 -0
  121. package/dist/adapters/yaml/index.js +9 -0
  122. package/dist/adapters/zod/index.d.ts +23 -0
  123. package/dist/adapters/zod/index.js +22 -0
  124. package/dist/config.d.ts +6 -0
  125. package/dist/config.js +5 -0
  126. package/dist/domain/__tests__/data.d.ts +17 -0
  127. package/dist/domain/__tests__/data.js +27 -0
  128. package/dist/domain/__tests__/environment.test.d.ts +1 -0
  129. package/dist/domain/__tests__/environment.test.js +282 -0
  130. package/dist/domain/__tests__/info.test.d.ts +1 -0
  131. package/dist/domain/__tests__/info.test.js +77 -0
  132. package/dist/domain/__tests__/package-json.test.d.ts +1 -0
  133. package/dist/domain/__tests__/package-json.test.js +39 -0
  134. package/dist/domain/__tests__/repository.test.d.ts +1 -0
  135. package/dist/domain/__tests__/repository.test.js +101 -0
  136. package/dist/domain/__tests__/workspace.test.d.ts +1 -0
  137. package/dist/domain/__tests__/workspace.test.js +57 -0
  138. package/dist/domain/cloud-account.d.ts +28 -0
  139. package/dist/domain/cloud-account.js +12 -0
  140. package/dist/domain/codemod.d.ts +11 -0
  141. package/dist/domain/codemod.js +1 -0
  142. package/dist/domain/dependencies.d.ts +10 -0
  143. package/dist/domain/dependencies.js +1 -0
  144. package/dist/domain/doctor.d.ts +10 -0
  145. package/dist/domain/doctor.js +50 -0
  146. package/dist/domain/environment.d.ts +40 -0
  147. package/dist/domain/environment.js +57 -0
  148. package/dist/domain/github-repo.d.ts +6 -0
  149. package/dist/domain/github-repo.js +8 -0
  150. package/dist/domain/github.d.ts +37 -0
  151. package/dist/domain/github.js +29 -0
  152. package/dist/domain/info.d.ts +11 -0
  153. package/dist/domain/info.js +52 -0
  154. package/dist/domain/package-json.d.ts +42 -0
  155. package/dist/domain/package-json.js +69 -0
  156. package/dist/domain/remote-backend.d.ts +8 -0
  157. package/dist/domain/remote-backend.js +9 -0
  158. package/dist/domain/repository.d.ts +13 -0
  159. package/dist/domain/repository.js +72 -0
  160. package/dist/domain/validation.d.ts +16 -0
  161. package/dist/domain/validation.js +1 -0
  162. package/dist/domain/workspace.d.ts +9 -0
  163. package/dist/domain/workspace.js +32 -0
  164. package/dist/index.d.ts +2 -0
  165. package/dist/index.js +35 -0
  166. package/dist/use-cases/__tests__/apply-codemod.test.d.ts +1 -0
  167. package/dist/use-cases/__tests__/apply-codemod.test.js +73 -0
  168. package/dist/use-cases/__tests__/list-codemods.test.d.ts +1 -0
  169. package/dist/use-cases/__tests__/list-codemods.test.js +38 -0
  170. package/dist/use-cases/apply-codemod.d.ts +5 -0
  171. package/dist/use-cases/apply-codemod.js +14 -0
  172. package/dist/use-cases/list-codemods.d.ts +4 -0
  173. package/dist/use-cases/list-codemods.js +1 -0
  174. package/package.json +19 -8
  175. package/templates/environment/bootstrapper/{{env.name}}/data.tf.hbs +13 -0
  176. package/templates/environment/bootstrapper/{{env.name}}/main.tf.hbs +70 -0
  177. package/templates/environment/bootstrapper/{{env.name}}/providers.tf.hbs +26 -0
  178. package/templates/environment/core/{{env.name}}/main.tf.hbs +21 -0
  179. package/templates/environment/core/{{env.name}}/outputs.tf.hbs +8 -0
  180. package/templates/environment/core/{{env.name}}/providers.tf.hbs +21 -0
  181. package/templates/environment/shared/backend.tf.hbs +14 -0
  182. package/templates/environment/shared/locals.tf.hbs +26 -0
  183. package/templates/monorepo/.editorconfig +8 -0
  184. package/templates/monorepo/.node-version.hbs +1 -0
  185. package/templates/monorepo/.pre-commit-config.yaml.hbs +34 -0
  186. package/templates/monorepo/.prettierignore +5 -0
  187. package/templates/monorepo/.terraform-version.hbs +1 -0
  188. package/templates/monorepo/.trivyignore +16 -0
  189. package/templates/monorepo/README.md.hbs +163 -0
  190. package/templates/monorepo/infra/repository/main.tf.hbs +11 -0
  191. package/templates/monorepo/infra/repository/outputs.tf.hbs +11 -0
  192. package/templates/monorepo/infra/repository/providers.tf.hbs +13 -0
  193. package/templates/monorepo/package.json.hbs +7 -0
  194. package/templates/monorepo/pnpm-workspace.yaml +7 -0
  195. package/templates/monorepo/turbo.json +29 -0
@@ -0,0 +1,73 @@
1
+ import { errAsync, okAsync } from "neverthrow";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { applyCodemodById } from "../apply-codemod.js";
4
+ const info = vi.fn().mockResolvedValue({
5
+ packageManager: "npm",
6
+ });
7
+ describe("applyCodemodById", () => {
8
+ it("applies the codemod when found", async () => {
9
+ const apply = vi.fn().mockResolvedValue(undefined);
10
+ const codemod = {
11
+ apply,
12
+ description: "test codemod",
13
+ id: "foo",
14
+ };
15
+ const registry = {
16
+ getAll: vi.fn(),
17
+ getById: vi
18
+ .fn()
19
+ .mockReturnValue(okAsync(codemod)),
20
+ };
21
+ const result = await applyCodemodById(registry, info)("foo");
22
+ expect(result.isOk()).toBe(true);
23
+ expect(apply).toHaveBeenCalledTimes(1);
24
+ });
25
+ it("returns an error when codemod is not found", async () => {
26
+ const registry = {
27
+ getAll: vi.fn(),
28
+ getById: vi
29
+ .fn()
30
+ .mockReturnValue(okAsync(undefined)),
31
+ };
32
+ const result = await applyCodemodById(registry, info)("missing-id");
33
+ expect(result.isErr()).toBe(true);
34
+ if (result.isErr()) {
35
+ expect(result.error).toBeInstanceOf(Error);
36
+ expect(result.error.message).toBe("Codemod with id missing-id not found");
37
+ }
38
+ });
39
+ it("propagates getById errors", async () => {
40
+ const registryError = new Error("registry failed");
41
+ const registry = {
42
+ getAll: vi.fn(),
43
+ getById: vi
44
+ .fn()
45
+ .mockReturnValue(errAsync(registryError)),
46
+ };
47
+ const result = await applyCodemodById(registry, info)("foo");
48
+ expect(result.isErr()).toBe(true);
49
+ if (result.isErr()) {
50
+ expect(result.error.message).toContain(registryError.message);
51
+ }
52
+ });
53
+ it("propagates apply errors", async () => {
54
+ const applyError = new Error("apply failed");
55
+ const codemod = {
56
+ apply: vi.fn().mockRejectedValue(applyError),
57
+ description: "test codemod",
58
+ id: "foo",
59
+ };
60
+ const registry = {
61
+ getAll: vi.fn(),
62
+ getById: vi
63
+ .fn()
64
+ .mockReturnValue(okAsync(codemod)),
65
+ };
66
+ const result = await applyCodemodById(registry, info)("foo");
67
+ expect(result.isErr()).toBe(true);
68
+ if (result.isErr()) {
69
+ expect(result.error).toBeInstanceOf(Error);
70
+ expect(result.error.message).toContain(applyError.message);
71
+ }
72
+ });
73
+ });
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,38 @@
1
+ import { errAsync, okAsync } from "neverthrow";
2
+ import { describe, expect, it, vi } from "vitest";
3
+ import { listCodemods } from "../list-codemods.js";
4
+ describe("listCodemods", () => {
5
+ it("returns codemods from the registry", async () => {
6
+ const codemods = [
7
+ {
8
+ apply: vi.fn().mockResolvedValue(undefined),
9
+ description: "a",
10
+ id: "a",
11
+ },
12
+ {
13
+ apply: vi.fn().mockResolvedValue(undefined),
14
+ description: "b",
15
+ id: "b",
16
+ },
17
+ ];
18
+ const registry = {
19
+ getAll: vi.fn().mockReturnValue(okAsync(codemods)),
20
+ getById: vi.fn(),
21
+ };
22
+ const result = await listCodemods(registry)();
23
+ expect(result.isOk()).toBe(true);
24
+ expect(registry.getAll).toHaveBeenCalledTimes(1);
25
+ });
26
+ it("propagates registry errors", async () => {
27
+ const error = new Error("boom");
28
+ const registry = {
29
+ getAll: vi.fn().mockReturnValue(errAsync(error)),
30
+ getById: vi.fn(),
31
+ };
32
+ const result = await listCodemods(registry)();
33
+ expect(result.isErr()).toBe(true);
34
+ if (result.isErr()) {
35
+ expect(result.error).toBe(error);
36
+ }
37
+ });
38
+ });
@@ -0,0 +1,5 @@
1
+ import { ResultAsync } from "neverthrow";
2
+ import { CodemodRegistry } from "../domain/codemod.js";
3
+ import { GetInfo } from "../domain/info.js";
4
+ export type ApplyCodemodById = (id: string) => ResultAsync<void, Error>;
5
+ export declare const applyCodemodById: (registry: CodemodRegistry, getInfo: GetInfo) => ApplyCodemodById;
@@ -0,0 +1,14 @@
1
+ import { errAsync, okAsync, ResultAsync } from "neverthrow";
2
+ const getCodemodById = (registry, id) => registry
3
+ .getById(id)
4
+ .andThen((codemod) => codemod
5
+ ? okAsync(codemod)
6
+ : errAsync(new Error(`Codemod with id ${id} not found`)));
7
+ const safeGetInfo = (getInfo) => ResultAsync.fromPromise(getInfo(), (error) => new Error("Failed to get info", { cause: error }));
8
+ export const applyCodemodById = (registry, getInfo) => (id) => ResultAsync.combine([
9
+ safeGetInfo(getInfo),
10
+ getCodemodById(registry, id),
11
+ ]).andThen(([info, codemod]) => ResultAsync.fromPromise(codemod.apply(info), (error) => {
12
+ const message = error instanceof Error ? `: ${error.message}` : "";
13
+ return new Error("Failed to apply codemod" + message, { cause: error });
14
+ }));
@@ -0,0 +1,4 @@
1
+ import { ResultAsync } from "neverthrow";
2
+ import { Codemod, CodemodRegistry } from "../domain/codemod.js";
3
+ export type ListCodemods = () => ResultAsync<Codemod[], Error>;
4
+ export declare const listCodemods: (registry: CodemodRegistry) => ListCodemods;
@@ -0,0 +1 @@
1
+ export const listCodemods = (registry) => () => registry.getAll();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagopa/dx-cli",
3
- "version": "0.15.1",
3
+ "version": "0.15.3",
4
4
  "type": "module",
5
5
  "description": "A CLI useful to manage DX tools.",
6
6
  "repository": {
@@ -13,38 +13,50 @@
13
13
  "CLI"
14
14
  ],
15
15
  "files": [
16
- "bin"
16
+ "bin",
17
+ "dist",
18
+ "templates"
17
19
  ],
18
20
  "bin": {
19
21
  "dx": "./bin/index.js"
20
22
  },
21
23
  "dependencies": {
24
+ "@azure/arm-authorization": "^9.0.0",
25
+ "@azure/arm-msi": "^2.2.0",
26
+ "@azure/arm-resourcegraph": "^4.2.1",
27
+ "@azure/arm-resources": "^7.0.0",
28
+ "@azure/arm-resources-subscriptions": "^2.1.0",
29
+ "@azure/arm-storage": "^19.1.0",
30
+ "@azure/identity": "^4.13.0",
31
+ "@azure/storage-blob": "^12.29.1",
22
32
  "@logtape/logtape": "^1.3.4",
33
+ "@microsoft/microsoft-graph-client": "^3.0.7",
23
34
  "chalk": "^5.6.2",
24
35
  "commander": "^14.0.2",
25
36
  "core-js": "^3.47.0",
26
37
  "execa": "^9.6.1",
27
38
  "glob": "^11.1.0",
39
+ "inquirer": "^9.3.8",
28
40
  "neverthrow": "^8.2.0",
29
- "node-plop": "^0.32.3",
30
41
  "octokit": "^5.0.5",
31
42
  "ora": "^9.0.0",
32
43
  "replace-in-file": "^8.4.0",
33
44
  "semver": "^7.7.2",
34
45
  "yaml": "^2.8.2",
35
46
  "zod": "^4.2.1",
36
- "@pagopa/dx-savemoney": "^0.1.4",
37
- "@pagopa/monorepo-generator": "^0.15.1"
47
+ "@pagopa/dx-savemoney": "^0.1.4"
38
48
  },
39
49
  "devDependencies": {
40
50
  "@tsconfig/node22": "22.0.2",
51
+ "@types/inquirer": "^9.0.9",
41
52
  "@types/node": "^22.19.1",
42
53
  "@types/semver": "^7.7.1",
43
54
  "@vitest/coverage-v8": "^3.2.4",
44
55
  "eslint": "^9.39.2",
45
56
  "memfs": "^4.51.1",
57
+ "node-plop": "^0.32.3",
58
+ "plop": "^4.0.4",
46
59
  "prettier": "3.6.2",
47
- "tsup": "^8.5.1",
48
60
  "typescript": "~5.8.3",
49
61
  "vitest": "^3.2.4",
50
62
  "vitest-mock-extended": "^3.1.0",
@@ -54,9 +66,8 @@
54
66
  "node": ">=22.0.0"
55
67
  },
56
68
  "scripts": {
57
- "build": "tsup",
58
69
  "format": "prettier --write .",
59
70
  "format:check": "prettier --check .",
60
- "typecheck": "tsc --noEmit"
71
+ "plop": "plop"
61
72
  }
62
73
  }
@@ -0,0 +1,13 @@
1
+ {{#with cloudAccountsByCsp.azure}}
2
+ data "azuread_group" "admins" {
3
+ display_name = "{{resourcePrefix @root}}-adgroup-admin"
4
+ }
5
+
6
+ data "azuread_group" "developers" {
7
+ display_name = "{{resourcePrefix @root}}-adgroup-developers"
8
+ }
9
+
10
+ data "azuread_group" "externals" {
11
+ display_name = "{{resourcePrefix @root}}-adgroup-externals"
12
+ }
13
+ {{/with}}
@@ -0,0 +1,70 @@
1
+ {{#with cloudAccountsByCsp.azure}}
2
+ {{#each this}}
3
+ module "azure-{{displayName}}_core_values" {
4
+ source = "pagopa-dx/azure-core-values-exporter/azurerm"
5
+ version = "~> 0.0"
6
+
7
+ providers = {
8
+ azurerm = azurerm.{{displayName}}
9
+ }
10
+
11
+ core_state = {
12
+ resource_group_name = "{{@root.terraform.backend.resourceGroupName}}"
13
+ storage_account_name = "{{@root.terraform.backend.storageAccountName}}"
14
+ subscription_id = "{{@root.terraform.backend.subscriptionId}}"
15
+ container_name = "terraform-state"
16
+ key = "{{@root.env.prefix}}.core.{{@root.env.name}}.tfstate"
17
+ }
18
+ }
19
+
20
+ module "azure-{{displayName}}_bootstrap" {
21
+ source = "pagopa-dx/azure-github-environment-bootstrap/azurerm"
22
+ version = "~> 3.0"
23
+
24
+ providers = {
25
+ azurerm = azurerm.{{displayName}}
26
+ }
27
+
28
+ environment = merge(local.environment, local.azure_accounts.{{displayName}})
29
+
30
+ subscription_id = module.azure-{{displayName}}_core_values.subscription_id
31
+ tenant_id = module.azure-{{displayName}}_core_values.tenant_id
32
+
33
+ entraid_groups = {
34
+ admins_object_id = data.azuread_group.admins.object_id
35
+ devs_object_id = data.azuread_group.developers.object_id
36
+ externals_object_id = data.azuread_group.externals.object_id
37
+ }
38
+
39
+ terraform_storage_account = {
40
+ name = "{{@root.terraform.backend.storageAccountName}}"
41
+ resource_group_name = "{{@root.terraform.backend.resourceGroupName}}"
42
+ }
43
+
44
+ repository = {
45
+ owner = "{{@root.github.owner}}"
46
+ name = "{{@root.github.repo}}"
47
+ }
48
+
49
+ github_private_runner = {
50
+ container_app_environment_id = module.azure-{{displayName}}_core_values.github_runner.environment_id
51
+ container_app_environment_location = local.azure_accounts.{{displayName}}.location
52
+ labels = [
53
+ "{{@root.env.name}}"
54
+ ]
55
+ key_vault = {
56
+ name = module.azure-{{displayName}}_core_values.common_key_vault.name
57
+ resource_group_name = module.azure-{{displayName}}_core_values.common_key_vault.resource_group_name
58
+ }
59
+ }
60
+
61
+ pep_vnet_id = module.azure-{{displayName}}_core_values.common_vnet.id
62
+ private_dns_zone_resource_group_id = module.azure-{{displayName}}_core_values.network_resource_group_id
63
+ opex_resource_group_id = module.azure-{{displayName}}_core_values.opex_resource_group_id
64
+
65
+ tags = local.tags
66
+ }
67
+ {{/each}}
68
+ {{/with}}
69
+
70
+
@@ -0,0 +1,26 @@
1
+ terraform {
2
+ required_providers {
3
+ {{#with cloudAccountsByCsp.azure}}
4
+ azurerm = {
5
+ source = "hashicorp/azurerm"
6
+ version = "~> 4.0"
7
+ }
8
+
9
+ azuread = {
10
+ source = "hashicorp/azuread"
11
+ version = "~> 2.0"
12
+ }
13
+ {{/with}}
14
+ }
15
+ }
16
+
17
+ {{#with cloudAccountsByCsp.azure}}
18
+ {{#each this}}
19
+ provider "azurerm" {
20
+ features {}
21
+ storage_use_azuread = true
22
+ subscription_id = "{{id}}"
23
+ alias = "{{displayName}}"
24
+ }
25
+ {{/each}}
26
+ {{/with}}
@@ -0,0 +1,21 @@
1
+ {{#with cloudAccountsByCsp.azure}}
2
+ {{#each this}}
3
+ module "azure-{{displayName}}_core" {
4
+ source = "pagopa-dx/azure-core-infra/azurerm"
5
+ version = "~> 2.0"
6
+
7
+ providers = {
8
+ azurerm = azurerm.{{displayName}}
9
+ }
10
+
11
+ environment = merge(local.environment, local.azure_accounts.{{displayName}}, {
12
+ app_name = "core"
13
+ })
14
+
15
+ tags = local.tags
16
+ }
17
+
18
+ {{/each}}
19
+ {{/with}}
20
+
21
+
@@ -0,0 +1,8 @@
1
+
2
+ output "values" {
3
+ value = {
4
+ {{#each cloudAccountsByCsp.azure}}
5
+ "{{id}}" = module.azure-{{displayName}}_core
6
+ {{/each}}
7
+ }
8
+ }
@@ -0,0 +1,21 @@
1
+ terraform {
2
+ required_providers {
3
+ {{#with cloudAccountsByCsp.azure}}
4
+ azurerm = {
5
+ source = "hashicorp/azurerm"
6
+ version = "~> 4.0"
7
+ }
8
+ {{/with}}
9
+ }
10
+ }
11
+
12
+ {{#with cloudAccountsByCsp.azure}}
13
+ {{#each this}}
14
+ provider "azurerm" {
15
+ features {}
16
+ storage_use_azuread = true
17
+ subscription_id = "{{id}}"
18
+ alias = "{{displayName}}"
19
+ }
20
+ {{/each}}
21
+ {{/with}}
@@ -0,0 +1,14 @@
1
+ {{#*inline "azurerm"}}
2
+ backend "azurerm" {
3
+ resource_group_name = "{{resourceGroupName}}"
4
+ storage_account_name = "{{storageAccountName}}"
5
+ container_name = "terraform-state"
6
+ key = "{{key}}"
7
+ subscription_id = "{{subscriptionId}}"
8
+ use_azuread_auth = true
9
+ }
10
+ {{/inline}}
11
+
12
+ terraform {
13
+ {{> (lookup terraform.backend 'type') terraform.backend key=terraformBackendKey }}
14
+ }
@@ -0,0 +1,26 @@
1
+ locals {
2
+ environment = {
3
+ prefix = "{{@root.env.prefix}}"
4
+ env_short = "{{envShort @root.env.name}}"
5
+ domain = "{{@root.workspace.domain}}"
6
+ instance_number = "01"
7
+ }
8
+
9
+ {{#with cloudAccountsByCsp.azure}}
10
+ azure_accounts = {
11
+ {{#each this}}
12
+ {{displayName}} = {
13
+ location = "{{this.defaultLocation}}"
14
+ }
15
+ {{/each}}
16
+ }
17
+ {{/with}}
18
+
19
+ tags = {
20
+ CreatedBy = "Terraform"
21
+ Environment = "{{env.name}}"
22
+ {{#each tags}}
23
+ {{@key}} = "{{this}}"
24
+ {{/each}}
25
+ }
26
+ }
@@ -0,0 +1,8 @@
1
+ [*]
2
+ charset = utf-8
3
+ insert_final_newline = true
4
+ end_of_line = lf
5
+ indent_style = space
6
+ indent_size = 2
7
+ max_line_length = 80
8
+ trim_trailing_whitespace = true
@@ -0,0 +1 @@
1
+ {{ nodeVersion }}
@@ -0,0 +1,34 @@
1
+ repos:
2
+ - repo: https://github.com/pagopa/dx
3
+ rev: pre_commit_scripts@0.1.0
4
+ hooks:
5
+ - id: terraform_providers_lock_staged
6
+ - id: lock_modules
7
+ exclude: ^.*/(_modules|modules|\.terraform)(/.*)?$
8
+ files: infra/(resources/prod|repository)
9
+ - repo: https://github.com/antonbabenko/pre-commit-terraform
10
+ rev: "{{ preCommitTerraformVersion }}"
11
+ hooks:
12
+ - id: terraform_tflint
13
+ args:
14
+ - --args=--config=__GIT_WORKING_DIR__/.tflint.hcl
15
+ - id: terraform_fmt
16
+ - id: terraform_docs
17
+ name: terraform_docs on resources
18
+ args:
19
+ - --hook-config=--create-file-if-not-exist=true
20
+ exclude: |
21
+ (?x)^(
22
+ src\/(?:.*\/)?(?:_?modules)\/.*
23
+ )$
24
+ - id: terraform_validate
25
+ exclude: '(\/_?modules\/.*)'
26
+ args:
27
+ - --args=-json
28
+ - --args=-no-color
29
+ - --hook-config=--retry-once-with-cleanup=true
30
+ - id: terraform_trivy
31
+ files: ^src/
32
+ args:
33
+ - --args=--skip-dirs="**/.terraform"
34
+ - --args=--ignorefile=__GIT_WORKING_DIR__/.trivyignore
@@ -0,0 +1,5 @@
1
+ # Ignore all files with a .hbs extension
2
+ **/*.hbs
3
+
4
+ # Ignore built files
5
+ dist
@@ -0,0 +1 @@
1
+ {{ terraformVersion }}
@@ -0,0 +1,16 @@
1
+ # https://avd.aquasec.com/misconfig/azure/
2
+
3
+ # GitHub repository shouldn’t be public.
4
+ AVD-GIT-0001
5
+
6
+ # GitHub branch protection does not require signed commits.
7
+ AVD-GIT-0004
8
+
9
+ # LOW: Secret should have an expiry date specified
10
+ AVD-AZU-0017
11
+
12
+ # LOW: Secret does not have a content-type specified
13
+ AVD-AZU-0015
14
+
15
+ # CRITICAL: Vault network ACL does not block access by default
16
+ AVD-AZU-0013
@@ -0,0 +1,163 @@
1
+ # {{ repoName }}
2
+
3
+ {{ repoDescription }}
4
+
5
+ ## Getting Started
6
+
7
+ ### Using Devcontainer
8
+
9
+ The preferred way to setup your development environment is to use [Devcontainer](https://containers.dev) ([Host system requirements](https://code.visualstudio.com/docs/devcontainers/containers#_system-requirements)).
10
+
11
+ > [!TIP]
12
+ > If you are on macOS we recommend using [Rancher Desktop](https://rancherdesktop.io/) configured to use `VZ` as _Virtual Machine Type_ and `virtiofs` as volume _Mount Type_.
13
+
14
+ #### Visual Studio Code
15
+
16
+ 1. Make sure `docker` is available and running in your host system
17
+ 2. Install the [Devcontainer Extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
18
+ 3. Open the project root folder and select `Dev Containers: Reopen in Container` from the command palette
19
+ 4. Visual Studio Code will build the devcontainer image and then open the project inside the container, with all the needed tools and extension configured
20
+
21
+ #### Console
22
+
23
+ If you use a code editor that doesn't support Dev Container, you can still run it in your terminal.
24
+
25
+ 1. Follow the instructions of the following chapter ("Using local machine") to setup your local environment
26
+ 2. Run devcontainer from your terminal
27
+ ```bash
28
+ pnpm devcontainer up --workspace-folder .
29
+ pnpm devcontainer exec --workspace-folder . /bin/bash
30
+ ```
31
+
32
+ ### Using local machine
33
+
34
+ This project uses specific versions of `node`, `pnpm` and `terraform`. To make sure your development setup matches with production follow the recommended installation methods.
35
+
36
+ 1. Install and configure the following tools in your machine
37
+
38
+ - [nodenv](https://github.com/nodenv/nodenv) - Node version manager
39
+ - [tfenv](https://github.com/tfutils/tfenv) - Terraform version manager
40
+ - [terraform-docs](https://terraform-docs.io/user-guide/installation/) - Generate Terraform modules documentation in various formats
41
+ - [tflint](https://github.com/terraform-linters/tflint) - A Pluggable Terraform Linter
42
+ - [pre-commit](https://pre-commit.com/) - A framework for managing and maintaining multi-language pre-commit hooks
43
+
44
+ 2. Install `node` at the right version used by this project
45
+
46
+ ```bash
47
+ cd {{ repoName }}
48
+ nodenv install
49
+ ```
50
+
51
+ 3. Build all the workspaces contained by this repo
52
+ ```bash
53
+ pnpm build
54
+ ```
55
+
56
+ ## Release management
57
+
58
+ We use [changesets](https://github.com/changesets/changesets) to automate package versioning and releases.
59
+
60
+ Each Pull Request that includes changes that require a version bump must include a _changeset file_ that describes the introduced changes.
61
+
62
+ To create a _changeset file_ run the following command and follow the instructions.
63
+
64
+ ```bash
65
+ pnpm changeset
66
+ ```
67
+
68
+ ## Useful commands
69
+
70
+ This project uses `pnpm` and `turbo` with workspaces to manage projects and dependencies. Here is a list of useful commands to work in this repo.
71
+
72
+ ### Work with workspaces
73
+
74
+ ```bash
75
+ # build all the workspaces using turbo
76
+ pnpm build
77
+ # or
78
+ pnpm turbo build
79
+
80
+ # to execute COMMAND on WORKSPACE_NAME
81
+ pnpm --filter WORKSPACE_NAME COMMAND
82
+ # to execute COMMAND on all workspaces
83
+ pnpm -r COMMAND
84
+
85
+ # run the typecheck script on all workspaces
86
+ pnpm -r typecheck
87
+ ```
88
+
89
+ ### Add dependencies
90
+
91
+ ```bash
92
+ # add a dependency to the workspace root
93
+ pnpm -w add turbo
94
+
95
+ # add vitest as devDependency on citizen-func
96
+ pnpm --filter citizen-func add -D vitest
97
+
98
+ # add zod as dependency on each workspace
99
+ pnpm -r add zod
100
+ ```
101
+
102
+ ## Folder structure
103
+
104
+ ### `/apps`
105
+
106
+ It contains the applications included in the project.
107
+ Each folder is meant to produce a deployable artifact; how and where to deploy it is demanded to a single application.
108
+
109
+ Each sub-folder is a workspace.
110
+
111
+ ### `/packages`
112
+
113
+ Packages are reusable modules that implement a specific logic of the project. They are meant for sharing implementations across other apps and packages of the same projects, as well as being published in public registries.
114
+
115
+ Packages that are meant for internal code sharing have `private: true` in their `package.json` file; all the others are meant to be published into the public registry.
116
+
117
+ Each sub-folder is a workspace.
118
+
119
+ ### `/infra`
120
+
121
+ It contains the _infrastructure-as-code_ project that defines the resources for the project as well as the execution environments. Database schemas and migrations are defined here too, in case they are needed.
122
+
123
+ ### `/docs`
124
+
125
+ Technical documentation about the project. Topics that may be included are architecture overviews, [ADRs](https://adr.github.io/), coding standards, and anything that can be relevant for a developer approaching the project as a contributor or as an auditor.
126
+
127
+ User documentation doesn't usually go in here. For public packages, it must go in the package's `README` file so that it will also be uploaded to the registry; user-faced documentation websites, when needed by the project, go under the `/apps` folder as they are treated as end-user applications.
128
+
129
+ ## Releases
130
+
131
+ Releases are handled using [Changeset](https://github.com/changesets/changesets).
132
+ Changeset takes care of bumping packages, updating the changelog, and tagging the repository accordingly.
133
+
134
+ #### How it works
135
+
136
+ - When opening a Pull Request with a change intended to be published, [add a changeset file](https://github.com/changesets/changesets/blob/main/docs/adding-a-changeset.md) to the proposed changes.
137
+ - Once the Pull Request is merged, a new Pull Request named `Version Packages` will be automatically opened with all the release changes such as version bumping for each involved app or package and changelog update; if an open `Version Packages` PR already exists, it will be updated and the package versions calculated accordingly (see https://github.com/changesets/changesets/blob/main/docs/decisions.md#how-changesets-are-combined).
138
+ Only apps and packages mentioned in the changeset files will be bumped.
139
+ - Review the `Version Packages` PR and merge it when ready. Changeset files will be deleted.
140
+ - A Release entry is created for each app or package whose version has been bumped.
141
+
142
+ ### Folder structure
143
+
144
+ The IaC template contains the following projects:
145
+
146
+ #### repository
147
+
148
+ Set up the current repository settings.
149
+ It's intended to be executed once on a local machine at project initialization.
150
+
151
+ ```sh
152
+ cd infra/repository
153
+
154
+ # Substitute subscription_name with the actual subscription name if you selected Azure as CSP
155
+ az account set --name <subscription_name>
156
+
157
+ terraform init
158
+ terraform plan
159
+ terraform apply
160
+ ```
161
+ ### Workflow automation
162
+
163
+ The workflow `infra_plan.yaml` is executed on every PR that edits the `infra/resources` folder or the workflow definition itself. It executes a `terraform plan` and comments the PR with the result. If the plan fails, the workflow fails.