@pagopa/dx-cli 0.15.2 → 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.
- package/bin/index.js +8 -1280
- package/dist/adapters/azure/__tests__/cloud-account-repository.test.d.ts +1 -0
- package/dist/adapters/azure/__tests__/cloud-account-repository.test.js +95 -0
- package/dist/adapters/azure/__tests__/cloud-account-service.test.d.ts +1 -0
- package/dist/adapters/azure/__tests__/cloud-account-service.test.js +95 -0
- package/dist/adapters/azure/cloud-account-repository.d.ts +12 -0
- package/dist/adapters/azure/cloud-account-repository.js +23 -0
- package/dist/adapters/azure/cloud-account-service.d.ts +22 -0
- package/dist/adapters/azure/cloud-account-service.js +255 -0
- package/dist/adapters/azure/locations.d.ts +7 -0
- package/dist/adapters/azure/locations.js +21 -0
- package/dist/adapters/codemods/__tests__/registry.test.d.ts +1 -0
- package/dist/adapters/codemods/__tests__/registry.test.js +59 -0
- package/dist/adapters/codemods/__tests__/use-azure-appsvc.test.d.ts +1 -0
- package/dist/adapters/codemods/__tests__/use-azure-appsvc.test.js +77 -0
- package/dist/adapters/codemods/__tests__/use-pnpm.test.d.ts +1 -0
- package/dist/adapters/codemods/__tests__/use-pnpm.test.js +148 -0
- package/dist/adapters/codemods/git.d.ts +2 -0
- package/dist/adapters/codemods/git.js +18 -0
- package/dist/adapters/codemods/index.d.ts +3 -0
- package/dist/adapters/codemods/index.js +9 -0
- package/dist/adapters/codemods/registry.d.ts +8 -0
- package/dist/adapters/codemods/registry.js +16 -0
- package/dist/adapters/codemods/update-code-review.d.ts +3 -0
- package/dist/adapters/codemods/update-code-review.js +60 -0
- package/dist/adapters/codemods/use-azure-appsvc.d.ts +3 -0
- package/dist/adapters/codemods/use-azure-appsvc.js +84 -0
- package/dist/adapters/codemods/use-pnpm.d.ts +22 -0
- package/dist/adapters/codemods/use-pnpm.js +214 -0
- package/dist/adapters/codemods/yaml.d.ts +2 -0
- package/dist/adapters/codemods/yaml.js +8 -0
- package/dist/adapters/commander/commands/codemod.d.ts +8 -0
- package/dist/adapters/commander/commands/codemod.js +22 -0
- package/dist/adapters/commander/commands/doctor.d.ts +4 -0
- package/dist/adapters/commander/commands/doctor.js +12 -0
- package/dist/adapters/commander/commands/info.d.ts +3 -0
- package/dist/adapters/commander/commands/info.js +9 -0
- package/dist/adapters/commander/commands/init.d.ts +7 -0
- package/dist/adapters/commander/commands/init.js +126 -0
- package/dist/adapters/commander/commands/savemoney.d.ts +2 -0
- package/dist/adapters/commander/commands/savemoney.js +26 -0
- package/dist/adapters/commander/index.d.ts +7 -0
- package/dist/adapters/commander/index.js +19 -0
- package/dist/adapters/execa/terraform.d.ts +27 -0
- package/dist/adapters/execa/terraform.js +28 -0
- package/dist/adapters/github/__tests__/github-repo.spec.d.ts +1 -0
- package/dist/adapters/github/__tests__/github-repo.spec.js +67 -0
- package/dist/adapters/github/github-repo.d.ts +2 -0
- package/dist/adapters/github/github-repo.js +31 -0
- package/dist/adapters/logtape/validation-reporter.d.ts +2 -0
- package/dist/adapters/logtape/validation-reporter.js +14 -0
- package/dist/adapters/node/__tests__/data.d.ts +18 -0
- package/dist/adapters/node/__tests__/data.js +22 -0
- package/dist/adapters/node/__tests__/package-json.test.d.ts +1 -0
- package/dist/adapters/node/__tests__/package-json.test.js +86 -0
- package/dist/adapters/node/__tests__/repository.test.d.ts +1 -0
- package/dist/adapters/node/__tests__/repository.test.js +77 -0
- package/dist/adapters/node/fs/__tests__/file-reader.test.d.ts +1 -0
- package/dist/adapters/node/fs/__tests__/file-reader.test.js +80 -0
- package/dist/adapters/node/fs/file-reader.d.ts +24 -0
- package/dist/adapters/node/fs/file-reader.js +26 -0
- package/dist/adapters/node/json/__tests__/index.test.d.ts +1 -0
- package/dist/adapters/node/json/__tests__/index.test.js +14 -0
- package/dist/adapters/node/json/index.d.ts +2 -0
- package/dist/adapters/node/json/index.js +2 -0
- package/dist/adapters/node/package-json.d.ts +2 -0
- package/dist/adapters/node/package-json.js +22 -0
- package/dist/adapters/node/release.d.ts +2 -0
- package/dist/adapters/node/release.js +33 -0
- package/dist/adapters/node/repository.d.ts +2 -0
- package/dist/adapters/node/repository.js +47 -0
- package/dist/adapters/octokit/__tests__/index.test.d.ts +1 -0
- package/dist/adapters/octokit/__tests__/index.test.js +197 -0
- package/dist/adapters/octokit/index.d.ts +24 -0
- package/dist/adapters/octokit/index.js +65 -0
- package/dist/adapters/plop/actions/__tests__/init-cloud-accounts.test.d.ts +1 -0
- package/dist/adapters/plop/actions/__tests__/init-cloud-accounts.test.js +115 -0
- package/dist/adapters/plop/actions/__tests__/provision-terraform-backend.test.d.ts +1 -0
- package/dist/adapters/plop/actions/__tests__/provision-terraform-backend.test.js +116 -0
- package/dist/adapters/plop/actions/fetch-github-release.d.ts +12 -0
- package/dist/adapters/plop/actions/fetch-github-release.js +20 -0
- package/dist/adapters/plop/actions/get-node-version.d.ts +2 -0
- package/dist/adapters/plop/actions/get-node-version.js +9 -0
- package/dist/adapters/plop/actions/get-terraform-backend.d.ts +3 -0
- package/dist/adapters/plop/actions/get-terraform-backend.js +17 -0
- package/dist/adapters/plop/actions/init-cloud-accounts.d.ts +5 -0
- package/dist/adapters/plop/actions/init-cloud-accounts.js +13 -0
- package/dist/adapters/plop/actions/provision-terraform-backend.d.ts +10 -0
- package/dist/adapters/plop/actions/provision-terraform-backend.js +16 -0
- package/dist/adapters/plop/actions/semver.d.ts +19 -0
- package/dist/adapters/plop/actions/semver.js +27 -0
- package/dist/adapters/plop/actions/setup-pnpm.d.ts +2 -0
- package/dist/adapters/plop/actions/setup-pnpm.js +26 -0
- package/dist/adapters/plop/generators/environment/__tests__/actions.test.d.ts +2 -0
- package/dist/adapters/plop/generators/environment/__tests__/actions.test.js +55 -0
- package/dist/adapters/plop/generators/environment/actions.d.ts +2 -0
- package/dist/adapters/plop/generators/environment/actions.js +54 -0
- package/dist/adapters/plop/generators/environment/index.d.ts +3 -0
- package/dist/adapters/plop/generators/environment/index.js +19 -0
- package/dist/adapters/plop/generators/environment/prompts.d.ts +66 -0
- package/dist/adapters/plop/generators/environment/prompts.js +166 -0
- package/dist/adapters/plop/generators/monorepo/actions.d.ts +51 -0
- package/dist/adapters/plop/generators/monorepo/actions.js +35 -0
- package/dist/adapters/plop/generators/monorepo/index.d.ts +6 -0
- package/dist/adapters/plop/generators/monorepo/index.js +17 -0
- package/dist/adapters/plop/generators/monorepo/prompts.d.ts +10 -0
- package/dist/adapters/plop/generators/monorepo/prompts.js +31 -0
- package/dist/adapters/plop/helpers/__tests__/resource-prefix.test.d.ts +1 -0
- package/dist/adapters/plop/helpers/__tests__/resource-prefix.test.js +113 -0
- package/dist/adapters/plop/helpers/env-short.d.ts +3 -0
- package/dist/adapters/plop/helpers/env-short.js +9 -0
- package/dist/adapters/plop/helpers/resource-prefix.d.ts +5 -0
- package/dist/adapters/plop/helpers/resource-prefix.js +18 -0
- package/dist/adapters/plop/index.d.ts +8 -0
- package/dist/adapters/plop/index.js +24 -0
- package/dist/adapters/terraform/fmt.d.ts +1 -0
- package/dist/adapters/terraform/fmt.js +17 -0
- package/dist/adapters/yaml/__tests__/index.test.d.ts +1 -0
- package/dist/adapters/yaml/__tests__/index.test.js +53 -0
- package/dist/adapters/yaml/index.d.ts +8 -0
- package/dist/adapters/yaml/index.js +9 -0
- package/dist/adapters/zod/index.d.ts +23 -0
- package/dist/adapters/zod/index.js +22 -0
- package/dist/config.d.ts +6 -0
- package/dist/config.js +5 -0
- package/dist/domain/__tests__/data.d.ts +17 -0
- package/dist/domain/__tests__/data.js +27 -0
- package/dist/domain/__tests__/environment.test.d.ts +1 -0
- package/dist/domain/__tests__/environment.test.js +282 -0
- package/dist/domain/__tests__/info.test.d.ts +1 -0
- package/dist/domain/__tests__/info.test.js +77 -0
- package/dist/domain/__tests__/package-json.test.d.ts +1 -0
- package/dist/domain/__tests__/package-json.test.js +39 -0
- package/dist/domain/__tests__/repository.test.d.ts +1 -0
- package/dist/domain/__tests__/repository.test.js +101 -0
- package/dist/domain/__tests__/workspace.test.d.ts +1 -0
- package/dist/domain/__tests__/workspace.test.js +57 -0
- package/dist/domain/cloud-account.d.ts +28 -0
- package/dist/domain/cloud-account.js +12 -0
- package/dist/domain/codemod.d.ts +11 -0
- package/dist/domain/codemod.js +1 -0
- package/dist/domain/dependencies.d.ts +10 -0
- package/dist/domain/dependencies.js +1 -0
- package/dist/domain/doctor.d.ts +10 -0
- package/dist/domain/doctor.js +50 -0
- package/dist/domain/environment.d.ts +40 -0
- package/dist/domain/environment.js +57 -0
- package/dist/domain/github-repo.d.ts +6 -0
- package/dist/domain/github-repo.js +8 -0
- package/dist/domain/github.d.ts +37 -0
- package/dist/domain/github.js +29 -0
- package/dist/domain/info.d.ts +11 -0
- package/dist/domain/info.js +52 -0
- package/dist/domain/package-json.d.ts +42 -0
- package/dist/domain/package-json.js +69 -0
- package/dist/domain/remote-backend.d.ts +8 -0
- package/dist/domain/remote-backend.js +9 -0
- package/dist/domain/repository.d.ts +13 -0
- package/dist/domain/repository.js +72 -0
- package/dist/domain/validation.d.ts +16 -0
- package/dist/domain/validation.js +1 -0
- package/dist/domain/workspace.d.ts +9 -0
- package/dist/domain/workspace.js +32 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +35 -0
- package/dist/use-cases/__tests__/apply-codemod.test.d.ts +1 -0
- package/dist/use-cases/__tests__/apply-codemod.test.js +73 -0
- package/dist/use-cases/__tests__/list-codemods.test.d.ts +1 -0
- package/dist/use-cases/__tests__/list-codemods.test.js +38 -0
- package/dist/use-cases/apply-codemod.d.ts +5 -0
- package/dist/use-cases/apply-codemod.js +14 -0
- package/dist/use-cases/list-codemods.d.ts +4 -0
- package/dist/use-cases/list-codemods.js +1 -0
- package/package.json +19 -8
- package/templates/environment/bootstrapper/{{env.name}}/data.tf.hbs +13 -0
- package/templates/environment/bootstrapper/{{env.name}}/main.tf.hbs +70 -0
- package/templates/environment/bootstrapper/{{env.name}}/providers.tf.hbs +26 -0
- package/templates/environment/core/{{env.name}}/main.tf.hbs +21 -0
- package/templates/environment/core/{{env.name}}/outputs.tf.hbs +8 -0
- package/templates/environment/core/{{env.name}}/providers.tf.hbs +21 -0
- package/templates/environment/shared/backend.tf.hbs +14 -0
- package/templates/environment/shared/locals.tf.hbs +26 -0
- package/templates/monorepo/.editorconfig +8 -0
- package/templates/monorepo/.node-version.hbs +1 -0
- package/templates/monorepo/.pre-commit-config.yaml.hbs +34 -0
- package/templates/monorepo/.prettierignore +5 -0
- package/templates/monorepo/.terraform-version.hbs +1 -0
- package/templates/monorepo/.trivyignore +16 -0
- package/templates/monorepo/README.md.hbs +163 -0
- package/templates/monorepo/infra/repository/main.tf.hbs +11 -0
- package/templates/monorepo/infra/repository/outputs.tf.hbs +11 -0
- package/templates/monorepo/infra/repository/providers.tf.hbs +13 -0
- package/templates/monorepo/package.json.hbs +7 -0
- package/templates/monorepo/pnpm-workspace.yaml +7 -0
- 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 @@
|
|
|
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.
|
|
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
|
-
"
|
|
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,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 @@
|
|
|
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 @@
|
|
|
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.
|