@pagopa/dx-cli 0.15.2 → 0.15.4
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 +18 -7
- 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,282 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { getInitializationStatus, getTerraformBackend, hasUserPermissionToInitialize, } from "../environment.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-account-id",
|
|
16
|
+
...overrides,
|
|
17
|
+
});
|
|
18
|
+
const createMockEnvironment = (overrides = {}) => ({
|
|
19
|
+
cloudAccounts: [createMockCloudAccount()],
|
|
20
|
+
name: "dev",
|
|
21
|
+
prefix: "dx",
|
|
22
|
+
...overrides,
|
|
23
|
+
});
|
|
24
|
+
const createMockTerraformBackend = (overrides = {}) => ({
|
|
25
|
+
resourceGroupName: "dx-d-itn-tf-rg",
|
|
26
|
+
storageAccountName: "dxditntfst",
|
|
27
|
+
subscriptionId: "00000000-0000-0000-0000-000000000000",
|
|
28
|
+
type: "azurerm",
|
|
29
|
+
...overrides,
|
|
30
|
+
});
|
|
31
|
+
describe("getInitializationStatus", () => {
|
|
32
|
+
it("should return initialized true when all cloud accounts are initialized and backend exists", async () => {
|
|
33
|
+
const mockBackend = createMockTerraformBackend();
|
|
34
|
+
const mockService = createMockCloudAccountService({
|
|
35
|
+
getTerraformBackend: vi.fn().mockResolvedValue(mockBackend),
|
|
36
|
+
isInitialized: vi.fn().mockResolvedValue(true),
|
|
37
|
+
});
|
|
38
|
+
const environment = createMockEnvironment();
|
|
39
|
+
const result = await getInitializationStatus(mockService, environment);
|
|
40
|
+
expect(result).toEqual({ initialized: true });
|
|
41
|
+
});
|
|
42
|
+
it("should return CLOUD_ACCOUNT_NOT_INITIALIZED issue when cloud account is not initialized", async () => {
|
|
43
|
+
const cloudAccount = createMockCloudAccount({ id: "uninitialized-id" });
|
|
44
|
+
const mockBackend = createMockTerraformBackend();
|
|
45
|
+
const mockService = createMockCloudAccountService({
|
|
46
|
+
getTerraformBackend: vi.fn().mockResolvedValue(mockBackend),
|
|
47
|
+
isInitialized: vi.fn().mockResolvedValue(false),
|
|
48
|
+
});
|
|
49
|
+
const environment = createMockEnvironment({
|
|
50
|
+
cloudAccounts: [cloudAccount],
|
|
51
|
+
});
|
|
52
|
+
const result = await getInitializationStatus(mockService, environment);
|
|
53
|
+
expect(result).toEqual({
|
|
54
|
+
initialized: false,
|
|
55
|
+
issues: [
|
|
56
|
+
{
|
|
57
|
+
cloudAccount,
|
|
58
|
+
type: "CLOUD_ACCOUNT_NOT_INITIALIZED",
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
it("should return MISSING_REMOTE_BACKEND issue when terraform backend is not found", async () => {
|
|
64
|
+
const mockService = createMockCloudAccountService({
|
|
65
|
+
getTerraformBackend: vi.fn().mockResolvedValue(undefined),
|
|
66
|
+
isInitialized: vi.fn().mockResolvedValue(true),
|
|
67
|
+
});
|
|
68
|
+
const environment = createMockEnvironment();
|
|
69
|
+
const result = await getInitializationStatus(mockService, environment);
|
|
70
|
+
expect(result).toEqual({
|
|
71
|
+
initialized: false,
|
|
72
|
+
issues: [
|
|
73
|
+
{
|
|
74
|
+
type: "MISSING_REMOTE_BACKEND",
|
|
75
|
+
},
|
|
76
|
+
],
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
it("should return multiple issues when both cloud account is not initialized and backend is missing", async () => {
|
|
80
|
+
const cloudAccount = createMockCloudAccount();
|
|
81
|
+
const mockService = createMockCloudAccountService({
|
|
82
|
+
getTerraformBackend: vi.fn().mockResolvedValue(undefined),
|
|
83
|
+
isInitialized: vi.fn().mockResolvedValue(false),
|
|
84
|
+
});
|
|
85
|
+
const environment = createMockEnvironment({
|
|
86
|
+
cloudAccounts: [cloudAccount],
|
|
87
|
+
});
|
|
88
|
+
const result = await getInitializationStatus(mockService, environment);
|
|
89
|
+
expect(result).toEqual({
|
|
90
|
+
initialized: false,
|
|
91
|
+
issues: [
|
|
92
|
+
{
|
|
93
|
+
cloudAccount,
|
|
94
|
+
type: "CLOUD_ACCOUNT_NOT_INITIALIZED",
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
type: "MISSING_REMOTE_BACKEND",
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
it("should check initialization for each cloud account with correct parameters", async () => {
|
|
103
|
+
const cloudAccount1 = createMockCloudAccount({ id: "account-1" });
|
|
104
|
+
const cloudAccount2 = createMockCloudAccount({ id: "account-2" });
|
|
105
|
+
const mockBackend = createMockTerraformBackend();
|
|
106
|
+
const isInitializedMock = vi.fn().mockResolvedValue(true);
|
|
107
|
+
const mockService = createMockCloudAccountService({
|
|
108
|
+
getTerraformBackend: vi.fn().mockResolvedValue(mockBackend),
|
|
109
|
+
isInitialized: isInitializedMock,
|
|
110
|
+
});
|
|
111
|
+
const environment = createMockEnvironment({
|
|
112
|
+
cloudAccounts: [cloudAccount1, cloudAccount2],
|
|
113
|
+
name: "prod",
|
|
114
|
+
prefix: "io",
|
|
115
|
+
});
|
|
116
|
+
await getInitializationStatus(mockService, environment);
|
|
117
|
+
expect(isInitializedMock).toHaveBeenCalledTimes(2);
|
|
118
|
+
expect(isInitializedMock).toHaveBeenCalledWith("account-1", expect.objectContaining({
|
|
119
|
+
name: "prod",
|
|
120
|
+
prefix: "io",
|
|
121
|
+
}));
|
|
122
|
+
expect(isInitializedMock).toHaveBeenCalledWith("account-2", expect.objectContaining({
|
|
123
|
+
name: "prod",
|
|
124
|
+
prefix: "io",
|
|
125
|
+
}));
|
|
126
|
+
});
|
|
127
|
+
it("should return issues for multiple uninitialized cloud accounts", async () => {
|
|
128
|
+
const cloudAccount1 = createMockCloudAccount({ id: "account-1" });
|
|
129
|
+
const cloudAccount2 = createMockCloudAccount({ id: "account-2" });
|
|
130
|
+
const mockBackend = createMockTerraformBackend();
|
|
131
|
+
const mockService = createMockCloudAccountService({
|
|
132
|
+
getTerraformBackend: vi.fn().mockResolvedValue(mockBackend),
|
|
133
|
+
isInitialized: vi.fn().mockResolvedValue(false),
|
|
134
|
+
});
|
|
135
|
+
const environment = createMockEnvironment({
|
|
136
|
+
cloudAccounts: [cloudAccount1, cloudAccount2],
|
|
137
|
+
});
|
|
138
|
+
const result = await getInitializationStatus(mockService, environment);
|
|
139
|
+
expect(result).toEqual({
|
|
140
|
+
initialized: false,
|
|
141
|
+
issues: [
|
|
142
|
+
{
|
|
143
|
+
cloudAccount: cloudAccount1,
|
|
144
|
+
type: "CLOUD_ACCOUNT_NOT_INITIALIZED",
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
cloudAccount: cloudAccount2,
|
|
148
|
+
type: "CLOUD_ACCOUNT_NOT_INITIALIZED",
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
describe("getTerraformBackend", () => {
|
|
155
|
+
it("should return the terraform backend when it exists", async () => {
|
|
156
|
+
const mockBackend = createMockTerraformBackend();
|
|
157
|
+
const mockService = createMockCloudAccountService({
|
|
158
|
+
getTerraformBackend: vi.fn().mockResolvedValue(mockBackend),
|
|
159
|
+
});
|
|
160
|
+
const environment = createMockEnvironment();
|
|
161
|
+
const result = await getTerraformBackend(mockService, environment);
|
|
162
|
+
expect(result).toEqual(mockBackend);
|
|
163
|
+
});
|
|
164
|
+
it("should return undefined when no terraform backend exists", async () => {
|
|
165
|
+
const mockService = createMockCloudAccountService({
|
|
166
|
+
getTerraformBackend: vi.fn().mockResolvedValue(undefined),
|
|
167
|
+
});
|
|
168
|
+
const environment = createMockEnvironment();
|
|
169
|
+
const result = await getTerraformBackend(mockService, environment);
|
|
170
|
+
expect(result).toBeUndefined();
|
|
171
|
+
});
|
|
172
|
+
it("should call getTerraformBackend with correct parameters", async () => {
|
|
173
|
+
const getTerraformBackendMock = vi.fn().mockResolvedValue(undefined);
|
|
174
|
+
const mockService = createMockCloudAccountService({
|
|
175
|
+
getTerraformBackend: getTerraformBackendMock,
|
|
176
|
+
});
|
|
177
|
+
const environment = createMockEnvironment({
|
|
178
|
+
cloudAccounts: [createMockCloudAccount({ id: "my-account" })],
|
|
179
|
+
name: "uat",
|
|
180
|
+
prefix: "io",
|
|
181
|
+
});
|
|
182
|
+
await getTerraformBackend(mockService, environment);
|
|
183
|
+
expect(getTerraformBackendMock).toHaveBeenCalledWith("my-account", expect.objectContaining({
|
|
184
|
+
name: "uat",
|
|
185
|
+
prefix: "io",
|
|
186
|
+
}));
|
|
187
|
+
});
|
|
188
|
+
it("should return the first backend found when multiple cloud accounts exist", async () => {
|
|
189
|
+
const mockBackend = createMockTerraformBackend({
|
|
190
|
+
storageAccountName: "firstaccountst",
|
|
191
|
+
});
|
|
192
|
+
const getTerraformBackendMock = vi.fn().mockResolvedValue(mockBackend);
|
|
193
|
+
const mockService = createMockCloudAccountService({
|
|
194
|
+
getTerraformBackend: getTerraformBackendMock,
|
|
195
|
+
});
|
|
196
|
+
const environment = createMockEnvironment({
|
|
197
|
+
cloudAccounts: [
|
|
198
|
+
createMockCloudAccount({ id: "account-1" }),
|
|
199
|
+
createMockCloudAccount({ id: "account-2" }),
|
|
200
|
+
],
|
|
201
|
+
});
|
|
202
|
+
const result = await getTerraformBackend(mockService, environment);
|
|
203
|
+
expect(result).toEqual(mockBackend);
|
|
204
|
+
// Should only call for the first account due to early return
|
|
205
|
+
expect(getTerraformBackendMock).toHaveBeenCalledTimes(1);
|
|
206
|
+
});
|
|
207
|
+
it("should return undefined when environment has no cloud accounts", async () => {
|
|
208
|
+
const mockService = createMockCloudAccountService();
|
|
209
|
+
const environment = createMockEnvironment({
|
|
210
|
+
cloudAccounts: [],
|
|
211
|
+
});
|
|
212
|
+
const result = await getTerraformBackend(mockService, environment);
|
|
213
|
+
expect(result).toBeUndefined();
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
describe("hasUserPermissionToInitialize", () => {
|
|
217
|
+
it("should return true when all cloud accounts have permission", async () => {
|
|
218
|
+
const mockService = createMockCloudAccountService({
|
|
219
|
+
hasUserPermissionToInitialize: vi.fn().mockResolvedValue(true),
|
|
220
|
+
});
|
|
221
|
+
const environment = createMockEnvironment({
|
|
222
|
+
cloudAccounts: [
|
|
223
|
+
createMockCloudAccount({ id: "account-1" }),
|
|
224
|
+
createMockCloudAccount({ id: "account-2" }),
|
|
225
|
+
],
|
|
226
|
+
});
|
|
227
|
+
const result = await hasUserPermissionToInitialize(mockService, environment);
|
|
228
|
+
expect(result).toBe(true);
|
|
229
|
+
});
|
|
230
|
+
it("should return false when any cloud account lacks permission", async () => {
|
|
231
|
+
const hasUserPermissionMock = vi
|
|
232
|
+
.fn()
|
|
233
|
+
.mockResolvedValueOnce(true)
|
|
234
|
+
.mockResolvedValueOnce(false);
|
|
235
|
+
const mockService = createMockCloudAccountService({
|
|
236
|
+
hasUserPermissionToInitialize: hasUserPermissionMock,
|
|
237
|
+
});
|
|
238
|
+
const environment = createMockEnvironment({
|
|
239
|
+
cloudAccounts: [
|
|
240
|
+
createMockCloudAccount({ id: "account-1" }),
|
|
241
|
+
createMockCloudAccount({ id: "account-2" }),
|
|
242
|
+
],
|
|
243
|
+
});
|
|
244
|
+
const result = await hasUserPermissionToInitialize(mockService, environment);
|
|
245
|
+
expect(result).toBe(false);
|
|
246
|
+
expect(hasUserPermissionMock).toHaveBeenCalledTimes(2);
|
|
247
|
+
});
|
|
248
|
+
it("should short-circuit and return false on first unauthorized account", async () => {
|
|
249
|
+
const hasUserPermissionMock = vi.fn().mockResolvedValue(false);
|
|
250
|
+
const mockService = createMockCloudAccountService({
|
|
251
|
+
hasUserPermissionToInitialize: hasUserPermissionMock,
|
|
252
|
+
});
|
|
253
|
+
const environment = createMockEnvironment({
|
|
254
|
+
cloudAccounts: [
|
|
255
|
+
createMockCloudAccount({ id: "account-1" }),
|
|
256
|
+
createMockCloudAccount({ id: "account-2" }),
|
|
257
|
+
createMockCloudAccount({ id: "account-3" }),
|
|
258
|
+
],
|
|
259
|
+
});
|
|
260
|
+
const result = await hasUserPermissionToInitialize(mockService, environment);
|
|
261
|
+
expect(result).toBe(false);
|
|
262
|
+
// Should only check the first account before short-circuiting
|
|
263
|
+
expect(hasUserPermissionMock).toHaveBeenCalledTimes(1);
|
|
264
|
+
expect(hasUserPermissionMock).toHaveBeenCalledWith("account-1");
|
|
265
|
+
});
|
|
266
|
+
it("should call service with correct cloud account IDs", async () => {
|
|
267
|
+
const hasUserPermissionMock = vi.fn().mockResolvedValue(true);
|
|
268
|
+
const mockService = createMockCloudAccountService({
|
|
269
|
+
hasUserPermissionToInitialize: hasUserPermissionMock,
|
|
270
|
+
});
|
|
271
|
+
const environment = createMockEnvironment({
|
|
272
|
+
cloudAccounts: [
|
|
273
|
+
createMockCloudAccount({ id: "account-a" }),
|
|
274
|
+
createMockCloudAccount({ id: "account-b" }),
|
|
275
|
+
],
|
|
276
|
+
});
|
|
277
|
+
await hasUserPermissionToInitialize(mockService, environment);
|
|
278
|
+
expect(hasUserPermissionMock).toHaveBeenCalledTimes(2);
|
|
279
|
+
expect(hasUserPermissionMock).toHaveBeenNthCalledWith(1, "account-a");
|
|
280
|
+
expect(hasUserPermissionMock).toHaveBeenNthCalledWith(2, "account-b");
|
|
281
|
+
});
|
|
282
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { errAsync, okAsync } from "neverthrow";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { getInfo } from "../info.js";
|
|
4
|
+
import { makeMockDependencies, makeMockPackageJson, makeMockRepositoryRoot, } from "./data.js";
|
|
5
|
+
describe("getInfo", () => {
|
|
6
|
+
describe("packageManager", () => {
|
|
7
|
+
it("should return default packageManager (npm) when packageManager is not detected", async () => {
|
|
8
|
+
const mockPackageJson = makeMockPackageJson({
|
|
9
|
+
packageManager: undefined,
|
|
10
|
+
});
|
|
11
|
+
const mockDependencies = makeMockDependencies();
|
|
12
|
+
const repositoryRoot = makeMockRepositoryRoot();
|
|
13
|
+
mockDependencies.repositoryReader.findRepositoryRoot.mockReturnValue(okAsync(repositoryRoot));
|
|
14
|
+
mockDependencies.packageJsonReader.readPackageJson.mockReturnValue(okAsync(mockPackageJson));
|
|
15
|
+
mockDependencies.repositoryReader.fileExists.mockReturnValue(okAsync(false));
|
|
16
|
+
mockDependencies.repositoryReader.readFile.mockReturnValue(okAsync("22.0.0"));
|
|
17
|
+
const result = await getInfo(mockDependencies)();
|
|
18
|
+
expect(result.packageManager).toStrictEqual("npm");
|
|
19
|
+
expect(mockDependencies.repositoryReader.fileExists).nthCalledWith(1, "a/repo/root/pnpm-lock.yaml");
|
|
20
|
+
expect(mockDependencies.repositoryReader.fileExists).nthCalledWith(2, "a/repo/root/yarn.lock");
|
|
21
|
+
expect(mockDependencies.repositoryReader.fileExists).nthCalledWith(3, "a/repo/root/package-lock.json");
|
|
22
|
+
});
|
|
23
|
+
it("should return yarn when yarn.lock is present", async () => {
|
|
24
|
+
const mockPackageJson = makeMockPackageJson({
|
|
25
|
+
packageManager: undefined,
|
|
26
|
+
});
|
|
27
|
+
const mockDependencies = makeMockDependencies();
|
|
28
|
+
mockDependencies.packageJsonReader.readPackageJson.mockReturnValue(okAsync(mockPackageJson));
|
|
29
|
+
mockDependencies.repositoryReader.fileExists
|
|
30
|
+
.mockReturnValueOnce(okAsync(false))
|
|
31
|
+
.mockReturnValueOnce(okAsync(true)); // yarn lock file exists
|
|
32
|
+
mockDependencies.repositoryReader.readFile.mockReturnValue(okAsync("22.0.0"));
|
|
33
|
+
const repositoryRoot = makeMockRepositoryRoot();
|
|
34
|
+
mockDependencies.repositoryReader.findRepositoryRoot.mockReturnValue(okAsync(repositoryRoot));
|
|
35
|
+
const result = await getInfo(mockDependencies)();
|
|
36
|
+
expect(result.packageManager).toStrictEqual("yarn");
|
|
37
|
+
expect(mockDependencies.repositoryReader.fileExists).nthCalledWith(1, "a/repo/root/pnpm-lock.yaml");
|
|
38
|
+
expect(mockDependencies.repositoryReader.fileExists).nthCalledWith(2, "a/repo/root/yarn.lock");
|
|
39
|
+
expect(mockDependencies.repositoryReader.fileExists).not.toHaveBeenCalledWith("a/repo/root/package-lock.json");
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it("should return all info", async () => {
|
|
43
|
+
const mockPackageJson = makeMockPackageJson({
|
|
44
|
+
devDependencies: new Map([["turbo", "^2.5.0"]]),
|
|
45
|
+
});
|
|
46
|
+
const repositoryRoot = makeMockRepositoryRoot();
|
|
47
|
+
const mockDependencies = makeMockDependencies();
|
|
48
|
+
mockDependencies.repositoryReader.findRepositoryRoot.mockReturnValue(okAsync(repositoryRoot));
|
|
49
|
+
mockDependencies.packageJsonReader.readPackageJson.mockReturnValue(okAsync(mockPackageJson));
|
|
50
|
+
mockDependencies.repositoryReader.readFile
|
|
51
|
+
.mockReturnValueOnce(okAsync("\n22.0.0\n"))
|
|
52
|
+
.mockReturnValueOnce(okAsync("1.0.0\n"));
|
|
53
|
+
const result = await getInfo(mockDependencies)();
|
|
54
|
+
expect(result).toStrictEqual({
|
|
55
|
+
node: "22.0.0",
|
|
56
|
+
packageManager: "pnpm",
|
|
57
|
+
terraform: "1.0.0",
|
|
58
|
+
turbo: "^2.5.0",
|
|
59
|
+
});
|
|
60
|
+
expect(mockDependencies.repositoryReader.readFile).toHaveBeenCalledWith("a/repo/root/.node-version");
|
|
61
|
+
expect(mockDependencies.repositoryReader.readFile).toHaveBeenCalledWith("a/repo/root/.terraform-version");
|
|
62
|
+
});
|
|
63
|
+
it("should only required information", async () => {
|
|
64
|
+
const repositoryRoot = makeMockRepositoryRoot();
|
|
65
|
+
const mockDependencies = makeMockDependencies();
|
|
66
|
+
mockDependencies.repositoryReader.findRepositoryRoot.mockReturnValue(okAsync(repositoryRoot));
|
|
67
|
+
mockDependencies.packageJsonReader.readPackageJson.mockReturnValue(okAsync(makeMockPackageJson()));
|
|
68
|
+
mockDependencies.repositoryReader.readFile.mockReturnValue(errAsync(new Error("File not found")));
|
|
69
|
+
const result = await getInfo(mockDependencies)();
|
|
70
|
+
expect(result).toStrictEqual({
|
|
71
|
+
node: undefined,
|
|
72
|
+
packageManager: "pnpm",
|
|
73
|
+
terraform: undefined,
|
|
74
|
+
turbo: undefined,
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { errAsync, ok, okAsync } from "neverthrow";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { checkMonorepoScripts } from "../package-json.js";
|
|
4
|
+
import { makeMockDependencies, makeMockRepositoryRoot } from "./data.js";
|
|
5
|
+
describe("checkMonorepoScripts", () => {
|
|
6
|
+
const repositoryRoot = makeMockRepositoryRoot();
|
|
7
|
+
it("should return error result when getScripts fails", async () => {
|
|
8
|
+
const deps = makeMockDependencies();
|
|
9
|
+
const errorMessage = "Oh No!";
|
|
10
|
+
deps.packageJsonReader.getScripts.mockReturnValueOnce(errAsync(new Error(errorMessage)));
|
|
11
|
+
const result = await checkMonorepoScripts(deps, repositoryRoot);
|
|
12
|
+
expect(result.isErr()).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
it("should return ok result with successful validation when all required scripts are present", async () => {
|
|
15
|
+
const deps = makeMockDependencies();
|
|
16
|
+
const scripts = new Map()
|
|
17
|
+
.set("build", "eslint .")
|
|
18
|
+
.set("code-review", "eslint .");
|
|
19
|
+
deps.packageJsonReader.getScripts.mockReturnValueOnce(okAsync(scripts));
|
|
20
|
+
deps.packageJsonReader.getRootRequiredScripts.mockReturnValueOnce(new Map().set("code-review", "eslint ."));
|
|
21
|
+
const result = await checkMonorepoScripts(deps, repositoryRoot);
|
|
22
|
+
expect(result).toStrictEqual(ok({
|
|
23
|
+
checkName: "Monorepo Scripts",
|
|
24
|
+
isValid: true,
|
|
25
|
+
successMessage: "Monorepo scripts are correctly set up",
|
|
26
|
+
}));
|
|
27
|
+
});
|
|
28
|
+
it("should return ok result with failed validation when required scripts are missing", async () => {
|
|
29
|
+
const deps = makeMockDependencies();
|
|
30
|
+
deps.packageJsonReader.getScripts.mockReturnValueOnce(okAsync(new Map()));
|
|
31
|
+
deps.packageJsonReader.getRootRequiredScripts.mockReturnValueOnce(new Map().set("code-review", "eslint ."));
|
|
32
|
+
const result = await checkMonorepoScripts(deps, repositoryRoot);
|
|
33
|
+
expect(result).toStrictEqual(ok({
|
|
34
|
+
checkName: "Monorepo Scripts",
|
|
35
|
+
errorMessage: "Missing required scripts: code-review",
|
|
36
|
+
isValid: false,
|
|
37
|
+
}));
|
|
38
|
+
});
|
|
39
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { errAsync, ok, okAsync } from "neverthrow";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { checkPreCommitConfig, checkTurboConfig } from "../repository.js";
|
|
4
|
+
import { makeMockConfig, makeMockDependencies, makeMockRepositoryRoot, } from "./data.js";
|
|
5
|
+
describe("checkPreCommitConfig", () => {
|
|
6
|
+
it("should return ok result with successful validation when .pre-commit-config.yaml exists", async () => {
|
|
7
|
+
const deps = makeMockDependencies();
|
|
8
|
+
const repositoryRoot = makeMockRepositoryRoot();
|
|
9
|
+
deps.repositoryReader.fileExists.mockReturnValueOnce(okAsync(true));
|
|
10
|
+
const result = await checkPreCommitConfig(deps, repositoryRoot);
|
|
11
|
+
expect(result).toStrictEqual(ok({
|
|
12
|
+
checkName: "Pre-commit Configuration",
|
|
13
|
+
isValid: true,
|
|
14
|
+
successMessage: "Pre-commit configuration is present in the repository root",
|
|
15
|
+
}));
|
|
16
|
+
expect(deps.repositoryReader.fileExists).toHaveBeenCalledWith("a/repo/root/.pre-commit-config.yaml");
|
|
17
|
+
});
|
|
18
|
+
it("should return ok result with failed validation when .pre-commit-config.yaml does not exist", async () => {
|
|
19
|
+
const deps = makeMockDependencies();
|
|
20
|
+
const repositoryRoot = makeMockRepositoryRoot();
|
|
21
|
+
const errorMessage = ".pre-commit-config.yaml not found in repository root. Make sure to have pre-commit configured for the repository.";
|
|
22
|
+
deps.repositoryReader.fileExists.mockReturnValueOnce(errAsync(new Error(errorMessage)));
|
|
23
|
+
const result = await checkPreCommitConfig(deps, repositoryRoot);
|
|
24
|
+
expect(result).toStrictEqual(ok({
|
|
25
|
+
checkName: "Pre-commit Configuration",
|
|
26
|
+
errorMessage,
|
|
27
|
+
isValid: false,
|
|
28
|
+
}));
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe("checkTurboConfig", () => {
|
|
32
|
+
const config = makeMockConfig();
|
|
33
|
+
const repositoryRoot = makeMockRepositoryRoot();
|
|
34
|
+
it("should return ok result with successful validation when turbo.json exists and turbo dependency is present", async () => {
|
|
35
|
+
const deps = makeMockDependencies();
|
|
36
|
+
deps.repositoryReader.fileExists.mockReturnValueOnce(okAsync(true));
|
|
37
|
+
deps.packageJsonReader.getDependencies.mockReturnValueOnce(okAsync(new Map().set("turbo", "^2.5.2")));
|
|
38
|
+
const result = await checkTurboConfig(deps, repositoryRoot, config);
|
|
39
|
+
expect(result).toStrictEqual(ok({
|
|
40
|
+
checkName: "Turbo Configuration",
|
|
41
|
+
isValid: true,
|
|
42
|
+
successMessage: "Turbo configuration is present in the monorepo root and turbo dependency is installed",
|
|
43
|
+
}));
|
|
44
|
+
expect(deps.repositoryReader.fileExists).toHaveBeenCalledWith("a/repo/root/turbo.json");
|
|
45
|
+
});
|
|
46
|
+
it("should return ok result with failed validation when turbo.json exists but turbo dependency is missing", async () => {
|
|
47
|
+
const deps = makeMockDependencies();
|
|
48
|
+
deps.repositoryReader.fileExists.mockReturnValueOnce(okAsync(true));
|
|
49
|
+
deps.packageJsonReader.getDependencies.mockReturnValueOnce(okAsync(new Map().set("eslint", "^8.0.0")));
|
|
50
|
+
const result = await checkTurboConfig(deps, repositoryRoot, config);
|
|
51
|
+
expect(result).toStrictEqual(ok({
|
|
52
|
+
checkName: "Turbo Configuration",
|
|
53
|
+
errorMessage: "Turbo dependency not found in devDependencies. Please add 'turbo' to your devDependencies.",
|
|
54
|
+
isValid: false,
|
|
55
|
+
}));
|
|
56
|
+
});
|
|
57
|
+
it("should return ok result with failed validation when turbo.json does not exist", async () => {
|
|
58
|
+
const deps = makeMockDependencies();
|
|
59
|
+
const errorMessage = "turbo.json not found in repository root. Make sure to have Turbo configured for the monorepo.";
|
|
60
|
+
deps.repositoryReader.fileExists.mockReturnValueOnce(errAsync(new Error(errorMessage)));
|
|
61
|
+
const result = await checkTurboConfig(deps, repositoryRoot, config);
|
|
62
|
+
expect(result).toStrictEqual(ok({
|
|
63
|
+
checkName: "Turbo Configuration",
|
|
64
|
+
errorMessage,
|
|
65
|
+
isValid: false,
|
|
66
|
+
}));
|
|
67
|
+
});
|
|
68
|
+
it("should return the error message when turbo is not listed in devDependencies", async () => {
|
|
69
|
+
const deps = makeMockDependencies();
|
|
70
|
+
deps.repositoryReader.fileExists.mockReturnValueOnce(okAsync(true));
|
|
71
|
+
deps.packageJsonReader.getDependencies.mockReturnValueOnce(okAsync(new Map().set("eslint", "^8.0.0")));
|
|
72
|
+
const result = await checkTurboConfig(deps, repositoryRoot, config);
|
|
73
|
+
expect(result).toStrictEqual(ok({
|
|
74
|
+
checkName: "Turbo Configuration",
|
|
75
|
+
errorMessage: "Turbo dependency not found in devDependencies. Please add 'turbo' to your devDependencies.",
|
|
76
|
+
isValid: false,
|
|
77
|
+
}));
|
|
78
|
+
});
|
|
79
|
+
it("should return the error message when turbo version is less than minimum", async () => {
|
|
80
|
+
const deps = makeMockDependencies();
|
|
81
|
+
deps.repositoryReader.fileExists.mockReturnValueOnce(okAsync(true));
|
|
82
|
+
deps.packageJsonReader.getDependencies.mockReturnValueOnce(okAsync(new Map().set("turbo", "1.0.0")));
|
|
83
|
+
const result = await checkTurboConfig(deps, repositoryRoot, config);
|
|
84
|
+
expect(result).toStrictEqual(ok({
|
|
85
|
+
checkName: "Turbo Configuration",
|
|
86
|
+
errorMessage: `Turbo version (1.0.0) is too low. Minimum required version is ${config.minVersions.turbo}.`,
|
|
87
|
+
isValid: false,
|
|
88
|
+
}));
|
|
89
|
+
});
|
|
90
|
+
it("should return the success message when turbo version is ok", async () => {
|
|
91
|
+
const deps = makeMockDependencies();
|
|
92
|
+
deps.repositoryReader.fileExists.mockReturnValueOnce(okAsync(true));
|
|
93
|
+
deps.packageJsonReader.getDependencies.mockReturnValueOnce(okAsync(new Map().set("turbo", config.minVersions.turbo)));
|
|
94
|
+
const result = await checkTurboConfig(deps, repositoryRoot, config);
|
|
95
|
+
expect(result).toStrictEqual(ok({
|
|
96
|
+
checkName: "Turbo Configuration",
|
|
97
|
+
isValid: true,
|
|
98
|
+
successMessage: "Turbo configuration is present in the monorepo root and turbo dependency is installed",
|
|
99
|
+
}));
|
|
100
|
+
});
|
|
101
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { err, ok } from "neverthrow";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import { checkWorkspaces, workspaceSchema } from "../workspace.js";
|
|
4
|
+
import { makeMockDependencies } from "./data.js";
|
|
5
|
+
describe("checkWorkspaces", () => {
|
|
6
|
+
const monorepoDir = "/path/to/monorepo";
|
|
7
|
+
const validWorkspaces = [
|
|
8
|
+
workspaceSchema.parse({
|
|
9
|
+
name: "workspace1",
|
|
10
|
+
path: "/path/to/workspace1",
|
|
11
|
+
}),
|
|
12
|
+
workspaceSchema.parse({
|
|
13
|
+
name: "workspace2",
|
|
14
|
+
path: "/path/to/workspace2",
|
|
15
|
+
}),
|
|
16
|
+
];
|
|
17
|
+
it("should return the list of workspaces", async () => {
|
|
18
|
+
const deps = makeMockDependencies();
|
|
19
|
+
deps.repositoryReader.getWorkspaces.mockResolvedValueOnce(ok(validWorkspaces));
|
|
20
|
+
const result = await checkWorkspaces(deps, monorepoDir);
|
|
21
|
+
expect(result).toStrictEqual(ok({
|
|
22
|
+
checkName: "Workspaces",
|
|
23
|
+
isValid: true,
|
|
24
|
+
successMessage: "Found 2 workspaces",
|
|
25
|
+
}));
|
|
26
|
+
});
|
|
27
|
+
it("should return error when getWorkspaces fails", async () => {
|
|
28
|
+
const deps = makeMockDependencies();
|
|
29
|
+
deps.repositoryReader.getWorkspaces.mockResolvedValueOnce(err(new Error("Failed to get workspaces")));
|
|
30
|
+
const result = await checkWorkspaces(deps, monorepoDir);
|
|
31
|
+
expect(result).toStrictEqual(ok({
|
|
32
|
+
checkName: "Workspaces",
|
|
33
|
+
errorMessage: "Something is wrong with the workspaces configuration. If you need help, please contact the DevEx team.",
|
|
34
|
+
isValid: false,
|
|
35
|
+
}));
|
|
36
|
+
});
|
|
37
|
+
it("should return success when workspaces are found", async () => {
|
|
38
|
+
const deps = makeMockDependencies();
|
|
39
|
+
deps.repositoryReader.getWorkspaces.mockResolvedValueOnce(ok([validWorkspaces[0]]));
|
|
40
|
+
const result = await checkWorkspaces(deps, monorepoDir);
|
|
41
|
+
expect(result).toStrictEqual(ok({
|
|
42
|
+
checkName: "Workspaces",
|
|
43
|
+
isValid: true,
|
|
44
|
+
successMessage: "Found 1 workspace",
|
|
45
|
+
}));
|
|
46
|
+
});
|
|
47
|
+
it("should return error when no workspace configuration is found", async () => {
|
|
48
|
+
const deps = makeMockDependencies();
|
|
49
|
+
deps.repositoryReader.getWorkspaces.mockResolvedValueOnce(ok([]));
|
|
50
|
+
const result = await checkWorkspaces(deps, monorepoDir);
|
|
51
|
+
expect(result).toStrictEqual(ok({
|
|
52
|
+
checkName: "Workspaces",
|
|
53
|
+
errorMessage: "No workspace configuration found. Make sure to configure workspaces in pnpm-workspace.yaml.",
|
|
54
|
+
isValid: false,
|
|
55
|
+
}));
|
|
56
|
+
});
|
|
57
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
import { type EnvironmentId } from "./environment.js";
|
|
3
|
+
import { TerraformBackend } from "./remote-backend.js";
|
|
4
|
+
export declare const cloudAccountSchema: z.ZodObject<{
|
|
5
|
+
csp: z.ZodDefault<z.ZodEnum<{
|
|
6
|
+
azure: "azure";
|
|
7
|
+
}>>;
|
|
8
|
+
defaultLocation: z.ZodString;
|
|
9
|
+
displayName: z.ZodString;
|
|
10
|
+
id: z.ZodString;
|
|
11
|
+
}, z.core.$strip>;
|
|
12
|
+
export type CloudAccount = z.infer<typeof cloudAccountSchema>;
|
|
13
|
+
export type CloudAccountRepository = {
|
|
14
|
+
list(): Promise<CloudAccount[]>;
|
|
15
|
+
};
|
|
16
|
+
export type CloudAccountService = {
|
|
17
|
+
getTerraformBackend(cloudAccountId: CloudAccount["id"], environment: EnvironmentId): Promise<TerraformBackend | undefined>;
|
|
18
|
+
hasUserPermissionToInitialize(cloudAccountId: CloudAccount["id"]): Promise<boolean>;
|
|
19
|
+
initialize(cloudAccount: CloudAccount, environment: EnvironmentId, tags?: Record<string, string>): Promise<void>;
|
|
20
|
+
isInitialized(cloudAccountId: CloudAccount["id"], environment: EnvironmentId): Promise<boolean>;
|
|
21
|
+
provisionTerraformBackend(cloudAccount: CloudAccount, environment: EnvironmentId, tags?: Record<string, string>): Promise<TerraformBackend>;
|
|
22
|
+
};
|
|
23
|
+
export declare const cloudRegionSchema: z.ZodObject<{
|
|
24
|
+
displayName: z.ZodString;
|
|
25
|
+
name: z.ZodString;
|
|
26
|
+
short: z.ZodString;
|
|
27
|
+
}, z.core.$strip>;
|
|
28
|
+
export type CloudRegion = z.infer<typeof cloudRegionSchema>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from "zod/v4";
|
|
2
|
+
export const cloudAccountSchema = z.object({
|
|
3
|
+
csp: z.enum(["azure"]).default("azure"),
|
|
4
|
+
defaultLocation: z.string(),
|
|
5
|
+
displayName: z.string().min(1),
|
|
6
|
+
id: z.string().min(1),
|
|
7
|
+
});
|
|
8
|
+
export const cloudRegionSchema = z.object({
|
|
9
|
+
displayName: z.string().min(1),
|
|
10
|
+
name: z.string().min(1),
|
|
11
|
+
short: z.string().min(1).toLowerCase(),
|
|
12
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ResultAsync } from "neverthrow";
|
|
2
|
+
import { InfoResult } from "./info.js";
|
|
3
|
+
export type Codemod = {
|
|
4
|
+
apply: (info: InfoResult) => Promise<void>;
|
|
5
|
+
description: string;
|
|
6
|
+
id: string;
|
|
7
|
+
};
|
|
8
|
+
export type CodemodRegistry = {
|
|
9
|
+
getAll: () => ResultAsync<Codemod[], Error>;
|
|
10
|
+
getById: (id: string) => ResultAsync<Codemod | undefined, Error>;
|
|
11
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { GitHubService } from "./github.js";
|
|
2
|
+
import { PackageJsonReader } from "./package-json.js";
|
|
3
|
+
import { RepositoryReader } from "./repository.js";
|
|
4
|
+
import { ValidationReporter } from "./validation.js";
|
|
5
|
+
export type Dependencies = {
|
|
6
|
+
gitHubService: GitHubService;
|
|
7
|
+
packageJsonReader: PackageJsonReader;
|
|
8
|
+
repositoryReader: RepositoryReader;
|
|
9
|
+
validationReporter: ValidationReporter;
|
|
10
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Config } from "../config.js";
|
|
2
|
+
import { Dependencies } from "./dependencies.js";
|
|
3
|
+
import { ValidationCheck } from "./validation.js";
|
|
4
|
+
type DoctorResult = {
|
|
5
|
+
checks: ValidationCheck[];
|
|
6
|
+
hasErrors: boolean;
|
|
7
|
+
};
|
|
8
|
+
export declare const runDoctor: (dependencies: Dependencies, config: Config) => Promise<DoctorResult>;
|
|
9
|
+
export declare const printDoctorResult: ({ validationReporter }: Dependencies, result: DoctorResult) => void[];
|
|
10
|
+
export {};
|