@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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagopa/dx-cli",
3
- "version": "0.23.0",
3
+ "version": "0.23.1",
4
4
  "type": "module",
5
5
  "description": "A CLI useful to manage DX tools.",
6
6
  "repository": {
@@ -48,7 +48,7 @@
48
48
  "semver": "^7.7.4",
49
49
  "yaml": "^2.8.4",
50
50
  "zod": "^4.4.2",
51
- "@pagopa/dx-savemoney": "^0.3.0"
51
+ "@pagopa/dx-savemoney": "^0.3.1"
52
52
  },
53
53
  "devDependencies": {
54
54
  "@tsconfig/node24": "24.0.4",
@@ -56,15 +56,15 @@
56
56
  "@types/libsodium-wrappers": "^0.8.2",
57
57
  "@types/node": "^22.19.17",
58
58
  "@types/semver": "^7.7.1",
59
- "@vitest/coverage-v8": "^3.2.4",
59
+ "@vitest/coverage-v8": "^4.1.8",
60
60
  "eslint": "^10.3.0",
61
61
  "fast-check": "^4.8.0",
62
62
  "memfs": "^4.57.2",
63
63
  "plop": "^4.0.5",
64
64
  "prettier": "3.8.3",
65
65
  "typescript": "~5.9.3",
66
- "vitest": "^3.2.4",
67
- "vitest-mock-extended": "^3.1.1",
66
+ "vitest": "^4.1.8",
67
+ "vitest-mock-extended": "^4.0.0",
68
68
  "@pagopa/eslint-config": "^6.0.4"
69
69
  },
70
70
  "engines": {
@@ -68,7 +68,6 @@
68
68
  },
69
69
  "build": {
70
70
  "targetName": "build",
71
- "configName": "tsconfig.json",
72
71
  "buildDepsName": "build-deps",
73
72
  "watchDepsName": "watch-deps"
74
73
  }
@@ -1,95 +0,0 @@
1
- import { describe, expect, it, vi } from "vitest";
2
- import { AzureSubscriptionRepository } from "../cloud-account-repository.js";
3
- const createMockSubscription = (overrides = {}) => ({
4
- displayName: "Test Subscription",
5
- state: "Enabled",
6
- subscriptionId: "00000000-0000-0000-0000-000000000001",
7
- ...overrides,
8
- });
9
- const createMockSubscriptionClient = (subscriptions) => {
10
- const listIterator = async function* () {
11
- for (const sub of subscriptions) {
12
- yield sub;
13
- }
14
- };
15
- return {
16
- subscriptions: {
17
- list: listIterator,
18
- },
19
- };
20
- };
21
- vi.mock("@azure/arm-resources-subscriptions", () => ({
22
- SubscriptionClient: vi.fn(),
23
- }));
24
- vi.mock("@azure/identity", () => ({
25
- DefaultAzureCredential: vi.fn(),
26
- }));
27
- import { SubscriptionClient } from "@azure/arm-resources-subscriptions";
28
- import { DefaultAzureCredential } from "@azure/identity";
29
- const MockedSubscriptionClient = SubscriptionClient;
30
- describe("AzureSubscriptionRepository", () => {
31
- it("should return a list of enabled subscriptions", async () => {
32
- const subscriptions = [
33
- createMockSubscription({
34
- displayName: "Sub 1",
35
- subscriptionId: "sub-1",
36
- }),
37
- createMockSubscription({
38
- displayName: "Sub 2",
39
- subscriptionId: "sub-2",
40
- }),
41
- ];
42
- MockedSubscriptionClient.mockImplementation(() => createMockSubscriptionClient(subscriptions));
43
- const repository = new AzureSubscriptionRepository(new DefaultAzureCredential());
44
- const result = await repository.list();
45
- expect(result).toHaveLength(2);
46
- expect(result[0]).toMatchObject({
47
- displayName: "Sub 1",
48
- id: "sub-1",
49
- });
50
- expect(result[1]).toMatchObject({
51
- displayName: "Sub 2",
52
- id: "sub-2",
53
- });
54
- });
55
- it("should filter out disabled subscriptions", async () => {
56
- const subscriptions = [
57
- createMockSubscription({
58
- displayName: "Enabled Sub",
59
- state: "Enabled",
60
- subscriptionId: "enabled-sub",
61
- }),
62
- createMockSubscription({
63
- displayName: "Disabled Sub",
64
- state: "Disabled",
65
- subscriptionId: "disabled-sub",
66
- }),
67
- ];
68
- MockedSubscriptionClient.mockImplementation(() => createMockSubscriptionClient(subscriptions));
69
- const repository = new AzureSubscriptionRepository(new DefaultAzureCredential());
70
- const result = await repository.list();
71
- expect(result).toHaveLength(1);
72
- expect(result[0]).toMatchObject({
73
- displayName: "Enabled Sub",
74
- id: "enabled-sub",
75
- });
76
- });
77
- it("should return an empty array when no subscriptions exist", async () => {
78
- MockedSubscriptionClient.mockImplementation(() => createMockSubscriptionClient([]));
79
- const repository = new AzureSubscriptionRepository(new DefaultAzureCredential());
80
- const result = await repository.list();
81
- expect(result).toEqual([]);
82
- });
83
- it("should filter out subscriptions with other states", async () => {
84
- const subscriptions = [
85
- createMockSubscription({ state: "Enabled" }),
86
- createMockSubscription({ state: "Warned" }),
87
- createMockSubscription({ state: "PastDue" }),
88
- createMockSubscription({ state: "Deleted" }),
89
- ];
90
- MockedSubscriptionClient.mockImplementation(() => createMockSubscriptionClient(subscriptions));
91
- const repository = new AzureSubscriptionRepository(new DefaultAzureCredential());
92
- const result = await repository.list();
93
- expect(result).toHaveLength(1);
94
- });
95
- });
@@ -1,378 +0,0 @@
1
- import { DefaultAzureCredential } from "@azure/identity";
2
- import { test as baseTest, beforeEach, describe, expect, vi } from "vitest";
3
- import { AzureCloudAccountService } from "../cloud-account-service.js";
4
- const { queryResources } = vi.hoisted(() => ({
5
- queryResources: vi.fn().mockRejectedValue(new Error("Not implemented")),
6
- }));
7
- const { mockProviderGet, mockProviderRegister } = vi.hoisted(() => ({
8
- mockProviderGet: vi
9
- .fn()
10
- .mockResolvedValue({ registrationState: "Registered" }),
11
- mockProviderRegister: vi.fn().mockResolvedValue({}),
12
- }));
13
- const { mockRoleAssignmentsCreate, mockRoleAssignmentsListForScope } = vi.hoisted(() => ({
14
- mockRoleAssignmentsCreate: vi.fn().mockResolvedValue({}),
15
- mockRoleAssignmentsListForScope: vi.fn(),
16
- }));
17
- const { mockCreateFederatedIdentityCredential, mockCreateIdentity, mockCreateKeyVault, mockCreateResourceGroup, mockDeleteResourceGroup, mockGetSubscription, mockKeyVaultNameAvailability, mockSetSecret, } = vi.hoisted(() => ({
18
- mockCreateFederatedIdentityCredential: vi.fn().mockResolvedValue({}),
19
- mockCreateIdentity: vi
20
- .fn()
21
- .mockResolvedValue({ clientId: "client-1", principalId: "principal-1" }),
22
- mockCreateKeyVault: vi.fn().mockResolvedValue({}),
23
- mockCreateResourceGroup: vi.fn().mockResolvedValue({}),
24
- mockDeleteResourceGroup: vi.fn().mockResolvedValue({}),
25
- mockGetSubscription: vi.fn().mockResolvedValue({ tenantId: "tenant-1" }),
26
- mockKeyVaultNameAvailability: vi.fn().mockResolvedValue({
27
- nameAvailable: true,
28
- }),
29
- mockSetSecret: vi.fn().mockResolvedValue({}),
30
- }));
31
- vi.mock("@azure/arm-authorization", () => ({
32
- AuthorizationManagementClient: class {
33
- roleAssignments = {
34
- create: mockRoleAssignmentsCreate,
35
- listForScope: mockRoleAssignmentsListForScope,
36
- };
37
- },
38
- }));
39
- vi.mock("@azure/arm-keyvault", () => ({
40
- KeyVaultManagementClient: class {
41
- vaults = {
42
- beginCreateOrUpdateAndWait: mockCreateKeyVault,
43
- checkNameAvailability: mockKeyVaultNameAvailability,
44
- };
45
- },
46
- }));
47
- vi.mock("@azure/arm-msi", () => ({
48
- ManagedServiceIdentityClient: class {
49
- federatedIdentityCredentials = {
50
- createOrUpdate: mockCreateFederatedIdentityCredential,
51
- };
52
- userAssignedIdentities = {
53
- createOrUpdate: mockCreateIdentity,
54
- };
55
- },
56
- }));
57
- vi.mock("@azure/identity", () => ({
58
- DefaultAzureCredential: vi.fn(),
59
- }));
60
- vi.mock("@azure/arm-resourcegraph", () => ({
61
- ResourceGraphClient: class {
62
- resources = queryResources;
63
- },
64
- }));
65
- vi.mock("@azure/arm-resources", () => ({
66
- ResourceManagementClient: class {
67
- providers = {
68
- get: mockProviderGet,
69
- register: mockProviderRegister,
70
- };
71
- resourceGroups = {
72
- beginDeleteAndWait: mockDeleteResourceGroup,
73
- createOrUpdate: mockCreateResourceGroup,
74
- };
75
- },
76
- }));
77
- vi.mock("@azure/arm-resources-subscriptions", () => ({
78
- SubscriptionClient: class {
79
- subscriptions = {
80
- get: mockGetSubscription,
81
- };
82
- },
83
- }));
84
- vi.mock("@azure/keyvault-secrets", () => ({
85
- SecretClient: class {
86
- setSecret = mockSetSecret;
87
- },
88
- }));
89
- const test = baseTest.extend({
90
- // the empty pattern is required by vitest!!!
91
- // eslint-disable-next-line no-empty-pattern
92
- cloudAccountService: async ({}, use) => {
93
- const cloudAccountService = new AzureCloudAccountService(new DefaultAzureCredential());
94
- await use(cloudAccountService);
95
- },
96
- });
97
- beforeEach(() => {
98
- queryResources.mockReset();
99
- queryResources.mockResolvedValue({ data: [], totalRecords: 0 });
100
- mockCreateFederatedIdentityCredential.mockClear();
101
- mockCreateIdentity.mockClear();
102
- mockCreateIdentity.mockResolvedValue({
103
- clientId: "client-1",
104
- principalId: "principal-1",
105
- });
106
- mockCreateKeyVault.mockClear();
107
- mockCreateResourceGroup.mockClear();
108
- mockDeleteResourceGroup.mockClear();
109
- mockGetSubscription.mockClear();
110
- mockGetSubscription.mockResolvedValue({ tenantId: "tenant-1" });
111
- mockKeyVaultNameAvailability.mockClear();
112
- mockKeyVaultNameAvailability.mockResolvedValue({ nameAvailable: true });
113
- mockProviderGet.mockClear();
114
- mockProviderGet.mockResolvedValue({ registrationState: "Registered" });
115
- mockProviderRegister.mockClear();
116
- mockRoleAssignmentsCreate.mockClear();
117
- mockRoleAssignmentsListForScope.mockReset();
118
- mockSetSecret.mockClear();
119
- });
120
- describe("getTerraformBackend", () => {
121
- test("returns undefined when no matching storage account is found", async ({ cloudAccountService, }) => {
122
- queryResources.mockResolvedValueOnce({
123
- data: [],
124
- totalRecords: 0,
125
- });
126
- const result = await cloudAccountService.getTerraformBackend("sub-1", {
127
- name: "dev",
128
- prefix: "dx",
129
- });
130
- expect(result).toBeUndefined();
131
- });
132
- test("return the only matching storage account", async ({ cloudAccountService, }) => {
133
- queryResources.mockResolvedValueOnce({
134
- data: [
135
- {
136
- location: "italynorth",
137
- name: "dxditntfstatest01",
138
- resourceGroup: "dx-d-itn-tfstate-rg-01",
139
- subscriptionId: "sub-1",
140
- type: "microsoft.storage/storageaccounts",
141
- },
142
- ],
143
- totalRecords: 1,
144
- });
145
- const result = await cloudAccountService.getTerraformBackend("sub-1", {
146
- name: "dev",
147
- prefix: "dx",
148
- });
149
- expect(result).toEqual(expect.objectContaining({
150
- resourceGroupName: "dx-d-itn-tfstate-rg-01",
151
- storageAccountName: "dxditntfstatest01",
152
- type: "azurerm",
153
- }));
154
- });
155
- test("returns the best matching storage account among multiple", async ({ cloudAccountService, }) => {
156
- queryResources.mockResolvedValueOnce({
157
- data: [
158
- {
159
- location: "italynorth",
160
- name: "dxditntfstatest01",
161
- resourceGroup: "dx-d-itn-tfstate-rg-01",
162
- subscriptionId: "sub-1",
163
- type: "microsoft.storage/storageaccounts",
164
- },
165
- {
166
- location: "italynorth",
167
- name: "dxditntfstatest02",
168
- resourceGroup: "dx-d-itn-tfstate-rg-01",
169
- subscriptionId: "sub-1",
170
- type: "microsoft.storage/storageaccounts",
171
- },
172
- {
173
- location: "westeurope",
174
- name: "dxdweutfstatest01",
175
- resourceGroup: "dx-d-weu-tfstate-rg-01",
176
- subscriptionId: "sub-1",
177
- type: "microsoft.storage/storageaccounts",
178
- },
179
- ],
180
- totalRecords: 3,
181
- });
182
- const result = await cloudAccountService.getTerraformBackend("sub-1", {
183
- name: "dev",
184
- prefix: "dx",
185
- });
186
- expect(result).toEqual(expect.objectContaining({
187
- resourceGroupName: "dx-d-itn-tfstate-rg-01",
188
- storageAccountName: "dxditntfstatest02",
189
- type: "azurerm",
190
- }));
191
- });
192
- });
193
- describe("isInitialized", () => {
194
- test("returns true when both bootstrap identity and common Key Vault exist and all providers are registered", async ({ cloudAccountService, }) => {
195
- // First call: identity query → found
196
- queryResources.mockResolvedValueOnce({ data: [], totalRecords: 1 });
197
- // Second call: key vault query → found
198
- queryResources.mockResolvedValueOnce({ data: [], totalRecords: 1 });
199
- // Provider checks → all registered (default mock)
200
- const result = await cloudAccountService.isInitialized("sub-1", {
201
- name: "dev",
202
- prefix: "dx",
203
- });
204
- expect(result).toBe(true);
205
- });
206
- test("returns false when bootstrap identity exists but common Key Vault does not", async ({ cloudAccountService, }) => {
207
- // First call: identity query → found
208
- queryResources.mockResolvedValueOnce({ data: [], totalRecords: 1 });
209
- // Second call: key vault query → not found
210
- queryResources.mockResolvedValueOnce({ data: [], totalRecords: 0 });
211
- const result = await cloudAccountService.isInitialized("sub-1", {
212
- name: "dev",
213
- prefix: "dx",
214
- });
215
- expect(result).toBe(false);
216
- });
217
- test("returns false when common Key Vault exists but bootstrap identity does not", async ({ cloudAccountService, }) => {
218
- // First call: identity query → not found
219
- queryResources.mockResolvedValueOnce({ data: [], totalRecords: 0 });
220
- // Second call: key vault query → found
221
- queryResources.mockResolvedValueOnce({ data: [], totalRecords: 1 });
222
- const result = await cloudAccountService.isInitialized("sub-1", {
223
- name: "dev",
224
- prefix: "dx",
225
- });
226
- expect(result).toBe(false);
227
- });
228
- test("returns false when resources exist but a required provider is not registered", async ({ cloudAccountService, }) => {
229
- // Both resources exist
230
- queryResources.mockResolvedValueOnce({ data: [], totalRecords: 1 });
231
- queryResources.mockResolvedValueOnce({ data: [], totalRecords: 1 });
232
- // One provider is not registered
233
- mockProviderGet.mockResolvedValueOnce({
234
- registrationState: "NotRegistered",
235
- });
236
- const result = await cloudAccountService.isInitialized("sub-1", {
237
- name: "dev",
238
- prefix: "dx",
239
- });
240
- expect(result).toBe(false);
241
- });
242
- });
243
- describe("initialize", () => {
244
- test("assigns bootstrap roles and creates bootstrap environment secrets", async ({ cloudAccountService, }) => {
245
- const createOrUpdateEnvironmentSecret = vi
246
- .fn()
247
- .mockResolvedValue(undefined);
248
- await cloudAccountService.initialize({
249
- csp: "azure",
250
- defaultLocation: "italynorth",
251
- displayName: "Test subscription",
252
- id: "sub-1",
253
- }, {
254
- name: "dev",
255
- prefix: "dx",
256
- }, {
257
- clientId: "app-client-id",
258
- id: "app-id",
259
- installationId: "installation-id",
260
- key: "private-key\n",
261
- }, {
262
- owner: "pagopa",
263
- repo: "dx",
264
- }, {
265
- createBranch: vi.fn(),
266
- createOrUpdateEnvironmentSecret,
267
- createPullRequest: vi.fn(),
268
- getFileContent: vi.fn(),
269
- getRepository: vi.fn(),
270
- updateFile: vi.fn(),
271
- });
272
- expect(mockRoleAssignmentsCreate).toHaveBeenCalledTimes(3);
273
- expect(mockRoleAssignmentsCreate).toHaveBeenCalledWith("/subscriptions/sub-1", expect.any(String), expect.objectContaining({
274
- principalId: "principal-1",
275
- principalType: "ServicePrincipal",
276
- roleDefinitionId: "/subscriptions/sub-1/providers/Microsoft.Authorization/roleDefinitions/f58310d9-a9f6-439a-9e8d-f62e7b41a168",
277
- }));
278
- expect(mockRoleAssignmentsCreate).toHaveBeenCalledWith("/subscriptions/sub-1", expect.any(String), expect.objectContaining({
279
- principalId: "principal-1",
280
- principalType: "ServicePrincipal",
281
- roleDefinitionId: "/subscriptions/sub-1/providers/Microsoft.Authorization/roleDefinitions/b24988ac-6180-42a0-ab88-20f7382dd24c",
282
- }));
283
- expect(mockRoleAssignmentsCreate).toHaveBeenCalledWith("/subscriptions/sub-1", expect.any(String), expect.objectContaining({
284
- principalId: "principal-1",
285
- principalType: "ServicePrincipal",
286
- roleDefinitionId: "/subscriptions/sub-1/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe",
287
- }));
288
- expect(mockCreateFederatedIdentityCredential).toHaveBeenCalledWith("dx-d-itn-common-rg-01", "dx-d-itn-bootstrap-id-01", "dx-bootstrapper-dev-cd", {
289
- audiences: ["api://AzureADTokenExchange"],
290
- issuer: "https://token.actions.githubusercontent.com",
291
- subject: "repo:pagopa/dx:environment:bootstrapper-dev-cd",
292
- });
293
- expect(createOrUpdateEnvironmentSecret).toHaveBeenCalledTimes(7);
294
- expect(createOrUpdateEnvironmentSecret).toHaveBeenCalledWith({
295
- environmentName: "bootstrapper-dev-cd",
296
- owner: "pagopa",
297
- repo: "dx",
298
- secretName: "ARM_CLIENT_ID",
299
- secretValue: "client-1",
300
- });
301
- expect(createOrUpdateEnvironmentSecret).toHaveBeenCalledWith({
302
- environmentName: "bootstrapper-dev-cd",
303
- owner: "pagopa",
304
- repo: "dx",
305
- secretName: "ARM_TENANT_ID",
306
- secretValue: "tenant-1",
307
- });
308
- expect(createOrUpdateEnvironmentSecret).toHaveBeenCalledWith({
309
- environmentName: "bootstrapper-dev-cd",
310
- owner: "pagopa",
311
- repo: "dx",
312
- secretName: "ARM_SUBSCRIPTION_ID",
313
- secretValue: "sub-1",
314
- });
315
- expect(createOrUpdateEnvironmentSecret).toHaveBeenCalledWith({
316
- environmentName: "bootstrapper-dev-cd",
317
- owner: "pagopa",
318
- repo: "dx",
319
- secretName: "GH_APP_ID",
320
- secretValue: "app-id",
321
- });
322
- expect(createOrUpdateEnvironmentSecret).toHaveBeenCalledWith({
323
- environmentName: "bootstrapper-dev-cd",
324
- owner: "pagopa",
325
- repo: "dx",
326
- secretName: "GH_APP_CLIENT_ID",
327
- secretValue: "app-client-id",
328
- });
329
- expect(createOrUpdateEnvironmentSecret).toHaveBeenCalledWith({
330
- environmentName: "bootstrapper-dev-cd",
331
- owner: "pagopa",
332
- repo: "dx",
333
- secretName: "GH_APP_INSTALLATION_ID",
334
- secretValue: "installation-id",
335
- });
336
- expect(createOrUpdateEnvironmentSecret).toHaveBeenCalledWith({
337
- environmentName: "bootstrapper-dev-cd",
338
- owner: "pagopa",
339
- repo: "dx",
340
- secretName: "GH_APP_KEY",
341
- secretValue: "private-key",
342
- });
343
- });
344
- test("uses a repository-specific federated credential name", async ({ cloudAccountService, }) => {
345
- const createOrUpdateEnvironmentSecret = vi
346
- .fn()
347
- .mockResolvedValue(undefined);
348
- await cloudAccountService.initialize({
349
- csp: "azure",
350
- defaultLocation: "italynorth",
351
- displayName: "Test subscription",
352
- id: "sub-1",
353
- }, {
354
- name: "dev",
355
- prefix: "dx",
356
- }, {
357
- clientId: "app-client-id",
358
- id: "app-id",
359
- installationId: "installation-id",
360
- key: "private-key\n",
361
- }, {
362
- owner: "pagopa",
363
- repo: "dx-playground",
364
- }, {
365
- createBranch: vi.fn(),
366
- createOrUpdateEnvironmentSecret,
367
- createPullRequest: vi.fn(),
368
- getFileContent: vi.fn(),
369
- getRepository: vi.fn(),
370
- updateFile: vi.fn(),
371
- });
372
- expect(mockCreateFederatedIdentityCredential).toHaveBeenCalledWith("dx-d-itn-common-rg-01", "dx-d-itn-bootstrap-id-01", "dx-playground-bootstrapper-dev-cd", {
373
- audiences: ["api://AzureADTokenExchange"],
374
- issuer: "https://token.actions.githubusercontent.com",
375
- subject: "repo:pagopa/dx-playground:environment:bootstrapper-dev-cd",
376
- });
377
- });
378
- });
@@ -1 +0,0 @@
1
- export {};
@@ -1,56 +0,0 @@
1
- import { ok } from "neverthrow";
2
- import { describe, expect, it, vi } from "vitest";
3
- import { LocalCodemodRegistry } from "../registry.js";
4
- describe("LocalCodemodRegistry", () => {
5
- const makeCodemod = (id, description = id) => ({
6
- apply: vi.fn().mockResolvedValue(undefined),
7
- description,
8
- id,
9
- });
10
- it("returns empty list when no codemods are registered", async () => {
11
- const registry = new LocalCodemodRegistry();
12
- const result = await registry.getAll();
13
- expect(result).toStrictEqual(ok([]));
14
- });
15
- it("adds codemods and lists them via getAll", async () => {
16
- const registry = new LocalCodemodRegistry();
17
- const a = makeCodemod("a", "A");
18
- const b = makeCodemod("b", "B");
19
- registry.add(a);
20
- registry.add(b);
21
- const result = await registry.getAll();
22
- expect.assertions(3);
23
- expect(result.isOk()).toBe(true);
24
- const expected = result.unwrapOr([]);
25
- expect(expected).toHaveLength(2);
26
- expect(expected).toEqual(expect.arrayContaining([
27
- expect.objectContaining({ id: "a" }),
28
- expect.objectContaining({ id: "b" }),
29
- ]));
30
- });
31
- it("retrieves a codemod by id and returns undefined when missing", async () => {
32
- const registry = new LocalCodemodRegistry();
33
- const a = makeCodemod("a", "A");
34
- registry.add(a);
35
- const found = await registry.getById("a");
36
- expect(found.isOk()).toBe(true);
37
- const expected = found.unwrapOr(undefined);
38
- expect(expected).toBe(a);
39
- const missing = await registry.getById("nope");
40
- expect(missing.isOk()).toBe(true);
41
- const missingValue = missing.unwrapOr(undefined);
42
- expect(missingValue).toBeUndefined();
43
- });
44
- it("overwrites an existing codemod when adding with the same id", async () => {
45
- const registry = new LocalCodemodRegistry();
46
- const first = makeCodemod("a", "first");
47
- const second = makeCodemod("a", "second");
48
- registry.add(first);
49
- registry.add(second);
50
- const byId = await registry.getById("a");
51
- expect(byId.isOk()).toBe(true);
52
- const byIdValue = byId.unwrapOr(undefined);
53
- expect(byIdValue).toBe(second);
54
- expect(byIdValue).not.toBe(first);
55
- });
56
- });
@@ -1,77 +0,0 @@
1
- import { describe, expect, it } from "vitest";
2
- import { migrateWorkflow } from "../use-azure-appsvc.js";
3
- describe("migrateWorkflow", () => {
4
- const sha = "testsha";
5
- const migrate = migrateWorkflow(sha);
6
- it("adds disable_auto_staging_deploy under with for web_app_deploy", () => {
7
- const input = `
8
- jobs:
9
- deploy:
10
- uses: pagopa/dx/.github/workflows/web_app_deploy.yaml@main
11
- with:
12
- web_app_name: my-app
13
- use_staging_slot: true
14
- `;
15
- const output = migrate(input, "workflow.yaml");
16
- expect(output).toContain("disable_auto_staging_deploy: true");
17
- });
18
- it("adds disable_auto_staging_deploy under with for function_app_deploy", () => {
19
- const input = `
20
- jobs:
21
- deploy:
22
- uses: pagopa/dx/.github/workflows/function_app_deploy.yaml@main
23
- with:
24
- function_app_name: my-func
25
- use_staging_slot: true
26
- `;
27
- const output = migrate(input, "workflow.yaml");
28
- expect(output).toContain("disable_auto_staging_deploy: true");
29
- });
30
- it("renames function_app_name to web_app_name", () => {
31
- const input = `
32
- jobs:
33
- deploy:
34
- uses: pagopa/dx/.github/workflows/function_app_deploy.yaml@main
35
- with:
36
- function_app_name: my-func
37
- `;
38
- const output = migrate(input, "workflow.yaml");
39
- expect(output).toContain("web_app_name: my-func");
40
- expect(output).not.toContain("function_app_name:");
41
- });
42
- it("removes use_staging_slot", () => {
43
- const input = `
44
- jobs:
45
- deploy:
46
- uses: pagopa/dx/.github/workflows/web_app_deploy.yaml@main
47
- with:
48
- web_app_name: my-app
49
- use_staging_slot: true
50
- `;
51
- const output = migrate(input, "workflow.yaml");
52
- expect(output).not.toContain("use_staging_slot:");
53
- });
54
- it("updates uses to release-azure-appsvc.yaml@sha", () => {
55
- const input = `
56
- jobs:
57
- deploy:
58
- uses: pagopa/dx/.github/workflows/web_app_deploy.yaml@main
59
- with:
60
- web_app_name: my-app
61
- `;
62
- const output = migrate(input, "workflow.yaml");
63
- expect(output).toContain(`uses: pagopa/dx/.github/workflows/release-azure-appsvc-v1.yaml@${sha}`);
64
- });
65
- it("does not change unrelated workflows", () => {
66
- const input = `
67
- jobs:
68
- build:
69
- runs-on: ubuntu-latest
70
- steps:
71
- - name: Checkout
72
- uses: actions/checkout@v3
73
- `;
74
- const output = migrate(input, "workflow.yaml");
75
- expect(output).toBe(input);
76
- });
77
- });
@@ -1 +0,0 @@
1
- export {};