@pagopa/dx-cli 0.15.1 → 0.15.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (195) hide show
  1. package/bin/index.js +8 -1280
  2. package/dist/adapters/azure/__tests__/cloud-account-repository.test.d.ts +1 -0
  3. package/dist/adapters/azure/__tests__/cloud-account-repository.test.js +95 -0
  4. package/dist/adapters/azure/__tests__/cloud-account-service.test.d.ts +1 -0
  5. package/dist/adapters/azure/__tests__/cloud-account-service.test.js +95 -0
  6. package/dist/adapters/azure/cloud-account-repository.d.ts +12 -0
  7. package/dist/adapters/azure/cloud-account-repository.js +23 -0
  8. package/dist/adapters/azure/cloud-account-service.d.ts +22 -0
  9. package/dist/adapters/azure/cloud-account-service.js +255 -0
  10. package/dist/adapters/azure/locations.d.ts +7 -0
  11. package/dist/adapters/azure/locations.js +21 -0
  12. package/dist/adapters/codemods/__tests__/registry.test.d.ts +1 -0
  13. package/dist/adapters/codemods/__tests__/registry.test.js +59 -0
  14. package/dist/adapters/codemods/__tests__/use-azure-appsvc.test.d.ts +1 -0
  15. package/dist/adapters/codemods/__tests__/use-azure-appsvc.test.js +77 -0
  16. package/dist/adapters/codemods/__tests__/use-pnpm.test.d.ts +1 -0
  17. package/dist/adapters/codemods/__tests__/use-pnpm.test.js +148 -0
  18. package/dist/adapters/codemods/git.d.ts +2 -0
  19. package/dist/adapters/codemods/git.js +18 -0
  20. package/dist/adapters/codemods/index.d.ts +3 -0
  21. package/dist/adapters/codemods/index.js +9 -0
  22. package/dist/adapters/codemods/registry.d.ts +8 -0
  23. package/dist/adapters/codemods/registry.js +16 -0
  24. package/dist/adapters/codemods/update-code-review.d.ts +3 -0
  25. package/dist/adapters/codemods/update-code-review.js +60 -0
  26. package/dist/adapters/codemods/use-azure-appsvc.d.ts +3 -0
  27. package/dist/adapters/codemods/use-azure-appsvc.js +84 -0
  28. package/dist/adapters/codemods/use-pnpm.d.ts +22 -0
  29. package/dist/adapters/codemods/use-pnpm.js +214 -0
  30. package/dist/adapters/codemods/yaml.d.ts +2 -0
  31. package/dist/adapters/codemods/yaml.js +8 -0
  32. package/dist/adapters/commander/commands/codemod.d.ts +8 -0
  33. package/dist/adapters/commander/commands/codemod.js +22 -0
  34. package/dist/adapters/commander/commands/doctor.d.ts +4 -0
  35. package/dist/adapters/commander/commands/doctor.js +12 -0
  36. package/dist/adapters/commander/commands/info.d.ts +3 -0
  37. package/dist/adapters/commander/commands/info.js +9 -0
  38. package/dist/adapters/commander/commands/init.d.ts +7 -0
  39. package/dist/adapters/commander/commands/init.js +126 -0
  40. package/dist/adapters/commander/commands/savemoney.d.ts +2 -0
  41. package/dist/adapters/commander/commands/savemoney.js +26 -0
  42. package/dist/adapters/commander/index.d.ts +7 -0
  43. package/dist/adapters/commander/index.js +19 -0
  44. package/dist/adapters/execa/terraform.d.ts +27 -0
  45. package/dist/adapters/execa/terraform.js +28 -0
  46. package/dist/adapters/github/__tests__/github-repo.spec.d.ts +1 -0
  47. package/dist/adapters/github/__tests__/github-repo.spec.js +67 -0
  48. package/dist/adapters/github/github-repo.d.ts +2 -0
  49. package/dist/adapters/github/github-repo.js +31 -0
  50. package/dist/adapters/logtape/validation-reporter.d.ts +2 -0
  51. package/dist/adapters/logtape/validation-reporter.js +14 -0
  52. package/dist/adapters/node/__tests__/data.d.ts +18 -0
  53. package/dist/adapters/node/__tests__/data.js +22 -0
  54. package/dist/adapters/node/__tests__/package-json.test.d.ts +1 -0
  55. package/dist/adapters/node/__tests__/package-json.test.js +86 -0
  56. package/dist/adapters/node/__tests__/repository.test.d.ts +1 -0
  57. package/dist/adapters/node/__tests__/repository.test.js +77 -0
  58. package/dist/adapters/node/fs/__tests__/file-reader.test.d.ts +1 -0
  59. package/dist/adapters/node/fs/__tests__/file-reader.test.js +80 -0
  60. package/dist/adapters/node/fs/file-reader.d.ts +24 -0
  61. package/dist/adapters/node/fs/file-reader.js +26 -0
  62. package/dist/adapters/node/json/__tests__/index.test.d.ts +1 -0
  63. package/dist/adapters/node/json/__tests__/index.test.js +14 -0
  64. package/dist/adapters/node/json/index.d.ts +2 -0
  65. package/dist/adapters/node/json/index.js +2 -0
  66. package/dist/adapters/node/package-json.d.ts +2 -0
  67. package/dist/adapters/node/package-json.js +22 -0
  68. package/dist/adapters/node/release.d.ts +2 -0
  69. package/dist/adapters/node/release.js +33 -0
  70. package/dist/adapters/node/repository.d.ts +2 -0
  71. package/dist/adapters/node/repository.js +47 -0
  72. package/dist/adapters/octokit/__tests__/index.test.d.ts +1 -0
  73. package/dist/adapters/octokit/__tests__/index.test.js +197 -0
  74. package/dist/adapters/octokit/index.d.ts +24 -0
  75. package/dist/adapters/octokit/index.js +65 -0
  76. package/dist/adapters/plop/actions/__tests__/init-cloud-accounts.test.d.ts +1 -0
  77. package/dist/adapters/plop/actions/__tests__/init-cloud-accounts.test.js +115 -0
  78. package/dist/adapters/plop/actions/__tests__/provision-terraform-backend.test.d.ts +1 -0
  79. package/dist/adapters/plop/actions/__tests__/provision-terraform-backend.test.js +116 -0
  80. package/dist/adapters/plop/actions/fetch-github-release.d.ts +12 -0
  81. package/dist/adapters/plop/actions/fetch-github-release.js +20 -0
  82. package/dist/adapters/plop/actions/get-node-version.d.ts +2 -0
  83. package/dist/adapters/plop/actions/get-node-version.js +9 -0
  84. package/dist/adapters/plop/actions/get-terraform-backend.d.ts +3 -0
  85. package/dist/adapters/plop/actions/get-terraform-backend.js +17 -0
  86. package/dist/adapters/plop/actions/init-cloud-accounts.d.ts +5 -0
  87. package/dist/adapters/plop/actions/init-cloud-accounts.js +13 -0
  88. package/dist/adapters/plop/actions/provision-terraform-backend.d.ts +10 -0
  89. package/dist/adapters/plop/actions/provision-terraform-backend.js +16 -0
  90. package/dist/adapters/plop/actions/semver.d.ts +19 -0
  91. package/dist/adapters/plop/actions/semver.js +27 -0
  92. package/dist/adapters/plop/actions/setup-pnpm.d.ts +2 -0
  93. package/dist/adapters/plop/actions/setup-pnpm.js +26 -0
  94. package/dist/adapters/plop/generators/environment/__tests__/actions.test.d.ts +2 -0
  95. package/dist/adapters/plop/generators/environment/__tests__/actions.test.js +55 -0
  96. package/dist/adapters/plop/generators/environment/actions.d.ts +2 -0
  97. package/dist/adapters/plop/generators/environment/actions.js +54 -0
  98. package/dist/adapters/plop/generators/environment/index.d.ts +3 -0
  99. package/dist/adapters/plop/generators/environment/index.js +19 -0
  100. package/dist/adapters/plop/generators/environment/prompts.d.ts +66 -0
  101. package/dist/adapters/plop/generators/environment/prompts.js +166 -0
  102. package/dist/adapters/plop/generators/monorepo/actions.d.ts +51 -0
  103. package/dist/adapters/plop/generators/monorepo/actions.js +35 -0
  104. package/dist/adapters/plop/generators/monorepo/index.d.ts +6 -0
  105. package/dist/adapters/plop/generators/monorepo/index.js +17 -0
  106. package/dist/adapters/plop/generators/monorepo/prompts.d.ts +10 -0
  107. package/dist/adapters/plop/generators/monorepo/prompts.js +31 -0
  108. package/dist/adapters/plop/helpers/__tests__/resource-prefix.test.d.ts +1 -0
  109. package/dist/adapters/plop/helpers/__tests__/resource-prefix.test.js +113 -0
  110. package/dist/adapters/plop/helpers/env-short.d.ts +3 -0
  111. package/dist/adapters/plop/helpers/env-short.js +9 -0
  112. package/dist/adapters/plop/helpers/resource-prefix.d.ts +5 -0
  113. package/dist/adapters/plop/helpers/resource-prefix.js +18 -0
  114. package/dist/adapters/plop/index.d.ts +8 -0
  115. package/dist/adapters/plop/index.js +24 -0
  116. package/dist/adapters/terraform/fmt.d.ts +1 -0
  117. package/dist/adapters/terraform/fmt.js +17 -0
  118. package/dist/adapters/yaml/__tests__/index.test.d.ts +1 -0
  119. package/dist/adapters/yaml/__tests__/index.test.js +53 -0
  120. package/dist/adapters/yaml/index.d.ts +8 -0
  121. package/dist/adapters/yaml/index.js +9 -0
  122. package/dist/adapters/zod/index.d.ts +23 -0
  123. package/dist/adapters/zod/index.js +22 -0
  124. package/dist/config.d.ts +6 -0
  125. package/dist/config.js +5 -0
  126. package/dist/domain/__tests__/data.d.ts +17 -0
  127. package/dist/domain/__tests__/data.js +27 -0
  128. package/dist/domain/__tests__/environment.test.d.ts +1 -0
  129. package/dist/domain/__tests__/environment.test.js +282 -0
  130. package/dist/domain/__tests__/info.test.d.ts +1 -0
  131. package/dist/domain/__tests__/info.test.js +77 -0
  132. package/dist/domain/__tests__/package-json.test.d.ts +1 -0
  133. package/dist/domain/__tests__/package-json.test.js +39 -0
  134. package/dist/domain/__tests__/repository.test.d.ts +1 -0
  135. package/dist/domain/__tests__/repository.test.js +101 -0
  136. package/dist/domain/__tests__/workspace.test.d.ts +1 -0
  137. package/dist/domain/__tests__/workspace.test.js +57 -0
  138. package/dist/domain/cloud-account.d.ts +28 -0
  139. package/dist/domain/cloud-account.js +12 -0
  140. package/dist/domain/codemod.d.ts +11 -0
  141. package/dist/domain/codemod.js +1 -0
  142. package/dist/domain/dependencies.d.ts +10 -0
  143. package/dist/domain/dependencies.js +1 -0
  144. package/dist/domain/doctor.d.ts +10 -0
  145. package/dist/domain/doctor.js +50 -0
  146. package/dist/domain/environment.d.ts +40 -0
  147. package/dist/domain/environment.js +57 -0
  148. package/dist/domain/github-repo.d.ts +6 -0
  149. package/dist/domain/github-repo.js +8 -0
  150. package/dist/domain/github.d.ts +37 -0
  151. package/dist/domain/github.js +29 -0
  152. package/dist/domain/info.d.ts +11 -0
  153. package/dist/domain/info.js +52 -0
  154. package/dist/domain/package-json.d.ts +42 -0
  155. package/dist/domain/package-json.js +69 -0
  156. package/dist/domain/remote-backend.d.ts +8 -0
  157. package/dist/domain/remote-backend.js +9 -0
  158. package/dist/domain/repository.d.ts +13 -0
  159. package/dist/domain/repository.js +72 -0
  160. package/dist/domain/validation.d.ts +16 -0
  161. package/dist/domain/validation.js +1 -0
  162. package/dist/domain/workspace.d.ts +9 -0
  163. package/dist/domain/workspace.js +32 -0
  164. package/dist/index.d.ts +2 -0
  165. package/dist/index.js +35 -0
  166. package/dist/use-cases/__tests__/apply-codemod.test.d.ts +1 -0
  167. package/dist/use-cases/__tests__/apply-codemod.test.js +73 -0
  168. package/dist/use-cases/__tests__/list-codemods.test.d.ts +1 -0
  169. package/dist/use-cases/__tests__/list-codemods.test.js +38 -0
  170. package/dist/use-cases/apply-codemod.d.ts +5 -0
  171. package/dist/use-cases/apply-codemod.js +14 -0
  172. package/dist/use-cases/list-codemods.d.ts +4 -0
  173. package/dist/use-cases/list-codemods.js +1 -0
  174. package/package.json +19 -8
  175. package/templates/environment/bootstrapper/{{env.name}}/data.tf.hbs +13 -0
  176. package/templates/environment/bootstrapper/{{env.name}}/main.tf.hbs +70 -0
  177. package/templates/environment/bootstrapper/{{env.name}}/providers.tf.hbs +26 -0
  178. package/templates/environment/core/{{env.name}}/main.tf.hbs +21 -0
  179. package/templates/environment/core/{{env.name}}/outputs.tf.hbs +8 -0
  180. package/templates/environment/core/{{env.name}}/providers.tf.hbs +21 -0
  181. package/templates/environment/shared/backend.tf.hbs +14 -0
  182. package/templates/environment/shared/locals.tf.hbs +26 -0
  183. package/templates/monorepo/.editorconfig +8 -0
  184. package/templates/monorepo/.node-version.hbs +1 -0
  185. package/templates/monorepo/.pre-commit-config.yaml.hbs +34 -0
  186. package/templates/monorepo/.prettierignore +5 -0
  187. package/templates/monorepo/.terraform-version.hbs +1 -0
  188. package/templates/monorepo/.trivyignore +16 -0
  189. package/templates/monorepo/README.md.hbs +163 -0
  190. package/templates/monorepo/infra/repository/main.tf.hbs +11 -0
  191. package/templates/monorepo/infra/repository/outputs.tf.hbs +11 -0
  192. package/templates/monorepo/infra/repository/providers.tf.hbs +13 -0
  193. package/templates/monorepo/package.json.hbs +7 -0
  194. package/templates/monorepo/pnpm-workspace.yaml +7 -0
  195. package/templates/monorepo/turbo.json +29 -0
@@ -0,0 +1,77 @@
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
+ });
@@ -0,0 +1,148 @@
1
+ import { beforeEach, describe, expect, test, vi } from "vitest";
2
+ import YAML from "yaml";
3
+ import { extractPackageExtensions, NPM, preparePackageJsonForPnpm, usePnpm, writePnpmWorkspaceFile, Yarn, } from "../use-pnpm.js";
4
+ const { readFile, stdout, writeFile } = vi.hoisted(() => ({
5
+ readFile: vi.fn(async () => ""),
6
+ stdout: vi.fn(),
7
+ writeFile: vi.fn(),
8
+ }));
9
+ vi.mock("execa", () => ({
10
+ $: vi.fn((opts) => {
11
+ const hasOptions = typeof opts === "object" && Object.hasOwn(opts, "lines");
12
+ if (hasOptions) {
13
+ return () => stdout().then((output) => ({
14
+ stdout: output.split("\n"),
15
+ }));
16
+ }
17
+ return stdout().then((output) => ({
18
+ stdout: output,
19
+ }));
20
+ }),
21
+ }));
22
+ vi.mock("node:fs/promises", () => ({
23
+ default: {
24
+ appendFile: () => Promise.resolve(),
25
+ readFile,
26
+ rm: () => Promise.resolve(),
27
+ stat: () => Promise.resolve({
28
+ isFile: () => true,
29
+ }),
30
+ writeFile,
31
+ },
32
+ }));
33
+ vi.mock("../git.js", async () => ({
34
+ getLatestCommitShaOrRef: async () => "dummy-sha",
35
+ }));
36
+ describe("pm", () => {
37
+ test("yarn workspaces are parsed correctly", async () => {
38
+ const yarn = new Yarn();
39
+ stdout.mockResolvedValueOnce(`{"location":".","name":"io-messages"}\n{"location":"apps/citizen-func","name":"citizen-func"}`);
40
+ const workspaces = await yarn.listWorkspaces();
41
+ expect(workspaces).toEqual(["io-messages", "citizen-func"]);
42
+ });
43
+ test("npm workspaces are parsed correctly", async () => {
44
+ const npm = new NPM();
45
+ stdout.mockResolvedValueOnce(`[{ "name": "io-messages", "location": "." },{ "name": "citizen-func", "location": "apps/citizen-func" }]`);
46
+ const workspaces = await npm.listWorkspaces();
47
+ expect(workspaces).toEqual(["io-messages", "citizen-func"]);
48
+ });
49
+ });
50
+ describe("extractPackageExtensions", () => {
51
+ beforeEach(() => {
52
+ vi.clearAllMocks();
53
+ });
54
+ test("returns packageExtensions only if present", async () => {
55
+ const yarnrc = {
56
+ packageExtensions: {
57
+ "some-package@*": {
58
+ peerDependencies: {
59
+ react: "*",
60
+ },
61
+ },
62
+ },
63
+ };
64
+ readFile.mockResolvedValueOnce(YAML.stringify(yarnrc));
65
+ await expect(extractPackageExtensions()).resolves.toEqual(yarnrc.packageExtensions);
66
+ expect(readFile).toHaveBeenCalledOnce();
67
+ });
68
+ test("returns undefined if packageExtensions is not present", async () => {
69
+ const yarnrc = {
70
+ someOtherField: {},
71
+ };
72
+ readFile.mockResolvedValueOnce(YAML.stringify(yarnrc));
73
+ await expect(extractPackageExtensions()).resolves.toBeUndefined();
74
+ expect(readFile).toHaveBeenCalledOnce();
75
+ });
76
+ });
77
+ describe("preparePackageJsonForPnpm", () => {
78
+ beforeEach(() => {
79
+ vi.clearAllMocks();
80
+ });
81
+ test("removes packageManager field and keeps workspaces", async () => {
82
+ const packageJson = {
83
+ name: "test-monorepo",
84
+ packageManager: "yarn@1.22.10",
85
+ version: "1.0.0",
86
+ workspaces: ["packages/*"],
87
+ };
88
+ readFile.mockResolvedValueOnce(JSON.stringify(packageJson, null, 2));
89
+ const workspaces = await preparePackageJsonForPnpm();
90
+ expect(workspaces).toEqual(["packages/*"]);
91
+ expect(readFile).toHaveBeenCalledOnce();
92
+ expect(writeFile).toHaveBeenCalledWith("package.json", JSON.stringify({
93
+ name: packageJson.name,
94
+ version: packageJson.version,
95
+ }, null, 2));
96
+ });
97
+ });
98
+ describe("writePnpmWorkspaceFile", () => {
99
+ beforeEach(() => {
100
+ vi.clearAllMocks();
101
+ });
102
+ test("writes pnpm-workspace.yaml with given workspaces", async () => {
103
+ const workspaces = ["packages/*", "apps/*"];
104
+ const packageExtensions = {
105
+ "express@*": {
106
+ peerDependencies: {
107
+ typescript: "*",
108
+ },
109
+ },
110
+ };
111
+ await writePnpmWorkspaceFile(workspaces, packageExtensions);
112
+ expect(writeFile).toHaveBeenCalledWith("pnpm-workspace.yaml", expect.stringContaining(YAML.stringify({ packages: workspaces })), "utf-8");
113
+ expect(writeFile).toHaveBeenCalledWith("pnpm-workspace.yaml", expect.stringContaining(YAML.stringify({ packageExtensions })), "utf-8");
114
+ });
115
+ });
116
+ describe("usePnpm", () => {
117
+ beforeEach(() => {
118
+ vi.resetAllMocks();
119
+ });
120
+ test("rejects if the project is already using pnpm", async () => {
121
+ await expect(usePnpm("pnpm", "10.20")).rejects.toThrow();
122
+ });
123
+ test.each([
124
+ { expected: false, version: "18.0.0" },
125
+ { expected: false, version: "20.10.0" },
126
+ { expected: false, version: "20.19.4" },
127
+ { expected: true, version: "22.0.0" },
128
+ { expected: true, version: "20.19.5" },
129
+ ])("rejects if Node.js version is less than required ($version)", async ({ expected, version }) => {
130
+ stdout.mockResolvedValue("[]");
131
+ readFile.mockResolvedValueOnce(JSON.stringify({ name: "test-monorepo", workspaces: [] }));
132
+ await expect(usePnpm("npm", version).then(() => true, () => false)).resolves.toBe(expected);
133
+ });
134
+ test("moves workspaces from package.json to pnpm-workspace.yaml", async () => {
135
+ const packageJson = {
136
+ name: "test-monorepo",
137
+ packageManager: "yarn@1.22.10",
138
+ version: "1.0.0",
139
+ workspaces: ["packages/*"],
140
+ };
141
+ readFile.mockResolvedValueOnce(JSON.stringify(packageJson, null, 2));
142
+ stdout.mockResolvedValue(`[]`); // npm list workspaces
143
+ await usePnpm("npm", "22.0.0");
144
+ expect(writeFile).toHaveBeenNthCalledWith(2, "pnpm-workspace.yaml", expect.stringContaining(YAML.stringify({
145
+ packages: packageJson.workspaces,
146
+ })), "utf-8");
147
+ });
148
+ });
@@ -0,0 +1,2 @@
1
+ export declare const getLatestCommitSha: (owner: string, repo: string, ref?: string) => Promise<string>;
2
+ export declare const getLatestCommitShaOrRef: (owner: string, repo: string, ref?: string) => Promise<string>;
@@ -0,0 +1,18 @@
1
+ import { getLogger } from "@logtape/logtape";
2
+ import { Octokit } from "octokit";
3
+ export const getLatestCommitSha = async (owner, repo, ref = "main") => {
4
+ const octokit = new Octokit();
5
+ const response = await octokit.rest.repos.getCommit({
6
+ owner,
7
+ ref,
8
+ repo,
9
+ });
10
+ return response.data.sha;
11
+ };
12
+ export const getLatestCommitShaOrRef = async (owner, repo, ref = "main") => {
13
+ const logger = getLogger(["dx-cli", "codemod"]);
14
+ return getLatestCommitSha(owner, repo, ref).catch(() => {
15
+ logger.warn("Failed to fetch the latest commit from {owner}/{repo}, fallback to {fallback}", { fallback: ref, owner, repo });
16
+ return ref;
17
+ });
18
+ };
@@ -0,0 +1,3 @@
1
+ import { LocalCodemodRegistry } from "./registry.js";
2
+ declare const registry: LocalCodemodRegistry;
3
+ export default registry;
@@ -0,0 +1,9 @@
1
+ import { LocalCodemodRegistry } from "./registry.js";
2
+ import { updateCodeReview } from "./update-code-review.js";
3
+ import { useAzureAppsvc } from "./use-azure-appsvc.js";
4
+ import usePnpm from "./use-pnpm.js";
5
+ const registry = new LocalCodemodRegistry();
6
+ registry.add(usePnpm);
7
+ registry.add(useAzureAppsvc);
8
+ registry.add(updateCodeReview);
9
+ export default registry;
@@ -0,0 +1,8 @@
1
+ import { Codemod, CodemodRegistry } from "../../domain/codemod.js";
2
+ export declare class LocalCodemodRegistry implements CodemodRegistry {
3
+ #private;
4
+ constructor();
5
+ add(codemod: Codemod): void;
6
+ getAll(): import("neverthrow").ResultAsync<Codemod[], never>;
7
+ getById(id: string): import("neverthrow").ResultAsync<Codemod | undefined, never>;
8
+ }
@@ -0,0 +1,16 @@
1
+ import { okAsync } from "neverthrow";
2
+ export class LocalCodemodRegistry {
3
+ #m;
4
+ constructor() {
5
+ this.#m = new Map();
6
+ }
7
+ add(codemod) {
8
+ this.#m.set(codemod.id, codemod);
9
+ }
10
+ getAll() {
11
+ return okAsync(Array.from(this.#m.values()));
12
+ }
13
+ getById(id) {
14
+ return okAsync(this.#m.get(id));
15
+ }
16
+ }
@@ -0,0 +1,3 @@
1
+ import { Codemod } from "../../domain/codemod.js";
2
+ export declare const updateJSCodeReviewJob: (sha: string) => (workflow: string, filename: string) => string;
3
+ export declare const updateCodeReview: Codemod;
@@ -0,0 +1,60 @@
1
+ import { getLogger } from "@logtape/logtape";
2
+ import { replaceInFile } from "replace-in-file";
3
+ import * as YAML from "yaml";
4
+ import { getLatestCommitSha } from "./git.js";
5
+ import { isChildOf } from "./yaml.js";
6
+ export const updateJSCodeReviewJob = (sha) => (workflow, filename) => {
7
+ const logger = getLogger(["dx-cli", "codemod"]);
8
+ const document = YAML.parseDocument(workflow);
9
+ let updated = false;
10
+ YAML.visit(document, {
11
+ Map(_, map, path) {
12
+ if (map.has("jobs") || isChildOf(path, "jobs")) {
13
+ return undefined;
14
+ }
15
+ if (map.has("uses")) {
16
+ const uses = map.get("uses");
17
+ if (typeof uses === "string" &&
18
+ uses.startsWith("pagopa/dx/.github/workflows/js_code_review.yaml@")) {
19
+ map.set("secrets", "inherit");
20
+ map.set("permissions", {
21
+ contents: "read",
22
+ "pull-requests": "write",
23
+ });
24
+ map.set("uses", `pagopa/dx/.github/workflows/js_code_review.yaml@${sha}`);
25
+ updated = true;
26
+ }
27
+ }
28
+ return YAML.visit.SKIP;
29
+ },
30
+ });
31
+ if (updated) {
32
+ logger.info("Workflow {filename} updated", {
33
+ filename,
34
+ });
35
+ return YAML.stringify(document);
36
+ }
37
+ return workflow;
38
+ };
39
+ export const updateCodeReview = {
40
+ apply: async () => {
41
+ const logger = getLogger(["dx-cli", "codemod"]);
42
+ const owner = "pagopa";
43
+ const repo = "dx";
44
+ return getLatestCommitSha(owner, repo)
45
+ .then(async (sha) => {
46
+ await replaceInFile({
47
+ allowEmptyPaths: true,
48
+ files: [".github/workflows/*.yaml"],
49
+ processor: updateJSCodeReviewJob(sha),
50
+ });
51
+ })
52
+ .catch(() => {
53
+ logger.error("Failed to fetch the latest commit sha from {repository}", {
54
+ repository: `${owner}/${repo}`,
55
+ });
56
+ });
57
+ },
58
+ description: "Update js_code_review workflow to its latest version",
59
+ id: "update-code-review",
60
+ };
@@ -0,0 +1,3 @@
1
+ import { Codemod } from "../../domain/codemod.js";
2
+ export declare const migrateWorkflow: (sha: string) => (workflow: string, filename: string) => string;
3
+ export declare const useAzureAppsvc: Codemod;
@@ -0,0 +1,84 @@
1
+ import { getLogger } from "@logtape/logtape";
2
+ import { replaceInFile } from "replace-in-file";
3
+ import YAML from "yaml";
4
+ import { getLatestCommitShaOrRef } from "./git.js";
5
+ import { isChildOf } from "./yaml.js";
6
+ export const migrateWorkflow = (sha) => (workflow, filename) => {
7
+ const logger = getLogger(["dx-cli", "codemod"]);
8
+ logger.debug("Processing {filename} file", { filename });
9
+ const document = YAML.parseDocument(workflow);
10
+ let updated = false;
11
+ /**
12
+ * Visit the YAML AST to find and update specific keys
13
+ * - Visit the tree until we find job with "uses" containing "web_app_deploy" or "function_app_deploy"
14
+ * - Add "disable_auto_staging_deploy: true" under "with"
15
+ * - Rename "function_app_name" to "web_app_name"
16
+ * - Remove "use_staging_slot"
17
+ * - Update "uses" to point to "pagopa/dx/.github/workflows/release-azure-appsvc.yaml@LATEST_SHA"
18
+ */
19
+ YAML.visit(document, {
20
+ Map(_, map, path) {
21
+ if (isChildOf(path, "jobs") || isChildOf(path, "with")) {
22
+ return undefined;
23
+ }
24
+ if (map.has("jobs")) {
25
+ return undefined;
26
+ }
27
+ if (map.has("uses")) {
28
+ const uses = map.get("uses");
29
+ if (typeof uses === "string" &&
30
+ uses.match(/^pagopa\/dx\/.github\/workflows\/(web|function)_app_deploy/)) {
31
+ logger.debug("Adding disable_auto_staging_deploy");
32
+ map.addIn(["with", "disable_auto_staging_deploy"], true);
33
+ map.set("permissions", {
34
+ attestations: "write",
35
+ contents: "read",
36
+ "id-token": "write",
37
+ });
38
+ updated = true;
39
+ return undefined;
40
+ }
41
+ }
42
+ return YAML.visit.SKIP;
43
+ },
44
+ Pair(_, pair) {
45
+ if (YAML.isScalar(pair.key)) {
46
+ if (pair.key.value === "function_app_name") {
47
+ updated = true;
48
+ logger.debug("Updating function_app_name to web_app_name");
49
+ return new YAML.Pair("web_app_name", pair.value);
50
+ }
51
+ if (pair.key.value === "use_staging_slot") {
52
+ updated = true;
53
+ logger.debug("Removing use_staging_slot");
54
+ return YAML.visit.REMOVE;
55
+ }
56
+ if (pair.key.value === "uses") {
57
+ updated = true;
58
+ logger.debug("Updating uses value");
59
+ return new YAML.Pair("uses", `pagopa/dx/.github/workflows/release-azure-appsvc-v1.yaml@${sha}`);
60
+ }
61
+ }
62
+ },
63
+ });
64
+ if (updated) {
65
+ logger.info("Workflow {filename} updated", {
66
+ filename,
67
+ });
68
+ return YAML.stringify(document);
69
+ }
70
+ logger.debug("No changes applied to {filename}", { filename });
71
+ return workflow;
72
+ };
73
+ export const useAzureAppsvc = {
74
+ apply: async () => {
75
+ const sha = await getLatestCommitShaOrRef("pagopa", "dx");
76
+ await replaceInFile({
77
+ allowEmptyPaths: true,
78
+ files: [".github/workflows/*.yaml"],
79
+ processor: migrateWorkflow(sha),
80
+ });
81
+ },
82
+ description: "Refactor legacy deploy workflows to use release-azure-appsvc",
83
+ id: "use-azure-appsvc",
84
+ };
@@ -0,0 +1,22 @@
1
+ type NodePackageManager = {
2
+ listWorkspaces(): Promise<string[]>;
3
+ lockFileName: string;
4
+ };
5
+ export declare class NPM implements NodePackageManager {
6
+ lockFileName: string;
7
+ listWorkspaces(): Promise<string[]>;
8
+ }
9
+ export declare class Yarn implements NodePackageManager {
10
+ lockFileName: string;
11
+ listWorkspaces(): Promise<string[]>;
12
+ }
13
+ export declare function extractPackageExtensions(): Promise<object | undefined>;
14
+ export declare function preparePackageJsonForPnpm(): Promise<string[]>;
15
+ export declare function writePnpmWorkspaceFile(workspaces: string[], packageExtensions: object | undefined): Promise<void>;
16
+ export declare const usePnpm: (packageManager: string, currentNodeVersion: string) => Promise<void>;
17
+ declare const _default: {
18
+ apply: (info: import("../../domain/info.js").InfoResult) => Promise<void>;
19
+ description: string;
20
+ id: string;
21
+ };
22
+ export default _default;