@pagopa/dx-cli 0.23.0 → 0.23.1

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 (98) hide show
  1. package/package.json +5 -5
  2. package/templates/monorepo/nx.json +0 -1
  3. package/dist/adapters/azure/__tests__/cloud-account-repository.test.d.ts +0 -1
  4. package/dist/adapters/azure/__tests__/cloud-account-repository.test.js +0 -95
  5. package/dist/adapters/azure/__tests__/cloud-account-service.test.d.ts +0 -1
  6. package/dist/adapters/azure/__tests__/cloud-account-service.test.js +0 -378
  7. package/dist/adapters/codemods/__tests__/registry.test.d.ts +0 -1
  8. package/dist/adapters/codemods/__tests__/registry.test.js +0 -56
  9. package/dist/adapters/codemods/__tests__/use-azure-appsvc.test.d.ts +0 -1
  10. package/dist/adapters/codemods/__tests__/use-azure-appsvc.test.js +0 -77
  11. package/dist/adapters/codemods/__tests__/use-pnpm.test.d.ts +0 -1
  12. package/dist/adapters/codemods/__tests__/use-pnpm.test.js +0 -148
  13. package/dist/adapters/commander/__tests__/env.test.d.ts +0 -1
  14. package/dist/adapters/commander/__tests__/env.test.js +0 -45
  15. package/dist/adapters/commander/__tests__/error-reporting.test.d.ts +0 -1
  16. package/dist/adapters/commander/__tests__/error-reporting.test.js +0 -63
  17. package/dist/adapters/commander/__tests__/exit-with-error.test.d.ts +0 -1
  18. package/dist/adapters/commander/__tests__/exit-with-error.test.js +0 -92
  19. package/dist/adapters/commander/__tests__/global-options.test.d.ts +0 -1
  20. package/dist/adapters/commander/__tests__/global-options.test.js +0 -33
  21. package/dist/adapters/commander/__tests__/spec.test.d.ts +0 -8
  22. package/dist/adapters/commander/__tests__/spec.test.js +0 -264
  23. package/dist/adapters/commander/commands/__tests__/add.test.d.ts +0 -4
  24. package/dist/adapters/commander/commands/__tests__/add.test.js +0 -167
  25. package/dist/adapters/commander/commands/__tests__/init-command.test.d.ts +0 -4
  26. package/dist/adapters/commander/commands/__tests__/init-command.test.js +0 -44
  27. package/dist/adapters/commander/commands/__tests__/init.test.d.ts +0 -4
  28. package/dist/adapters/commander/commands/__tests__/init.test.js +0 -48
  29. package/dist/adapters/commander/commands/__tests__/preconditions.test.d.ts +0 -1
  30. package/dist/adapters/commander/commands/__tests__/preconditions.test.js +0 -32
  31. package/dist/adapters/commander/commands/__tests__/savemoney.test.d.ts +0 -8
  32. package/dist/adapters/commander/commands/__tests__/savemoney.test.js +0 -60
  33. package/dist/adapters/commander/commands/__tests__/spec.test.d.ts +0 -7
  34. package/dist/adapters/commander/commands/__tests__/spec.test.js +0 -85
  35. package/dist/adapters/commander/presenters/__tests__/index.test.d.ts +0 -1
  36. package/dist/adapters/commander/presenters/__tests__/index.test.js +0 -23
  37. package/dist/adapters/commander/presenters/__tests__/json.test.d.ts +0 -1
  38. package/dist/adapters/commander/presenters/__tests__/json.test.js +0 -108
  39. package/dist/adapters/commander/presenters/__tests__/text.test.d.ts +0 -1
  40. package/dist/adapters/commander/presenters/__tests__/text.test.js +0 -60
  41. package/dist/adapters/github/__tests__/github-repo.spec.d.ts +0 -1
  42. package/dist/adapters/github/__tests__/github-repo.spec.js +0 -67
  43. package/dist/adapters/node/__tests__/data.d.ts +0 -18
  44. package/dist/adapters/node/__tests__/data.js +0 -22
  45. package/dist/adapters/node/__tests__/package-json.test.d.ts +0 -1
  46. package/dist/adapters/node/__tests__/package-json.test.js +0 -86
  47. package/dist/adapters/node/__tests__/repository.test.d.ts +0 -1
  48. package/dist/adapters/node/__tests__/repository.test.js +0 -77
  49. package/dist/adapters/node/fs/__tests__/file-reader.test.d.ts +0 -1
  50. package/dist/adapters/node/fs/__tests__/file-reader.test.js +0 -80
  51. package/dist/adapters/node/json/__tests__/index.test.d.ts +0 -1
  52. package/dist/adapters/node/json/__tests__/index.test.js +0 -14
  53. package/dist/adapters/octokit/__tests__/index.test.d.ts +0 -1
  54. package/dist/adapters/octokit/__tests__/index.test.js +0 -414
  55. package/dist/adapters/pagopa-technology/__tests__/authorization.test.d.ts +0 -4
  56. package/dist/adapters/pagopa-technology/__tests__/authorization.test.js +0 -548
  57. package/dist/adapters/plop/__tests__/run-actions.test.d.ts +0 -1
  58. package/dist/adapters/plop/__tests__/run-actions.test.js +0 -68
  59. package/dist/adapters/plop/actions/__tests__/init-cloud-accounts.test.d.ts +0 -1
  60. package/dist/adapters/plop/actions/__tests__/init-cloud-accounts.test.js +0 -171
  61. package/dist/adapters/plop/actions/__tests__/provision-terraform-backend.test.d.ts +0 -1
  62. package/dist/adapters/plop/actions/__tests__/provision-terraform-backend.test.js +0 -134
  63. package/dist/adapters/plop/generators/__tests__/temp-dir.d.ts +0 -2
  64. package/dist/adapters/plop/generators/__tests__/temp-dir.js +0 -13
  65. package/dist/adapters/plop/generators/environment/__tests__/actions.test.d.ts +0 -2
  66. package/dist/adapters/plop/generators/environment/__tests__/actions.test.js +0 -92
  67. package/dist/adapters/plop/generators/environment/__tests__/generation.test.d.ts +0 -1
  68. package/dist/adapters/plop/generators/environment/__tests__/generation.test.js +0 -213
  69. package/dist/adapters/plop/generators/environment/__tests__/prompts.test.d.ts +0 -1
  70. package/dist/adapters/plop/generators/environment/__tests__/prompts.test.js +0 -182
  71. package/dist/adapters/plop/generators/monorepo/__tests__/generation.test.d.ts +0 -1
  72. package/dist/adapters/plop/generators/monorepo/__tests__/generation.test.js +0 -79
  73. package/dist/adapters/plop/helpers/__tests__/resource-prefix.test.d.ts +0 -1
  74. package/dist/adapters/plop/helpers/__tests__/resource-prefix.test.js +0 -113
  75. package/dist/adapters/plop/helpers/__tests__/terraform-state-key.test.d.ts +0 -1
  76. package/dist/adapters/plop/helpers/__tests__/terraform-state-key.test.js +0 -35
  77. package/dist/adapters/plop/helpers/__tests__/validate-prompt.test.d.ts +0 -1
  78. package/dist/adapters/plop/helpers/__tests__/validate-prompt.test.js +0 -60
  79. package/dist/adapters/yaml/__tests__/index.test.d.ts +0 -1
  80. package/dist/adapters/yaml/__tests__/index.test.js +0 -53
  81. package/dist/domain/__tests__/data.d.ts +0 -15
  82. package/dist/domain/__tests__/data.js +0 -26
  83. package/dist/domain/__tests__/environment.test.d.ts +0 -1
  84. package/dist/domain/__tests__/environment.test.js +0 -332
  85. package/dist/domain/__tests__/info.test.d.ts +0 -1
  86. package/dist/domain/__tests__/info.test.js +0 -77
  87. package/dist/domain/__tests__/package-json.test.d.ts +0 -1
  88. package/dist/domain/__tests__/package-json.test.js +0 -39
  89. package/dist/domain/__tests__/repository.test.d.ts +0 -1
  90. package/dist/domain/__tests__/repository.test.js +0 -111
  91. package/dist/domain/__tests__/workspace.test.d.ts +0 -1
  92. package/dist/domain/__tests__/workspace.test.js +0 -57
  93. package/dist/use-cases/__tests__/apply-codemod.test.d.ts +0 -1
  94. package/dist/use-cases/__tests__/apply-codemod.test.js +0 -71
  95. package/dist/use-cases/__tests__/list-codemods.test.d.ts +0 -1
  96. package/dist/use-cases/__tests__/list-codemods.test.js +0 -37
  97. package/dist/use-cases/__tests__/request-authorization.test.d.ts +0 -4
  98. package/dist/use-cases/__tests__/request-authorization.test.js +0 -43
@@ -1,171 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { initCloudAccounts } from "../init-cloud-accounts.js";
3
- const createMockGitHubService = () => ({
4
- createBranch: vi.fn(),
5
- createOrUpdateEnvironmentSecret: vi.fn().mockResolvedValue(undefined),
6
- createPullRequest: vi.fn(),
7
- getFileContent: vi.fn(),
8
- getRepository: vi.fn(),
9
- updateFile: vi.fn(),
10
- });
11
- const createMockCloudAccountService = (overrides = {}) => ({
12
- getTerraformBackend: vi.fn().mockResolvedValue(undefined),
13
- hasUserPermissionToInitialize: vi.fn().mockResolvedValue(true),
14
- initialize: vi.fn().mockResolvedValue(undefined),
15
- isInitialized: vi.fn().mockResolvedValue(true),
16
- provisionTerraformBackend: vi.fn().mockResolvedValue(undefined),
17
- ...overrides,
18
- });
19
- const createMockCloudAccount = (overrides = {}) => ({
20
- csp: "azure",
21
- defaultLocation: "westeurope",
22
- displayName: "Test-Account",
23
- id: "test-subscription-id",
24
- ...overrides,
25
- });
26
- const createMockPayload = (overrides = {}) => ({
27
- env: {
28
- cloudAccounts: [createMockCloudAccount()],
29
- name: "dev",
30
- prefix: "dx",
31
- },
32
- github: {
33
- owner: "pagopa",
34
- repo: "dx",
35
- },
36
- init: {
37
- cloudAccountsToInitialize: [],
38
- runnerAppCredentials: {
39
- clientId: "test-app-client-id",
40
- id: "test-app-id",
41
- installationId: "test-installation-id",
42
- key: "test-private-key",
43
- },
44
- terraformBackend: {
45
- cloudAccount: createMockCloudAccount(),
46
- },
47
- },
48
- tags: {},
49
- workspace: {
50
- domain: "test",
51
- },
52
- ...overrides,
53
- });
54
- describe("initCloudAccounts", () => {
55
- it("should initialize all cloud accounts in cloudAccountsToInitialize", async () => {
56
- const cloudAccount1 = createMockCloudAccount({ id: "account-1" });
57
- const cloudAccount2 = createMockCloudAccount({ id: "account-2" });
58
- const initializeMock = vi.fn().mockResolvedValue(undefined);
59
- const mockService = createMockCloudAccountService({
60
- initialize: initializeMock,
61
- });
62
- const payload = createMockPayload({
63
- env: {
64
- cloudAccounts: [],
65
- name: "prod",
66
- prefix: "io",
67
- },
68
- init: {
69
- cloudAccountsToInitialize: [cloudAccount1, cloudAccount2],
70
- runnerAppCredentials: {
71
- clientId: "test-app-client-id",
72
- id: "test-app-id",
73
- installationId: "test-installation-id",
74
- key: "test-private-key",
75
- },
76
- terraformBackend: {
77
- cloudAccount: createMockCloudAccount(),
78
- },
79
- },
80
- });
81
- await initCloudAccounts(payload, mockService, createMockGitHubService());
82
- expect(initializeMock).toHaveBeenCalledTimes(2);
83
- expect(initializeMock).toHaveBeenCalledWith(cloudAccount1, expect.objectContaining({ name: "prod", prefix: "io" }), {
84
- clientId: "test-app-client-id",
85
- id: "test-app-id",
86
- installationId: "test-installation-id",
87
- key: "test-private-key",
88
- }, {
89
- owner: "pagopa",
90
- repo: "dx",
91
- }, expect.any(Object), {});
92
- expect(initializeMock).toHaveBeenCalledWith(cloudAccount2, expect.objectContaining({ name: "prod", prefix: "io" }), {
93
- clientId: "test-app-client-id",
94
- id: "test-app-id",
95
- installationId: "test-installation-id",
96
- key: "test-private-key",
97
- }, {
98
- owner: "pagopa",
99
- repo: "dx",
100
- }, expect.any(Object), {});
101
- });
102
- it("should not call initialize when cloudAccountsToInitialize is empty", async () => {
103
- const initializeMock = vi.fn().mockResolvedValue(undefined);
104
- const mockService = createMockCloudAccountService({
105
- initialize: initializeMock,
106
- });
107
- const payload = createMockPayload({
108
- init: {
109
- cloudAccountsToInitialize: [],
110
- runnerAppCredentials: {
111
- clientId: "test-app-client-id",
112
- id: "test-app-id",
113
- installationId: "test-installation-id",
114
- key: "test-private-key",
115
- },
116
- terraformBackend: {
117
- cloudAccount: createMockCloudAccount(),
118
- },
119
- },
120
- });
121
- await initCloudAccounts(payload, mockService, createMockGitHubService());
122
- expect(initializeMock).not.toHaveBeenCalled();
123
- });
124
- it("should not call initialize when payload.init is undefined", async () => {
125
- const initializeMock = vi.fn().mockResolvedValue(undefined);
126
- const mockService = createMockCloudAccountService({
127
- initialize: initializeMock,
128
- });
129
- const payload = createMockPayload({
130
- init: undefined,
131
- });
132
- await initCloudAccounts(payload, mockService, createMockGitHubService());
133
- expect(initializeMock).not.toHaveBeenCalled();
134
- });
135
- it("should use prefix and environment name from payload.env", async () => {
136
- const cloudAccount = createMockCloudAccount();
137
- const initializeMock = vi.fn().mockResolvedValue(undefined);
138
- const mockService = createMockCloudAccountService({
139
- initialize: initializeMock,
140
- });
141
- const payload = createMockPayload({
142
- env: {
143
- cloudAccounts: [],
144
- name: "uat",
145
- prefix: "pagopa",
146
- },
147
- init: {
148
- cloudAccountsToInitialize: [cloudAccount],
149
- runnerAppCredentials: {
150
- clientId: "test-app-client-id",
151
- id: "test-app-id",
152
- installationId: "test-installation-id",
153
- key: "test-private-key",
154
- },
155
- terraformBackend: {
156
- cloudAccount: createMockCloudAccount(),
157
- },
158
- },
159
- });
160
- await initCloudAccounts(payload, mockService, createMockGitHubService());
161
- expect(initializeMock).toHaveBeenCalledWith(cloudAccount, expect.objectContaining({ name: "uat", prefix: "pagopa" }), {
162
- clientId: "test-app-client-id",
163
- id: "test-app-id",
164
- installationId: "test-installation-id",
165
- key: "test-private-key",
166
- }, {
167
- owner: "pagopa",
168
- repo: "dx",
169
- }, expect.any(Object), {});
170
- });
171
- });
@@ -1,134 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { provisionTerraformBackend } from "../provision-terraform-backend.js";
3
- const createMockCloudAccountService = (overrides = {}) => ({
4
- getTerraformBackend: vi.fn().mockResolvedValue(undefined),
5
- hasUserPermissionToInitialize: vi.fn().mockResolvedValue(true),
6
- initialize: vi.fn().mockResolvedValue(undefined),
7
- isInitialized: vi.fn().mockResolvedValue(true),
8
- provisionTerraformBackend: vi.fn().mockResolvedValue(undefined),
9
- ...overrides,
10
- });
11
- const createMockCloudAccount = (overrides = {}) => ({
12
- csp: "azure",
13
- defaultLocation: "westeurope",
14
- displayName: "Test-Account",
15
- id: "test-subscription-id",
16
- ...overrides,
17
- });
18
- const createMockTerraformBackend = (overrides = {}) => ({
19
- resourceGroupName: "dx-d-itn-tf-rg",
20
- storageAccountName: "dxditntfst",
21
- subscriptionId: "00000000-0000-0000-0000-000000000000",
22
- type: "azurerm",
23
- ...overrides,
24
- });
25
- const createMockPayload = (overrides = {}) => ({
26
- env: {
27
- cloudAccounts: [createMockCloudAccount()],
28
- name: "dev",
29
- prefix: "dx",
30
- },
31
- github: {
32
- owner: "pagopa",
33
- repo: "dx",
34
- },
35
- init: {
36
- cloudAccountsToInitialize: [],
37
- runnerAppCredentials: {
38
- clientId: "test-app-client-id",
39
- id: "test-app-id",
40
- installationId: "test-installation-id",
41
- key: "test-private-key",
42
- },
43
- terraformBackend: {
44
- cloudAccount: createMockCloudAccount(),
45
- },
46
- },
47
- tags: {},
48
- workspace: {
49
- domain: "test",
50
- },
51
- ...overrides,
52
- });
53
- describe("provisionTerraformBackend", () => {
54
- it("should provision terraform backend and return it", async () => {
55
- const mockBackend = createMockTerraformBackend();
56
- const provisionMock = vi.fn().mockResolvedValue(mockBackend);
57
- const mockService = createMockCloudAccountService({
58
- provisionTerraformBackend: provisionMock,
59
- });
60
- const payload = createMockPayload();
61
- const result = await provisionTerraformBackend(payload, mockService);
62
- expect(result).toEqual(mockBackend);
63
- });
64
- it("should call provisionTerraformBackend with correct parameters", async () => {
65
- const cloudAccount = createMockCloudAccount({ id: "my-subscription" });
66
- const provisionMock = vi
67
- .fn()
68
- .mockResolvedValue(createMockTerraformBackend());
69
- const mockService = createMockCloudAccountService({
70
- provisionTerraformBackend: provisionMock,
71
- });
72
- const payload = createMockPayload({
73
- env: {
74
- cloudAccounts: [cloudAccount],
75
- name: "prod",
76
- prefix: "io",
77
- },
78
- init: {
79
- cloudAccountsToInitialize: [],
80
- runnerAppCredentials: {
81
- clientId: "test-app-client-id",
82
- id: "test-app-id",
83
- installationId: "test-installation-id",
84
- key: "test-private-key",
85
- },
86
- terraformBackend: {
87
- cloudAccount,
88
- },
89
- },
90
- });
91
- await provisionTerraformBackend(payload, mockService);
92
- expect(provisionMock).toHaveBeenCalledWith(cloudAccount, expect.objectContaining({ name: "prod", prefix: "io" }), {});
93
- });
94
- it("should throw an error when payload.init is undefined", async () => {
95
- const mockService = createMockCloudAccountService();
96
- const payload = createMockPayload({
97
- init: undefined,
98
- });
99
- await expect(provisionTerraformBackend(payload, mockService)).rejects.toThrow("This action requires initialization data in the payload");
100
- });
101
- it("should use the terraformBackend cloudAccount from init", async () => {
102
- const envCloudAccount = createMockCloudAccount({ id: "env-account" });
103
- const backendCloudAccount = createMockCloudAccount({
104
- id: "backend-account",
105
- });
106
- const provisionMock = vi
107
- .fn()
108
- .mockResolvedValue(createMockTerraformBackend());
109
- const mockService = createMockCloudAccountService({
110
- provisionTerraformBackend: provisionMock,
111
- });
112
- const payload = createMockPayload({
113
- env: {
114
- cloudAccounts: [envCloudAccount],
115
- name: "uat",
116
- prefix: "dx",
117
- },
118
- init: {
119
- cloudAccountsToInitialize: [],
120
- runnerAppCredentials: {
121
- clientId: "test-app-client-id",
122
- id: "test-app-id",
123
- installationId: "test-installation-id",
124
- key: "test-private-key",
125
- },
126
- terraformBackend: {
127
- cloudAccount: backendCloudAccount,
128
- },
129
- },
130
- });
131
- await provisionTerraformBackend(payload, mockService);
132
- expect(provisionMock).toHaveBeenCalledWith(backendCloudAccount, expect.objectContaining({ name: "uat", prefix: "dx" }), {});
133
- });
134
- });
@@ -1,2 +0,0 @@
1
- export declare const cleanupTempDir: (tmpDir: string) => Promise<void>;
2
- export declare const readGeneratedFiles: (rootDir: string, filePaths: readonly string[]) => Promise<Record<string, string>>;
@@ -1,13 +0,0 @@
1
- /**
2
- * Temp directory helpers for Plop generator integration tests.
3
- */
4
- import fs from "node:fs/promises";
5
- import path from "node:path";
6
- export const cleanupTempDir = async (tmpDir) => {
7
- await fs.rm(tmpDir, { force: true, recursive: true });
8
- };
9
- const readGeneratedFile = async (rootDir, filePath) => [
10
- filePath,
11
- await fs.readFile(path.join(rootDir, filePath), "utf-8"),
12
- ];
13
- export const readGeneratedFiles = async (rootDir, filePaths) => Object.fromEntries(await Promise.all(filePaths.map((filePath) => readGeneratedFile(rootDir, filePath))));
@@ -1,2 +0,0 @@
1
- import { Payload } from "../prompts.js";
2
- export declare const getPayload: (includeInit?: boolean) => Payload;
@@ -1,92 +0,0 @@
1
- import { describe, expect, test } from "vitest";
2
- import { z } from "zod";
3
- import getActions from "../actions.js";
4
- const terraformBackendActionSchema = z.object({
5
- data: z.object({
6
- terraformBackendKey: z.string(),
7
- }),
8
- type: z.literal("addMany"),
9
- });
10
- export const getPayload = (includeInit = false) => {
11
- const cloudAccount = {
12
- csp: "azure",
13
- defaultLocation: "westeurope",
14
- displayName: "Test-Account",
15
- id: "test-subscription-id",
16
- };
17
- const payload = {
18
- env: {
19
- cloudAccounts: [cloudAccount],
20
- name: "dev",
21
- prefix: "dx",
22
- },
23
- github: {
24
- owner: "pagopa",
25
- repo: "dx",
26
- },
27
- tags: {},
28
- workspace: {
29
- domain: "mytest",
30
- },
31
- };
32
- if (includeInit) {
33
- payload.init = {
34
- cloudAccountsToInitialize: [cloudAccount],
35
- runnerAppCredentials: {
36
- clientId: "test-app-client-id",
37
- id: "test-app-id",
38
- installationId: "test-installation-id",
39
- key: "test-private-key",
40
- },
41
- terraformBackend: {
42
- cloudAccount,
43
- },
44
- };
45
- }
46
- return payload;
47
- };
48
- describe("actions", () => {
49
- test.each([
50
- {
51
- payload: getPayload(true),
52
- },
53
- {
54
- payload: getPayload(false),
55
- },
56
- ])("correct order of actions", ({ payload }) => {
57
- const actionsOrder = [
58
- "getTerraformBackend",
59
- "addMany",
60
- "addMany",
61
- "addMany",
62
- ];
63
- if (payload.init) {
64
- actionsOrder.unshift("initCloudAccounts", "provisionTerraformBackend");
65
- actionsOrder.push("addMany", "addMany");
66
- }
67
- const actions = getActions("/templates/path")(payload);
68
- const actionTypes = actions
69
- .filter((action) => typeof action === "object" && Object.hasOwn(action, "type"))
70
- .map((action) => action.type);
71
- expect(actionTypes).toEqual(actionsOrder);
72
- });
73
- test.each([
74
- {
75
- expectedKeys: [
76
- "dx/mytest/bootstrapper.tfstate",
77
- "dx/mytest/core.tfstate",
78
- ],
79
- payload: getPayload(true),
80
- },
81
- {
82
- expectedKeys: ["dx/mytest/bootstrapper.tfstate"],
83
- payload: getPayload(false),
84
- },
85
- ])("uses prefix/domain/scope state keys in shared backend actions", ({ expectedKeys, payload }) => {
86
- const actions = getActions("/templates/path")(payload);
87
- const terraformBackendKeys = actions
88
- .filter((action) => terraformBackendActionSchema.safeParse(action).success)
89
- .map((action) => action.data.terraformBackendKey);
90
- expect(terraformBackendKeys).toEqual(expectedKeys);
91
- });
92
- });
@@ -1,213 +0,0 @@
1
- import nodePlop from "node-plop";
2
- /**
3
- * Contract tests for the environment generator.
4
- *
5
- * They generate real files in a temp directory while asserting only
6
- * generator-specific behavior: which domain actions run for a given
7
- * generator state and which high-value values are materialized into
8
- * the generated infrastructure files.
9
- */
10
- import fs from "node:fs/promises";
11
- import os from "node:os";
12
- import path from "node:path";
13
- import { afterAll, beforeAll, describe, expect, it, vi } from "vitest";
14
- import setGetTerraformBackend from "../../../actions/get-terraform-backend.js";
15
- import setInitCloudAccountsAction from "../../../actions/init-cloud-accounts.js";
16
- import setProvisionTerraformBackendAction from "../../../actions/provision-terraform-backend.js";
17
- import setEnvShortHelper from "../../../helpers/env-short.js";
18
- import setEqHelper from "../../../helpers/eq.js";
19
- import setResourcePrefixHelper from "../../../helpers/resource-prefix.js";
20
- import setTerraformStateKeyHelper from "../../../helpers/terraform-state-key.js";
21
- import { resolveTemplatesPath } from "../../../templates-path.js";
22
- import { cleanupTempDir, readGeneratedFiles, } from "../../__tests__/temp-dir.js";
23
- import getActions from "../actions.js";
24
- import { PLOP_ENVIRONMENT_GENERATOR_NAME } from "../index.js";
25
- vi.mock("../../../../terraform/fmt.js", () => ({
26
- formatTerraformCode: vi.fn((content) => content),
27
- }));
28
- /**
29
- * Register helpers and stub action types for the environment generator.
30
- * Cloud-service action types are registered with DI mock objects.
31
- */
32
- const registerEnvironmentSetup = (plop, mockCloudAccountService, mockGitHubService) => {
33
- setEnvShortHelper(plop);
34
- setResourcePrefixHelper(plop);
35
- setEqHelper(plop);
36
- setTerraformStateKeyHelper(plop);
37
- setGetTerraformBackend(plop, mockCloudAccountService);
38
- setProvisionTerraformBackendAction(plop, mockCloudAccountService);
39
- setInitCloudAccountsAction(plop, mockCloudAccountService, mockGitHubService);
40
- };
41
- const mockTerraformBackend = {
42
- resourceGroupName: "dx-d-itn-tf-rg",
43
- storageAccountName: "dxditntfst",
44
- subscriptionId: "00000000-0000-0000-0000-000000000000",
45
- type: "azurerm",
46
- };
47
- const createMockCloudAccountService = (backend, isInitialized) => ({
48
- getTerraformBackend: vi.fn().mockResolvedValue(backend),
49
- hasUserPermissionToInitialize: vi.fn().mockResolvedValue(true),
50
- initialize: vi.fn().mockResolvedValue(undefined),
51
- isInitialized: vi.fn().mockResolvedValue(isInitialized),
52
- provisionTerraformBackend: vi.fn().mockResolvedValue(backend),
53
- });
54
- const createMockGitHubService = () => ({
55
- createBranch: vi.fn().mockResolvedValue(undefined),
56
- createOrUpdateEnvironmentSecret: vi.fn().mockResolvedValue(undefined),
57
- createPullRequest: vi.fn().mockResolvedValue(undefined),
58
- getFileContent: vi.fn().mockResolvedValue(undefined),
59
- getRepository: vi.fn().mockResolvedValue(undefined),
60
- updateFile: vi.fn().mockResolvedValue(undefined),
61
- });
62
- const runEnvironmentGenerator = async ({ mockCloudAccountService, mockGitHubService, payload, tmpDirPrefix, }) => {
63
- const originalCwd = process.cwd();
64
- const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), tmpDirPrefix));
65
- process.chdir(tmpDir);
66
- const plop = await nodePlop();
67
- registerEnvironmentSetup(plop, mockCloudAccountService, mockGitHubService);
68
- plop.setGenerator(PLOP_ENVIRONMENT_GENERATOR_NAME, {
69
- actions: getActions(resolveTemplatesPath("environment")),
70
- description: "Generate a new deployment environment",
71
- prompts: [],
72
- });
73
- const generator = plop.getGenerator(PLOP_ENVIRONMENT_GENERATOR_NAME);
74
- const result = await generator.runActions(payload);
75
- const realFailures = result.failures.filter((f) => f.error !== "Aborted due to previous action failure");
76
- if (realFailures.length > 0) {
77
- const summary = realFailures.map((f) => `${f.type}: ${f.error}`).join("\n");
78
- throw new Error(`Generator failed:\n${summary}`);
79
- }
80
- return { originalCwd, tmpDir };
81
- };
82
- describe("environment generator — file generation (no init)", () => {
83
- let tmpDir;
84
- let originalCwd;
85
- const payload = {
86
- env: {
87
- cloudAccounts: [
88
- {
89
- csp: "azure",
90
- defaultLocation: "italynorth",
91
- displayName: "DEV-DX",
92
- id: "sub-dev-123",
93
- },
94
- ],
95
- name: "dev",
96
- prefix: "dx",
97
- },
98
- github: {
99
- owner: "pagopa",
100
- repo: "my-project",
101
- },
102
- tags: {
103
- BusinessUnit: "Platform",
104
- CostCenter: "TS000",
105
- ManagementTeam: "Engineering",
106
- },
107
- workspace: {
108
- domain: "payments",
109
- },
110
- };
111
- const mockCloudAccountService = createMockCloudAccountService(mockTerraformBackend, true);
112
- const mockGitHubService = createMockGitHubService();
113
- beforeAll(async () => {
114
- ({ originalCwd, tmpDir } = await runEnvironmentGenerator({
115
- mockCloudAccountService,
116
- mockGitHubService,
117
- payload,
118
- tmpDirPrefix: "dx-cli-env-test-",
119
- }));
120
- });
121
- afterAll(async () => {
122
- process.chdir(originalCwd);
123
- await cleanupTempDir(tmpDir);
124
- });
125
- it("materializes bootstrapper files from payload and backend state", async () => {
126
- const generatedFiles = await readGeneratedFiles(tmpDir, [
127
- `.github/workflows/_release-terraform-apply-bootstrapper-${payload.env.name}.yaml`,
128
- `infra/bootstrapper/${payload.env.name}/main.tf`,
129
- `infra/bootstrapper/${payload.env.name}/providers.tf`,
130
- `infra/bootstrapper/${payload.env.name}/backend.tf`,
131
- `infra/bootstrapper/${payload.env.name}/locals.tf`,
132
- ]);
133
- expect(generatedFiles).toMatchSnapshot();
134
- });
135
- it("skips init-only side effects and core files when init is absent", async () => {
136
- const corePath = path.join(tmpDir, "infra", "core", payload.env.name);
137
- expect(mockCloudAccountService.getTerraformBackend).toHaveBeenCalledWith(payload.env.cloudAccounts[0].id, payload.env);
138
- expect(mockCloudAccountService.initialize).not.toHaveBeenCalled();
139
- expect(mockCloudAccountService.provisionTerraformBackend).not.toHaveBeenCalled();
140
- await expect(fs.stat(corePath)).rejects.toThrow();
141
- });
142
- });
143
- describe("environment generator — file generation (with init)", () => {
144
- let tmpDir;
145
- let originalCwd;
146
- const cloudAccount = {
147
- csp: "azure",
148
- defaultLocation: "italynorth",
149
- displayName: "DEV-DX",
150
- id: "sub-dev-123",
151
- };
152
- const payload = {
153
- env: {
154
- cloudAccounts: [cloudAccount],
155
- name: "dev",
156
- prefix: "dx",
157
- },
158
- github: {
159
- owner: "pagopa",
160
- repo: "my-project",
161
- },
162
- init: {
163
- cloudAccountsToInitialize: [cloudAccount],
164
- runnerAppCredentials: {
165
- clientId: "test-app-client-id",
166
- id: "test-app-id",
167
- installationId: "test-installation-id",
168
- key: "test-private-key",
169
- },
170
- terraformBackend: {
171
- cloudAccount,
172
- },
173
- },
174
- tags: {
175
- BusinessUnit: "Platform",
176
- CostCenter: "TS000",
177
- ManagementTeam: "Engineering",
178
- },
179
- workspace: {
180
- domain: "payments",
181
- },
182
- };
183
- const mockCloudAccountService = createMockCloudAccountService(mockTerraformBackend, false);
184
- const mockGitHubService = createMockGitHubService();
185
- beforeAll(async () => {
186
- ({ originalCwd, tmpDir } = await runEnvironmentGenerator({
187
- mockCloudAccountService,
188
- mockGitHubService,
189
- payload,
190
- tmpDirPrefix: "dx-cli-env-init-test-",
191
- }));
192
- });
193
- afterAll(async () => {
194
- process.chdir(originalCwd);
195
- await cleanupTempDir(tmpDir);
196
- });
197
- it("runs init-specific actions when init is provided", () => {
198
- expect(mockCloudAccountService.initialize).toHaveBeenCalledWith(cloudAccount, payload.env,
199
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
200
- payload.init.runnerAppCredentials, payload.github, mockGitHubService, payload.tags);
201
- expect(mockCloudAccountService.provisionTerraformBackend).toHaveBeenCalledWith(cloudAccount, payload.env, payload.tags);
202
- expect(mockCloudAccountService.getTerraformBackend).not.toHaveBeenCalled();
203
- });
204
- it("materializes init-specific infrastructure files", async () => {
205
- const generatedFiles = await readGeneratedFiles(tmpDir, [
206
- `infra/core/${payload.env.name}/main.tf`,
207
- `infra/core/${payload.env.name}/providers.tf`,
208
- `infra/core/${payload.env.name}/backend.tf`,
209
- `infra/bootstrapper/${payload.env.name}/main.tf`,
210
- ]);
211
- expect(generatedFiles).toMatchSnapshot();
212
- });
213
- });