@intentius/chant-lexicon-helm 0.46.0 → 0.50.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/archive-render.d.ts +94 -0
- package/dist/archive-render.d.ts.map +1 -0
- package/dist/commands.d.ts +54 -0
- package/dist/commands.d.ts.map +1 -0
- package/dist/config.d.ts +135 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/deep-observe-hooks.d.ts +2 -0
- package/dist/deep-observe-hooks.d.ts.map +1 -0
- package/dist/deep-observe.d.ts +54 -0
- package/dist/deep-observe.d.ts.map +1 -0
- package/dist/describe-resources.d.ts +17 -0
- package/dist/describe-resources.d.ts.map +1 -0
- package/dist/index.d.ts +19 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +5 -3
- package/dist/lint/audit-catalog.d.ts.map +1 -1
- package/dist/lint/post-synth/index.d.ts.map +1 -1
- package/dist/lint/post-synth/whm503.d.ts +34 -0
- package/dist/lint/post-synth/whm503.d.ts.map +1 -0
- package/dist/lint/post-synth/whm504.d.ts +20 -0
- package/dist/lint/post-synth/whm504.d.ts.map +1 -0
- package/dist/manifest.json +25 -13
- package/dist/okf/index.md +2 -0
- package/dist/okf/rules/WHM503.md +15 -0
- package/dist/okf/rules/WHM504.md +11 -0
- package/dist/okf/types/Values.md +1 -0
- package/dist/op/activities/cluster-probe.d.ts +44 -0
- package/dist/op/activities/cluster-probe.d.ts.map +1 -0
- package/dist/op/activities/helm.d.ts +179 -5
- package/dist/op/activities/helm.d.ts.map +1 -1
- package/dist/op/activities/index.d.ts +4 -2
- package/dist/op/activities/index.d.ts.map +1 -1
- package/dist/op/builders.d.ts +47 -0
- package/dist/op/builders.d.ts.map +1 -0
- package/dist/pinnability/actions.d.ts +76 -0
- package/dist/pinnability/actions.d.ts.map +1 -0
- package/dist/pinnability/classify.d.ts +129 -0
- package/dist/pinnability/classify.d.ts.map +1 -0
- package/dist/pinnability/conditions.d.ts +109 -0
- package/dist/pinnability/conditions.d.ts.map +1 -0
- package/dist/pinnability/index.d.ts +17 -0
- package/dist/pinnability/index.d.ts.map +1 -0
- package/dist/pinnability/localize.d.ts +124 -0
- package/dist/pinnability/localize.d.ts.map +1 -0
- package/dist/pinnability/render-stream.d.ts +27 -0
- package/dist/pinnability/render-stream.d.ts.map +1 -0
- package/dist/pinnability/values.d.ts +69 -0
- package/dist/pinnability/values.d.ts.map +1 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/release-observe.d.ts +109 -0
- package/dist/release-observe.d.ts.map +1 -0
- package/dist/render-diff.d.ts +192 -0
- package/dist/render-diff.d.ts.map +1 -0
- package/dist/render-digest.d.ts +135 -0
- package/dist/render-digest.d.ts.map +1 -0
- package/dist/render-store.d.ts +310 -0
- package/dist/render-store.d.ts.map +1 -0
- package/dist/render-wrapper.d.ts +140 -0
- package/dist/render-wrapper.d.ts.map +1 -0
- package/dist/render.d.ts +81 -0
- package/dist/render.d.ts.map +1 -1
- package/dist/rules/whm503.ts +101 -0
- package/dist/rules/whm504.ts +52 -0
- package/dist/skills/chant-helm.md +7 -0
- package/dist/values-probe.d.ts +177 -0
- package/dist/values-probe.d.ts.map +1 -0
- package/dist/wrapper-chart.d.ts +61 -0
- package/dist/wrapper-chart.d.ts.map +1 -0
- package/package.json +10 -4
- package/src/archive-render.test.ts +201 -0
- package/src/archive-render.ts +119 -0
- package/src/commands.test.ts +487 -0
- package/src/commands.ts +445 -0
- package/src/config.test.ts +130 -0
- package/src/config.ts +220 -0
- package/src/deep-observe-hooks.ts +20 -0
- package/src/deep-observe.test.ts +165 -0
- package/src/deep-observe.ts +121 -0
- package/src/describe-resources.test.ts +255 -0
- package/src/describe-resources.ts +198 -0
- package/src/index.ts +106 -2
- package/src/lifecycle-integration.test.ts +289 -0
- package/src/lint/audit-catalog.ts +2 -0
- package/src/lint/post-synth/index.ts +4 -0
- package/src/lint/post-synth/whm503.test.ts +134 -0
- package/src/lint/post-synth/whm503.ts +101 -0
- package/src/lint/post-synth/whm504.test.ts +105 -0
- package/src/lint/post-synth/whm504.ts +52 -0
- package/src/op/activities/cluster-probe.test.ts +66 -0
- package/src/op/activities/cluster-probe.ts +148 -0
- package/src/op/activities/helm.test.ts +824 -0
- package/src/op/activities/helm.ts +628 -5
- package/src/op/activities/index.ts +17 -2
- package/src/op/builders.test.ts +70 -0
- package/src/op/builders.ts +66 -0
- package/src/pinnability/actions.ts +263 -0
- package/src/pinnability/classify.ts +579 -0
- package/src/pinnability/conditions.ts +0 -0
- package/src/pinnability/index.ts +77 -0
- package/src/pinnability/localize.test.ts +234 -0
- package/src/pinnability/localize.ts +644 -0
- package/src/pinnability/pinnability.test.ts +560 -0
- package/src/pinnability/render-stream.ts +59 -0
- package/src/pinnability/values.ts +205 -0
- package/src/plugin.test.ts +3 -1
- package/src/plugin.ts +97 -12
- package/src/release-observe.ts +392 -0
- package/src/render-diff.test.ts +366 -0
- package/src/render-diff.ts +407 -0
- package/src/render-digest.test.ts +186 -0
- package/src/render-digest.ts +207 -0
- package/src/render-store.test.ts +412 -0
- package/src/render-store.ts +621 -0
- package/src/render-wrapper.test.ts +259 -0
- package/src/render-wrapper.ts +274 -0
- package/src/render.test.ts +383 -4
- package/src/render.ts +319 -8
- package/src/skills/chant-helm.md +7 -0
- package/src/values-probe.test.ts +400 -0
- package/src/values-probe.ts +627 -0
- package/src/wrapper-chart.test.ts +110 -0
- package/src/wrapper-chart.ts +124 -0
package/dist/okf/index.md
CHANGED
|
@@ -37,3 +37,5 @@ okf_version: '0.2'
|
|
|
37
37
|
* [WHM407](/rules/WHM407.md) - Secrets with inline data should use ExternalSecret or SealedSecret
|
|
38
38
|
* [WHM501](/rules/WHM501.md) - Detect values keys that are defined but never referenced in templates
|
|
39
39
|
* [WHM502](/rules/WHM502.md) - Detect deprecated or invalid Kubernetes API versions
|
|
40
|
+
* [WHM503](/rules/WHM503.md) - Pinned render artifact must not carry populated Secret data/stringData
|
|
41
|
+
* [WHM504](/rules/WHM504.md) - Detect supplied values that never survive coalescing (shadowed, disabled subchart, unknown subchart)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: post-synth-check
|
|
3
|
+
title: WHM503
|
|
4
|
+
description: Pinned render artifact must not carry populated Secret data/stringData
|
|
5
|
+
id: WHM503
|
|
6
|
+
severity: error
|
|
7
|
+
category: post-synth
|
|
8
|
+
lexicon: helm
|
|
9
|
+
docs: https://intentius.io/chant/lexicons/helm/rules/
|
|
10
|
+
---
|
|
11
|
+
Pinned render artifact must not carry populated Secret data/stringData
|
|
12
|
+
|
|
13
|
+
## Applies to
|
|
14
|
+
|
|
15
|
+
- [Values](/types/Values.md)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: post-synth-check
|
|
3
|
+
title: WHM504
|
|
4
|
+
description: Detect supplied values that never survive coalescing (shadowed, disabled subchart, unknown subchart)
|
|
5
|
+
id: WHM504
|
|
6
|
+
severity: error
|
|
7
|
+
category: post-synth
|
|
8
|
+
lexicon: helm
|
|
9
|
+
docs: https://intentius.io/chant/lexicons/helm/rules/
|
|
10
|
+
---
|
|
11
|
+
Detect supplied values that never survive coalescing (shadowed, disabled subchart, unknown subchart)
|
package/dist/okf/types/Values.md
CHANGED
|
@@ -22,3 +22,4 @@ Typed values definition — emits values.yaml and values.schema.json.
|
|
|
22
22
|
- [WHM405](/rules/WHM405.md): Resource specs should include cpu and memory in limits/requests
|
|
23
23
|
- [WHM407](/rules/WHM407.md): Secrets with inline data should use ExternalSecret or SealedSecret
|
|
24
24
|
- [WHM501](/rules/WHM501.md): Detect values keys that are defined but never referenced in templates
|
|
25
|
+
- [WHM503](/rules/WHM503.md): Pinned render artifact must not carry populated Secret data/stringData
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/** What the probe read off the live cluster. */
|
|
2
|
+
export interface LiveClusterCapabilities {
|
|
3
|
+
/** The server's full version string (`serverVersion.gitVersion`), e.g. `v1.33.6+k3s1`. */
|
|
4
|
+
kubeVersion: string;
|
|
5
|
+
/** The server's `major.minor`, e.g. `1.33`, parsed from `serverVersion.major`/`minor` (or `gitVersion` when those are absent). */
|
|
6
|
+
majorMinor: string;
|
|
7
|
+
/** Every API version the cluster serves, one `group/version` (or `v1`) per entry, from `kubectl api-versions`. */
|
|
8
|
+
apiVersions: string[];
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Thrown when the cluster's capabilities cannot be read at all — kubectl
|
|
12
|
+
* missing, cluster unreachable, or unparseable output. A deploy that
|
|
13
|
+
* declared a profile cannot verify its guarantee through this error, so the
|
|
14
|
+
* caller must refuse to proceed rather than deploy blind.
|
|
15
|
+
*/
|
|
16
|
+
export declare class ClusterProbeError extends Error {
|
|
17
|
+
constructor(message: string);
|
|
18
|
+
}
|
|
19
|
+
/** `major.minor` from a declared or live version string (`1.33`, `1.33.6`, `v1.33.6+k3s1`). Undefined when the string has no parseable major.minor. */
|
|
20
|
+
export declare function majorMinorOf(version: string): string | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Read the target cluster's capabilities. Uses whatever kubeconfig/context
|
|
23
|
+
* the process environment provides — the same ambient target `helm upgrade`
|
|
24
|
+
* itself will act on, so the probe and the deploy see one cluster.
|
|
25
|
+
*/
|
|
26
|
+
export declare function probeClusterCapabilities(signal?: AbortSignal): Promise<LiveClusterCapabilities>;
|
|
27
|
+
/** The declared facts a profile asserts about a cluster — the activity-side profile shape. */
|
|
28
|
+
export interface DeclaredCapabilityProfile {
|
|
29
|
+
name?: string;
|
|
30
|
+
kubeVersion?: string;
|
|
31
|
+
apiVersions?: string[];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Every way `live` diverges from what `profile` declares, one message per
|
|
35
|
+
* divergence, each naming the declared and the live value. Empty when the
|
|
36
|
+
* cluster matches the profile.
|
|
37
|
+
*
|
|
38
|
+
* kubeVersion compares on major.minor (see module doc). apiVersions is a
|
|
39
|
+
* subset check: everything the profile declares must be served; extra API
|
|
40
|
+
* versions on the cluster are not a divergence, since a render only ever
|
|
41
|
+
* probed the declared set.
|
|
42
|
+
*/
|
|
43
|
+
export declare function compareCapabilityProfile(profile: DeclaredCapabilityProfile, live: LiveClusterCapabilities): string[];
|
|
44
|
+
//# sourceMappingURL=cluster-probe.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cluster-probe.d.ts","sourceRoot":"","sources":["../../../src/op/activities/cluster-probe.ts"],"names":[],"mappings":"AAyBA,gDAAgD;AAChD,MAAM,WAAW,uBAAuB;IACtC,0FAA0F;IAC1F,WAAW,EAAE,MAAM,CAAC;IACpB,kIAAkI;IAClI,UAAU,EAAE,MAAM,CAAC;IACnB,kHAAkH;IAClH,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED;;;;;GAKG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,OAAO,EAAE,MAAM;CAI5B;AAED,uJAAuJ;AACvJ,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAGhE;AA6BD;;;;GAIG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAqBrG;AAED,8FAA8F;AAC9F,MAAM,WAAW,yBAAyB;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,yBAAyB,EAClC,IAAI,EAAE,uBAAuB,GAC5B,MAAM,EAAE,CAkBV"}
|
|
@@ -1,18 +1,192 @@
|
|
|
1
|
+
import { type AutoReleaseResult } from "@intentius/chant/components/auto-release";
|
|
2
|
+
/**
|
|
3
|
+
* The cluster capability profile a deploy is declared against (epic #1228).
|
|
4
|
+
* Declared, never sniffed — the epic's finding 1 shows the default kube
|
|
5
|
+
* version is a property of the helm binary, so an undeclared profile cannot
|
|
6
|
+
* be part of a stable identity. When declared it joins the input digest.
|
|
7
|
+
*/
|
|
8
|
+
export interface HelmCapabilityProfile {
|
|
9
|
+
/** The profile's declared name (its `helm.capabilityProfiles` key), used in assertion messages. Not part of the digest — only the declared facts are. */
|
|
10
|
+
name?: string;
|
|
11
|
+
/** Kubernetes version the render targets (`--kube-version`). */
|
|
12
|
+
kubeVersion?: string;
|
|
13
|
+
/** Extra API versions the render assumes (`--api-versions`). Order-insensitive for the digest. */
|
|
14
|
+
apiVersions?: string[];
|
|
15
|
+
}
|
|
1
16
|
export interface HelmInstallArgs {
|
|
2
17
|
/** Helm release name. */
|
|
3
18
|
name: string;
|
|
4
|
-
/**
|
|
5
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Chart reference (local path or `repo/chart`). Required for an unpinned
|
|
21
|
+
* deploy; refused alongside `contentDigest` — a pinned deploy's bytes come
|
|
22
|
+
* from the render store, never from a deploy-time render.
|
|
23
|
+
*/
|
|
24
|
+
chart?: string;
|
|
25
|
+
/**
|
|
26
|
+
* `sha256:` content digest of a stored pinned render (#1242). When set,
|
|
27
|
+
* the deploy takes the pinned path: the recorded render is loaded from the
|
|
28
|
+
* render store, its digest verified, and those exact bytes installed as a
|
|
29
|
+
* structure-preserving wrapper chart — no deploy-time render. The chart /
|
|
30
|
+
* values / set / chartVersion render inputs are refused in this mode.
|
|
31
|
+
*/
|
|
32
|
+
contentDigest?: string;
|
|
33
|
+
/** Render store root override for the pinned path (tests, non-default stores). Defaults to `CHANT_HELM_RENDER_ROOT` / `~/.chant/helm-renders`. */
|
|
34
|
+
renderStoreRoot?: string;
|
|
35
|
+
/** Chart version to pin (`--version`). Part of the input digest. */
|
|
36
|
+
chartVersion?: string;
|
|
6
37
|
/** Path to a values file. */
|
|
7
38
|
values?: string;
|
|
8
|
-
/** Kubernetes namespace. */
|
|
39
|
+
/** Kubernetes namespace. Defaults to the stored render's namespace on the pinned path. */
|
|
9
40
|
namespace?: string;
|
|
10
41
|
/** Additional --set arguments. */
|
|
11
42
|
set?: Record<string, string>;
|
|
43
|
+
/** Capability profile the deploy is declared against, if any. Part of the input digest when declared, and asserted against the live target cluster before any helm mutation (#1244). */
|
|
44
|
+
capabilityProfile?: HelmCapabilityProfile;
|
|
45
|
+
/**
|
|
46
|
+
* Deliberate escape hatch for the capability-profile assertion (#1244).
|
|
47
|
+
* When the live cluster diverges from the declared profile — or cannot be
|
|
48
|
+
* probed at all — the deploy normally refuses before any helm mutation.
|
|
49
|
+
* Set `true` to deploy anyway; the bypassed divergences are warned about
|
|
50
|
+
* and recorded in the release record (`profileOverride`), so the ledger
|
|
51
|
+
* shows the release knowingly skewed from its declared profile. Has no
|
|
52
|
+
* effect when the cluster matches, and none when no profile is declared.
|
|
53
|
+
*/
|
|
54
|
+
overrideProfileAssertion?: boolean;
|
|
55
|
+
/** Component name for the release record. Defaults to the release `name` — a chart's release is its deploy unit. */
|
|
56
|
+
component?: string;
|
|
57
|
+
/** Environment for the release record. Defaults to `"local"`, the same default `chant run --components` applies. */
|
|
58
|
+
env?: string;
|
|
59
|
+
/** Run id for the release record. Defaults to `$GITHUB_RUN_ID`/`$CI_PIPELINE_ID`, then a locally generated id — the same fallback chain `chant components release` uses. */
|
|
60
|
+
runId?: string;
|
|
61
|
+
/** Set `false` to skip release-record emission, mirroring `--no-release-record`. Default: emission is ON. */
|
|
62
|
+
recordRelease?: boolean;
|
|
63
|
+
}
|
|
64
|
+
/** What `helmInstall` returns: the input digest and the release-record outcome, so a workflow can carry both. */
|
|
65
|
+
export interface HelmInstallResult {
|
|
66
|
+
/**
|
|
67
|
+
* `sha256:` digest over the deploy's *inputs* — chart, chart version,
|
|
68
|
+
* resolved values, capability profile if declared (#1243). This is the
|
|
69
|
+
* input-side join key: two environments deploying the same chart at the
|
|
70
|
+
* same version with the same values share it even when their clusters
|
|
71
|
+
* legitimately differ. It is deliberately not a rendered-output digest —
|
|
72
|
+
* that is the pinned-render work of later #1228 phases. Absent only when
|
|
73
|
+
* the digest could not be computed (see `release.reason`).
|
|
74
|
+
*/
|
|
75
|
+
inputDigest?: string;
|
|
76
|
+
/** Outcome of the ledger append — `recorded: true` carries the `ReleaseRecord` written. */
|
|
77
|
+
release: AutoReleaseResult;
|
|
78
|
+
/**
|
|
79
|
+
* Outcome of the deploy-time capability-profile assertion (#1244). Present
|
|
80
|
+
* exactly when the deploy declared a profile with assertable facts (on the
|
|
81
|
+
* pinned path the stored render's profile always is one). A mismatch
|
|
82
|
+
* without the override never reaches a result — the activity throws before
|
|
83
|
+
* any helm mutation — so a present outcome is either a verified match or a
|
|
84
|
+
* deliberate, recorded override.
|
|
85
|
+
*/
|
|
86
|
+
profileAssertion?: HelmProfileAssertionOutcome;
|
|
87
|
+
/** Helm release name the deploy targeted (`args.name`). */
|
|
88
|
+
releaseName: string;
|
|
89
|
+
/** Namespace the deploy targeted, or `null` when helm's default applied. */
|
|
90
|
+
namespace: string | null;
|
|
91
|
+
/**
|
|
92
|
+
* True when this deploy took the pinned path (#1242): recorded bytes
|
|
93
|
+
* loaded from the render store, digest-verified, installed as a wrapper
|
|
94
|
+
* chart with no deploy-time render.
|
|
95
|
+
*/
|
|
96
|
+
pinned: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* `sha256:` content digest of the installed render — the artifact identity
|
|
99
|
+
* (the epic's `renderDigest`, named for the #1237 split). Pinned path only:
|
|
100
|
+
* an unpinned deploy has no rendered-output identity to report.
|
|
101
|
+
*/
|
|
102
|
+
contentDigest?: string;
|
|
103
|
+
/**
|
|
104
|
+
* Release revision after the deploy, from `helm get metadata -o json`.
|
|
105
|
+
* Pinned path only, and absent when the metadata read failed after a
|
|
106
|
+
* successful install (best-effort, like the ledger append).
|
|
107
|
+
*/
|
|
108
|
+
revision?: number;
|
|
109
|
+
/** Chart version installed — `helm get metadata`'s `version`, falling back to the stored render's. Pinned path only. */
|
|
110
|
+
chartVersion?: string | null;
|
|
111
|
+
/** Number of CRD documents shipped in the wrapper's `crds/` (uninstall-safe; epic finding 4). Pinned path only. */
|
|
112
|
+
crdsApplied?: number;
|
|
113
|
+
/** Number of non-CRD documents installed through the wrapper's templates (hook documents included). Pinned path only. */
|
|
114
|
+
docsApplied?: number;
|
|
115
|
+
/** Number of hook documents among `docsApplied` — helm registers and runs them from their recorded annotations (epic finding 5). Pinned path only. */
|
|
116
|
+
hooksRun?: number;
|
|
12
117
|
}
|
|
118
|
+
/** Thrown by the pinned path (#1242) when `contentDigest` resolves to nothing in the render store. */
|
|
119
|
+
export declare class PinnedRenderNotFoundError extends Error {
|
|
120
|
+
constructor(contentDigest: string, root: string);
|
|
121
|
+
}
|
|
122
|
+
/** Thrown by the pinned path (#1242) when the stored bytes no longer hash to their digest — store corruption, caught before any mutation. */
|
|
123
|
+
export declare class PinnedRenderIntegrityError extends Error {
|
|
124
|
+
constructor(contentDigest: string, actual: string);
|
|
125
|
+
}
|
|
126
|
+
/** Thrown by the pinned path (#1242) when the call mixes pinned and unpinned inputs, or targets a release name the bytes were not rendered for. */
|
|
127
|
+
export declare class PinnedInstallInputError extends Error {
|
|
128
|
+
constructor(message: string);
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Thrown by the pinned path (#1242) when the deploy's declared capability
|
|
132
|
+
* profile disagrees with the profile recorded in the stored render's
|
|
133
|
+
* manifest. Distinct from `CapabilityProfileMismatchError` (#1244, declared
|
|
134
|
+
* vs *live cluster*): this is declared vs *recorded*, checked first and
|
|
135
|
+
* entirely offline.
|
|
136
|
+
*/
|
|
137
|
+
export declare class PinnedProfileMismatchError extends Error {
|
|
138
|
+
constructor(release: string, contentDigest: string, divergences: string[]);
|
|
139
|
+
}
|
|
140
|
+
/** How the deploy-time profile assertion (#1244) concluded, when a profile was declared. */
|
|
141
|
+
export type HelmProfileAssertionOutcome = {
|
|
142
|
+
matched: true;
|
|
143
|
+
} | {
|
|
144
|
+
matched: false;
|
|
145
|
+
divergences: string[];
|
|
146
|
+
overridden: true;
|
|
147
|
+
};
|
|
148
|
+
/**
|
|
149
|
+
* Thrown before any helm mutation when the target cluster does not match the
|
|
150
|
+
* deploy's declared capability profile (#1244). The message names every
|
|
151
|
+
* divergence — declared vs live — so the refusal is specific, never a shrug.
|
|
152
|
+
*/
|
|
153
|
+
export declare class CapabilityProfileMismatchError extends Error {
|
|
154
|
+
readonly divergences: string[];
|
|
155
|
+
constructor(release: string, profileName: string | undefined, divergences: string[]);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* The input-side identity of a helm deploy (#1243): a `sha256:` digest over
|
|
159
|
+
* the canonical JSON of `{ chart, chartVersion, values, capabilityProfile? }`.
|
|
160
|
+
* Canonical JSON (core's `canonicalJson`, RFC 8785 shape) sorts object keys,
|
|
161
|
+
* so the digest is stable across value key order; `apiVersions` is sorted
|
|
162
|
+
* for the same reason. The digest changes when any actual input changes —
|
|
163
|
+
* the chart, its version, a value, the declared profile.
|
|
164
|
+
*
|
|
165
|
+
* Delegates to `helmInputDigest` (#1237) — the same helper `HelmRender`
|
|
166
|
+
* records as a pinned render's `inputDigest` — so a deploy and a render of
|
|
167
|
+
* the same inputs share their identity by construction.
|
|
168
|
+
*/
|
|
169
|
+
export declare function helmInstallInputDigest(args: HelmInstallArgs): string;
|
|
13
170
|
/**
|
|
14
|
-
*
|
|
171
|
+
* Deploy a helm release and append a `ReleaseRecord` (#1243).
|
|
172
|
+
*
|
|
173
|
+
* Two paths, selected by `contentDigest`:
|
|
174
|
+
*
|
|
175
|
+
* - **Unpinned** (no `contentDigest`): `helm upgrade --install <name>
|
|
176
|
+
* <chart>`, exactly as before #1242 — helm renders at deploy time. The
|
|
177
|
+
* ledger record is keyed by the input digest.
|
|
178
|
+
* - **Pinned** (`contentDigest` set, #1242): the recorded render is loaded
|
|
179
|
+
* from the render store, its digest verified, and those exact bytes
|
|
180
|
+
* installed as a structure-preserving wrapper chart — no deploy-time
|
|
181
|
+
* render. The ledger record is keyed by the content digest and carries
|
|
182
|
+
* the stored render's input digest alongside it.
|
|
183
|
+
*
|
|
184
|
+
* A ledger-append failure after a successful deploy warns and never throws:
|
|
185
|
+
* the deploy already happened, so a ledger-write hiccup must not turn a
|
|
186
|
+
* finished deploy into a failed activity — the record is observability, not
|
|
187
|
+
* part of the deploy itself.
|
|
188
|
+
*
|
|
15
189
|
* Uses longInfra profile — 20m timeout, heartbeat every 15s.
|
|
16
190
|
*/
|
|
17
|
-
export declare function helmInstall(args: HelmInstallArgs, signal?: AbortSignal): Promise<
|
|
191
|
+
export declare function helmInstall(args: HelmInstallArgs, signal?: AbortSignal): Promise<HelmInstallResult>;
|
|
18
192
|
//# sourceMappingURL=helm.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helm.d.ts","sourceRoot":"","sources":["../../../src/op/activities/helm.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"helm.d.ts","sourceRoot":"","sources":["../../../src/op/activities/helm.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* The `helmInstall` step builder stays in core (@intentius/chant/op), re-exported
|
|
7
7
|
* from the temporal Op-authoring barrel like the other core builders.
|
|
8
8
|
*/
|
|
9
|
-
export { helmInstall } from "./helm.js";
|
|
10
|
-
export type { HelmInstallArgs } from "./helm.js";
|
|
9
|
+
export { helmInstall, helmInstallInputDigest, CapabilityProfileMismatchError, PinnedRenderNotFoundError, PinnedRenderIntegrityError, PinnedInstallInputError, PinnedProfileMismatchError, } from "./helm.js";
|
|
10
|
+
export type { HelmInstallArgs, HelmInstallResult, HelmCapabilityProfile, HelmProfileAssertionOutcome, } from "./helm.js";
|
|
11
|
+
export { probeClusterCapabilities, compareCapabilityProfile, ClusterProbeError } from "./cluster-probe.js";
|
|
12
|
+
export type { LiveClusterCapabilities, DeclaredCapabilityProfile } from "./cluster-probe.js";
|
|
11
13
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/op/activities/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EACL,WAAW,EACX,sBAAsB,EACtB,8BAA8B,EAC9B,yBAAyB,EACzB,0BAA0B,EAC1B,uBAAuB,EACvB,0BAA0B,GAC3B,MAAM,QAAQ,CAAC;AAChB,YAAY,EACV,eAAe,EACf,iBAAiB,EACjB,qBAAqB,EACrB,2BAA2B,GAC5B,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,wBAAwB,EAAE,wBAAwB,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACxG,YAAY,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed step-builder wrappers for this lexicon's `helmInstall` activity
|
|
3
|
+
* (chant #1288 Stage 2 — "regenerate the step builders as fully typed
|
|
4
|
+
* wrappers"). Core cannot import a lexicon's `*Args` types (lexicons depend
|
|
5
|
+
* on core, not the other way around), so a fully typed `helmInstall` /
|
|
6
|
+
* `helmInstallPinned` has to live beside {@link HelmInstallArgs} — here,
|
|
7
|
+
* next to `./activities/helm.ts`. `opts`'s type in each wrapper below IS
|
|
8
|
+
* `HelmInstallArgs` itself (via `Omit`/`WithStepRefs`) — never a
|
|
9
|
+
* hand-restated mirror — so the option surface Stage 1's zod contracts
|
|
10
|
+
* deliberately skipped (`capabilityProfile`, `set`, `deleteMode`-adjacent
|
|
11
|
+
* cross-field options) is authoring-time typed for free.
|
|
12
|
+
*
|
|
13
|
+
* Every field also accepts a {@link StepOutputRef} in its place
|
|
14
|
+
* ({@link WithStepRefs}, chant #1950).
|
|
15
|
+
*
|
|
16
|
+
* `core`'s own `helmInstall`/`helmInstallPinned` (in `@intentius/chant/op`,
|
|
17
|
+
* re-exported from `@intentius/chant-lexicon-temporal`) are UNCHANGED and
|
|
18
|
+
* produce byte-identical `ActivityStep` output for the same inputs — these
|
|
19
|
+
* are purely additive. Deliberately not swapped into the temporal barrel
|
|
20
|
+
* (see `lexicons/k8s/src/op/builders.ts`'s module doc for why: it would make
|
|
21
|
+
* temporal depend on this package at runtime, undoing the product-agnostic
|
|
22
|
+
* split #809 did). An author who wants the typed surface imports it from
|
|
23
|
+
* here — `@intentius/chant-lexicon-helm` — which a project using
|
|
24
|
+
* `helmInstall` already depends on.
|
|
25
|
+
*/
|
|
26
|
+
import { type ActivityStep, type NamedActivityStep, type WithStepRefs } from "@intentius/chant/op";
|
|
27
|
+
import type { HelmInstallArgs } from "./activities/helm.js";
|
|
28
|
+
/** Extra opts every wrapper below accepts alongside its activity's own fields. */
|
|
29
|
+
type StepOpts = {
|
|
30
|
+
profile?: ActivityStep["profile"];
|
|
31
|
+
id?: string;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Deploy a helm release — the fully typed twin of core's `helmInstall`.
|
|
35
|
+
* `opts` is {@link HelmInstallArgs} itself, minus the positional `name`/
|
|
36
|
+
* `chart`. Defaults to the `longInfra` profile.
|
|
37
|
+
*/
|
|
38
|
+
export declare const helmInstall: (name: string, chart: string, opts?: WithStepRefs<Omit<HelmInstallArgs, "name" | "chart">> & StepOpts) => NamedActivityStep;
|
|
39
|
+
/**
|
|
40
|
+
* Deploy a recorded pinned render by its `sha256:` content digest (#1242) —
|
|
41
|
+
* the fully typed twin of core's `helmInstallPinned`. `opts` is
|
|
42
|
+
* {@link HelmInstallArgs} itself, minus the positional `name`/
|
|
43
|
+
* `contentDigest`. Defaults to the `longInfra` profile.
|
|
44
|
+
*/
|
|
45
|
+
export declare const helmInstallPinned: (name: string, contentDigest: string, opts?: WithStepRefs<Omit<HelmInstallArgs, "name" | "contentDigest">> & StepOpts) => NamedActivityStep;
|
|
46
|
+
export {};
|
|
47
|
+
//# sourceMappingURL=builders.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/op/builders.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEzD,kFAAkF;AAClF,KAAK,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnE;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACtB,MAAM,MAAM,EACZ,OAAO,MAAM,EACb,OAAO,YAAY,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,QAAQ,KACtE,iBAGF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,eAAe,MAAM,EACrB,OAAO,YAAY,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,GAAG,eAAe,CAAC,CAAC,GAAG,QAAQ,KAC9E,iBAGF,CAAC"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go template action extraction and control-flow scoping (#1234, epic #1228).
|
|
3
|
+
*
|
|
4
|
+
* The pinnability gate inspects template ACTIONS (`{{ ... }}`), never raw
|
|
5
|
+
* text. That distinction is finding 9: cert-manager carries 52 textual
|
|
6
|
+
* "lookup" occurrences, all comment prose, and a real template-action count
|
|
7
|
+
* of 0 — a text-matching gate refuses a chart that is perfectly pinnable.
|
|
8
|
+
*
|
|
9
|
+
* Beyond extraction, this module reconstructs the control-flow structure of a
|
|
10
|
+
* template file — which `if` / `with` / `range` blocks enclose each action —
|
|
11
|
+
* so the classifier can ask whether a construct is REACHABLE under the
|
|
12
|
+
* supplied values, not merely present. Reachability is what separates
|
|
13
|
+
* "unpinnable" from "pinnable with a recorded conditional hazard": bundled
|
|
14
|
+
* grafana's control-flow `lookup` sits behind `persistence.enabled`, off by
|
|
15
|
+
* default, so a default-values render never consults the cluster.
|
|
16
|
+
*/
|
|
17
|
+
export type ActionKind = "if" | "elseif" | "else" | "with" | "range" | "define" | "block" | "end" | "other";
|
|
18
|
+
export interface TemplateAction {
|
|
19
|
+
/** Path of the file the action was found in (as given by the caller). */
|
|
20
|
+
file: string;
|
|
21
|
+
/** 1-based line the action starts on. */
|
|
22
|
+
line: number;
|
|
23
|
+
/** The action body between `{{` and `}}`, trim markers stripped. */
|
|
24
|
+
body: string;
|
|
25
|
+
/** Structural role of the action, from its leading keyword. */
|
|
26
|
+
kind: ActionKind;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* One enclosing control-flow frame for an action. `conditions` are the
|
|
30
|
+
* expressions that must hold for the frame's branch to run; `negatedConditions`
|
|
31
|
+
* are prior branch conditions that must NOT hold (an `else` / `else if`
|
|
32
|
+
* branch runs only when every earlier branch condition was false).
|
|
33
|
+
*/
|
|
34
|
+
export interface ScopeFrame {
|
|
35
|
+
kind: "if" | "with" | "range" | "define" | "block" | "dependency-condition";
|
|
36
|
+
conditions: string[];
|
|
37
|
+
negatedConditions: string[];
|
|
38
|
+
/**
|
|
39
|
+
* When a `with` block pins the dot to a `.Values` subtree, the path of that
|
|
40
|
+
* subtree — so bare `.enabled` inside `with .Values.persistence` resolves
|
|
41
|
+
* to `persistence.enabled`. `undefined` means the dot is unresolvable
|
|
42
|
+
* (a `range` element, a non-values `with`, a `define` invoked from an
|
|
43
|
+
* unknown context).
|
|
44
|
+
*/
|
|
45
|
+
dotValuesPath?: string[];
|
|
46
|
+
/** Dot is rebound to something we cannot resolve (range element etc.). */
|
|
47
|
+
dotUnresolvable?: boolean;
|
|
48
|
+
}
|
|
49
|
+
export interface ScopedAction {
|
|
50
|
+
action: TemplateAction;
|
|
51
|
+
/** Enclosing frames, outermost first. Empty for top-level actions. */
|
|
52
|
+
frames: ScopeFrame[];
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extract template actions from a source file, skipping comment actions
|
|
56
|
+
* (`{{/* ... *\/}}`). Text outside actions — including YAML `#` comments,
|
|
57
|
+
* where finding 9's 52 false positives lived — is never inspected by any
|
|
58
|
+
* scan built on this.
|
|
59
|
+
*/
|
|
60
|
+
export declare function extractActions(source: string, file: string): TemplateAction[];
|
|
61
|
+
/**
|
|
62
|
+
* The pipeline of an action, structural keyword and variable assignment
|
|
63
|
+
* stripped: `if X` → `X`, `range $i, $v := X` → `X`, `$pw := X` → `X`.
|
|
64
|
+
* This is what condition evaluation and call-reachability parse.
|
|
65
|
+
*/
|
|
66
|
+
export declare function actionPipeline(action: TemplateAction): string;
|
|
67
|
+
/**
|
|
68
|
+
* Walk a file's actions and attach the enclosing control-flow frames to each.
|
|
69
|
+
* `else` / `else if` branches carry the prior branch conditions as
|
|
70
|
+
* `negatedConditions`. Structure that cannot be tracked (an unbalanced
|
|
71
|
+
* `end`, template text split across files) degrades to fewer frames — which
|
|
72
|
+
* only ever makes the classifier MORE conservative, never less: a missing
|
|
73
|
+
* frame means a gate we cannot prove closed.
|
|
74
|
+
*/
|
|
75
|
+
export declare function scopeActions(actions: TemplateAction[]): ScopedAction[];
|
|
76
|
+
//# sourceMappingURL=actions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../../src/pinnability/actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,UAAU,GAClB,IAAI,GACJ,QAAQ,GACR,MAAM,GACN,MAAM,GACN,OAAO,GACP,QAAQ,GACR,OAAO,GACP,KAAK,GACL,OAAO,CAAC;AAEZ,MAAM,WAAW,cAAc;IAC7B,yEAAyE;IACzE,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,EAAE,UAAU,CAAC;CAClB;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,OAAO,GAAG,sBAAsB,CAAC;IAC5E,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,0EAA0E;IAC1E,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,sEAAsE;IACtE,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAaD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,cAAc,EAAE,CAqC7E;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CAO7D;AAeD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG,YAAY,EAAE,CAwGtE"}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pinnability gate (#1234, epic #1228 Phase 1).
|
|
3
|
+
*
|
|
4
|
+
* A render is pinnable exactly when every input to it is closed. `helm
|
|
5
|
+
* template` has three inputs beyond (chart, values) that are silently
|
|
6
|
+
* defaulted or silently empty:
|
|
7
|
+
*
|
|
8
|
+
* - cluster capabilities — closable via --kube-version / --api-versions
|
|
9
|
+
* - generated values — closable by supplying the value as an input
|
|
10
|
+
* - cluster state (lookup) — not closable offline
|
|
11
|
+
*
|
|
12
|
+
* The gate is therefore not "is this chart deterministic" but "are all of
|
|
13
|
+
* this render's inputs closed" — a property of `(chart, values)`, not of the
|
|
14
|
+
* chart alone. Concretely:
|
|
15
|
+
*
|
|
16
|
+
* - A control-flow `lookup` that is REACHABLE under the supplied values is
|
|
17
|
+
* a hard refusal: it changes which documents exist, and no value
|
|
18
|
+
* substitution recovers that.
|
|
19
|
+
* - A control-flow `lookup` the supplied values leave gated OFF is a
|
|
20
|
+
* recorded conditional hazard, not a refusal — bundled grafana's
|
|
21
|
+
* `lookup` behind `persistence.enabled: false` never runs, so the
|
|
22
|
+
* render is pinnable; flipping that value re-classifies the pair.
|
|
23
|
+
* - Value-position `lookup` is a declared-input requirement (epic
|
|
24
|
+
* Decisions): it changes a field, not the document set.
|
|
25
|
+
* - `.Capabilities.*` references require an explicit capability profile —
|
|
26
|
+
* the default is a property of the helm BINARY (3.16.2 says v1.31.0,
|
|
27
|
+
* 4.1.1 says v1.35.0), so an unpinned render's digest depends on who
|
|
28
|
+
* rendered it. 11 of the 13 survey charts hit this; it is the normal
|
|
29
|
+
* case, not an error.
|
|
30
|
+
* - Generated values (`randAlphaNum` and friends) are detected statically
|
|
31
|
+
* and named; the double-render localizer (#1236) confirms them
|
|
32
|
+
* dynamically. They classify as closable when a `.Values` path in the
|
|
33
|
+
* same action can supply them.
|
|
34
|
+
*
|
|
35
|
+
* A chart that fails is refused with the specific construct and location,
|
|
36
|
+
* and keeps working unpinned. Adoption is incremental.
|
|
37
|
+
*/
|
|
38
|
+
import { type GatePath } from "./conditions.js";
|
|
39
|
+
export type PinnabilityVerdict = "deterministic" | "pinnable" | "unpinnable";
|
|
40
|
+
/** One `.Capabilities.*` reference; any of these makes a profile required. */
|
|
41
|
+
export interface CapabilityRequirement {
|
|
42
|
+
file: string;
|
|
43
|
+
line: number;
|
|
44
|
+
capability: "KubeVersion" | "APIVersions";
|
|
45
|
+
}
|
|
46
|
+
/** An input that must be (or has been) closed for the render to pin. */
|
|
47
|
+
export interface ClosedInput {
|
|
48
|
+
kind: "generated-value" | "value-position-lookup" | "supplied-values";
|
|
49
|
+
file?: string;
|
|
50
|
+
line?: number;
|
|
51
|
+
/** Template function for generated values (randAlphaNum, genCA, ...). */
|
|
52
|
+
fn?: string;
|
|
53
|
+
/** Root-scoped `.Values` path that can supply the input, when one exists. */
|
|
54
|
+
valuesPath?: string;
|
|
55
|
+
/** Can this input be closed by supplying a value at all? */
|
|
56
|
+
suppliable?: boolean;
|
|
57
|
+
detail: string;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* A control-flow `lookup` the supplied values leave unreachable. Recorded —
|
|
61
|
+
* not refused — so that flipping the gating value later re-classifies the
|
|
62
|
+
* `(chart, values)` pair instead of silently changing which documents exist.
|
|
63
|
+
*/
|
|
64
|
+
export interface ConditionalHazard {
|
|
65
|
+
/** Instance scope in root coordinates ("" = the top-level chart, "grafana" = that subchart). */
|
|
66
|
+
chart: string;
|
|
67
|
+
file: string;
|
|
68
|
+
line: number;
|
|
69
|
+
/** The values path(s) currently gating the construct off, with their values. */
|
|
70
|
+
gates: GatePath[];
|
|
71
|
+
detail: string;
|
|
72
|
+
}
|
|
73
|
+
/** A control-flow `lookup` site, aggregated across chart instances. */
|
|
74
|
+
export interface ControlFlowLookup {
|
|
75
|
+
file: string;
|
|
76
|
+
line: number;
|
|
77
|
+
action: string;
|
|
78
|
+
status: "refused" | "hazard";
|
|
79
|
+
/** Instance scopes the site was assessed in ("" = root). */
|
|
80
|
+
charts: string[];
|
|
81
|
+
}
|
|
82
|
+
export interface ValuePositionLookup {
|
|
83
|
+
file: string;
|
|
84
|
+
line: number;
|
|
85
|
+
action: string;
|
|
86
|
+
}
|
|
87
|
+
/** Evidence from an actual double render (#1236 owns producing this). */
|
|
88
|
+
export interface RenderEvidence {
|
|
89
|
+
stable: boolean;
|
|
90
|
+
unstableLines: number;
|
|
91
|
+
}
|
|
92
|
+
export interface PinnabilityReport {
|
|
93
|
+
verdict: PinnabilityVerdict;
|
|
94
|
+
/** `.Capabilities.*` references, one entry per occurrence. Empty = no profile needed. */
|
|
95
|
+
requiresProfile: CapabilityRequirement[];
|
|
96
|
+
closedInputs: ClosedInput[];
|
|
97
|
+
hazards: ConditionalHazard[];
|
|
98
|
+
/** Human-readable summary; refusal reasons first, specific per construct. */
|
|
99
|
+
reasons: string[];
|
|
100
|
+
/** Raw lookup findings, for surfaces that need counts or locations. */
|
|
101
|
+
lookups: {
|
|
102
|
+
controlFlow: ControlFlowLookup[];
|
|
103
|
+
valuePosition: ValuePositionLookup[];
|
|
104
|
+
};
|
|
105
|
+
/** Non-fatal scan caveats (an unvendored dependency, etc.). */
|
|
106
|
+
warnings: string[];
|
|
107
|
+
}
|
|
108
|
+
export interface ClassifyChartOptions {
|
|
109
|
+
/** Values overrides, as `helm template --values` would merge them. */
|
|
110
|
+
values?: unknown;
|
|
111
|
+
/** Values files to load and merge (in order) over the chart defaults. */
|
|
112
|
+
valuesFiles?: string[];
|
|
113
|
+
/** Double-render evidence, when the caller has rendered. */
|
|
114
|
+
renderEvidence?: RenderEvidence;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Template files of ONE chart directory — `templates/` at any depth below
|
|
118
|
+
* it, excluding `charts/` (subcharts are their own instances) and NOTES.txt
|
|
119
|
+
* (rendered for the console, not the cluster).
|
|
120
|
+
*/
|
|
121
|
+
export declare function collectOwnTemplateFiles(chartDir: string): string[];
|
|
122
|
+
/**
|
|
123
|
+
* Classify a chart directory against the values a render would be given.
|
|
124
|
+
* Subchart-recursive: dependencies vendored under `charts/` are scanned with
|
|
125
|
+
* their own effective values (aliases get their own scope, `condition:`-
|
|
126
|
+
* disabled dependencies gate their contents — findings 11 and 12).
|
|
127
|
+
*/
|
|
128
|
+
export declare function classifyChart(chartDir: string, options?: ClassifyChartOptions): PinnabilityReport;
|
|
129
|
+
//# sourceMappingURL=classify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../../src/pinnability/classify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AAYH,OAAO,EAML,KAAK,QAAQ,EAEd,MAAM,cAAc,CAAC;AAStB,MAAM,MAAM,kBAAkB,GAAG,eAAe,GAAG,UAAU,GAAG,YAAY,CAAC;AAE7E,8EAA8E;AAC9E,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,aAAa,GAAG,aAAa,CAAC;CAC3C;AAED,wEAAwE;AACxE,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,iBAAiB,GAAG,uBAAuB,GAAG,iBAAiB,CAAC;IACtE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yEAAyE;IACzE,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,6EAA6E;IAC7E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,gGAAgG;IAChG,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,uEAAuE;AACvE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC7B,4DAA4D;IAC5D,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,kBAAkB,CAAC;IAC5B,yFAAyF;IACzF,eAAe,EAAE,qBAAqB,EAAE,CAAC;IACzC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,6EAA6E;IAC7E,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,uEAAuE;IACvE,OAAO,EAAE;QACP,WAAW,EAAE,iBAAiB,EAAE,CAAC;QACjC,aAAa,EAAE,mBAAmB,EAAE,CAAC;KACtC,CAAC;IACF,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,yEAAyE;IACzE,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,4DAA4D;IAC5D,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AA2DD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBlE;AA8FD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAChB,OAAO,GAAE,oBAAyB,GACjC,iBAAiB,CAqPnB"}
|