@intentius/chant-lexicon-helm 0.0.16
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/README.md +22 -0
- package/dist/integrity.json +36 -0
- package/dist/manifest.json +37 -0
- package/dist/meta.json +208 -0
- package/dist/rules/chart-metadata.ts +64 -0
- package/dist/rules/helm-helpers.ts +64 -0
- package/dist/rules/no-hardcoded-image.ts +62 -0
- package/dist/rules/values-no-secrets.ts +82 -0
- package/dist/rules/whm101.ts +46 -0
- package/dist/rules/whm102.ts +33 -0
- package/dist/rules/whm103.ts +59 -0
- package/dist/rules/whm104.ts +35 -0
- package/dist/rules/whm105.ts +30 -0
- package/dist/rules/whm201.ts +36 -0
- package/dist/rules/whm202.ts +50 -0
- package/dist/rules/whm203.ts +39 -0
- package/dist/rules/whm204.ts +60 -0
- package/dist/rules/whm301.ts +41 -0
- package/dist/rules/whm302.ts +40 -0
- package/dist/rules/whm401.ts +57 -0
- package/dist/rules/whm402.ts +45 -0
- package/dist/rules/whm403.ts +45 -0
- package/dist/rules/whm404.ts +36 -0
- package/dist/rules/whm405.ts +53 -0
- package/dist/rules/whm406.ts +34 -0
- package/dist/rules/whm407.ts +83 -0
- package/dist/rules/whm501.ts +103 -0
- package/dist/rules/whm502.ts +94 -0
- package/dist/skills/chant-helm-chart-patterns.md +229 -0
- package/dist/skills/chant-helm-chart-security-patterns.md +192 -0
- package/dist/skills/chant-helm-create-chart.md +211 -0
- package/dist/types/index.d.ts +132 -0
- package/package.json +34 -0
- package/src/codegen/docs-cli.ts +4 -0
- package/src/codegen/docs.ts +483 -0
- package/src/codegen/generate-cli.ts +28 -0
- package/src/codegen/generate.ts +249 -0
- package/src/codegen/naming.ts +38 -0
- package/src/codegen/package.ts +64 -0
- package/src/composites/composites.test.ts +1050 -0
- package/src/composites/helm-batch-job.ts +209 -0
- package/src/composites/helm-crd-lifecycle.ts +184 -0
- package/src/composites/helm-cron-job.ts +177 -0
- package/src/composites/helm-daemon-set.ts +169 -0
- package/src/composites/helm-external-secret.ts +93 -0
- package/src/composites/helm-library.ts +51 -0
- package/src/composites/helm-microservice.ts +331 -0
- package/src/composites/helm-monitored-service.ts +252 -0
- package/src/composites/helm-namespace-env.ts +154 -0
- package/src/composites/helm-secure-ingress.ts +114 -0
- package/src/composites/helm-stateful-service.ts +213 -0
- package/src/composites/helm-web-app.ts +264 -0
- package/src/composites/helm-worker.ts +207 -0
- package/src/composites/index.ts +38 -0
- package/src/coverage.test.ts +21 -0
- package/src/coverage.ts +50 -0
- package/src/generated/index.d.ts +132 -0
- package/src/generated/index.ts +13 -0
- package/src/generated/lexicon-helm.json +208 -0
- package/src/helpers.test.ts +51 -0
- package/src/helpers.ts +100 -0
- package/src/import/generator.ts +285 -0
- package/src/import/import.test.ts +224 -0
- package/src/import/parser.ts +160 -0
- package/src/import/template-stripper.ts +123 -0
- package/src/index.ts +108 -0
- package/src/intrinsics.test.ts +380 -0
- package/src/intrinsics.ts +484 -0
- package/src/lint/post-synth/helm-helpers.ts +64 -0
- package/src/lint/post-synth/post-synth.test.ts +504 -0
- package/src/lint/post-synth/whm101.ts +46 -0
- package/src/lint/post-synth/whm102.ts +33 -0
- package/src/lint/post-synth/whm103.ts +59 -0
- package/src/lint/post-synth/whm104.ts +35 -0
- package/src/lint/post-synth/whm105.ts +30 -0
- package/src/lint/post-synth/whm201.ts +36 -0
- package/src/lint/post-synth/whm202.ts +50 -0
- package/src/lint/post-synth/whm203.ts +39 -0
- package/src/lint/post-synth/whm204.ts +60 -0
- package/src/lint/post-synth/whm301.ts +41 -0
- package/src/lint/post-synth/whm302.ts +40 -0
- package/src/lint/post-synth/whm401.ts +57 -0
- package/src/lint/post-synth/whm402.ts +45 -0
- package/src/lint/post-synth/whm403.ts +45 -0
- package/src/lint/post-synth/whm404.ts +36 -0
- package/src/lint/post-synth/whm405.ts +53 -0
- package/src/lint/post-synth/whm406.ts +34 -0
- package/src/lint/post-synth/whm407.ts +83 -0
- package/src/lint/post-synth/whm501.ts +103 -0
- package/src/lint/post-synth/whm502.ts +94 -0
- package/src/lint/rules/chart-metadata.ts +64 -0
- package/src/lint/rules/lint-rules.test.ts +97 -0
- package/src/lint/rules/no-hardcoded-image.ts +62 -0
- package/src/lint/rules/values-no-secrets.ts +82 -0
- package/src/lsp/completions.test.ts +72 -0
- package/src/lsp/completions.ts +20 -0
- package/src/lsp/hover.test.ts +46 -0
- package/src/lsp/hover.ts +46 -0
- package/src/package-cli.ts +28 -0
- package/src/plugin.test.ts +71 -0
- package/src/plugin.ts +206 -0
- package/src/resources.ts +77 -0
- package/src/serializer.test.ts +930 -0
- package/src/serializer.ts +835 -0
- package/src/skills/chart-patterns.md +229 -0
- package/src/skills/chart-security-patterns.md +192 -0
- package/src/skills/create-chart.md +211 -0
- package/src/validate-cli.ts +21 -0
- package/src/validate.test.ts +37 -0
- package/src/validate.ts +36 -0
package/src/lsp/hover.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createRequire } from "module";
|
|
2
|
+
import type { HoverContext, HoverInfo } from "@intentius/chant/lsp/types";
|
|
3
|
+
import { LexiconIndex, lexiconHover, type LexiconEntry } from "@intentius/chant/lsp/lexicon-providers";
|
|
4
|
+
const require = createRequire(import.meta.url);
|
|
5
|
+
|
|
6
|
+
let cachedIndex: LexiconIndex | null = null;
|
|
7
|
+
|
|
8
|
+
function getIndex(): LexiconIndex {
|
|
9
|
+
if (cachedIndex) return cachedIndex;
|
|
10
|
+
const data = require("../generated/lexicon-helm.json") as Record<string, LexiconEntry>;
|
|
11
|
+
cachedIndex = new LexiconIndex(data);
|
|
12
|
+
return cachedIndex;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Provide hover information for Helm resource types.
|
|
17
|
+
*/
|
|
18
|
+
export function helmHover(ctx: HoverContext): HoverInfo | undefined {
|
|
19
|
+
return lexiconHover(ctx, getIndex(), resourceHover);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function resourceHover(className: string, entry: LexiconEntry): HoverInfo | undefined {
|
|
23
|
+
const lines: string[] = [];
|
|
24
|
+
|
|
25
|
+
lines.push(`**${className}**`);
|
|
26
|
+
lines.push("");
|
|
27
|
+
lines.push(`Helm type: \`${entry.resourceType}\``);
|
|
28
|
+
|
|
29
|
+
if (entry.kind === "resource") {
|
|
30
|
+
lines.push("");
|
|
31
|
+
lines.push("*Resource — serialized as a top-level Helm chart artifact*");
|
|
32
|
+
} else {
|
|
33
|
+
lines.push("");
|
|
34
|
+
lines.push("*Property — used as a nested value in Helm resources*");
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (entry.attrs && Object.keys(entry.attrs).length > 0) {
|
|
38
|
+
lines.push("");
|
|
39
|
+
lines.push("**Attributes:**");
|
|
40
|
+
for (const [key, value] of Object.entries(entry.attrs)) {
|
|
41
|
+
lines.push(`- \`${key}\` \u2192 \`${value}\``);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return { contents: lines.join("\n") };
|
|
46
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* CLI entry point for Helm lexicon packaging.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { packageLexicon } from "./codegen/package";
|
|
7
|
+
import { writeBundleSpec } from "@intentius/chant/codegen/package";
|
|
8
|
+
import { join, dirname } from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
|
|
11
|
+
const pkgDir = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
|
|
13
|
+
async function main() {
|
|
14
|
+
const verbose = process.argv.includes("--verbose") || process.argv.includes("-v");
|
|
15
|
+
const force = process.argv.includes("--force") || process.argv.includes("-f");
|
|
16
|
+
|
|
17
|
+
const { spec, stats } = await packageLexicon({ verbose, force });
|
|
18
|
+
|
|
19
|
+
const distDir = join(pkgDir, "..", "dist");
|
|
20
|
+
writeBundleSpec(spec, distDir);
|
|
21
|
+
|
|
22
|
+
console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
main().catch((err) => {
|
|
26
|
+
console.error("Packaging failed:", err);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { describe, test, expect } from "bun:test";
|
|
2
|
+
import { helmPlugin } from "./plugin";
|
|
3
|
+
import { isLexiconPlugin } from "@intentius/chant/lexicon";
|
|
4
|
+
|
|
5
|
+
describe("helmPlugin", () => {
|
|
6
|
+
test("is a valid LexiconPlugin", () => {
|
|
7
|
+
expect(isLexiconPlugin(helmPlugin)).toBe(true);
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
test("has name 'helm'", () => {
|
|
11
|
+
expect(helmPlugin.name).toBe("helm");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("serializer has name 'helm' and rulePrefix 'WHM'", () => {
|
|
15
|
+
expect(helmPlugin.serializer.name).toBe("helm");
|
|
16
|
+
expect(helmPlugin.serializer.rulePrefix).toBe("WHM");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test("provides intrinsics", () => {
|
|
20
|
+
const intrinsics = helmPlugin.intrinsics!();
|
|
21
|
+
expect(intrinsics.length).toBeGreaterThan(0);
|
|
22
|
+
const names = intrinsics.map((i) => i.name);
|
|
23
|
+
expect(names).toContain("values");
|
|
24
|
+
expect(names).toContain("Release");
|
|
25
|
+
expect(names).toContain("include");
|
|
26
|
+
expect(names).toContain("If");
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
test("provides lint rules", () => {
|
|
30
|
+
const rules = helmPlugin.lintRules!();
|
|
31
|
+
expect(rules.length).toBe(3);
|
|
32
|
+
const ids = rules.map((r) => r.id);
|
|
33
|
+
expect(ids).toContain("WHM001");
|
|
34
|
+
expect(ids).toContain("WHM002");
|
|
35
|
+
expect(ids).toContain("WHM003");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("provides post-synth checks", () => {
|
|
39
|
+
const checks = helmPlugin.postSynthChecks!();
|
|
40
|
+
expect(checks.length).toBe(20);
|
|
41
|
+
const ids = checks.map((c) => c.id);
|
|
42
|
+
expect(ids).toContain("WHM101");
|
|
43
|
+
expect(ids).toContain("WHM105");
|
|
44
|
+
expect(ids).toContain("WHM301");
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("detectTemplate identifies Chart.yaml data", () => {
|
|
48
|
+
expect(helmPlugin.detectTemplate!({ apiVersion: "v2", name: "test", version: "0.1.0" })).toBe(true);
|
|
49
|
+
expect(helmPlugin.detectTemplate!({ apiVersion: "v1", name: "test", version: "0.1.0" })).toBe(false);
|
|
50
|
+
expect(helmPlugin.detectTemplate!({ kind: "Deployment" })).toBe(false);
|
|
51
|
+
expect(helmPlugin.detectTemplate!(null)).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("initTemplates returns chart.ts scaffold", () => {
|
|
55
|
+
const templates = helmPlugin.initTemplates!();
|
|
56
|
+
expect(templates.src["chart.ts"]).toBeDefined();
|
|
57
|
+
expect(templates.src["chart.ts"]).toContain("new Chart");
|
|
58
|
+
expect(templates.src["chart.ts"]).toContain("new Values");
|
|
59
|
+
expect(templates.src["chart.ts"]).toContain("new Deployment");
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("skills() returns array with helm skills", () => {
|
|
63
|
+
const skills = helmPlugin.skills!();
|
|
64
|
+
expect(Array.isArray(skills)).toBe(true);
|
|
65
|
+
expect(skills.length).toBeGreaterThanOrEqual(3);
|
|
66
|
+
const names = skills.map((s) => s.name);
|
|
67
|
+
expect(names).toContain("chant-helm-create-chart");
|
|
68
|
+
expect(names).toContain("chant-helm-chart-patterns");
|
|
69
|
+
expect(names).toContain("chant-helm-chart-security-patterns");
|
|
70
|
+
});
|
|
71
|
+
});
|
package/src/plugin.ts
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helm lexicon plugin.
|
|
3
|
+
*
|
|
4
|
+
* Implements the LexiconPlugin interface with the Helm chart serializer,
|
|
5
|
+
* Helm-specific intrinsics, lint rules, and post-synth checks.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { LexiconPlugin, IntrinsicDef, InitTemplateSet, SkillDefinition } from "@intentius/chant/lexicon";
|
|
9
|
+
import { discoverLintRules, discoverPostSynthChecks } from "@intentius/chant/lint/discover";
|
|
10
|
+
import { readFileSync, readdirSync } from "fs";
|
|
11
|
+
import { join, dirname } from "path";
|
|
12
|
+
import { fileURLToPath } from "url";
|
|
13
|
+
import { helmSerializer } from "./serializer";
|
|
14
|
+
|
|
15
|
+
export const helmPlugin: LexiconPlugin = {
|
|
16
|
+
name: "helm",
|
|
17
|
+
serializer: helmSerializer,
|
|
18
|
+
|
|
19
|
+
lintRules() {
|
|
20
|
+
const rulesDir = join(dirname(fileURLToPath(import.meta.url)), "lint", "rules");
|
|
21
|
+
return discoverLintRules(rulesDir, import.meta.url);
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
postSynthChecks() {
|
|
25
|
+
const postSynthDir = join(dirname(fileURLToPath(import.meta.url)), "lint", "post-synth");
|
|
26
|
+
return discoverPostSynthChecks(postSynthDir, import.meta.url);
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
intrinsics(): IntrinsicDef[] {
|
|
30
|
+
return [
|
|
31
|
+
{ name: "values", description: "Proxy accessor for {{ .Values.x }} references" },
|
|
32
|
+
{ name: "Release", description: "Built-in Release object (Name, Namespace, etc.)" },
|
|
33
|
+
{ name: "ChartRef", description: "Built-in Chart object (Name, Version, AppVersion)" },
|
|
34
|
+
{ name: "include", description: 'Include a named template: {{ include "name" . }}' },
|
|
35
|
+
{ name: "required", description: 'Require a value: {{ required "msg" .Values.x }}' },
|
|
36
|
+
{ name: "helmDefault", description: 'Default value: {{ default "def" .Values.x }}' },
|
|
37
|
+
{ name: "toYaml", description: "Convert to YAML: {{ toYaml .Values.x | nindent N }}" },
|
|
38
|
+
{ name: "quote", description: "Quote a value: {{ .Values.x | quote }}" },
|
|
39
|
+
{ name: "printf", description: 'Format string: {{ printf "%s" .Values.x }}' },
|
|
40
|
+
{ name: "tpl", description: "Evaluate template: {{ tpl .Values.x . }}" },
|
|
41
|
+
{ name: "lookup", description: 'Lookup resource: {{ lookup "v1" "Secret" "ns" "name" }}' },
|
|
42
|
+
{ name: "Capabilities", description: "Built-in Capabilities object (KubeVersion, APIVersions, HelmVersion)" },
|
|
43
|
+
{ name: "Template", description: "Built-in Template object (Name, BasePath)" },
|
|
44
|
+
{ name: "filesGet", description: '.Files.Get: {{ .Files.Get "path" }}' },
|
|
45
|
+
{ name: "filesGlob", description: '.Files.Glob: {{ .Files.Glob "pattern" }}' },
|
|
46
|
+
{ name: "filesAsConfig", description: ".Files.Glob.AsConfig for ConfigMap data" },
|
|
47
|
+
{ name: "filesAsSecrets", description: ".Files.Glob.AsSecrets for Secret data" },
|
|
48
|
+
{ name: "ElseIf", description: "Else-if chaining: {{- else if .Values.x }}...{{- end }}" },
|
|
49
|
+
{ name: "If", description: "Conditional: {{- if .Values.x }}...{{- end }}" },
|
|
50
|
+
{ name: "Range", description: "Range loop: {{- range .Values.x }}...{{- end }}" },
|
|
51
|
+
{ name: "With", description: "With scope: {{- with .Values.x }}...{{- end }}" },
|
|
52
|
+
{ name: "withOrder", description: "Helm hook annotations for resource ordering (pre-install/pre-upgrade)" },
|
|
53
|
+
{ name: "argoWave", description: "Argo CD sync wave annotation" },
|
|
54
|
+
];
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
detectTemplate(data: unknown): boolean {
|
|
58
|
+
if (typeof data !== "object" || data === null) return false;
|
|
59
|
+
const obj = data as Record<string, unknown>;
|
|
60
|
+
// Helm charts have apiVersion: v2 in Chart.yaml
|
|
61
|
+
if (obj.apiVersion === "v2" && typeof obj.name === "string" && typeof obj.version === "string") {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
},
|
|
66
|
+
|
|
67
|
+
initTemplates(_template?: string): InitTemplateSet {
|
|
68
|
+
return {
|
|
69
|
+
src: {
|
|
70
|
+
"chart.ts": `import { Chart, Values, HelmNotes } from "@intentius/chant-lexicon-helm";
|
|
71
|
+
import { values, Release, include, toYaml, printf } from "@intentius/chant-lexicon-helm/intrinsics";
|
|
72
|
+
import { Deployment, Service } from "@intentius/chant-lexicon-k8s";
|
|
73
|
+
|
|
74
|
+
export const chart = new Chart({
|
|
75
|
+
apiVersion: "v2",
|
|
76
|
+
name: "my-app",
|
|
77
|
+
version: "0.1.0",
|
|
78
|
+
appVersion: "1.0.0",
|
|
79
|
+
type: "application",
|
|
80
|
+
description: "A Helm chart for my application",
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
export const valuesSchema = new Values({
|
|
84
|
+
replicaCount: 1,
|
|
85
|
+
image: {
|
|
86
|
+
repository: "nginx",
|
|
87
|
+
tag: "",
|
|
88
|
+
pullPolicy: "IfNotPresent",
|
|
89
|
+
},
|
|
90
|
+
service: {
|
|
91
|
+
type: "ClusterIP",
|
|
92
|
+
port: 80,
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export const deployment = new Deployment({
|
|
97
|
+
metadata: {
|
|
98
|
+
name: include("my-app.fullname"),
|
|
99
|
+
labels: include("my-app.labels"),
|
|
100
|
+
},
|
|
101
|
+
spec: {
|
|
102
|
+
replicas: values.replicaCount,
|
|
103
|
+
selector: {
|
|
104
|
+
matchLabels: include("my-app.selectorLabels"),
|
|
105
|
+
},
|
|
106
|
+
template: {
|
|
107
|
+
metadata: {
|
|
108
|
+
labels: include("my-app.selectorLabels"),
|
|
109
|
+
},
|
|
110
|
+
spec: {
|
|
111
|
+
containers: [{
|
|
112
|
+
name: "my-app",
|
|
113
|
+
image: printf("%s:%s", values.image.repository, values.image.tag),
|
|
114
|
+
ports: [{ containerPort: values.service.port, name: "http" }],
|
|
115
|
+
}],
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
export const service = new Service({
|
|
122
|
+
metadata: {
|
|
123
|
+
name: include("my-app.fullname"),
|
|
124
|
+
labels: include("my-app.labels"),
|
|
125
|
+
},
|
|
126
|
+
spec: {
|
|
127
|
+
type: values.service.type,
|
|
128
|
+
ports: [{
|
|
129
|
+
port: values.service.port,
|
|
130
|
+
targetPort: "http",
|
|
131
|
+
protocol: "TCP",
|
|
132
|
+
name: "http",
|
|
133
|
+
}],
|
|
134
|
+
selector: include("my-app.selectorLabels"),
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
`,
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
},
|
|
141
|
+
|
|
142
|
+
skills(): SkillDefinition[] {
|
|
143
|
+
const skillsDir = join(dirname(fileURLToPath(import.meta.url)), "skills");
|
|
144
|
+
const skills: SkillDefinition[] = [];
|
|
145
|
+
try {
|
|
146
|
+
for (const file of readdirSync(skillsDir)) {
|
|
147
|
+
if (!file.endsWith(".md")) continue;
|
|
148
|
+
const content = readFileSync(join(skillsDir, file), "utf-8");
|
|
149
|
+
const name = file.replace(/\.md$/, "");
|
|
150
|
+
// Derive a readable description from the filename
|
|
151
|
+
const desc = name.replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
152
|
+
skills.push({ name: `chant-helm-${name}`, description: desc, content });
|
|
153
|
+
}
|
|
154
|
+
} catch {
|
|
155
|
+
// No skills directory
|
|
156
|
+
}
|
|
157
|
+
return skills;
|
|
158
|
+
},
|
|
159
|
+
|
|
160
|
+
async docs(options?: { verbose?: boolean }): Promise<void> {
|
|
161
|
+
const { generateDocs } = await import("./codegen/docs");
|
|
162
|
+
await generateDocs({ verbose: options?.verbose });
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
async generate(options?: { verbose?: boolean }): Promise<void> {
|
|
166
|
+
const { generate, writeGeneratedFiles } = await import("./codegen/generate");
|
|
167
|
+
const { dirname } = await import("path");
|
|
168
|
+
const { fileURLToPath } = await import("url");
|
|
169
|
+
|
|
170
|
+
const result = await generate({ verbose: options?.verbose ?? true });
|
|
171
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
172
|
+
writeGeneratedFiles(result, pkgDir);
|
|
173
|
+
|
|
174
|
+
console.error(`Generated ${result.resources} resources, ${result.properties} property types`);
|
|
175
|
+
},
|
|
176
|
+
|
|
177
|
+
async validate(options?: { verbose?: boolean }): Promise<void> {
|
|
178
|
+
const { validate } = await import("./validate");
|
|
179
|
+
const { printValidationResult } = await import("@intentius/chant/codegen/validate");
|
|
180
|
+
const result = await validate();
|
|
181
|
+
printValidationResult(result);
|
|
182
|
+
},
|
|
183
|
+
|
|
184
|
+
async coverage(options?: { verbose?: boolean; minOverall?: number }): Promise<void> {
|
|
185
|
+
const { analyzeHelmCoverage } = await import("./coverage");
|
|
186
|
+
await analyzeHelmCoverage({
|
|
187
|
+
verbose: options?.verbose,
|
|
188
|
+
minOverall: options?.minOverall,
|
|
189
|
+
});
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
async package(options?: { verbose?: boolean; force?: boolean }): Promise<void> {
|
|
193
|
+
const { packageLexicon } = await import("./codegen/package");
|
|
194
|
+
const { writeBundleSpec } = await import("@intentius/chant/codegen/package");
|
|
195
|
+
const { join, dirname } = await import("path");
|
|
196
|
+
const { fileURLToPath } = await import("url");
|
|
197
|
+
|
|
198
|
+
const { spec, stats } = await packageLexicon({ verbose: options?.verbose, force: options?.force });
|
|
199
|
+
|
|
200
|
+
const pkgDir = dirname(dirname(fileURLToPath(import.meta.url)));
|
|
201
|
+
const distDir = join(pkgDir, "dist");
|
|
202
|
+
writeBundleSpec(spec, distDir);
|
|
203
|
+
|
|
204
|
+
console.error(`Packaged ${stats.resources} resources, ${stats.ruleCount} rules, ${stats.skillCount} skills`);
|
|
205
|
+
},
|
|
206
|
+
};
|
package/src/resources.ts
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helm-specific resource and property types.
|
|
3
|
+
*
|
|
4
|
+
* Created via createResource/createProperty from @intentius/chant/runtime.
|
|
5
|
+
* These are static types (no upstream schema to fetch).
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { createResource, createProperty } from "@intentius/chant/runtime";
|
|
9
|
+
|
|
10
|
+
const LEXICON = "helm";
|
|
11
|
+
|
|
12
|
+
// ── Resources ─────────────────────────────────────────────
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Helm::Chart — Chart.yaml metadata.
|
|
16
|
+
*
|
|
17
|
+
* Defines the chart's identity: apiVersion, name, version, appVersion,
|
|
18
|
+
* description, type (application|library), keywords, maintainers, dependencies.
|
|
19
|
+
*/
|
|
20
|
+
export const Chart = createResource("Helm::Chart", LEXICON, {});
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Helm::Values — Typed values definition.
|
|
24
|
+
*
|
|
25
|
+
* The props passed to the constructor become the default values emitted
|
|
26
|
+
* in values.yaml. The serializer also generates values.schema.json from
|
|
27
|
+
* the value types.
|
|
28
|
+
*/
|
|
29
|
+
export const Values = createResource("Helm::Values", LEXICON, {});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Helm::Test — Helm test pod.
|
|
33
|
+
*
|
|
34
|
+
* Annotated with `helm.sh/hook: test` in the serialized output.
|
|
35
|
+
* Props should contain a K8s Pod spec.
|
|
36
|
+
*/
|
|
37
|
+
export const HelmTest = createResource("Helm::Test", LEXICON, {});
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Helm::Notes — NOTES.txt template content.
|
|
41
|
+
*
|
|
42
|
+
* The `content` prop is emitted as templates/NOTES.txt.
|
|
43
|
+
*/
|
|
44
|
+
export const HelmNotes = createResource("Helm::Notes", LEXICON, {});
|
|
45
|
+
|
|
46
|
+
// ── Property types ────────────────────────────────────────
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Helm::Hook — Lifecycle hook annotation.
|
|
50
|
+
*
|
|
51
|
+
* Wraps a K8s resource with helm.sh/hook annotations.
|
|
52
|
+
* Props: { hook: string, weight?: number, deletePolicy?: string, resource: Declarable }
|
|
53
|
+
*/
|
|
54
|
+
export const HelmHook = createProperty("Helm::Hook", LEXICON);
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Helm::Dependency — Chart dependency entry.
|
|
58
|
+
*
|
|
59
|
+
* Props: { name, version, repository, condition?, tags?, enabled?, importValues?, alias? }
|
|
60
|
+
*/
|
|
61
|
+
export const HelmDependency = createProperty("Helm::Dependency", LEXICON);
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Helm::Maintainer — Chart maintainer entry.
|
|
65
|
+
*
|
|
66
|
+
* Props: { name, email?, url? }
|
|
67
|
+
*/
|
|
68
|
+
export const HelmMaintainer = createProperty("Helm::Maintainer", LEXICON);
|
|
69
|
+
|
|
70
|
+
// ── CRD ──────────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Helm::CRD — Custom Resource Definition placed in the crds/ directory.
|
|
74
|
+
*
|
|
75
|
+
* Props: { content: string, filename?: string }
|
|
76
|
+
*/
|
|
77
|
+
export const HelmCRD = createResource("Helm::CRD", LEXICON, {});
|