@intentius/chant-lexicon-helm 0.41.3 → 0.41.5
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/components/builders.d.ts +3 -0
- package/dist/components/builders.d.ts.map +1 -0
- package/dist/components/capability-plugin.d.ts +6 -0
- package/dist/components/capability-plugin.d.ts.map +1 -0
- package/dist/components/helm-upgrade.d.ts +41 -0
- package/dist/components/helm-upgrade.d.ts.map +1 -0
- package/dist/components/index.d.ts +12 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/describe-stack-status.d.ts +10 -0
- package/dist/describe-stack-status.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/dist/plugin.d.ts.map +1 -1
- package/package.json +7 -2
- package/src/components/builders.ts +11 -0
- package/src/components/capability-plugin.ts +30 -0
- package/src/components/helm-upgrade.test.ts +76 -0
- package/src/components/helm-upgrade.ts +133 -0
- package/src/components/index.ts +17 -0
- package/src/describe-stack-status.test.ts +62 -0
- package/src/describe-stack-status.ts +84 -0
- package/src/index.ts +6 -0
- package/src/plugin.ts +8 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builders.d.ts","sourceRoot":"","sources":["../../src/components/builders.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEvD,eAAO,MAAM,WAAW,yEAAyC,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type CapabilityPlugin } from "@intentius/chant/components/capability-plugin";
|
|
2
|
+
export declare const HELM_VERB_FAMILIES: {
|
|
3
|
+
readonly apply: readonly ["helm-upgrade"];
|
|
4
|
+
};
|
|
5
|
+
export declare const helmCapabilityPlugin: CapabilityPlugin;
|
|
6
|
+
//# sourceMappingURL=capability-plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capability-plugin.d.ts","sourceRoot":"","sources":["../../src/components/capability-plugin.ts"],"names":[],"mappings":"AAWA,OAAO,EAAqB,KAAK,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AAGzG,eAAO,MAAM,kBAAkB;;CAErB,CAAC;AAEX,eAAO,MAAM,oBAAoB,EAAE,gBAWlC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Capability } from "@intentius/chant/components/capability";
|
|
2
|
+
export interface HelmUpgradeInput {
|
|
3
|
+
/**
|
|
4
|
+
* The release name — the deploy unit. `helm upgrade --install` converges
|
|
5
|
+
* it; `describeStackStatus` reads it back; `components status --live`
|
|
6
|
+
* reports it. Required: an unnamed release is invisible to every one of
|
|
7
|
+
* those.
|
|
8
|
+
*/
|
|
9
|
+
release: string;
|
|
10
|
+
/** Chart reference: a local path, a `repo/chart` name, or an OCI ref. */
|
|
11
|
+
chart: string;
|
|
12
|
+
/** Target namespace. Omitted uses the kube context's default. */
|
|
13
|
+
namespace?: string;
|
|
14
|
+
/** Create the namespace if it does not exist (`--create-namespace`). */
|
|
15
|
+
createNamespace?: boolean;
|
|
16
|
+
/** Values files, passed as `-f` in order (later files win, Helm's rule). */
|
|
17
|
+
values?: string[];
|
|
18
|
+
/** Chart version constraint (`--version`). Omitted takes the latest. */
|
|
19
|
+
version?: string;
|
|
20
|
+
/** Wait for resources to become ready before returning (`--wait`). */
|
|
21
|
+
wait?: boolean;
|
|
22
|
+
/** Explicit kube context, overriding the environment's declared binding. */
|
|
23
|
+
context?: string;
|
|
24
|
+
}
|
|
25
|
+
/** What the upgrade did — Helm's own release facts, from `-o json`. */
|
|
26
|
+
export interface HelmUpgradeOutcome {
|
|
27
|
+
release: string;
|
|
28
|
+
namespace?: string;
|
|
29
|
+
/** Helm's release revision after this upgrade (1 on first install). */
|
|
30
|
+
revision?: number;
|
|
31
|
+
/** Helm's native status, e.g. "deployed". */
|
|
32
|
+
status?: string;
|
|
33
|
+
}
|
|
34
|
+
/** Injectable command runner, so tests assert the exact argv without a cluster or a helm binary. */
|
|
35
|
+
export type HelmRunner = (command: string) => Promise<{
|
|
36
|
+
stdout: string;
|
|
37
|
+
}>;
|
|
38
|
+
/** Factory with an injectable runner — the same seam `createKubectlApplyCapability` uses. */
|
|
39
|
+
export declare function createHelmUpgradeCapability(run?: HelmRunner): Capability<HelmUpgradeInput, HelmUpgradeOutcome>;
|
|
40
|
+
export declare const helmUpgradeCapability: Capability<HelmUpgradeInput, HelmUpgradeOutcome>;
|
|
41
|
+
//# sourceMappingURL=helm-upgrade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helm-upgrade.d.ts","sourceRoot":"","sources":["../../src/components/helm-upgrade.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,wCAAwC,CAAC;AAMxF,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,wEAAwE;IACxE,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sEAAsE;IACtE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,oGAAoG;AACpG,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AA8B1E,6FAA6F;AAC7F,wBAAgB,2BAA2B,CACzC,GAAG,GAAE,UAAsB,GAC1B,UAAU,CAAC,gBAAgB,EAAE,kBAAkB,CAAC,CA+BlD;AAED,eAAO,MAAM,qBAAqB,kDAAgC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The helm lexicon's component/release surface: the `helm-upgrade`
|
|
3
|
+
* capability, its typed step-builder, and the `helmCapabilityPlugin` core
|
|
4
|
+
* loads when a project declares `lexicons: ["helm"]` (#1495 piece 4).
|
|
5
|
+
* Component authors import the builders from here
|
|
6
|
+
* (`@intentius/chant-lexicon-helm/components`), the way AWS and k8s verbs
|
|
7
|
+
* come from their lexicons' `/components` entries.
|
|
8
|
+
*/
|
|
9
|
+
export { helmCapabilityPlugin, HELM_VERB_FAMILIES } from "./capability-plugin.js";
|
|
10
|
+
export * from "./builders.js";
|
|
11
|
+
export { helmUpgradeCapability, createHelmUpgradeCapability, type HelmUpgradeInput, type HelmUpgradeOutcome, type HelmRunner, } from "./helm-upgrade.js";
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC/E,cAAc,YAAY,CAAC;AAC3B,OAAO,EACL,qBAAqB,EACrB,2BAA2B,EAC3B,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,UAAU,GAChB,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { StackStatusObservation } from "@intentius/chant/lexicon";
|
|
2
|
+
/** Injectable command runner, so tests drive every branch without helm or a cluster. */
|
|
3
|
+
export type HelmRunner = (command: string) => Promise<{
|
|
4
|
+
stdout: string;
|
|
5
|
+
}>;
|
|
6
|
+
export declare function describeStackStatus(options: {
|
|
7
|
+
environment: string;
|
|
8
|
+
stack: string;
|
|
9
|
+
}, run?: HelmRunner): Promise<StackStatusObservation | null>;
|
|
10
|
+
//# sourceMappingURL=describe-stack-status.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe-stack-status.d.ts","sourceRoot":"","sources":["../src/describe-stack-status.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAMvE,wFAAwF;AACxF,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAS1E,wBAAsB,mBAAmB,CACvC,OAAO,EAAE;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAC/C,GAAG,GAAE,UAAsB,GAC1B,OAAO,CAAC,sBAAsB,GAAG,IAAI,CAAC,CAyCxC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { helmSerializer } from "./serializer.js";
|
|
2
2
|
export { helmPlugin } from "./plugin.js";
|
|
3
|
+
export { helmCapabilityPlugin, HELM_VERB_FAMILIES } from "./components/capability-plugin.js";
|
|
4
|
+
export { helmUpgradeCapability, createHelmUpgradeCapability, type HelmUpgradeInput, type HelmUpgradeOutcome } from "./components/helm-upgrade.js";
|
|
3
5
|
export { Chart, Values, ValuesOverride, HelmTest, HelmNotes, HelmHook, HelmDependency, HelmMaintainer, HelmCRD } from "./resources.js";
|
|
4
6
|
export { HelmRender } from "./render.js";
|
|
5
7
|
export type { HelmRenderProps } from "./render.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAKtC,OAAO,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,2BAA2B,EAAE,KAAK,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/I,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAGpI,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGhD,OAAO,EACL,OAAO,EACP,YAAY,EACZ,WAAW,EACX,cAAc,EACd,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,MAAM,EACN,OAAO,EACP,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,WAAW,EACX,MAAM,EACN,KAAK,EACL,MAAM,EACN,GAAG,EACH,MAAM,EACN,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,aAAa,EACb,cAAc,EACd,MAAM,EACN,EAAE,EACF,KAAK,EACL,IAAI,EACJ,SAAS,EACT,QAAQ,GACT,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,YAAY,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAG/C,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvE,OAAO,EACL,UAAU,EACV,mBAAmB,EACnB,WAAW,EACX,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,YAAY,EACV,eAAe,EACf,gBAAgB,EAChB,wBAAwB,EACxB,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,gBAAgB,EAChB,iBAAiB,EACjB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,EACxB,iBAAiB,EACjB,kBAAkB,EAClB,yBAAyB,EACzB,0BAA0B,EAC1B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,wBAAwB,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGlG,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "0512e5bf71bbc2af393f201a22524ab869eb7e360e8bcf3aec24a3f39f381667",
|
|
5
5
|
"meta.json": "14243c5730a07c6a6edc35ddd351438547d58df5cf345f2233a355b0c7611ccc",
|
|
6
6
|
"types/index.d.ts": "5377696ca8698cd2999e4680feb8e8e4b54a7b49fb603a87b2f27356114d1794",
|
|
7
7
|
"rules/chart-metadata.ts": "8f3377e893d5e2828460b7fe5924fca098334245a9a2fdb90f6b67e490eaf091",
|
|
@@ -34,5 +34,5 @@
|
|
|
34
34
|
"skills/chant-helm-patterns.md": "9e79e6a46391da46709d8aa57e2825a7cd9eb981cd923f02ad60836c49b2561e",
|
|
35
35
|
"skills/chant-helm-security.md": "bfc367eabceed2e84f1cf94501b407df78aeed963cec104f24a321d0962063c9"
|
|
36
36
|
},
|
|
37
|
-
"composite": "
|
|
37
|
+
"composite": "43154d62e8f2d12a5798cb6fc107c2b5cf271e9f376195dbd9e76c5f5c22cad8"
|
|
38
38
|
}
|
package/dist/manifest.json
CHANGED
package/dist/plugin.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAiC,MAAM,0BAA0B,CAAC;AAY7F,eAAO,MAAM,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAiC,MAAM,0BAA0B,CAAC;AAY7F,eAAO,MAAM,UAAU,EAAE,aAqXxB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-helm",
|
|
3
|
-
"version": "0.41.
|
|
3
|
+
"version": "0.41.5",
|
|
4
4
|
"description": "Helm chart lexicon for chant — declarative IaC in TypeScript",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://intentius.io/chant",
|
|
@@ -44,6 +44,11 @@
|
|
|
44
44
|
"types": "./dist/detect.d.ts",
|
|
45
45
|
"default": "./src/detect.ts"
|
|
46
46
|
},
|
|
47
|
+
"./components": {
|
|
48
|
+
"development": "./src/components/index.ts",
|
|
49
|
+
"types": "./dist/components/index.d.ts",
|
|
50
|
+
"default": "./src/components/index.ts"
|
|
51
|
+
},
|
|
47
52
|
"./lint/post-synth": {
|
|
48
53
|
"development": "./src/lint/post-synth/index.ts",
|
|
49
54
|
"types": "./dist/lint/post-synth/index.d.ts",
|
|
@@ -76,7 +81,7 @@
|
|
|
76
81
|
"@types/js-yaml": "^4.0.9"
|
|
77
82
|
},
|
|
78
83
|
"peerDependencies": {
|
|
79
|
-
"@intentius/chant": "^0.41.
|
|
84
|
+
"@intentius/chant": "^0.41.5",
|
|
80
85
|
"typescript": "^5.9.3"
|
|
81
86
|
}
|
|
82
87
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed step-builders for the helm lexicon's verbs — the same ergonomic
|
|
3
|
+
* sugar the aws and k8s lexicons' `components/builders.ts` offer (#658),
|
|
4
|
+
* reusing the exported `step` projection from `@intentius/chant/components`.
|
|
5
|
+
* No `noRollback` admission here, unlike `kubectlApply`: `helm-upgrade`
|
|
6
|
+
* carries a native rollback, so COMP003 never asks for the opt-out.
|
|
7
|
+
*/
|
|
8
|
+
import { step } from "@intentius/chant/components";
|
|
9
|
+
import type { HelmUpgradeInput } from "./helm-upgrade";
|
|
10
|
+
|
|
11
|
+
export const helmUpgrade = step<HelmUpgradeInput>("helm-upgrade");
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `helmCapabilityPlugin` — the helm lexicon's capability plugin (#1495
|
|
3
|
+
* piece 4).
|
|
4
|
+
*
|
|
5
|
+
* One leaf: `helm-upgrade`, the idempotent create-or-converge verb a Helm
|
|
6
|
+
* release levels everything to. Contributed through core's `CapabilityPlugin`
|
|
7
|
+
* contract the same way aws contributes `cfn-deploy` and k8s contributes
|
|
8
|
+
* `kubectl-apply` — a project declaring `lexicons: ["helm"]` gets the verb
|
|
9
|
+
* registered automatically when it runs components.
|
|
10
|
+
*/
|
|
11
|
+
import type { Capability } from "@intentius/chant/components/capability";
|
|
12
|
+
import { ownPackageVersion, type CapabilityPlugin } from "@intentius/chant/components/capability-plugin";
|
|
13
|
+
import { helmUpgradeCapability } from "./helm-upgrade";
|
|
14
|
+
|
|
15
|
+
export const HELM_VERB_FAMILIES = {
|
|
16
|
+
apply: ["helm-upgrade"],
|
|
17
|
+
} as const;
|
|
18
|
+
|
|
19
|
+
export const helmCapabilityPlugin: CapabilityPlugin = {
|
|
20
|
+
name: "helm",
|
|
21
|
+
// The lexicon package's own version (#1505) — literals go stale every
|
|
22
|
+
// lockstep release.
|
|
23
|
+
version: ownPackageVersion(import.meta.url),
|
|
24
|
+
capabilities(): Array<Capability<never, unknown>> {
|
|
25
|
+
return [helmUpgradeCapability as Capability<never, unknown>];
|
|
26
|
+
},
|
|
27
|
+
families(): Record<string, readonly string[]> {
|
|
28
|
+
return HELM_VERB_FAMILIES;
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { createHelmUpgradeCapability, helmUpgradeCapability } from "./helm-upgrade";
|
|
3
|
+
import { helmCapabilityPlugin } from "./capability-plugin";
|
|
4
|
+
import { isCapabilityPlugin } from "@intentius/chant/components/capability-plugin";
|
|
5
|
+
import { readFileSync } from "node:fs";
|
|
6
|
+
import type { DeployContext } from "@intentius/chant/components/capability";
|
|
7
|
+
|
|
8
|
+
const ctx: DeployContext = { env: "local", component: "test" };
|
|
9
|
+
|
|
10
|
+
describe("helm-upgrade capability (#1495 piece 4)", () => {
|
|
11
|
+
test("the plugin satisfies the CapabilityPlugin contract and registers the verb", () => {
|
|
12
|
+
expect(isCapabilityPlugin(helmCapabilityPlugin)).toBe(true);
|
|
13
|
+
expect(helmCapabilityPlugin.capabilities().map((c) => c.kind)).toContain("helm-upgrade");
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
test("the plugin's version is the lexicon package's own, not a literal (#1505)", () => {
|
|
17
|
+
const { version } = JSON.parse(
|
|
18
|
+
readFileSync(new URL("../../package.json", import.meta.url), "utf-8"),
|
|
19
|
+
) as { version: string };
|
|
20
|
+
expect(helmCapabilityPlugin.version).toBe(version);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("run shells `helm upgrade --install` with the release, chart, and every declared flag", async () => {
|
|
24
|
+
let seen = "";
|
|
25
|
+
const cap = createHelmUpgradeCapability(async (cmd) => {
|
|
26
|
+
seen = cmd;
|
|
27
|
+
return { stdout: JSON.stringify({ name: "api", namespace: "prod", version: 3, info: { status: "deployed" } }) };
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const out = await cap.run(ctx, {
|
|
31
|
+
release: "api",
|
|
32
|
+
chart: "./charts/api",
|
|
33
|
+
namespace: "prod",
|
|
34
|
+
createNamespace: true,
|
|
35
|
+
values: ["values.yaml", "values.prod.yaml"],
|
|
36
|
+
version: "1.2.3",
|
|
37
|
+
wait: true,
|
|
38
|
+
context: "k3d-test",
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
expect(seen).toBe(
|
|
42
|
+
"helm upgrade --install 'api' './charts/api' -o json -n 'prod' --create-namespace " +
|
|
43
|
+
"-f 'values.yaml' -f 'values.prod.yaml' --version '1.2.3' --wait --kube-context 'k3d-test'",
|
|
44
|
+
);
|
|
45
|
+
expect(out).toEqual({ release: "api", namespace: "prod", revision: 3, status: "deployed" });
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("non-JSON helm output still reports the release — the deploy already succeeded", async () => {
|
|
49
|
+
const cap = createHelmUpgradeCapability(async () => ({ stdout: "Release \"api\" has been upgraded.\n" }));
|
|
50
|
+
const out = await cap.run(ctx, { release: "api", chart: "repo/api", namespace: "prod" });
|
|
51
|
+
expect(out).toEqual({ release: "api", namespace: "prod" });
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
test("rollback shells `helm rollback` scoped to the release and namespace — the native compensation", async () => {
|
|
55
|
+
const commands: string[] = [];
|
|
56
|
+
const cap = createHelmUpgradeCapability(async (cmd) => {
|
|
57
|
+
commands.push(cmd);
|
|
58
|
+
return { stdout: "" };
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await cap.rollback!(ctx, { release: "api", chart: "repo/api", namespace: "prod", context: "k3d-test" });
|
|
62
|
+
expect(commands).toEqual(["helm rollback 'api' -n 'prod' --kube-context 'k3d-test'"]);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("no rollbackPolicy declared: a capability with a rollback method reads as native (COMP003)", () => {
|
|
66
|
+
expect(helmUpgradeCapability.rollback).toBeDefined();
|
|
67
|
+
expect(helmUpgradeCapability.rollbackPolicy).toBeUndefined();
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
test("a failing helm invocation rejects — a failed deploy must not report an outcome", async () => {
|
|
71
|
+
const cap = createHelmUpgradeCapability(async () => {
|
|
72
|
+
throw new Error("Error: UPGRADE FAILED: another operation is in progress");
|
|
73
|
+
});
|
|
74
|
+
await expect(cap.run(ctx, { release: "api", chart: "repo/api" })).rejects.toThrow(/UPGRADE FAILED/);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `helm-upgrade` — the Helm release leaf for the component model
|
|
3
|
+
* (#1495 piece 4).
|
|
4
|
+
*
|
|
5
|
+
* The closest analogue of `cfn-deploy` anywhere in chant: a Helm release has
|
|
6
|
+
* a name, a presence, and a native status, and `helm upgrade --install` is
|
|
7
|
+
* the one idempotent verb that creates or converges it. `release` doubles as
|
|
8
|
+
* both the thing Helm manages and the deploy unit the status walk reads
|
|
9
|
+
* (core `components/deploy-units.ts` — `{ kind: "helm-upgrade", field:
|
|
10
|
+
* "release", lexicon: "helm" }` was registered in #1499, waiting for this
|
|
11
|
+
* capability to exist).
|
|
12
|
+
*
|
|
13
|
+
* Unlike `kubectl-apply`, rollback is native: Helm retains previous release
|
|
14
|
+
* revisions, and `helm rollback <release>` restores the last one. So this
|
|
15
|
+
* capability carries a real `rollback` method and COMP003 treats it as
|
|
16
|
+
* `"native"` — no opt-out reason required on the step.
|
|
17
|
+
*
|
|
18
|
+
* The cluster is selected the same way the k8s lexicon's reads select it
|
|
19
|
+
* (#1488): the environment's declared binding (`k8s.profiles.<env>.context`)
|
|
20
|
+
* is passed as `--kube-context` when present; ambient otherwise. Helm rides
|
|
21
|
+
* the same binding rather than inventing a parallel one — a Helm release
|
|
22
|
+
* lives on the same cluster the k8s half observes.
|
|
23
|
+
*/
|
|
24
|
+
import { exec } from "node:child_process";
|
|
25
|
+
import { promisify } from "node:util";
|
|
26
|
+
import type { Capability, DeployContext } from "@intentius/chant/components/capability";
|
|
27
|
+
import { loadChantConfigUpward } from "@intentius/chant/config";
|
|
28
|
+
import { resolveClusterTarget } from "@intentius/chant/kubectl-context";
|
|
29
|
+
|
|
30
|
+
const execAsync = promisify(exec);
|
|
31
|
+
|
|
32
|
+
export interface HelmUpgradeInput {
|
|
33
|
+
/**
|
|
34
|
+
* The release name — the deploy unit. `helm upgrade --install` converges
|
|
35
|
+
* it; `describeStackStatus` reads it back; `components status --live`
|
|
36
|
+
* reports it. Required: an unnamed release is invisible to every one of
|
|
37
|
+
* those.
|
|
38
|
+
*/
|
|
39
|
+
release: string;
|
|
40
|
+
/** Chart reference: a local path, a `repo/chart` name, or an OCI ref. */
|
|
41
|
+
chart: string;
|
|
42
|
+
/** Target namespace. Omitted uses the kube context's default. */
|
|
43
|
+
namespace?: string;
|
|
44
|
+
/** Create the namespace if it does not exist (`--create-namespace`). */
|
|
45
|
+
createNamespace?: boolean;
|
|
46
|
+
/** Values files, passed as `-f` in order (later files win, Helm's rule). */
|
|
47
|
+
values?: string[];
|
|
48
|
+
/** Chart version constraint (`--version`). Omitted takes the latest. */
|
|
49
|
+
version?: string;
|
|
50
|
+
/** Wait for resources to become ready before returning (`--wait`). */
|
|
51
|
+
wait?: boolean;
|
|
52
|
+
/** Explicit kube context, overriding the environment's declared binding. */
|
|
53
|
+
context?: string;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/** What the upgrade did — Helm's own release facts, from `-o json`. */
|
|
57
|
+
export interface HelmUpgradeOutcome {
|
|
58
|
+
release: string;
|
|
59
|
+
namespace?: string;
|
|
60
|
+
/** Helm's release revision after this upgrade (1 on first install). */
|
|
61
|
+
revision?: number;
|
|
62
|
+
/** Helm's native status, e.g. "deployed". */
|
|
63
|
+
status?: string;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Injectable command runner, so tests assert the exact argv without a cluster or a helm binary. */
|
|
67
|
+
export type HelmRunner = (command: string) => Promise<{ stdout: string }>;
|
|
68
|
+
|
|
69
|
+
/** Shell-quote one argv element (paths and chart refs may carry spaces). */
|
|
70
|
+
function q(arg: string): string {
|
|
71
|
+
return `'${arg.replace(/'/g, "'\\''")}'`;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* The environment's kube context: the explicit input, else the declared
|
|
76
|
+
* binding (#1488 — used, never policed), else undefined (ambient).
|
|
77
|
+
*/
|
|
78
|
+
async function resolveContext(input: HelmUpgradeInput, env: string | undefined): Promise<string | undefined> {
|
|
79
|
+
if (input.context) return input.context;
|
|
80
|
+
if (!env) return undefined;
|
|
81
|
+
const { config } = await loadChantConfigUpward(process.cwd()).catch(() => ({ config: {} }));
|
|
82
|
+
const target = await resolveClusterTarget(config as Record<string, unknown>, env, "helm");
|
|
83
|
+
return target.context;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function upgradeCommand(input: HelmUpgradeInput, context: string | undefined): string {
|
|
87
|
+
const parts = ["helm", "upgrade", "--install", q(input.release), q(input.chart), "-o", "json"];
|
|
88
|
+
if (input.namespace) parts.push("-n", q(input.namespace));
|
|
89
|
+
if (input.createNamespace) parts.push("--create-namespace");
|
|
90
|
+
for (const f of input.values ?? []) parts.push("-f", q(f));
|
|
91
|
+
if (input.version) parts.push("--version", q(input.version));
|
|
92
|
+
if (input.wait) parts.push("--wait");
|
|
93
|
+
if (context) parts.push("--kube-context", q(context));
|
|
94
|
+
return parts.join(" ");
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Factory with an injectable runner — the same seam `createKubectlApplyCapability` uses. */
|
|
98
|
+
export function createHelmUpgradeCapability(
|
|
99
|
+
run: HelmRunner = execAsync,
|
|
100
|
+
): Capability<HelmUpgradeInput, HelmUpgradeOutcome> {
|
|
101
|
+
return {
|
|
102
|
+
kind: "helm-upgrade",
|
|
103
|
+
async run(ctx: DeployContext, input: HelmUpgradeInput): Promise<HelmUpgradeOutcome> {
|
|
104
|
+
const context = await resolveContext(input, ctx.env);
|
|
105
|
+
const { stdout } = await run(upgradeCommand(input, context));
|
|
106
|
+
let parsed: { name?: string; namespace?: string; version?: number; info?: { status?: string } } = {};
|
|
107
|
+
try {
|
|
108
|
+
parsed = JSON.parse(stdout) as typeof parsed;
|
|
109
|
+
} catch {
|
|
110
|
+
// Helm printed something non-JSON (older helm, or a plugin banner) —
|
|
111
|
+
// the upgrade still succeeded (a failure rejects the exec), so report
|
|
112
|
+
// the release without the extras rather than failing a done deploy.
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
release: input.release,
|
|
116
|
+
...(parsed.namespace ?? input.namespace ? { namespace: parsed.namespace ?? input.namespace } : {}),
|
|
117
|
+
...(typeof parsed.version === "number" ? { revision: parsed.version } : {}),
|
|
118
|
+
...(parsed.info?.status ? { status: parsed.info.status } : {}),
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
// Native compensation: restore the previous retained revision. Helm's
|
|
122
|
+
// bare `rollback <release>` targets exactly that.
|
|
123
|
+
async rollback(ctx: DeployContext, input: HelmUpgradeInput): Promise<void> {
|
|
124
|
+
const context = await resolveContext(input, ctx.env);
|
|
125
|
+
const parts = ["helm", "rollback", q(input.release)];
|
|
126
|
+
if (input.namespace) parts.push("-n", q(input.namespace));
|
|
127
|
+
if (context) parts.push("--kube-context", q(context));
|
|
128
|
+
await run(parts.join(" "));
|
|
129
|
+
},
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export const helmUpgradeCapability = createHelmUpgradeCapability();
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The helm lexicon's component/release surface: the `helm-upgrade`
|
|
3
|
+
* capability, its typed step-builder, and the `helmCapabilityPlugin` core
|
|
4
|
+
* loads when a project declares `lexicons: ["helm"]` (#1495 piece 4).
|
|
5
|
+
* Component authors import the builders from here
|
|
6
|
+
* (`@intentius/chant-lexicon-helm/components`), the way AWS and k8s verbs
|
|
7
|
+
* come from their lexicons' `/components` entries.
|
|
8
|
+
*/
|
|
9
|
+
export { helmCapabilityPlugin, HELM_VERB_FAMILIES } from "./capability-plugin";
|
|
10
|
+
export * from "./builders";
|
|
11
|
+
export {
|
|
12
|
+
helmUpgradeCapability,
|
|
13
|
+
createHelmUpgradeCapability,
|
|
14
|
+
type HelmUpgradeInput,
|
|
15
|
+
type HelmUpgradeOutcome,
|
|
16
|
+
type HelmRunner,
|
|
17
|
+
} from "./helm-upgrade";
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { describeStackStatus } from "./describe-stack-status";
|
|
3
|
+
|
|
4
|
+
const list = (entries: unknown) => async () => ({ stdout: JSON.stringify(entries) });
|
|
5
|
+
|
|
6
|
+
describe("helm describeStackStatus (#1495 piece 4)", () => {
|
|
7
|
+
test("a deployed release: present and healthy, with Helm's native status", async () => {
|
|
8
|
+
const obs = await describeStackStatus(
|
|
9
|
+
{ environment: "local", stack: "api" },
|
|
10
|
+
list([{ name: "api", namespace: "prod", status: "deployed", revision: "3" }]),
|
|
11
|
+
);
|
|
12
|
+
expect(obs).toEqual({ stack: "api", present: true, status: "deployed", healthy: true });
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
test("a failed release: present, unhealthy, status carried verbatim", async () => {
|
|
16
|
+
const obs = await describeStackStatus(
|
|
17
|
+
{ environment: "local", stack: "api" },
|
|
18
|
+
list([{ name: "api", namespace: "prod", status: "failed" }]),
|
|
19
|
+
);
|
|
20
|
+
expect(obs).toEqual({ stack: "api", present: true, status: "failed", healthy: false });
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test("pending-upgrade is present but not healthy — deployed is the one success state", async () => {
|
|
24
|
+
const obs = await describeStackStatus(
|
|
25
|
+
{ environment: "local", stack: "api" },
|
|
26
|
+
list([{ name: "api", status: "pending-upgrade" }]),
|
|
27
|
+
);
|
|
28
|
+
expect(obs).toMatchObject({ present: true, status: "pending-upgrade", healthy: false });
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
test("release not in the list: absent — the pre-first-install state", async () => {
|
|
32
|
+
const obs = await describeStackStatus(
|
|
33
|
+
{ environment: "local", stack: "api" },
|
|
34
|
+
list([{ name: "other", status: "deployed" }]),
|
|
35
|
+
);
|
|
36
|
+
expect(obs).toEqual({ stack: "api", present: false });
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("a namespace-qualified unit only matches its own namespace", async () => {
|
|
40
|
+
const entries = [
|
|
41
|
+
{ name: "api", namespace: "staging", status: "failed" },
|
|
42
|
+
{ name: "api", namespace: "prod", status: "deployed" },
|
|
43
|
+
];
|
|
44
|
+
const prod = await describeStackStatus({ environment: "local", stack: "prod/api" }, list(entries));
|
|
45
|
+
expect(prod).toMatchObject({ present: true, status: "deployed", healthy: true });
|
|
46
|
+
|
|
47
|
+
const gone = await describeStackStatus({ environment: "local", stack: "dev/api" }, list(entries));
|
|
48
|
+
expect(gone).toEqual({ stack: "dev/api", present: false });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("helm missing or cluster unreachable: null — indeterminate, never a confident absence", async () => {
|
|
52
|
+
const obs = await describeStackStatus({ environment: "local", stack: "api" }, async () => {
|
|
53
|
+
throw new Error("helm: command not found");
|
|
54
|
+
});
|
|
55
|
+
expect(obs).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("unparseable or non-array output: null", async () => {
|
|
59
|
+
expect(await describeStackStatus({ environment: "local", stack: "api" }, async () => ({ stdout: "WARNING: ..." }))).toBeNull();
|
|
60
|
+
expect(await describeStackStatus({ environment: "local", stack: "api" }, async () => ({ stdout: '{"not":"an array"}' }))).toBeNull();
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deploy-unit status for Helm (#1495 piece 4).
|
|
3
|
+
*
|
|
4
|
+
* A Helm deploy unit *is* a release: `helm list` already reports its
|
|
5
|
+
* presence, revision, and native status, and that status lands on
|
|
6
|
+
* `StackStatusObservation` almost field-for-field — `deployed` is the one
|
|
7
|
+
* terminal success state, so `healthy` is exactly `status === "deployed"`.
|
|
8
|
+
* This reads back what `helm-upgrade` (the paired capability) writes, the
|
|
9
|
+
* same one-name-both-jobs pairing `cfn-deploy`/`kubectl-apply` have.
|
|
10
|
+
*
|
|
11
|
+
* Tri-state, matching the k8s observer's contract:
|
|
12
|
+
* - release found → `{ present: true, status, healthy }`
|
|
13
|
+
* - release not in list → `{ present: false }` (pre-first-install)
|
|
14
|
+
* - helm missing, no cluster, exec failure, unparseable output → `null` —
|
|
15
|
+
* "I cannot tell", never a confident absence.
|
|
16
|
+
*
|
|
17
|
+
* Cluster selection follows #1488: the environment's declared k8s binding
|
|
18
|
+
* (`k8s.profiles.<env>.context`) is passed as `--kube-context` when present;
|
|
19
|
+
* ambient otherwise. A Helm release lives on the same cluster the k8s half
|
|
20
|
+
* observes, so it rides the same binding.
|
|
21
|
+
*/
|
|
22
|
+
import { exec } from "node:child_process";
|
|
23
|
+
import { promisify } from "node:util";
|
|
24
|
+
import type { StackStatusObservation } from "@intentius/chant/lexicon";
|
|
25
|
+
import { loadChantConfigUpward } from "@intentius/chant/config";
|
|
26
|
+
import { resolveClusterTarget } from "@intentius/chant/kubectl-context";
|
|
27
|
+
|
|
28
|
+
const execAsync = promisify(exec);
|
|
29
|
+
|
|
30
|
+
/** Injectable command runner, so tests drive every branch without helm or a cluster. */
|
|
31
|
+
export type HelmRunner = (command: string) => Promise<{ stdout: string }>;
|
|
32
|
+
|
|
33
|
+
interface HelmListEntry {
|
|
34
|
+
name?: string;
|
|
35
|
+
namespace?: string;
|
|
36
|
+
status?: string;
|
|
37
|
+
revision?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export async function describeStackStatus(
|
|
41
|
+
options: { environment: string; stack: string },
|
|
42
|
+
run: HelmRunner = execAsync,
|
|
43
|
+
): Promise<StackStatusObservation | null> {
|
|
44
|
+
// The unit is a release name, optionally namespace-qualified as
|
|
45
|
+
// "<namespace>/<name>" when the same release name exists in two namespaces.
|
|
46
|
+
const slash = options.stack.indexOf("/");
|
|
47
|
+
const wantNs = slash > 0 ? options.stack.slice(0, slash) : undefined;
|
|
48
|
+
const wantName = slash > 0 ? options.stack.slice(slash + 1) : options.stack;
|
|
49
|
+
|
|
50
|
+
let context: string | undefined;
|
|
51
|
+
try {
|
|
52
|
+
const { config } = await loadChantConfigUpward(process.cwd());
|
|
53
|
+
context = (await resolveClusterTarget(config as Record<string, unknown>, options.environment, "helm")).context;
|
|
54
|
+
} catch {
|
|
55
|
+
context = undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let stdout: string;
|
|
59
|
+
try {
|
|
60
|
+
({ stdout } = await run(`helm list -A -o json${context ? ` --kube-context '${context.replace(/'/g, "'\\''")}'` : ""}`));
|
|
61
|
+
} catch {
|
|
62
|
+
// Binary missing, no kubeconfig, cluster unreachable — indeterminate.
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let entries: HelmListEntry[];
|
|
67
|
+
try {
|
|
68
|
+
entries = JSON.parse(stdout) as HelmListEntry[];
|
|
69
|
+
if (!Array.isArray(entries)) return null;
|
|
70
|
+
} catch {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const found = entries.find(
|
|
75
|
+
(e) => e.name === wantName && (wantNs === undefined || e.namespace === wantNs),
|
|
76
|
+
);
|
|
77
|
+
if (!found) return { stack: options.stack, present: false };
|
|
78
|
+
|
|
79
|
+
return {
|
|
80
|
+
stack: options.stack,
|
|
81
|
+
present: true,
|
|
82
|
+
...(found.status ? { status: found.status, healthy: found.status === "deployed" } : {}),
|
|
83
|
+
};
|
|
84
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,12 @@ export { helmSerializer } from "./serializer";
|
|
|
4
4
|
// Plugin
|
|
5
5
|
export { helmPlugin } from "./plugin";
|
|
6
6
|
|
|
7
|
+
// #1495 piece 4 — the component surface. `helmCapabilityPlugin` exported from
|
|
8
|
+
// the package entry is what `loadCapabilityPluginFromLexicon` scans for, the
|
|
9
|
+
// same discovery the aws and k8s plugins ride.
|
|
10
|
+
export { helmCapabilityPlugin, HELM_VERB_FAMILIES } from "./components/capability-plugin";
|
|
11
|
+
export { helmUpgradeCapability, createHelmUpgradeCapability, type HelmUpgradeInput, type HelmUpgradeOutcome } from "./components/helm-upgrade";
|
|
12
|
+
|
|
7
13
|
// Resources
|
|
8
14
|
export { Chart, Values, ValuesOverride, HelmTest, HelmNotes, HelmHook, HelmDependency, HelmMaintainer, HelmCRD } from "./resources";
|
|
9
15
|
|
package/src/plugin.ts
CHANGED
|
@@ -382,4 +382,12 @@ export const service = new Service({
|
|
|
382
382
|
const { listArtifacts } = await import("./list-artifacts");
|
|
383
383
|
return listArtifacts(options);
|
|
384
384
|
},
|
|
385
|
+
|
|
386
|
+
// #1495 piece 4 — the deploy-unit observer for helm-upgrade units: a
|
|
387
|
+
// release's presence and native status, read back by the same name the
|
|
388
|
+
// capability deploys under. Dynamic import mirrors listArtifacts.
|
|
389
|
+
async describeStackStatus(options) {
|
|
390
|
+
const { describeStackStatus } = await import("./describe-stack-status");
|
|
391
|
+
return describeStackStatus(options);
|
|
392
|
+
},
|
|
385
393
|
};
|