@intentius/chant 0.44.14 → 0.46.0
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/dist/audit/discover.d.ts +26 -2
- package/dist/audit/discover.d.ts.map +1 -1
- package/dist/audit/report-model.d.ts +10 -0
- package/dist/audit/report-model.d.ts.map +1 -1
- package/dist/audit/rules-doc.d.ts.map +1 -1
- package/dist/cli/build-params-cli.d.ts +16 -7
- package/dist/cli/build-params-cli.d.ts.map +1 -1
- package/dist/cli/commands/audit.d.ts +20 -0
- package/dist/cli/commands/audit.d.ts.map +1 -1
- package/dist/cli/commands/build.d.ts +9 -0
- package/dist/cli/commands/build.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-docs.d.ts +13 -0
- package/dist/cli/commands/check-lexicon-docs.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon-examples.d.ts +24 -14
- package/dist/cli/commands/check-lexicon-examples.d.ts.map +1 -1
- package/dist/cli/commands/check-lexicon.d.ts +14 -0
- package/dist/cli/commands/check-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/codegen.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon/templates/docs.d.ts +5 -0
- package/dist/cli/commands/init-lexicon/templates/docs.d.ts.map +1 -1
- package/dist/cli/commands/init-lexicon.d.ts.map +1 -1
- package/dist/cli/commands/lexicon-surface-diff.d.ts +6 -0
- package/dist/cli/commands/lexicon-surface-diff.d.ts.map +1 -1
- package/dist/cli/commands/lint.d.ts.map +1 -1
- package/dist/cli/commands/onboard.d.ts +28 -0
- package/dist/cli/commands/onboard.d.ts.map +1 -1
- package/dist/cli/handlers/build.d.ts.map +1 -1
- package/dist/cli/handlers/graph.d.ts.map +1 -1
- package/dist/cli/handlers/lifecycle.d.ts +13 -0
- package/dist/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/handlers/run.d.ts.map +1 -1
- package/dist/cli/handlers/search.d.ts +27 -0
- package/dist/cli/handlers/search.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +7 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/codegen/docs-pages.d.ts +39 -0
- package/dist/codegen/docs-pages.d.ts.map +1 -0
- package/dist/codegen/docs-sections.d.ts.map +1 -1
- package/dist/codegen/docs-sidebar.d.ts +13 -2
- package/dist/codegen/docs-sidebar.d.ts.map +1 -1
- package/dist/codegen/docs-types.d.ts +30 -10
- package/dist/codegen/docs-types.d.ts.map +1 -1
- package/dist/codegen/docs.d.ts +14 -2
- package/dist/codegen/docs.d.ts.map +1 -1
- package/dist/codegen/lexicon-regen.d.ts +11 -0
- package/dist/codegen/lexicon-regen.d.ts.map +1 -1
- package/dist/codegen/surface-snapshot.d.ts +27 -3
- package/dist/codegen/surface-snapshot.d.ts.map +1 -1
- package/dist/codegen/validate.d.ts +21 -3
- package/dist/codegen/validate.d.ts.map +1 -1
- package/dist/components/capability-plugin.d.ts +13 -2
- package/dist/components/capability-plugin.d.ts.map +1 -1
- package/dist/components/driver.d.ts +38 -0
- package/dist/components/driver.d.ts.map +1 -1
- package/dist/components/index.d.ts +1 -1
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/starter-plugin.d.ts.map +1 -1
- package/dist/config.d.ts +85 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/discovery/fold-import.d.ts.map +1 -1
- package/dist/env.d.ts +12 -1
- package/dist/env.d.ts.map +1 -1
- package/dist/fold/fold.d.ts +100 -1
- package/dist/fold/fold.d.ts.map +1 -1
- package/dist/graph-ir.d.ts +12 -0
- package/dist/graph-ir.d.ts.map +1 -1
- package/dist/graph-ops.d.ts +17 -0
- package/dist/graph-ops.d.ts.map +1 -0
- package/dist/lexicon.d.ts +182 -2
- package/dist/lexicon.d.ts.map +1 -1
- package/dist/lifecycle/change-set.d.ts +23 -2
- package/dist/lifecycle/change-set.d.ts.map +1 -1
- package/dist/lifecycle/deep-observe.d.ts.map +1 -1
- package/dist/lifecycle/index.d.ts +1 -0
- package/dist/lifecycle/index.d.ts.map +1 -1
- package/dist/lifecycle/observe.d.ts +8 -0
- package/dist/lifecycle/observe.d.ts.map +1 -1
- package/dist/lifecycle/replay.d.ts.map +1 -1
- package/dist/lifecycle/snapshot.d.ts.map +1 -1
- package/dist/lifecycle/teardown.d.ts +130 -0
- package/dist/lifecycle/teardown.d.ts.map +1 -0
- package/dist/lifecycle/types.d.ts +7 -0
- package/dist/lifecycle/types.d.ts.map +1 -1
- package/dist/lint/engine.d.ts +6 -2
- package/dist/lint/engine.d.ts.map +1 -1
- package/dist/lint/policy.d.ts.map +1 -1
- package/dist/lint/rule.d.ts +31 -0
- package/dist/lint/rule.d.ts.map +1 -1
- package/dist/lint/rules/cor021-env-literal-name.d.ts +3 -0
- package/dist/lint/rules/cor021-env-literal-name.d.ts.map +1 -0
- package/dist/lint/rules/index.d.ts +2 -1
- package/dist/lint/rules/index.d.ts.map +1 -1
- package/dist/managed-fields.d.ts +33 -21
- package/dist/managed-fields.d.ts.map +1 -1
- package/dist/observation.d.ts +23 -1
- package/dist/observation.d.ts.map +1 -1
- package/dist/op/builders.d.ts +36 -7
- package/dist/op/builders.d.ts.map +1 -1
- package/dist/op/index.d.ts +1 -1
- package/dist/op/index.d.ts.map +1 -1
- package/dist/testing.d.ts +136 -0
- package/dist/testing.d.ts.map +1 -0
- package/dist/yaml.d.ts +0 -8
- package/dist/yaml.d.ts.map +1 -1
- package/package.json +6 -1
- package/src/__snapshots__/okf.test.ts.snap +20 -0
- package/src/audit/discover.test.ts +55 -1
- package/src/audit/discover.ts +70 -2
- package/src/audit/edge-init-safety.test.ts +149 -18
- package/src/audit/report-model.ts +12 -1
- package/src/audit/rules-doc.ts +1 -0
- package/src/build-params.test.ts +52 -0
- package/src/cli/build-params-cli.test.ts +25 -8
- package/src/cli/build-params-cli.ts +37 -23
- package/src/cli/commands/__fixtures__/audit-coverage/.github/workflows/ci.yml +5 -0
- package/src/cli/commands/__fixtures__/audit-coverage/Dockerfile +2 -0
- package/src/cli/commands/__fixtures__/audit-coverage/infra/main.tf +3 -0
- package/src/cli/commands/__fixtures__/audit-coverage/infra/stack.json +6 -0
- package/src/cli/commands/__fixtures__/audit-coverage/k8s/deploy.yaml +12 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/pages/getting-started.mdx +16 -0
- package/src/cli/commands/__fixtures__/init-lexicon-output/docs/src/content.config.ts +10 -2
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/generate-cli.ts +3 -1
- package/src/cli/commands/__fixtures__/init-lexicon-output/src/codegen/generate.ts +2 -1
- package/src/cli/commands/__snapshots__/init-lexicon.test.ts.snap +2 -1
- package/src/cli/commands/audit.test.ts +83 -1
- package/src/cli/commands/audit.ts +121 -28
- package/src/cli/commands/build.test.ts +275 -5
- package/src/cli/commands/build.ts +86 -14
- package/src/cli/commands/check-lexicon-docs.ts +30 -0
- package/src/cli/commands/check-lexicon-examples.test.ts +73 -7
- package/src/cli/commands/check-lexicon-examples.ts +66 -17
- package/src/cli/commands/check-lexicon.test.ts +46 -2
- package/src/cli/commands/check-lexicon.ts +64 -4
- package/src/cli/commands/init-lexicon/templates/codegen.ts +5 -2
- package/src/cli/commands/init-lexicon/templates/docs.ts +35 -2
- package/src/cli/commands/init-lexicon.test.ts +42 -1
- package/src/cli/commands/init-lexicon.ts +3 -1
- package/src/cli/commands/lexicon-rolling-upgrade.ts +1 -1
- package/src/cli/commands/lexicon-surface-diff.test.ts +1 -1
- package/src/cli/commands/lexicon-surface-diff.ts +10 -1
- package/src/cli/commands/lexicon-surface-diff.update.test.ts +112 -0
- package/src/cli/commands/lint.ts +19 -6
- package/src/cli/commands/onboard.test.ts +319 -225
- package/src/cli/commands/onboard.ts +144 -58
- package/src/cli/handlers/build.test.ts +3 -3
- package/src/cli/handlers/build.ts +2 -0
- package/src/cli/handlers/components.ts +2 -2
- package/src/cli/handlers/graph.test.ts +44 -0
- package/src/cli/handlers/graph.ts +24 -4
- package/src/cli/handlers/lifecycle.test.ts +348 -1
- package/src/cli/handlers/lifecycle.ts +235 -3
- package/src/cli/handlers/run.test.ts +5 -5
- package/src/cli/handlers/run.ts +1 -0
- package/src/cli/handlers/search-live.test.ts +217 -0
- package/src/cli/handlers/search.test.ts +41 -1
- package/src/cli/handlers/search.ts +60 -8
- package/src/cli/main.ts +17 -4
- package/src/cli/registry.ts +7 -0
- package/src/cli/security-boundary.test.ts +2 -1
- package/src/codegen/docs-pages.test.ts +194 -0
- package/src/codegen/docs-pages.ts +138 -0
- package/src/codegen/docs-sections.ts +0 -8
- package/src/codegen/docs-sidebar.ts +50 -37
- package/src/codegen/docs-types.ts +32 -4
- package/src/codegen/docs.ts +78 -40
- package/src/codegen/lexicon-regen.ts +22 -2
- package/src/codegen/rolling-upgrade.test.ts +1 -1
- package/src/codegen/rolling-upgrade.ts +1 -1
- package/src/codegen/surface-snapshot.test.ts +139 -0
- package/src/codegen/surface-snapshot.ts +297 -122
- package/src/codegen/validate.test.ts +49 -3
- package/src/codegen/validate.ts +36 -7
- package/src/components/auto-release.ts +1 -1
- package/src/components/capability-plugin.ts +23 -2
- package/src/components/driver.test.ts +45 -0
- package/src/components/driver.ts +64 -27
- package/src/components/index.ts +2 -0
- package/src/components/starter-plugin.ts +5 -2
- package/src/config.test.ts +40 -0
- package/src/config.ts +159 -8
- package/src/discovery/fold-import.test.ts +427 -2
- package/src/discovery/fold-import.ts +163 -7
- package/src/discovery/sandbox/driver.test.ts +11 -0
- package/src/env.test.ts +35 -1
- package/src/env.ts +17 -3
- package/src/fold/fold.test.ts +41 -0
- package/src/fold/fold.ts +372 -2
- package/src/graph-ir-live.test.ts +42 -0
- package/src/graph-ir.ts +42 -2
- package/src/graph-ops.test.ts +69 -0
- package/src/graph-ops.ts +42 -0
- package/src/lexicon.ts +182 -2
- package/src/lifecycle/change-set.test.ts +41 -0
- package/src/lifecycle/change-set.ts +30 -2
- package/src/lifecycle/deep-observe.ts +4 -0
- package/src/lifecycle/index.ts +1 -0
- package/src/lifecycle/observe.ts +29 -2
- package/src/lifecycle/replay.ts +3 -0
- package/src/lifecycle/snapshot.ts +3 -0
- package/src/lifecycle/teardown.test.ts +537 -0
- package/src/lifecycle/teardown.ts +357 -0
- package/src/lifecycle/types.ts +7 -0
- package/src/lint/engine.ts +7 -1
- package/src/lint/policy.ts +14 -3
- package/src/lint/rule.ts +23 -0
- package/src/lint/rules/cor021-env-literal-name.test.ts +128 -0
- package/src/lint/rules/cor021-env-literal-name.ts +114 -0
- package/src/lint/rules/index.ts +4 -1
- package/src/managed-fields.test.ts +15 -42
- package/src/managed-fields.ts +43 -26
- package/src/observation.test.ts +24 -8
- package/src/observation.ts +48 -4
- package/src/op/builders.ts +40 -7
- package/src/op/index.ts +1 -1
- package/src/ownership.test.ts +63 -1
- package/src/testing.test.ts +261 -0
- package/src/testing.ts +338 -0
- package/src/yaml.test.ts +15 -0
- package/src/yaml.ts +19 -2
|
@@ -2,15 +2,12 @@ import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
|
2
2
|
import { mkdirSync, writeFileSync, readFileSync, rmSync } from "fs";
|
|
3
3
|
import { join } from "path";
|
|
4
4
|
import { tmpdir } from "os";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
// Rather than mocking findRepoRoot, we test the observable behaviour via
|
|
13
|
-
// the CLI entry point. The unit tests below validate file-patching logic.
|
|
5
|
+
import {
|
|
6
|
+
onboardCommand,
|
|
7
|
+
patchDockerfile,
|
|
8
|
+
patchRootTsconfigPaths,
|
|
9
|
+
insertPrepackAfterEach,
|
|
10
|
+
} from "./onboard";
|
|
14
11
|
|
|
15
12
|
function makeTempDir(): string {
|
|
16
13
|
const dir = join(tmpdir(), `chant-onboard-test-${Date.now()}-${Math.random().toString(36).slice(2)}`);
|
|
@@ -18,46 +15,29 @@ function makeTempDir(): string {
|
|
|
18
15
|
return dir;
|
|
19
16
|
}
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
};
|
|
45
|
-
writeFileSync(join(root, "package.json"), JSON.stringify(pkg, null, 2));
|
|
46
|
-
|
|
47
|
-
// Simulate the patch by reading+writing
|
|
48
|
-
const content = JSON.parse(readFileSync(join(root, "package.json"), "utf-8"));
|
|
49
|
-
content.dependencies["@intentius/chant-lexicon-terraform"] = "workspace:*";
|
|
50
|
-
writeFileSync(join(root, "package.json"), JSON.stringify(content, null, 2));
|
|
51
|
-
|
|
52
|
-
const result = JSON.parse(readFileSync(join(root, "package.json"), "utf-8"));
|
|
53
|
-
expect(result.dependencies["@intentius/chant-lexicon-terraform"]).toBe("workspace:*");
|
|
54
|
-
});
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
// ── chant.yml ──────────────────────────────────────────
|
|
58
|
-
|
|
59
|
-
describe("chant.yml patching", () => {
|
|
60
|
-
const ciContent = `name: chant
|
|
18
|
+
const rootPackageJson = {
|
|
19
|
+
workspaces: ["packages/*", "lexicons/*"],
|
|
20
|
+
dependencies: {
|
|
21
|
+
"@intentius/chant-lexicon-aws": "workspace:*",
|
|
22
|
+
"@intentius/chant-lexicon-k8s": "workspace:*",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const rootTsconfig = {
|
|
27
|
+
compilerOptions: {
|
|
28
|
+
moduleResolution: "node",
|
|
29
|
+
baseUrl: ".",
|
|
30
|
+
paths: {
|
|
31
|
+
"@intentius/chant": ["packages/core/src/index.ts"],
|
|
32
|
+
"@intentius/chant/*": ["packages/core/src/*"],
|
|
33
|
+
"@intentius/chant-lexicon-aws": ["lexicons/aws/src/index.ts"],
|
|
34
|
+
"@intentius/chant-lexicon-aws/*": ["lexicons/aws/src/*"],
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
include: ["packages/core/src/**/*.ts", "lexicons/*/src/**/*.ts", "lexicons/*/examples/*/src/**/*.ts"],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const ciContent = `name: chant
|
|
61
41
|
on: [push]
|
|
62
42
|
jobs:
|
|
63
43
|
check:
|
|
@@ -92,163 +72,53 @@ jobs:
|
|
|
92
72
|
run: npm run --prefix lexicons/k8s prepack
|
|
93
73
|
`;
|
|
94
74
|
|
|
95
|
-
|
|
96
|
-
writeFileSync(join(root, ".github/workflows/chant.yml"), ciContent);
|
|
97
|
-
|
|
98
|
-
// Use the same logic as the command
|
|
99
|
-
const content = readFileSync(join(root, ".github/workflows/chant.yml"), "utf-8");
|
|
100
|
-
const lines = content.split("\n");
|
|
101
|
-
|
|
102
|
-
// Find contiguous groups and insert
|
|
103
|
-
const groups: { start: number; end: number }[] = [];
|
|
104
|
-
let groupStart = -1;
|
|
105
|
-
for (let i = 0; i <= lines.length; i++) {
|
|
106
|
-
const isPrepack =
|
|
107
|
-
i < lines.length &&
|
|
108
|
-
lines[i].includes("npm run --prefix lexicons/") &&
|
|
109
|
-
lines[i].includes("prepack");
|
|
110
|
-
if (isPrepack && groupStart === -1) {
|
|
111
|
-
groupStart = i;
|
|
112
|
-
} else if (!isPrepack && groupStart !== -1) {
|
|
113
|
-
groups.push({ start: groupStart, end: i - 1 });
|
|
114
|
-
groupStart = -1;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// Should find 2 contiguous groups (check + test) and 3 standalone (validate)
|
|
119
|
-
const multiLineGroups = groups.filter((g) => g.end > g.start);
|
|
120
|
-
expect(multiLineGroups.length).toBe(2);
|
|
121
|
-
|
|
122
|
-
// Insert into multi-line groups only
|
|
123
|
-
const insertAfter = multiLineGroups.map((g) => g.end);
|
|
124
|
-
for (const idx of insertAfter.reverse()) {
|
|
125
|
-
const newLine = lines[idx].replace(/lexicons\/[a-z0-9-]+/i, "lexicons/terraform");
|
|
126
|
-
lines.splice(idx + 1, 0, newLine);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const result = lines.join("\n");
|
|
130
|
-
// Should have 2 new terraform prepack lines (in the run: | blocks)
|
|
131
|
-
const matches = result.match(/lexicons\/terraform prepack/g);
|
|
132
|
-
expect(matches?.length).toBe(2);
|
|
133
|
-
|
|
134
|
-
// Should NOT have altered the validate standalone steps
|
|
135
|
-
const validateSection = result.split("validate:")[1];
|
|
136
|
-
expect(validateSection).not.toContain("lexicons/terraform");
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
test("adds validate step after last existing validate step", () => {
|
|
140
|
-
writeFileSync(join(root, ".github/workflows/chant.yml"), ciContent);
|
|
141
|
-
const content = readFileSync(join(root, ".github/workflows/chant.yml"), "utf-8");
|
|
142
|
-
const lines = content.split("\n");
|
|
143
|
-
|
|
144
|
-
let lastValidateRunIdx = -1;
|
|
145
|
-
for (let i = 0; i < lines.length; i++) {
|
|
146
|
-
if (lines[i].includes("Generate and validate")) {
|
|
147
|
-
if (i + 1 < lines.length && lines[i + 1].trimStart().startsWith("run:")) {
|
|
148
|
-
lastValidateRunIdx = i + 1;
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
expect(lastValidateRunIdx).toBeGreaterThan(0);
|
|
154
|
-
|
|
155
|
-
const block = [
|
|
156
|
-
"",
|
|
157
|
-
" - name: Generate and validate Terraform lexicon",
|
|
158
|
-
" run: npm run --prefix lexicons/terraform prepack",
|
|
159
|
-
];
|
|
160
|
-
lines.splice(lastValidateRunIdx + 1, 0, ...block);
|
|
161
|
-
const result = lines.join("\n");
|
|
162
|
-
|
|
163
|
-
expect(result).toContain("Generate and validate Terraform lexicon");
|
|
164
|
-
expect(result).toContain("npm run --prefix lexicons/terraform prepack");
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
// ── publish.yml ──────────────────────────────────────────
|
|
169
|
-
|
|
170
|
-
describe("publish.yml patching", () => {
|
|
171
|
-
const publishContent = `name: publish
|
|
75
|
+
const publishContent = `name: publish
|
|
172
76
|
on:
|
|
173
77
|
push:
|
|
174
78
|
tags: ['v*']
|
|
175
79
|
jobs:
|
|
176
80
|
test:
|
|
81
|
+
# 12 lexicon prepacks (build + validate) plus the full vitest suite
|
|
177
82
|
steps:
|
|
178
83
|
- run: npm run --prefix lexicons/aws prepack
|
|
179
84
|
- run: npm run --prefix lexicons/gitlab prepack
|
|
180
85
|
- run: npm run --prefix lexicons/k8s prepack
|
|
181
86
|
- run: npx vitest run
|
|
182
|
-
|
|
183
|
-
publish:
|
|
184
|
-
steps:
|
|
185
|
-
- name: Publish @intentius/chant-lexicon-aws
|
|
186
|
-
working-directory: lexicons/aws
|
|
187
|
-
run: npm publish --access public
|
|
188
|
-
|
|
189
|
-
- name: Publish @intentius/chant-lexicon-k8s
|
|
190
|
-
working-directory: lexicons/k8s
|
|
191
|
-
run: npm publish --access public
|
|
192
87
|
`;
|
|
193
88
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
expect(insertAfter.length).toBe(1);
|
|
211
|
-
|
|
212
|
-
const idx = insertAfter[0];
|
|
213
|
-
const newLine = lines[idx].replace(/lexicons\/[a-z0-9-]+/i, "lexicons/terraform");
|
|
214
|
-
lines.splice(idx + 1, 0, newLine);
|
|
215
|
-
|
|
216
|
-
const result = lines.join("\n");
|
|
217
|
-
expect(result).toContain("lexicons/terraform prepack");
|
|
218
|
-
});
|
|
219
|
-
|
|
220
|
-
test("adds publish step after last publish step", () => {
|
|
221
|
-
writeFileSync(join(root, ".github/workflows/publish.yml"), publishContent);
|
|
222
|
-
const content = readFileSync(join(root, ".github/workflows/publish.yml"), "utf-8");
|
|
223
|
-
const lines = content.split("\n");
|
|
224
|
-
|
|
225
|
-
let lastPublishRunIdx = -1;
|
|
226
|
-
for (let i = 0; i < lines.length; i++) {
|
|
227
|
-
if (lines[i].includes("npm publish --access public")) {
|
|
228
|
-
lastPublishRunIdx = i;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
expect(lastPublishRunIdx).toBeGreaterThan(0);
|
|
233
|
-
|
|
234
|
-
const block = [
|
|
235
|
-
"",
|
|
236
|
-
" - name: Publish @intentius/chant-lexicon-terraform",
|
|
237
|
-
" working-directory: lexicons/terraform",
|
|
238
|
-
" run: npm publish --access public",
|
|
239
|
-
];
|
|
240
|
-
lines.splice(lastPublishRunIdx + 1, 0, ...block);
|
|
241
|
-
const result = lines.join("\n");
|
|
242
|
-
|
|
243
|
-
expect(result).toContain("Publish @intentius/chant-lexicon-terraform");
|
|
244
|
-
expect(result).toContain("working-directory: lexicons/terraform");
|
|
245
|
-
});
|
|
246
|
-
});
|
|
89
|
+
// Mirrors test/Dockerfile.smoke on main: a loop, a comment and an echo that
|
|
90
|
+
// all contain the placeholder substring the old matcher anchored on (#1678).
|
|
91
|
+
const dockerLoopContent = `FROM node:22-slim
|
|
92
|
+
WORKDIR /app
|
|
93
|
+
COPY . .
|
|
94
|
+
RUN npm install
|
|
95
|
+
# Run: just prepack (or npm run --prefix lexicons/<lex> prepack) before building this Dockerfile.
|
|
96
|
+
RUN for lex in aws azure gcp gitlab k8s docker cedar; do \\
|
|
97
|
+
if [ ! -d "lexicons/$lex/dist" ]; then \\
|
|
98
|
+
echo "ERROR: lexicons/$lex/dist/ not found. Run codegen first: npm run --prefix lexicons/$lex prepack" >&2; \\
|
|
99
|
+
exit 1; \\
|
|
100
|
+
fi; \\
|
|
101
|
+
done
|
|
102
|
+
COPY test/integration.sh /app/test/integration.sh
|
|
103
|
+
`;
|
|
247
104
|
|
|
248
|
-
|
|
105
|
+
// Mirrors test/Dockerfile.smoke-npm: two loops, no prepack invocation at all.
|
|
106
|
+
const dockerNpmContent = `FROM node:22-slim AS build
|
|
107
|
+
WORKDIR /app
|
|
108
|
+
COPY . .
|
|
109
|
+
RUN CORE_VERSION=$(jq -r '.version' packages/core/package.json) && \\
|
|
110
|
+
for lex in aws azure gcp gitlab k8s docker fly fountain; do \\
|
|
111
|
+
cd /app/lexicons/$lex && jq 'del(.scripts)' package.json > tmp.json && mv tmp.json package.json; \\
|
|
112
|
+
done
|
|
113
|
+
|
|
114
|
+
# smoke.sh ran prepack locally; COPY . . already brought dist/ into this stage.
|
|
115
|
+
RUN mkdir -p /tarballs && \\
|
|
116
|
+
for lex in aws azure gcp gitlab k8s docker fly fountain; do \\
|
|
117
|
+
tar czf /tarballs/lexicon-\${lex}.tgz -C /app/lexicons/$lex ./package.json ./src ./dist || exit 1; \\
|
|
118
|
+
done
|
|
119
|
+
`;
|
|
249
120
|
|
|
250
|
-
|
|
251
|
-
const dockerContent = `FROM node:22-slim
|
|
121
|
+
const dockerPerLineContent = `FROM node:22-slim
|
|
252
122
|
WORKDIR /app
|
|
253
123
|
COPY . .
|
|
254
124
|
RUN npm install
|
|
@@ -258,38 +128,262 @@ RUN npm run --prefix lexicons/k8s prepack
|
|
|
258
128
|
COPY test/integration.sh /app/test/integration.sh
|
|
259
129
|
`;
|
|
260
130
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
131
|
+
function writeFixtureRepo(root: string): void {
|
|
132
|
+
mkdirSync(join(root, ".github/workflows"), { recursive: true });
|
|
133
|
+
mkdirSync(join(root, "test"), { recursive: true });
|
|
134
|
+
writeFileSync(join(root, "package.json"), JSON.stringify(rootPackageJson, null, 2) + "\n");
|
|
135
|
+
writeFileSync(join(root, "tsconfig.json"), JSON.stringify(rootTsconfig, null, 2) + "\n");
|
|
136
|
+
writeFileSync(join(root, ".github/workflows/chant.yml"), ciContent);
|
|
137
|
+
writeFileSync(join(root, ".github/workflows/publish.yml"), publishContent);
|
|
138
|
+
writeFileSync(join(root, "test/Dockerfile.smoke"), dockerLoopContent);
|
|
139
|
+
writeFileSync(join(root, "test/Dockerfile.smoke-npm"), dockerNpmContent);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const TRACKED = [
|
|
143
|
+
"package.json",
|
|
144
|
+
"tsconfig.json",
|
|
145
|
+
".github/workflows/chant.yml",
|
|
146
|
+
".github/workflows/publish.yml",
|
|
147
|
+
"test/Dockerfile.smoke",
|
|
148
|
+
"test/Dockerfile.smoke-npm",
|
|
149
|
+
];
|
|
150
|
+
|
|
151
|
+
function snapshot(root: string): Record<string, string> {
|
|
152
|
+
const out: Record<string, string> = {};
|
|
153
|
+
for (const f of TRACKED) out[f] = readFileSync(join(root, f), "utf-8");
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
describe("onboardCommand", () => {
|
|
158
|
+
let root: string;
|
|
159
|
+
|
|
160
|
+
beforeEach(() => {
|
|
161
|
+
root = makeTempDir();
|
|
162
|
+
writeFixtureRepo(root);
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
afterEach(() => {
|
|
166
|
+
rmSync(root, { recursive: true, force: true });
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("first run patches every file once", () => {
|
|
170
|
+
const result = onboardCommand({ name: "terraform", root });
|
|
171
|
+
expect(result.success).toBe(true);
|
|
172
|
+
expect(result.patched).toEqual([
|
|
173
|
+
"package.json (root dependency)",
|
|
174
|
+
"tsconfig.json (paths mapping)",
|
|
175
|
+
"chant.yml (prepack + validate)",
|
|
176
|
+
"publish.yml (prepack)",
|
|
177
|
+
"Dockerfile.smoke (lexicon list)",
|
|
178
|
+
"Dockerfile.smoke-npm (lexicon list)",
|
|
179
|
+
]);
|
|
180
|
+
expect(result.skipped).toEqual([]);
|
|
181
|
+
|
|
182
|
+
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf-8"));
|
|
183
|
+
expect(pkg.dependencies["@intentius/chant-lexicon-terraform"]).toBe("workspace:*");
|
|
184
|
+
|
|
185
|
+
const ci = readFileSync(join(root, ".github/workflows/chant.yml"), "utf-8");
|
|
186
|
+
expect(ci.match(/lexicons\/terraform prepack/g)?.length).toBe(3); // check + test + validate
|
|
187
|
+
expect(ci).toContain("Generate and validate Terraform lexicon");
|
|
188
|
+
|
|
189
|
+
const pub = readFileSync(join(root, ".github/workflows/publish.yml"), "utf-8");
|
|
190
|
+
expect(pub.match(/lexicons\/terraform prepack/g)?.length).toBe(1);
|
|
191
|
+
expect(pub).toContain(" - run: npm run --prefix lexicons/terraform prepack\n - run: npx vitest run");
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
test("second run is a byte-identical no-op and reports already covered (#1678)", () => {
|
|
195
|
+
onboardCommand({ name: "terraform", root });
|
|
196
|
+
const after1 = snapshot(root);
|
|
197
|
+
|
|
198
|
+
const result = onboardCommand({ name: "terraform", root });
|
|
199
|
+
const after2 = snapshot(root);
|
|
200
|
+
|
|
201
|
+
expect(after2).toEqual(after1);
|
|
202
|
+
expect(result.patched).toEqual([]);
|
|
203
|
+
expect(result.skipped).toEqual([
|
|
204
|
+
"package.json: @intentius/chant-lexicon-terraform already in dependencies",
|
|
205
|
+
"tsconfig.json: @intentius/chant-lexicon-terraform already in paths",
|
|
206
|
+
"chant.yml: terraform already in chant.yml",
|
|
207
|
+
"publish.yml: prepack for terraform already present",
|
|
208
|
+
"Dockerfile.smoke: already covers terraform",
|
|
209
|
+
"Dockerfile.smoke-npm: already covers terraform",
|
|
210
|
+
]);
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
test("running onboard three times leaves exactly one copy of everything", () => {
|
|
214
|
+
for (let i = 0; i < 3; i++) onboardCommand({ name: "terraform", root });
|
|
215
|
+
const ci = readFileSync(join(root, ".github/workflows/chant.yml"), "utf-8");
|
|
216
|
+
expect(ci.match(/lexicons\/terraform prepack/g)?.length).toBe(3);
|
|
217
|
+
const docker = readFileSync(join(root, "test/Dockerfile.smoke"), "utf-8");
|
|
218
|
+
expect(docker.match(/terraform/g)?.length).toBe(1);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe("root tsconfig.json paths (#1614)", () => {
|
|
223
|
+
let root: string;
|
|
224
|
+
|
|
225
|
+
beforeEach(() => {
|
|
226
|
+
root = makeTempDir();
|
|
227
|
+
writeFixtureRepo(root);
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
afterEach(() => {
|
|
231
|
+
rmSync(root, { recursive: true, force: true });
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
test("adds bare and subpath mappings", () => {
|
|
235
|
+
const result = patchRootTsconfigPaths(root, "terraform");
|
|
236
|
+
expect(result.patched).toBe(true);
|
|
237
|
+
|
|
238
|
+
const cfg = JSON.parse(readFileSync(join(root, "tsconfig.json"), "utf-8"));
|
|
239
|
+
expect(cfg.compilerOptions.paths["@intentius/chant-lexicon-terraform"]).toEqual([
|
|
240
|
+
"lexicons/terraform/src/index.ts",
|
|
241
|
+
]);
|
|
242
|
+
expect(cfg.compilerOptions.paths["@intentius/chant-lexicon-terraform/*"]).toEqual(["lexicons/terraform/src/*"]);
|
|
243
|
+
// Existing entries untouched
|
|
244
|
+
expect(cfg.compilerOptions.paths["@intentius/chant-lexicon-aws"]).toEqual(["lexicons/aws/src/index.ts"]);
|
|
245
|
+
expect(cfg.compilerOptions.moduleResolution).toBe("node");
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test("is idempotent", () => {
|
|
249
|
+
patchRootTsconfigPaths(root, "terraform");
|
|
250
|
+
const before = readFileSync(join(root, "tsconfig.json"), "utf-8");
|
|
251
|
+
const result = patchRootTsconfigPaths(root, "terraform");
|
|
252
|
+
expect(result.patched).toBe(false);
|
|
253
|
+
expect(result.reason).toContain("already in paths");
|
|
254
|
+
expect(readFileSync(join(root, "tsconfig.json"), "utf-8")).toBe(before);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test("skips an already-present lexicon", () => {
|
|
258
|
+
const result = patchRootTsconfigPaths(root, "aws");
|
|
259
|
+
expect(result.patched).toBe(false);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
test("creates the paths map when missing", () => {
|
|
263
|
+
writeFileSync(join(root, "tsconfig.json"), JSON.stringify({ compilerOptions: {} }) + "\n");
|
|
264
|
+
const result = patchRootTsconfigPaths(root, "terraform");
|
|
265
|
+
expect(result.patched).toBe(true);
|
|
266
|
+
const cfg = JSON.parse(readFileSync(join(root, "tsconfig.json"), "utf-8"));
|
|
267
|
+
expect(Object.keys(cfg.compilerOptions.paths)).toEqual([
|
|
268
|
+
"@intentius/chant-lexicon-terraform",
|
|
269
|
+
"@intentius/chant-lexicon-terraform/*",
|
|
270
|
+
]);
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
describe("Dockerfile patching (#1678)", () => {
|
|
275
|
+
let root: string;
|
|
276
|
+
|
|
277
|
+
beforeEach(() => {
|
|
278
|
+
root = makeTempDir();
|
|
279
|
+
mkdirSync(join(root, "test"), { recursive: true });
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
afterEach(() => {
|
|
283
|
+
rmSync(root, { recursive: true, force: true });
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test("loop-based Dockerfile.smoke gains exactly one list entry", () => {
|
|
287
|
+
const file = join(root, "test/Dockerfile.smoke");
|
|
288
|
+
writeFileSync(file, dockerLoopContent);
|
|
289
|
+
|
|
290
|
+
const result = patchDockerfile(file, "terraform");
|
|
291
|
+
expect(result.patched).toBe(true);
|
|
292
|
+
|
|
293
|
+
const out = readFileSync(file, "utf-8");
|
|
294
|
+
expect(out).toContain("RUN for lex in aws azure gcp gitlab k8s docker cedar terraform; do \\");
|
|
295
|
+
// No RUN line was appended after the comment or the echo
|
|
296
|
+
expect(out).not.toContain("RUN npm run --prefix lexicons/terraform prepack");
|
|
297
|
+
expect(out.match(/terraform/g)?.length).toBe(1);
|
|
298
|
+
// Everything else is untouched
|
|
299
|
+
expect(out.split("\n").length).toBe(dockerLoopContent.split("\n").length);
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
test("loop-based file already covering the lexicon is a no-op", () => {
|
|
303
|
+
const file = join(root, "test/Dockerfile.smoke");
|
|
304
|
+
writeFileSync(file, dockerLoopContent);
|
|
305
|
+
|
|
306
|
+
const result = patchDockerfile(file, "cedar");
|
|
307
|
+
expect(result.patched).toBe(false);
|
|
308
|
+
expect(result.reason).toBe("already covers cedar");
|
|
309
|
+
expect(readFileSync(file, "utf-8")).toBe(dockerLoopContent);
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
test("second patch of a loop-based file is byte-identical", () => {
|
|
313
|
+
const file = join(root, "test/Dockerfile.smoke");
|
|
314
|
+
writeFileSync(file, dockerLoopContent);
|
|
315
|
+
|
|
316
|
+
patchDockerfile(file, "terraform");
|
|
317
|
+
const once = readFileSync(file, "utf-8");
|
|
318
|
+
const result = patchDockerfile(file, "terraform");
|
|
319
|
+
expect(result.patched).toBe(false);
|
|
320
|
+
expect(readFileSync(file, "utf-8")).toBe(once);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
test("Dockerfile.smoke-npm adds the name to both loops and nothing else", () => {
|
|
324
|
+
const file = join(root, "test/Dockerfile.smoke-npm");
|
|
325
|
+
writeFileSync(file, dockerNpmContent);
|
|
326
|
+
|
|
327
|
+
const result = patchDockerfile(file, "terraform");
|
|
328
|
+
expect(result.patched).toBe(true);
|
|
329
|
+
|
|
330
|
+
const out = readFileSync(file, "utf-8");
|
|
331
|
+
expect(out.match(/for lex in aws azure gcp gitlab k8s docker fly fountain terraform; do/g)?.length).toBe(2);
|
|
332
|
+
expect(out.match(/terraform/g)?.length).toBe(2);
|
|
333
|
+
expect(out.split("\n").length).toBe(dockerNpmContent.split("\n").length);
|
|
334
|
+
|
|
335
|
+
// Reported as a no-op the second time, not as patched
|
|
336
|
+
expect(patchDockerfile(file, "terraform")).toEqual({ patched: false, reason: "already covers terraform" });
|
|
337
|
+
expect(readFileSync(file, "utf-8")).toBe(out);
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
test("per-lexicon RUN layout still gets a new RUN line after the last one", () => {
|
|
341
|
+
const file = join(root, "test/Dockerfile.smoke");
|
|
342
|
+
writeFileSync(file, dockerPerLineContent);
|
|
343
|
+
|
|
344
|
+
const result = patchDockerfile(file, "terraform");
|
|
345
|
+
expect(result.patched).toBe(true);
|
|
346
|
+
|
|
347
|
+
const out = readFileSync(file, "utf-8");
|
|
348
|
+
expect(out).toContain("RUN npm run --prefix lexicons/k8s prepack\nRUN npm run --prefix lexicons/terraform prepack\n");
|
|
349
|
+
expect(out.match(/lexicons\/terraform prepack/g)?.length).toBe(1);
|
|
350
|
+
|
|
351
|
+
expect(patchDockerfile(file, "terraform").patched).toBe(false);
|
|
352
|
+
expect(readFileSync(file, "utf-8")).toBe(out);
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
test("a file with nothing to anchor on is reported, not silently 'patched'", () => {
|
|
356
|
+
const file = join(root, "test/Dockerfile.smoke-npm");
|
|
357
|
+
const content = "FROM node:22-slim\nCOPY . .\n";
|
|
358
|
+
writeFileSync(file, content);
|
|
359
|
+
|
|
360
|
+
const result = patchDockerfile(file, "terraform");
|
|
361
|
+
expect(result.patched).toBe(false);
|
|
362
|
+
expect(result.reason).toContain("anchor");
|
|
363
|
+
expect(readFileSync(file, "utf-8")).toBe(content);
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
describe("insertPrepackAfterEach", () => {
|
|
368
|
+
test("ignores comments and echo lines that mention prepack", () => {
|
|
369
|
+
const lines = dockerLoopContent.split("\n");
|
|
370
|
+
const before = [...lines];
|
|
371
|
+
expect(insertPrepackAfterEach(lines, "terraform")).toBe(false);
|
|
372
|
+
expect(lines).toEqual(before);
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
test("anchors on real RUN lines only", () => {
|
|
376
|
+
const lines = [
|
|
377
|
+
"# npm run --prefix lexicons/<lex> prepack",
|
|
378
|
+
"RUN npm run --prefix lexicons/aws prepack",
|
|
379
|
+
'RUN echo "npm run --prefix lexicons/$lex prepack"',
|
|
380
|
+
];
|
|
381
|
+
expect(insertPrepackAfterEach(lines, "terraform")).toBe(true);
|
|
382
|
+
expect(lines).toEqual([
|
|
383
|
+
"# npm run --prefix lexicons/<lex> prepack",
|
|
384
|
+
"RUN npm run --prefix lexicons/aws prepack",
|
|
385
|
+
"RUN npm run --prefix lexicons/terraform prepack",
|
|
386
|
+
'RUN echo "npm run --prefix lexicons/$lex prepack"',
|
|
387
|
+
]);
|
|
294
388
|
});
|
|
295
389
|
});
|