@intentius/chant-lexicon-helm 0.0.22 → 0.1.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/integrity.json +7 -5
- package/dist/manifest.json +1 -1
- package/dist/rules/values-no-helm-tpl.ts +92 -0
- package/dist/rules/whm005-no-empty-wrapper.ts +54 -0
- package/dist/skills/{chant-helm-chart-patterns.md → chant-helm-patterns.md} +52 -0
- package/dist/skills/chant-helm.md +496 -0
- package/package.json +6 -3
- package/src/codegen/docs.ts +3 -2
- package/src/composites/composites.test.ts +116 -110
- package/src/composites/helm-batch-job.ts +33 -19
- package/src/composites/helm-crd-lifecycle.ts +37 -24
- package/src/composites/helm-cron-job.ts +25 -13
- package/src/composites/helm-daemon-set.ts +26 -14
- package/src/composites/helm-external-secret.ts +21 -12
- package/src/composites/helm-library.ts +21 -7
- package/src/composites/helm-microservice.ts +46 -29
- package/src/composites/helm-monitored-service.ts +75 -51
- package/src/composites/helm-namespace-env.ts +80 -52
- package/src/composites/helm-secure-ingress.ts +66 -50
- package/src/composites/helm-stateful-service.ts +29 -16
- package/src/composites/helm-web-app.ts +37 -22
- package/src/composites/helm-worker.ts +34 -20
- package/src/index.ts +4 -1
- package/src/intrinsics.ts +53 -0
- package/src/lint/post-synth/post-synth.test.ts +43 -0
- package/src/lint/post-synth/whm005-no-empty-wrapper.ts +54 -0
- package/src/lint/rules/lint-rules.test.ts +35 -0
- package/src/lint/rules/values-no-helm-tpl.ts +92 -0
- package/src/plugin.test.ts +7 -5
- package/src/plugin.ts +8 -42
- package/src/resources.ts +49 -0
- package/src/serializer.test.ts +113 -2
- package/src/serializer.ts +149 -13
- package/src/skills/{chart-patterns.md → chant-helm-patterns.md} +52 -0
- package/src/skills/chant-helm.md +496 -0
- package/dist/skills/chant-helm-create-chart.md +0 -211
- package/src/skills/create-chart.md +0 -211
- /package/dist/skills/{chant-helm-chart-security-patterns.md → chant-helm-security.md} +0 -0
- /package/src/skills/{chart-security-patterns.md → chant-helm-security.md} +0 -0
package/dist/integrity.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "xxhash64",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "8230c04a29b03431",
|
|
5
5
|
"meta.json": "b7aab243e162dfaf",
|
|
6
6
|
"types/index.d.ts": "e8011da51963f058",
|
|
7
7
|
"rules/no-hardcoded-image.ts": "c75aa9c33016c3b9",
|
|
8
8
|
"rules/values-no-secrets.ts": "213276bfe1fb8ff7",
|
|
9
|
+
"rules/values-no-helm-tpl.ts": "ed23236546936fd0",
|
|
9
10
|
"rules/chart-metadata.ts": "d0cff2b78fed78d3",
|
|
10
11
|
"rules/whm103.ts": "a777a13f2eaf1831",
|
|
11
12
|
"rules/whm104.ts": "e2d644da2a9dc605",
|
|
@@ -25,12 +26,13 @@
|
|
|
25
26
|
"rules/whm401.ts": "fe72c3c450a12f93",
|
|
26
27
|
"rules/whm105.ts": "8977ec834713b90c",
|
|
27
28
|
"rules/whm403.ts": "729d10edb48b0d03",
|
|
29
|
+
"rules/whm005-no-empty-wrapper.ts": "1a1baea985f0bd86",
|
|
28
30
|
"rules/whm405.ts": "ec82442f9120e5e0",
|
|
29
31
|
"rules/whm202.ts": "dbe1cbb3237be84f",
|
|
30
32
|
"rules/whm501.ts": "e9a9f2b4e034a51f",
|
|
31
|
-
"skills/chant-helm
|
|
32
|
-
"skills/chant-helm-
|
|
33
|
-
"skills/chant-helm-
|
|
33
|
+
"skills/chant-helm.md": "6476c552b9235085",
|
|
34
|
+
"skills/chant-helm-patterns.md": "cc9bfe5595f22710",
|
|
35
|
+
"skills/chant-helm-security.md": "a7b950513dac7d37"
|
|
34
36
|
},
|
|
35
|
-
"composite": "
|
|
37
|
+
"composite": "8872cd0d6c961e4d"
|
|
36
38
|
}
|
package/dist/manifest.json
CHANGED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHM004: HelmTpl Expression Has No Effect in Values Constructor
|
|
3
|
+
*
|
|
4
|
+
* Detects Values constructor props that use `v.xxx` (the `values` proxy)
|
|
5
|
+
* or any HelmTpl-like expression. values.yaml is static YAML — it is NOT
|
|
6
|
+
* processed as a Go template by Helm. These expressions silently become ''.
|
|
7
|
+
*
|
|
8
|
+
* Bad: new Values({ host: v.pgHost })
|
|
9
|
+
* Good: new Values({ host: runtimeSlot("Cloud SQL private IP") })
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { LintRule, LintDiagnostic, LintContext } from "@intentius/chant/lint/rule";
|
|
13
|
+
import * as ts from "typescript";
|
|
14
|
+
|
|
15
|
+
export const valuesNoHelmTplRule: LintRule = {
|
|
16
|
+
id: "WHM004",
|
|
17
|
+
severity: "warning",
|
|
18
|
+
category: "correctness",
|
|
19
|
+
description:
|
|
20
|
+
"HelmTpl expression has no effect in values.yaml — use runtimeSlot() for deploy-time values",
|
|
21
|
+
|
|
22
|
+
check(context: LintContext): LintDiagnostic[] {
|
|
23
|
+
const { sourceFile } = context;
|
|
24
|
+
const diagnostics: LintDiagnostic[] = [];
|
|
25
|
+
|
|
26
|
+
function visit(node: ts.Node): void {
|
|
27
|
+
if (
|
|
28
|
+
ts.isNewExpression(node) &&
|
|
29
|
+
ts.isIdentifier(node.expression) &&
|
|
30
|
+
node.expression.text === "Values" &&
|
|
31
|
+
node.arguments &&
|
|
32
|
+
node.arguments.length > 0
|
|
33
|
+
) {
|
|
34
|
+
const arg = node.arguments[0];
|
|
35
|
+
if (ts.isObjectLiteralExpression(arg)) {
|
|
36
|
+
checkObjectLiteral(arg, [], sourceFile, diagnostics);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
ts.forEachChild(node, visit);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
visit(sourceFile);
|
|
43
|
+
return diagnostics;
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Get the root identifier name of a property access / call chain.
|
|
49
|
+
* v.foo → "v"; values.x.pipe("fn") → "values"; runtimeSlot() → "runtimeSlot"
|
|
50
|
+
*/
|
|
51
|
+
function getRootIdentifier(node: ts.Node): string | null {
|
|
52
|
+
if (ts.isIdentifier(node)) return node.text;
|
|
53
|
+
if (ts.isPropertyAccessExpression(node)) return getRootIdentifier(node.expression);
|
|
54
|
+
if (ts.isCallExpression(node)) return getRootIdentifier(node.expression);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function isHelmTplExpr(node: ts.Node): boolean {
|
|
59
|
+
const root = getRootIdentifier(node);
|
|
60
|
+
return root === "v" || root === "values";
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function checkObjectLiteral(
|
|
64
|
+
obj: ts.ObjectLiteralExpression,
|
|
65
|
+
path: string[],
|
|
66
|
+
sourceFile: ts.SourceFile,
|
|
67
|
+
diagnostics: LintDiagnostic[],
|
|
68
|
+
): void {
|
|
69
|
+
for (const prop of obj.properties) {
|
|
70
|
+
if (!ts.isPropertyAssignment(prop)) continue;
|
|
71
|
+
|
|
72
|
+
const keyName = ts.isIdentifier(prop.name) || ts.isStringLiteral(prop.name)
|
|
73
|
+
? prop.name.text
|
|
74
|
+
: undefined;
|
|
75
|
+
const propPath = keyName ? [...path, keyName] : path;
|
|
76
|
+
|
|
77
|
+
if (isHelmTplExpr(prop.initializer)) {
|
|
78
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(prop.getStart());
|
|
79
|
+
const pathStr = propPath.join(".");
|
|
80
|
+
diagnostics.push({
|
|
81
|
+
file: sourceFile.fileName,
|
|
82
|
+
line: line + 1,
|
|
83
|
+
column: character + 1,
|
|
84
|
+
ruleId: "WHM004",
|
|
85
|
+
severity: "warning",
|
|
86
|
+
message: `HelmTpl expression has no effect in values.yaml (values.yaml is not a Go template). Use runtimeSlot() for deploy-time values or a static default.${pathStr ? ` (path: ${pathStr})` : ""}`,
|
|
87
|
+
});
|
|
88
|
+
} else if (ts.isObjectLiteralExpression(prop.initializer)) {
|
|
89
|
+
checkObjectLiteral(prop.initializer, propPath, sourceFile, diagnostics);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WHM005: Chart Has Sub-chart Dependencies But Generates No Templates
|
|
3
|
+
*
|
|
4
|
+
* A chart with HelmDependency entries but no templates/*.yaml files generates
|
|
5
|
+
* an empty templates/ directory. Deploying it requires `helm dependency build`
|
|
6
|
+
* as a non-obvious prerequisite.
|
|
7
|
+
*
|
|
8
|
+
* If you only need value overrides for an upstream chart, deploy it directly:
|
|
9
|
+
* helm upgrade upstream-chart -f values-override.yaml
|
|
10
|
+
* and use ValuesOverride to generate the override file.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { PostSynthCheck, PostSynthContext, PostSynthDiagnostic } from "@intentius/chant/lint/post-synth";
|
|
14
|
+
import { getChartFiles } from "./helm-helpers";
|
|
15
|
+
|
|
16
|
+
export const whm005: PostSynthCheck = {
|
|
17
|
+
id: "WHM005",
|
|
18
|
+
description:
|
|
19
|
+
"Chart with sub-chart dependencies but no templates should deploy upstream chart directly",
|
|
20
|
+
|
|
21
|
+
check(ctx: PostSynthContext): PostSynthDiagnostic[] {
|
|
22
|
+
const diagnostics: PostSynthDiagnostic[] = [];
|
|
23
|
+
|
|
24
|
+
for (const [, output] of ctx.outputs) {
|
|
25
|
+
const files = getChartFiles(output);
|
|
26
|
+
const chartYaml = files["Chart.yaml"];
|
|
27
|
+
if (!chartYaml) continue;
|
|
28
|
+
|
|
29
|
+
// Check for non-empty dependencies block
|
|
30
|
+
const hasDependencies = /^dependencies:/m.test(chartYaml);
|
|
31
|
+
if (!hasDependencies) continue;
|
|
32
|
+
|
|
33
|
+
// Check for template files (excluding _helpers.tpl and NOTES.txt)
|
|
34
|
+
const hasTemplates = Object.keys(files).some((path) => {
|
|
35
|
+
if (!path.startsWith("templates/")) return false;
|
|
36
|
+
const filename = path.slice("templates/".length);
|
|
37
|
+
if (filename === "_helpers.tpl" || filename === "NOTES.txt") return false;
|
|
38
|
+
return filename.endsWith(".yaml") || filename.endsWith(".yml");
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
if (!hasTemplates) {
|
|
42
|
+
diagnostics.push({
|
|
43
|
+
checkId: "WHM005",
|
|
44
|
+
severity: "warning",
|
|
45
|
+
message:
|
|
46
|
+
"Chart has sub-chart dependencies but generates no templates. Deploying this chart requires 'helm dependency build' first. If you only need value overrides for an upstream chart, deploy it directly with 'helm upgrade upstream-chart -f values-override.yaml' and use ValuesOverride to generate the override file.",
|
|
47
|
+
lexicon: "helm",
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return diagnostics;
|
|
53
|
+
},
|
|
54
|
+
};
|
|
@@ -215,6 +215,58 @@ ChartRef.Name // {{ .Chart.Name }}
|
|
|
215
215
|
ChartRef.Version // {{ .Chart.Version }}
|
|
216
216
|
```
|
|
217
217
|
|
|
218
|
+
## Deploying Upstream Charts with Value Overrides
|
|
219
|
+
|
|
220
|
+
When you need to deploy an upstream chart (like `gitlab/gitlab`) with custom values, avoid wrapper charts with no templates. Instead:
|
|
221
|
+
|
|
222
|
+
1. Use `runtimeSlot()` in `new Values({...})` for deploy-time values (DB IPs, bucket names, replicas)
|
|
223
|
+
2. Use `ValuesOverride` for static values shared across all environments (disabled bundled services, shared secret refs)
|
|
224
|
+
3. Deploy the upstream chart directly with `-f` flags
|
|
225
|
+
|
|
226
|
+
```typescript
|
|
227
|
+
import { Values, ValuesOverride, runtimeSlot } from "@intentius/chant-lexicon-helm";
|
|
228
|
+
|
|
229
|
+
// Runtime slots → values-runtime-slots.yaml (deploy-time checklist)
|
|
230
|
+
export const vals = new Values({
|
|
231
|
+
global: {
|
|
232
|
+
psql: { host: runtimeSlot("Cloud SQL private IP") },
|
|
233
|
+
redis: { host: runtimeSlot("Memorystore host") },
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// Static overrides → values-base.yaml (shared across all deployments)
|
|
238
|
+
export const baseOverride = new ValuesOverride({
|
|
239
|
+
filename: "values-base",
|
|
240
|
+
values: {
|
|
241
|
+
postgresql: { install: false },
|
|
242
|
+
redis: { install: false },
|
|
243
|
+
certmanager: { install: false },
|
|
244
|
+
"nginx-ingress": { enabled: false },
|
|
245
|
+
},
|
|
246
|
+
});
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Outputs:
|
|
250
|
+
- `chart-dir/values.yaml` — defaults; runtime slots appear as `''`
|
|
251
|
+
- `chart-dir/values-base.yaml` — generated static overrides
|
|
252
|
+
- `chart-dir/values-runtime-slots.yaml` — deploy-time slots with descriptions as comments
|
|
253
|
+
|
|
254
|
+
Deploy:
|
|
255
|
+
```bash
|
|
256
|
+
# chant build generates chart-dir/ including values-base.yaml
|
|
257
|
+
chant build
|
|
258
|
+
|
|
259
|
+
# Fill in runtime-slot values (one per environment)
|
|
260
|
+
# values-prod.yaml contains: global.psql.host, global.redis.host, etc.
|
|
261
|
+
|
|
262
|
+
helm upgrade --install my-release upstream/chart \
|
|
263
|
+
-f chart-dir/values-base.yaml \
|
|
264
|
+
-f values-prod.yaml \
|
|
265
|
+
--wait
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
**WHM005** warns when a chart has `HelmDependency` entries but generates no templates — this is the "empty wrapper" anti-pattern that requires `helm dependency build` as a non-obvious prerequisite.
|
|
269
|
+
|
|
218
270
|
## Template Functions
|
|
219
271
|
|
|
220
272
|
```typescript
|