@intentius/chant-lexicon-pulumi 0.124.55 → 0.124.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/changed-units.d.ts +5 -0
- package/dist/changed-units.d.ts.map +1 -0
- package/dist/changed-units.js +101 -0
- package/dist/check-step.d.ts +61 -0
- package/dist/check-step.d.ts.map +1 -0
- package/dist/check-step.js +270 -0
- package/dist/composites/pulumi-adopt-op.d.ts.map +1 -1
- package/dist/composites/pulumi-adopt-op.js +4 -2
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/dist/member-outputs.d.ts +10 -3
- package/dist/member-outputs.d.ts.map +1 -1
- package/dist/member-outputs.js +11 -3
- package/dist/op/activities/pulumi-adopt.d.ts +5 -0
- package/dist/op/activities/pulumi-adopt.d.ts.map +1 -1
- package/dist/op/activities/pulumi-adopt.js +7 -2
- package/dist/op/activity-contracts.d.ts +2 -0
- package/dist/op/activity-contracts.d.ts.map +1 -1
- package/dist/op/activity-contracts.js +2 -2
- package/dist/planned-output-changes.d.ts +60 -0
- package/dist/planned-output-changes.d.ts.map +1 -0
- package/dist/planned-output-changes.js +94 -0
- package/dist/plugin.d.ts.map +1 -1
- package/dist/plugin.js +24 -0
- package/dist/preview-tips.d.ts +71 -0
- package/dist/preview-tips.d.ts.map +1 -0
- package/dist/preview-tips.js +76 -0
- package/dist/pulumi-up.d.ts +24 -1
- package/dist/pulumi-up.d.ts.map +1 -1
- package/dist/pulumi-up.js +64 -16
- package/dist/release-copy.d.ts +42 -2
- package/dist/release-copy.d.ts.map +1 -1
- package/dist/release-copy.js +96 -22
- package/dist/run.d.ts +27 -8
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +55 -14
- package/package.json +2 -2
- package/src/changed-units.test.ts +87 -0
- package/src/changed-units.ts +96 -0
- package/src/check-step.test.ts +191 -0
- package/src/check-step.ts +316 -0
- package/src/composites/pulumi-adopt-op.test.ts +35 -0
- package/src/composites/pulumi-adopt-op.ts +4 -2
- package/src/index.ts +2 -0
- package/src/member-outputs.test.ts +28 -6
- package/src/member-outputs.ts +22 -4
- package/src/op/activities/pulumi-adopt.ts +13 -2
- package/src/op/activity-contracts.ts +2 -2
- package/src/planned-output-changes.test.ts +85 -0
- package/src/planned-output-changes.ts +141 -0
- package/src/plugin.ts +26 -0
- package/src/preview-tips.test.ts +135 -0
- package/src/preview-tips.ts +128 -0
- package/src/pulumi-up.test.ts +100 -0
- package/src/pulumi-up.ts +84 -18
- package/src/release-copy.test.ts +90 -2
- package/src/release-copy.ts +103 -22
- package/src/run-plan-flags.test.ts +53 -0
- package/src/run.test.ts +1 -1
- package/src/run.ts +57 -14
- package/src/stack-export-snapshot.test.ts +3 -1
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@ A step pinned to its own engine release sets `engineVersion` (and `engineRoot` w
|
|
|
27
27
|
|
|
28
28
|
The CI install lines take a version, download the release's Linux archive and its checksums file, and fail unless the archive matches its line there. For the default releases (Pulumi 3.272.0, plunge 0.1.0) the line must also hold the sha256 the lexicon records per architecture. Each release goes under its own versioned directory and is linked into `/usr/local/bin`, and a line skips the download when that directory already holds the binary, or for Pulumi when the `pulumi` on PATH is that version.
|
|
29
29
|
|
|
30
|
-
The preview streams its engine events (`PULUMI_ENABLE_STREAMING_JSON_PREVIEW=true`, `src/engine-events.ts`), so one run gives the change set and CrossGuard's findings. A mandatory violation denies the plan. On plunge the saved plan's stamp refuses a plan whose records moved (plunge exit 40, chant's moved code 4). On stock Pulumi the apply previews again, then compares the steps in `up`'s event stream with the approved shape (`src/plan-shape.ts`), and a step outside it fails the apply. A member on the resource lock grain, the default on plunge, leaves `same` and `read` steps out of its digest. The step's `config` is written into a scratch copy of `Pulumi.<stack>.yaml` and passed with `--config-file`, never `--config`, which writes the working tree's file. A release cut records the stack's directory (`releaseInputs`), unless its backend is a file path relative to that directory. Under a release, a promote or rollback previews and applies the recorded copy, after `pulumi install` (or `plunge install`) in the copy when its runtime needs one (`src/release-copy.ts`); a Node copy with no recorded lockfile is refused by name.
|
|
30
|
+
The preview streams its engine events (`PULUMI_ENABLE_STREAMING_JSON_PREVIEW=true`, `src/engine-events.ts`), so one run gives the change set and CrossGuard's findings. A mandatory violation denies the plan. On plunge the saved plan's stamp refuses a plan whose records moved (plunge exit 40, chant's moved code 4). On stock Pulumi the apply previews again, then compares the steps in `up`'s event stream with the approved shape (`src/plan-shape.ts`), and a step outside it fails the apply. A member on the resource lock grain, the default on plunge, leaves `same` and `read` steps out of its digest. The step's `config` is written into a scratch copy of `Pulumi.<stack>.yaml` and passed with `--config-file`, never `--config`, which writes the working tree's file. A release cut records the stack's directory (`releaseInputs`), unless its backend is a file path relative to that directory. Under a release, a promote or rollback previews and applies the recorded copy, after `pulumi install` (or `plunge install`) in the copy when its runtime needs one (`src/release-copy.ts`); a Node copy with no recorded lockfile is refused by name. A job's checkout gets the same install before its first engine run when nothing installed the program there (`prepareProgram`), and a Node checkout with no lockfile is refused by name.
|
|
31
31
|
|
|
32
32
|
After `up`, the capability runs `stack export --stack <s>`, replaces every secret with `[secret]`, drops the secrets provider's state, and writes the export through chant's index store as `<env>/<stack>__pulumi-export` ([#4546](https://github.com/INTENTIUS/chant/issues/4546), `refs/chant/snapshots` by default). The graph, the preview's prior state and the drift read take that export first, so a stack chant applies needs no checked-in `stack-export.json`. A failed export leaves the apply standing and says why in the step's `exportSnapshot` output.
|
|
33
33
|
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The unit core names for a `pulumi-up` step on `stack` in `dir` (deploy-units.ts `pulumiStackUnit`). */
|
|
2
|
+
export declare function pulumiStackUnit(dir: string, stack: string): string;
|
|
3
|
+
/** The stack units `changedFiles` (relative to `projectRoot`, `/` separators) touch, sorted. */
|
|
4
|
+
export declare function pulumiChangedUnits(projectRoot: string, changedFiles: readonly string[]): string[];
|
|
5
|
+
//# sourceMappingURL=changed-units.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"changed-units.d.ts","sourceRoot":"","sources":["../src/changed-units.ts"],"names":[],"mappings":"AAgCA,0GAA0G;AAC1G,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAGlE;AA2CD,gGAAgG;AAChG,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAejG"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Pulumi stacks a change touched, judged from the changed files alone
|
|
3
|
+
* (`LexiconPlugin.changedUnits`, #3183; INTENTIUS/plywood#22). A Pulumi
|
|
4
|
+
* program and its stack configs are not chant source, so `chant lifecycle
|
|
5
|
+
* affected`'s artifact diff never shows them, and without this a pull request
|
|
6
|
+
* that edits `Pulumi.dev.yaml` selects no component at all.
|
|
7
|
+
*
|
|
8
|
+
* A file belongs to the nearest directory at or above it holding a
|
|
9
|
+
* `Pulumi.yaml` (or `Pulumi.yml`), the project, never above the project root:
|
|
10
|
+
*
|
|
11
|
+
* - `Pulumi.<stack>.yaml` in that directory is the stack's config, so it
|
|
12
|
+
* touches that stack alone;
|
|
13
|
+
* - any other file there or below (the program, `Pulumi.yaml`, the
|
|
14
|
+
* package files) touches every stack of the project, which is each
|
|
15
|
+
* `Pulumi.<stack>.yaml` beside `Pulumi.yaml` at head and any the change
|
|
16
|
+
* deleted. A stack with no config file has no file to find it by, so a
|
|
17
|
+
* program change does not reach it.
|
|
18
|
+
*
|
|
19
|
+
* Files under a directory whose name starts with a dot (`.forgejo`, `.chant`,
|
|
20
|
+
* `.git`) or under `node_modules` are not the program. A file outside every
|
|
21
|
+
* project, such as a module the program imports from `../shared`, is not
|
|
22
|
+
* claimed.
|
|
23
|
+
*
|
|
24
|
+
* Each unit is named as core's `DEPLOY_UNIT_RULES` names a `pulumi-up` step:
|
|
25
|
+
* `<dir>/<stack>`, or `<stack>` for a project at the project root.
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
28
|
+
import { join, posix } from "node:path";
|
|
29
|
+
const PROJECT_FILES = ["Pulumi.yaml", "Pulumi.yml"];
|
|
30
|
+
const STACK_CONFIG = /^Pulumi\.(.+)\.ya?ml$/;
|
|
31
|
+
/** The unit core names for a `pulumi-up` step on `stack` in `dir` (deploy-units.ts `pulumiStackUnit`). */
|
|
32
|
+
export function pulumiStackUnit(dir, stack) {
|
|
33
|
+
const d = dir.replace(/\\/g, "/").replace(/^(\.\/)+/, "").replace(/\/+$/, "");
|
|
34
|
+
return d === "" || d === "." ? stack : `${d}/${stack}`;
|
|
35
|
+
}
|
|
36
|
+
/** The project directory (relative, `""` for the root) holding `file`, or undefined when none does. */
|
|
37
|
+
function projectOf(projectRoot, file, changed) {
|
|
38
|
+
let dir = posix.dirname(file);
|
|
39
|
+
for (;;) {
|
|
40
|
+
const rel = dir === "." ? "" : dir;
|
|
41
|
+
for (const name of PROJECT_FILES) {
|
|
42
|
+
const p = rel === "" ? name : `${rel}/${name}`;
|
|
43
|
+
// A deleted Pulumi.yaml still names its project for the change that deleted it.
|
|
44
|
+
if (existsSync(join(projectRoot, p)) || changed.has(p))
|
|
45
|
+
return rel;
|
|
46
|
+
}
|
|
47
|
+
if (rel === "")
|
|
48
|
+
return undefined;
|
|
49
|
+
dir = posix.dirname(dir);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** The stacks of the project in `dir`: the stack configs at head, and the ones the change names. */
|
|
53
|
+
function stacksOf(projectRoot, dir, changed) {
|
|
54
|
+
const out = new Set();
|
|
55
|
+
let names = [];
|
|
56
|
+
try {
|
|
57
|
+
names = readdirSync(join(projectRoot, dir));
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
// The project directory is gone at head; the change's own files still name stacks.
|
|
61
|
+
}
|
|
62
|
+
for (const n of names) {
|
|
63
|
+
const m = STACK_CONFIG.exec(n);
|
|
64
|
+
if (m)
|
|
65
|
+
out.add(m[1]);
|
|
66
|
+
}
|
|
67
|
+
for (const f of changed) {
|
|
68
|
+
if (posix.dirname(f) !== (dir === "" ? "." : dir))
|
|
69
|
+
continue;
|
|
70
|
+
const m = STACK_CONFIG.exec(posix.basename(f));
|
|
71
|
+
if (m)
|
|
72
|
+
out.add(m[1]);
|
|
73
|
+
}
|
|
74
|
+
return [...out];
|
|
75
|
+
}
|
|
76
|
+
function ignored(file) {
|
|
77
|
+
const parts = file.split("/");
|
|
78
|
+
return parts.slice(0, -1).some((p) => p.startsWith(".") || p === "node_modules");
|
|
79
|
+
}
|
|
80
|
+
/** The stack units `changedFiles` (relative to `projectRoot`, `/` separators) touch, sorted. */
|
|
81
|
+
export function pulumiChangedUnits(projectRoot, changedFiles) {
|
|
82
|
+
const files = changedFiles.map((f) => f.replace(/\\/g, "/").replace(/^\.\//, "")).filter((f) => f !== "" && !f.startsWith("../") && !ignored(f));
|
|
83
|
+
const changed = new Set(files);
|
|
84
|
+
const units = new Set();
|
|
85
|
+
const whole = new Set();
|
|
86
|
+
for (const f of files) {
|
|
87
|
+
const dir = projectOf(projectRoot, f, changed);
|
|
88
|
+
if (dir === undefined)
|
|
89
|
+
continue;
|
|
90
|
+
const here = posix.dirname(f) === (dir === "" ? "." : dir);
|
|
91
|
+
const m = STACK_CONFIG.exec(posix.basename(f));
|
|
92
|
+
if (here && m && !PROJECT_FILES.includes(posix.basename(f)))
|
|
93
|
+
units.add(pulumiStackUnit(dir, m[1]));
|
|
94
|
+
else
|
|
95
|
+
whole.add(dir);
|
|
96
|
+
}
|
|
97
|
+
for (const dir of whole)
|
|
98
|
+
for (const stack of stacksOf(projectRoot, dir, files))
|
|
99
|
+
units.add(pulumiStackUnit(dir, stack));
|
|
100
|
+
return [...units].sort();
|
|
101
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import type { CheckStageMember, CheckStepOutcome, CheckStepsAdapter, CheckStepsContext } from "@intentius/chant/components/check-steps";
|
|
2
|
+
import { type PulumiMemberEngine } from "./member-engine.js";
|
|
3
|
+
import { type PulumiRunner } from "./run.js";
|
|
4
|
+
/** A runner for `bin` with exactly `env` (the check job's), never the process's whole environment. */
|
|
5
|
+
export declare function checkRunner(bin: PulumiMemberEngine, env: Record<string, string>): PulumiRunner;
|
|
6
|
+
/** One key the project declares in `Pulumi.yaml`'s `config:`. */
|
|
7
|
+
export interface PulumiConfigKey {
|
|
8
|
+
/** The full key, `<project>:<name>` for a project key. */
|
|
9
|
+
key: string;
|
|
10
|
+
type?: string;
|
|
11
|
+
items?: {
|
|
12
|
+
type?: string;
|
|
13
|
+
};
|
|
14
|
+
secret: boolean;
|
|
15
|
+
/** Whether it has a `default` or a project-level `value`. */
|
|
16
|
+
hasDefault: boolean;
|
|
17
|
+
}
|
|
18
|
+
/** The project's config schema: its name, the keys it declares, and where its stack files are. */
|
|
19
|
+
export interface PulumiProjectSchema {
|
|
20
|
+
project: string;
|
|
21
|
+
keys: PulumiConfigKey[];
|
|
22
|
+
/** The directory the stack files are in, relative to the project (`stackConfigDir`), or "." */
|
|
23
|
+
stackConfigDir: string;
|
|
24
|
+
}
|
|
25
|
+
/** Read `Pulumi.yaml`'s schema from its parsed document. A short-form entry (`key: value`) is a value with no type. */
|
|
26
|
+
export declare function pulumiProjectSchema(doc: unknown): PulumiProjectSchema;
|
|
27
|
+
/**
|
|
28
|
+
* What is wrong with one stack's config (`config:` of its
|
|
29
|
+
* `Pulumi.<stack>.yaml`, parsed) against the project's schema, as lines
|
|
30
|
+
* naming the stack and key. Empty when it passes. Keys of other namespaces
|
|
31
|
+
* (a provider's `aws:region`) are not checked: the project declares no type
|
|
32
|
+
* for them.
|
|
33
|
+
*/
|
|
34
|
+
export declare function pulumiStackConfigProblems(schema: PulumiProjectSchema, stack: string, stackDoc: unknown): string[];
|
|
35
|
+
/** The stacks the project lists by their `Pulumi.<stack>.yaml` files in `dir`, sorted. */
|
|
36
|
+
export declare function listedStacks(dir: string): string[];
|
|
37
|
+
/** What `pulumi about --json` reported, for the check report. */
|
|
38
|
+
export interface PulumiAboutDetail {
|
|
39
|
+
engine: PulumiMemberEngine;
|
|
40
|
+
version?: string;
|
|
41
|
+
plugins: Array<{
|
|
42
|
+
name: string;
|
|
43
|
+
version?: string;
|
|
44
|
+
}>;
|
|
45
|
+
backend?: {
|
|
46
|
+
name?: string;
|
|
47
|
+
url?: string;
|
|
48
|
+
user?: string;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/** Read `pulumi about --json`'s document. Undefined when it is not JSON. */
|
|
52
|
+
export declare function pulumiAboutDetail(engine: PulumiMemberEngine, stdout: string | undefined): PulumiAboutDetail | undefined;
|
|
53
|
+
export interface PulumiCheckStepsOptions {
|
|
54
|
+
/** The runner for an engine, given the check job's environment. Default {@link checkRunner}. */
|
|
55
|
+
runner?: (engine: PulumiMemberEngine, env: Record<string, string>) => PulumiRunner;
|
|
56
|
+
}
|
|
57
|
+
/** The steps for one member, in order: install, each stack's config, about. */
|
|
58
|
+
export declare function pulumiMemberCheck(member: CheckStageMember, ctx: Pick<CheckStepsContext, "env" | "log">, opts?: PulumiCheckStepsOptions): Promise<CheckStepOutcome[]>;
|
|
59
|
+
/** The pulumi lexicon's check steps, for `LexiconPlugin.checkSteps`. */
|
|
60
|
+
export declare function pulumiCheckSteps(opts?: PulumiCheckStepsOptions): CheckStepsAdapter;
|
|
61
|
+
//# sourceMappingURL=check-step.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-step.d.ts","sourceRoot":"","sources":["../src/check-step.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAExI,OAAO,EAAsB,KAAK,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAA+C,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAOvF,sGAAsG;AACtG,wBAAgB,WAAW,CAAC,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAE9F;AAID,iEAAiE;AACjE,MAAM,WAAW,eAAe;IAC9B,0DAA0D;IAC1D,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;IAChB,6DAA6D;IAC7D,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,kGAAkG;AAClG,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,eAAe,EAAE,CAAC;IACxB,+FAA+F;IAC/F,cAAc,EAAE,MAAM,CAAC;CACxB;AASD,uHAAuH;AACvH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,mBAAmB,CAsBrE;AAoBD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,mBAAmB,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,EAAE,CA2BjH;AAOD,0FAA0F;AAC1F,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAMlD;AASD,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,kBAAkB,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACnD,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1D;AAED,4EAA4E;AAC5E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,iBAAiB,GAAG,SAAS,CAkBvH;AAUD,MAAM,WAAW,uBAAuB;IACtC,gGAAgG;IAChG,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,YAAY,CAAC;CACpF;AAED,+EAA+E;AAC/E,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,EAAE,IAAI,CAAC,iBAAiB,EAAE,KAAK,GAAG,KAAK,CAAC,EAAE,IAAI,GAAE,uBAA4B,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAsF9K;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,IAAI,GAAE,uBAA4B,GAAG,iBAAiB,CAUtF"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pulumi lexicon's steps in chant's check stage (#4633). `chant ci
|
|
3
|
+
* check` runs them after the `ci.hooks.check` hooks, for each workspace
|
|
4
|
+
* member of kind `pulumi` (`LexiconPlugin.checkSteps`,
|
|
5
|
+
* `@intentius/chant/components/check-steps`), so a product's check
|
|
6
|
+
* (`plywood check`) gets them through chant with nothing of its own:
|
|
7
|
+
*
|
|
8
|
+
* - `pulumi-install`: `pulumi install` (`plunge install` for a member on
|
|
9
|
+
* plunge, `./member-engine.ts`) in the member's directory, which fetches
|
|
10
|
+
* the program's dependencies and plugins the way `Pulumi.yaml` says;
|
|
11
|
+
* - `stack-config`: each stack's `Pulumi.<stack>.yaml` checked against the
|
|
12
|
+
* project's config schema in `Pulumi.yaml`, with no command run (a key
|
|
13
|
+
* with a type and no default must be set, a value must read as its type,
|
|
14
|
+
* and a `secret: true` key must be encrypted). The stacks are the ones the
|
|
15
|
+
* project lists by their files, plus the member's declared stack;
|
|
16
|
+
* - `pulumi-about`: `pulumi about --json`, which reports the engine, its
|
|
17
|
+
* plugins and the backend for the report.
|
|
18
|
+
*
|
|
19
|
+
* The argv go through `runCheckPulumi` (`./run.ts`), which refuses any
|
|
20
|
+
* other. The environment is the check job's ({@link CheckStepsContext.env}):
|
|
21
|
+
* no forge token, no OIDC request variables, no cloud credential, so neither
|
|
22
|
+
* command can write a stack. A failure names the member and stack, and the
|
|
23
|
+
* check exits with chant's `failed` code.
|
|
24
|
+
*
|
|
25
|
+
* The runner is injectable, so the tests run no binary.
|
|
26
|
+
*/
|
|
27
|
+
import { execFile } from "node:child_process";
|
|
28
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
29
|
+
import { join } from "node:path";
|
|
30
|
+
import { promisify } from "node:util";
|
|
31
|
+
import { parseYAML } from "@intentius/chant/yaml";
|
|
32
|
+
import { pulumiMemberEngine } from "./member-engine.js";
|
|
33
|
+
import { engineEnv, pulumiRunFailure, runCheckPulumi } from "./run.js";
|
|
34
|
+
const execFileAsync = promisify(execFile);
|
|
35
|
+
/** The lexicon name the report carries. */
|
|
36
|
+
const LEXICON = "pulumi";
|
|
37
|
+
/** A runner for `bin` with exactly `env` (the check job's), never the process's whole environment. */
|
|
38
|
+
export function checkRunner(bin, env) {
|
|
39
|
+
return (args, opts) => execFileAsync(bin, args, { cwd: opts.cwd, maxBuffer: 64 * 1024 * 1024, env: engineEnv({ ...env, ...opts.env }) });
|
|
40
|
+
}
|
|
41
|
+
const isRecord = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
42
|
+
/** The key in its full form: a bare name belongs to the project. */
|
|
43
|
+
function fullKey(project, key) {
|
|
44
|
+
return key.includes(":") ? key : `${project}:${key}`;
|
|
45
|
+
}
|
|
46
|
+
/** Read `Pulumi.yaml`'s schema from its parsed document. A short-form entry (`key: value`) is a value with no type. */
|
|
47
|
+
export function pulumiProjectSchema(doc) {
|
|
48
|
+
const d = isRecord(doc) ? doc : {};
|
|
49
|
+
const project = typeof d.name === "string" ? d.name : "";
|
|
50
|
+
const config = isRecord(d.config) ? d.config : {};
|
|
51
|
+
const keys = [];
|
|
52
|
+
for (const [name, entry] of Object.entries(config)) {
|
|
53
|
+
const key = fullKey(project, name);
|
|
54
|
+
const schema = isRecord(entry) && ("type" in entry || "default" in entry || "value" in entry || "secret" in entry || "description" in entry || "items" in entry);
|
|
55
|
+
if (!schema) {
|
|
56
|
+
keys.push({ key, secret: false, hasDefault: true });
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
const e = entry;
|
|
60
|
+
keys.push({
|
|
61
|
+
key,
|
|
62
|
+
...(typeof e.type === "string" ? { type: e.type } : {}),
|
|
63
|
+
...(isRecord(e.items) && typeof e.items.type === "string" ? { items: { type: e.items.type } } : {}),
|
|
64
|
+
secret: e.secret === true,
|
|
65
|
+
hasDefault: "default" in e || "value" in e,
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return { project, keys, stackConfigDir: typeof d.stackConfigDir === "string" && d.stackConfigDir.length > 0 ? d.stackConfigDir : "." };
|
|
69
|
+
}
|
|
70
|
+
const isSecure = (v) => isRecord(v) && typeof v.secure === "string";
|
|
71
|
+
/** Whether a scalar stack value reads as `type`. Values are strings once Pulumi reads them, so `"3"` is an integer. */
|
|
72
|
+
function readsAs(type, value) {
|
|
73
|
+
switch (type) {
|
|
74
|
+
case "string":
|
|
75
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
|
|
76
|
+
case "integer":
|
|
77
|
+
return (typeof value === "number" && Number.isInteger(value)) || (typeof value === "string" && /^-?[0-9]+$/.test(value.trim()));
|
|
78
|
+
case "boolean":
|
|
79
|
+
return typeof value === "boolean" || value === "true" || value === "false";
|
|
80
|
+
case "array":
|
|
81
|
+
return Array.isArray(value);
|
|
82
|
+
default:
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* What is wrong with one stack's config (`config:` of its
|
|
88
|
+
* `Pulumi.<stack>.yaml`, parsed) against the project's schema, as lines
|
|
89
|
+
* naming the stack and key. Empty when it passes. Keys of other namespaces
|
|
90
|
+
* (a provider's `aws:region`) are not checked: the project declares no type
|
|
91
|
+
* for them.
|
|
92
|
+
*/
|
|
93
|
+
export function pulumiStackConfigProblems(schema, stack, stackDoc) {
|
|
94
|
+
const raw = isRecord(stackDoc) && isRecord(stackDoc.config) ? stackDoc.config : {};
|
|
95
|
+
const values = new Map();
|
|
96
|
+
for (const [k, v] of Object.entries(raw))
|
|
97
|
+
values.set(fullKey(schema.project, k), v);
|
|
98
|
+
const problems = [];
|
|
99
|
+
for (const k of schema.keys) {
|
|
100
|
+
if (!k.type && !k.secret)
|
|
101
|
+
continue;
|
|
102
|
+
if (!values.has(k.key)) {
|
|
103
|
+
if (k.type && !k.hasDefault)
|
|
104
|
+
problems.push(`stack ${stack} is missing the configuration value ${k.key} (type ${k.type}, no default)`);
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
107
|
+
const value = values.get(k.key);
|
|
108
|
+
if (k.secret && !isSecure(value)) {
|
|
109
|
+
problems.push(`stack ${stack} sets ${k.key} in plain text, and the project declares it secret; set it with pulumi config set --secret`);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
if (isSecure(value) || !k.type)
|
|
113
|
+
continue;
|
|
114
|
+
if (!readsAs(k.type, value)) {
|
|
115
|
+
problems.push(`stack ${stack} sets ${k.key} to ${JSON.stringify(value)}, which is not of type ${k.type}`);
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
if (k.type === "array" && k.items?.type && Array.isArray(value)) {
|
|
119
|
+
const bad = value.findIndex((item) => !isSecure(item) && !readsAs(k.items.type, item));
|
|
120
|
+
if (bad >= 0)
|
|
121
|
+
problems.push(`stack ${stack} sets ${k.key}[${bad}] to ${JSON.stringify(value[bad])}, which is not of type ${k.items.type}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
return problems;
|
|
125
|
+
}
|
|
126
|
+
/** The project's file in `dir`, `Pulumi.yaml` or `Pulumi.yml`. */
|
|
127
|
+
function projectFile(dir) {
|
|
128
|
+
return ["Pulumi.yaml", "Pulumi.yml"].map((f) => join(dir, f)).find((f) => existsSync(f));
|
|
129
|
+
}
|
|
130
|
+
/** The stacks the project lists by their `Pulumi.<stack>.yaml` files in `dir`, sorted. */
|
|
131
|
+
export function listedStacks(dir) {
|
|
132
|
+
if (!existsSync(dir))
|
|
133
|
+
return [];
|
|
134
|
+
return readdirSync(dir)
|
|
135
|
+
.map((f) => /^Pulumi\.(.+)\.ya?ml$/.exec(f)?.[1])
|
|
136
|
+
.filter((s) => s !== undefined)
|
|
137
|
+
.sort();
|
|
138
|
+
}
|
|
139
|
+
/** The stack file for `stack` in `dir`, if there is one. */
|
|
140
|
+
function stackFile(dir, stack) {
|
|
141
|
+
return [`Pulumi.${stack}.yaml`, `Pulumi.${stack}.yml`].map((f) => join(dir, f)).find((f) => existsSync(f));
|
|
142
|
+
}
|
|
143
|
+
/** Read `pulumi about --json`'s document. Undefined when it is not JSON. */
|
|
144
|
+
export function pulumiAboutDetail(engine, stdout) {
|
|
145
|
+
if (!stdout)
|
|
146
|
+
return undefined;
|
|
147
|
+
let doc;
|
|
148
|
+
try {
|
|
149
|
+
doc = JSON.parse(stdout);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
if (!isRecord(doc))
|
|
155
|
+
return undefined;
|
|
156
|
+
const cli = isRecord(doc.cli) ? doc.cli : {};
|
|
157
|
+
const plugins = Array.isArray(doc.plugins)
|
|
158
|
+
? doc.plugins.filter(isRecord).map((p) => ({ name: String(p.name ?? ""), ...(typeof p.version === "string" ? { version: p.version } : {}) })).filter((p) => p.name)
|
|
159
|
+
: [];
|
|
160
|
+
const b = isRecord(doc.backend) ? doc.backend : undefined;
|
|
161
|
+
const backend = b
|
|
162
|
+
? { ...(typeof b.name === "string" ? { name: b.name } : {}), ...(typeof b.url === "string" ? { url: b.url } : {}), ...(typeof b.user === "string" ? { user: b.user } : {}) }
|
|
163
|
+
: undefined;
|
|
164
|
+
return { engine, ...(typeof cli.version === "string" ? { version: cli.version } : {}), plugins, ...(backend ? { backend } : {}) };
|
|
165
|
+
}
|
|
166
|
+
// ── The steps ───────────────────────────────────────────────────────
|
|
167
|
+
/** The last lines of what a failed run printed, for its reason. */
|
|
168
|
+
function tail(text) {
|
|
169
|
+
const lines = (text ?? "").trim().split("\n").filter(Boolean);
|
|
170
|
+
return lines.slice(-3).join(" | ");
|
|
171
|
+
}
|
|
172
|
+
/** The steps for one member, in order: install, each stack's config, about. */
|
|
173
|
+
export async function pulumiMemberCheck(member, ctx, opts = {}) {
|
|
174
|
+
const fields = member.fields ?? {};
|
|
175
|
+
const declaredEngine = fields.engine === "pulumi" || fields.engine === "plunge" ? fields.engine : undefined;
|
|
176
|
+
const declaredStack = typeof fields.stack === "string" && fields.stack.length > 0 ? fields.stack : undefined;
|
|
177
|
+
const { engine } = pulumiMemberEngine(member.dir, declaredEngine, { env: ctx.env });
|
|
178
|
+
const run = (opts.runner ?? checkRunner)(engine, ctx.env);
|
|
179
|
+
const out = [];
|
|
180
|
+
const base = { lexicon: LEXICON, member: member.name };
|
|
181
|
+
const file = projectFile(member.dir);
|
|
182
|
+
if (!file) {
|
|
183
|
+
out.push({ ...base, step: "pulumi-install", exit: 1, outcome: "failed", reason: `member ${member.name} has no Pulumi.yaml in ${member.dir}` });
|
|
184
|
+
return out;
|
|
185
|
+
}
|
|
186
|
+
// pulumi install
|
|
187
|
+
let installed = true;
|
|
188
|
+
try {
|
|
189
|
+
await runCheckPulumi(run, ["install"], member.dir);
|
|
190
|
+
out.push({ ...base, step: "pulumi-install", exit: 0, outcome: "passed" });
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
installed = false;
|
|
194
|
+
const f = pulumiRunFailure(err);
|
|
195
|
+
const why = f.missingBinary ? `${engine} is not installed in the check job` : tail(f.stderr) || tail(f.stdout) || f.message;
|
|
196
|
+
out.push({ ...base, step: "pulumi-install", exit: f.exitCode ?? 1, outcome: "failed", reason: `${engine} install failed for member ${member.name}: ${why}` });
|
|
197
|
+
}
|
|
198
|
+
// Stack config, run by nothing but this module.
|
|
199
|
+
let schema;
|
|
200
|
+
try {
|
|
201
|
+
schema = pulumiProjectSchema(parseYAML(readFileSync(file, "utf-8")));
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
out.push({ ...base, step: "stack-config", exit: 1, outcome: "failed", reason: `member ${member.name}: ${file} does not read as YAML (${err instanceof Error ? err.message : String(err)})` });
|
|
205
|
+
}
|
|
206
|
+
if (schema) {
|
|
207
|
+
const stackDir = join(member.dir, schema.stackConfigDir);
|
|
208
|
+
const stacks = [...new Set([...listedStacks(stackDir), ...(declaredStack ? [declaredStack] : [])])].sort();
|
|
209
|
+
if (stacks.length === 0)
|
|
210
|
+
out.push({ ...base, step: "stack-config", exit: 0, outcome: "skipped", reason: `member ${member.name} lists no stack (no Pulumi.<stack>.yaml in ${stackDir})` });
|
|
211
|
+
for (const stack of stacks) {
|
|
212
|
+
const at = stackFile(stackDir, stack);
|
|
213
|
+
let doc = {};
|
|
214
|
+
if (at) {
|
|
215
|
+
try {
|
|
216
|
+
doc = parseYAML(readFileSync(at, "utf-8"));
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
out.push({ ...base, step: "stack-config", stack, exit: 1, outcome: "failed", reason: `member ${member.name}, stack ${stack}: ${at} does not read as YAML (${err instanceof Error ? err.message : String(err)})` });
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
const problems = pulumiStackConfigProblems(schema, stack, doc);
|
|
224
|
+
out.push(problems.length === 0
|
|
225
|
+
? { ...base, step: "stack-config", stack, exit: 0, outcome: "passed" }
|
|
226
|
+
: { ...base, step: "stack-config", stack, exit: 1, outcome: "failed", reason: `member ${member.name}: ${problems.join("; ")}`, detail: { problems } });
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// pulumi about --json
|
|
230
|
+
if (!installed) {
|
|
231
|
+
out.push({ ...base, step: "pulumi-about", exit: 0, outcome: "skipped", reason: `member ${member.name}: ${engine} install failed, so about did not run` });
|
|
232
|
+
return out;
|
|
233
|
+
}
|
|
234
|
+
const aboutArgs = declaredStack ? ["about", "--json", "--stack", declaredStack] : ["about", "--json"];
|
|
235
|
+
const stackPart = declaredStack ? { stack: declaredStack } : {};
|
|
236
|
+
try {
|
|
237
|
+
const { stdout } = await runCheckPulumi(run, aboutArgs, member.dir);
|
|
238
|
+
const detail = pulumiAboutDetail(engine, stdout);
|
|
239
|
+
out.push(detail
|
|
240
|
+
? { ...base, step: "pulumi-about", ...stackPart, exit: 0, outcome: "passed", detail }
|
|
241
|
+
: { ...base, step: "pulumi-about", ...stackPart, exit: 1, outcome: "failed", reason: `${engine} about --json for member ${member.name} printed no JSON` });
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
const f = pulumiRunFailure(err);
|
|
245
|
+
// about exits non-zero when one of its reads fails (no backend login in a check job), and still prints what it read.
|
|
246
|
+
const detail = pulumiAboutDetail(engine, f.stdout);
|
|
247
|
+
if (detail) {
|
|
248
|
+
ctx.log(`pulumi check: ${engine} about for ${member.name} exited ${f.exitCode ?? 1} and reported: ${tail(f.stderr) || "no reason"}`);
|
|
249
|
+
out.push({ ...base, step: "pulumi-about", ...stackPart, exit: f.exitCode ?? 1, outcome: "passed", detail });
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
const why = f.missingBinary ? `${engine} is not installed in the check job` : tail(f.stderr) || f.message;
|
|
253
|
+
out.push({ ...base, step: "pulumi-about", ...stackPart, exit: f.exitCode ?? 1, outcome: "failed", reason: `${engine} about failed for member ${member.name}${declaredStack ? `, stack ${declaredStack}` : ""}: ${why}` });
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return out;
|
|
257
|
+
}
|
|
258
|
+
/** The pulumi lexicon's check steps, for `LexiconPlugin.checkSteps`. */
|
|
259
|
+
export function pulumiCheckSteps(opts = {}) {
|
|
260
|
+
return {
|
|
261
|
+
lexicon: LEXICON,
|
|
262
|
+
kinds: ["pulumi"],
|
|
263
|
+
async run(ctx) {
|
|
264
|
+
const out = [];
|
|
265
|
+
for (const member of ctx.members)
|
|
266
|
+
out.push(...(await pulumiMemberCheck(member, ctx, opts)));
|
|
267
|
+
return out;
|
|
268
|
+
},
|
|
269
|
+
};
|
|
270
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pulumi-adopt-op.d.ts","sourceRoot":"","sources":["../../src/composites/pulumi-adopt-op.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,OAAO,EAA6B,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAG5E,0BAA0B;AAC1B,MAAM,WAAW,gBAAgB;IAC/B,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,mHAAmH;IACnH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,sHAAsH;IACtH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,qFAAqF;IACrF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2HAA2H;IAC3H,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qGAAqG;IACrG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6FAA6F;IAC7F,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AAED,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,EAAE,EAAE,YAAY,CAAC,OAAO,UAAU,CAAC,CAAC;CACrC;AAID,wBAAgB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,sBAAsB,
|
|
1
|
+
{"version":3,"file":"pulumi-adopt-op.d.ts","sourceRoot":"","sources":["../../src/composites/pulumi-adopt-op.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,OAAO,EAA6B,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAG5E,0BAA0B;AAC1B,MAAM,WAAW,gBAAgB;IAC/B,yBAAyB;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IACZ,0BAA0B;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,mHAAmH;IACnH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;OAKG;IACH,IAAI,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,sHAAsH;IACtH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,iFAAiF;IACjF,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,qFAAqF;IACrF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2HAA2H;IAC3H,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qGAAqG;IACrG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2DAA2D;IAC3D,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6FAA6F;IAC7F,UAAU,CAAC,EAAE,OAAO,GAAG;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AAED,MAAM,WAAW,sBAAsB;IACrC,0EAA0E;IAC1E,EAAE,EAAE,YAAY,CAAC,OAAO,UAAU,CAAC,CAAC;CACrC;AAID,wBAAgB,aAAa,CAAC,MAAM,EAAE,mBAAmB,GAAG,sBAAsB,CAwFjF"}
|
|
@@ -96,9 +96,11 @@ export function PulumiAdoptOp(config) {
|
|
|
96
96
|
}));
|
|
97
97
|
const waves = config.stacks.flatMap((s, i) => {
|
|
98
98
|
const file = s.from ? { file: exports[i].out.file } : {};
|
|
99
|
-
|
|
99
|
+
// Every step gets the stack's backend, so Preview and Adopt read the store Check and Export read.
|
|
100
|
+
const backend = s.backend ? { backend: s.backend } : {};
|
|
101
|
+
const preview = pulumiAdoptPreview(s.member, { dir: s.dir, stack: s.stack, ...where, ...file, ...backend, id: `preview-${i}` });
|
|
100
102
|
preview.outcomeAttribute = { name: single ? "Adoptable" : `Adoptable-${slug(s.member)}-${slug(s.stack)}`, from: "resources" };
|
|
101
|
-
const adopt = pulumiAdopt(s.member, { dir: s.dir, stack: s.stack, ...where, ...file, planDigest: preview.out.planDigest, id: `adopt-${i}` });
|
|
103
|
+
const adopt = pulumiAdopt(s.member, { dir: s.dir, stack: s.stack, ...where, ...file, ...backend, planDigest: preview.out.planDigest, id: `adopt-${i}` });
|
|
102
104
|
adopt.outcomeAttribute = { name: single ? "Adopted" : `Adopted-${slug(s.member)}-${slug(s.stack)}`, from: "resources" };
|
|
103
105
|
const label = single ? "" : ` ${s.member}/${s.stack}`;
|
|
104
106
|
return [
|
package/dist/index.d.ts
CHANGED
|
@@ -23,4 +23,5 @@ export { PulumiAdoptOp, type PulumiAdoptOpConfig, type PulumiAdoptOpResources, t
|
|
|
23
23
|
export { parsePlungeAdoptView, pulumiAdoptDigest, adoptBucketTarget, type PlungeAdoptView, type PlungeAdoptStatus } from "./adopt.js";
|
|
24
24
|
export { pulumiPreview as pulumiPreviewStep, pulumiDrift as pulumiDriftStep } from "./op/builders.js";
|
|
25
25
|
export { pulumiExitOf, pulumiPlanMoved, PULUMI_EXIT, PLUNGE_PLAN_MOVED_EXIT } from "./exit-codes.js";
|
|
26
|
+
export { pulumiPlannedOutputChanges, type PulumiOutputChange, type PulumiPlannedOutputChanges } from "./planned-output-changes.js";
|
|
26
27
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,KAAK,YAAY,EAAE,MAAM,UAAU,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC5H,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,sBAAsB,GAC5B,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,iBAAiB,EACjB,yBAAyB,EACzB,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,0BAA0B,GAChC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,mBAAmB,EACnB,uBAAuB,EACvB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,iBAAiB,EACjB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,uBAAuB,EACvB,qBAAqB,EACrB,cAAc,EACd,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,4BAA4B,EAC5B,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,0BAA0B,EAC/B,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACvB,KAAK,+BAA+B,EACpC,KAAK,0BAA0B,GAChC,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,0BAA0B,EAAE,yBAAyB,EAAE,KAAK,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAC7E,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,0BAA0B,EAC1B,oBAAoB,EACpB,0BAA0B,EAC1B,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,GAC/B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,wBAAwB,EACxB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,uBAAuB,EACvB,uBAAuB,EACvB,+BAA+B,EAC/B,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,GACrB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,KAAK,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACpG,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,4BAA4B,EAC5B,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,GACxB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,eAAe,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,KAAK,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACpH,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,kBAAkB,EAAE,KAAK,gBAAgB,EAAE,mBAAmB,EAAE,KAAK,oBAAoB,EAAE,KAAK,mBAAmB,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAE9P,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,wBAAwB,EACxB,UAAU,EACV,mBAAmB,EACnB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,0BAA0B,GAChC,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC9J,OAAO,EAAE,aAAa,EAAE,KAAK,mBAAmB,EAAE,KAAK,sBAAsB,EAAE,KAAK,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAC3I,OAAO,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACnI,OAAO,EAAE,aAAa,IAAI,iBAAiB,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,eAAe,CAAC;AAEnG,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -27,3 +27,5 @@ export { parsePlungeAdoptView, pulumiAdoptDigest, adoptBucketTarget } from "./ad
|
|
|
27
27
|
export { pulumiPreview as pulumiPreviewStep, pulumiDrift as pulumiDriftStep } from "./op/builders.js";
|
|
28
28
|
// Pulumi and plunge exit statuses on chant's exit-code table (#4553).
|
|
29
29
|
export { pulumiExitOf, pulumiPlanMoved, PULUMI_EXIT, PLUNGE_PLAN_MOVED_EXIT } from "./exit-codes.js";
|
|
30
|
+
// Which stack outputs a preview changes, traced through the export (#4635).
|
|
31
|
+
export { pulumiPlannedOutputChanges } from "./planned-output-changes.js";
|
package/dist/integrity.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"algorithm": "sha256",
|
|
3
3
|
"artifacts": {
|
|
4
|
-
"manifest.json": "
|
|
4
|
+
"manifest.json": "bd4f4c6d8c0e2162c083f09b24e92eaef8d4d6000a8a3754a20051c8d325e939",
|
|
5
5
|
"meta.json": "ca3d163bab055381827226140568f3bef7eaac187cebd76878e0b63e9e442356",
|
|
6
6
|
"types/index.d.ts": "883bcdf6a960e21360e79df010ca2087719fffec60fc39541c5ecd32d661e328",
|
|
7
7
|
"rules/member-dir-absolute.ts": "4805d5e247ad544f942e1b2c36fc15a5087ca0aacaf804183a269021bd60e276",
|
|
@@ -25,5 +25,5 @@
|
|
|
25
25
|
"skills/chant-pulumi-stack-export.md": "aadd67f5e067de61dfda43d57492bca08bd22429e4baf314d6856a810dc0e8dc",
|
|
26
26
|
"skills/chant-pulumi-plunge.md": "8a7f2f9f1124744dee9645905f141057ca01f5a88e34e1bc3858d69406d7ff3a"
|
|
27
27
|
},
|
|
28
|
-
"composite": "
|
|
28
|
+
"composite": "24002abc5170f337f1d8d38e0a8be8e4aa119a771e14ed829945a0ebbc198060"
|
|
29
29
|
}
|
package/dist/manifest.json
CHANGED
package/dist/member-outputs.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { EngineOutputSource, EnginePlannedOutputs } from "@intentius/chant/components/verbs/member-outputs";
|
|
2
2
|
import type { ChangeSetPart } from "@intentius/chant/change-set";
|
|
3
|
+
import { type PulumiOutputChange } from "./planned-output-changes.js";
|
|
3
4
|
import { type PulumiMemberEngine, type PulumiRunner } from "./run.js";
|
|
4
5
|
/** Where a member's applied outputs are read from. */
|
|
5
6
|
export type PulumiAppliedFrom = "cli" | "export";
|
|
@@ -26,14 +27,20 @@ export declare function pulumiPartHasChanges(part: ChangeSetPart): boolean;
|
|
|
26
27
|
* the preview's error. A preview that plans no stack outputs (no stack step,
|
|
27
28
|
* or one without outputs, which is what a real `pulumi preview --json`
|
|
28
29
|
* prints, #4475) gives the export's outputs when it plans nothing to apply,
|
|
29
|
-
* since no apply will move them
|
|
30
|
-
*
|
|
30
|
+
* since no apply will move them. With changes, each output is traced to the
|
|
31
|
+
* export's resources (#4635, {@link pulumiPlannedOutputChanges}): the ones
|
|
32
|
+
* the preview leaves alone keep their value, and the rest are unknown, so
|
|
33
|
+
* nothing reads a value the preview may move. `outputChanges` lists each
|
|
34
|
+
* output's verdict and why.
|
|
31
35
|
*/
|
|
32
36
|
export declare function pulumiMemberPlannedOutputs(member: string, read: {
|
|
33
37
|
part: ChangeSetPart;
|
|
34
38
|
preview: unknown;
|
|
35
39
|
exported?: unknown;
|
|
36
|
-
|
|
40
|
+
targeted?: boolean;
|
|
41
|
+
}): EnginePlannedOutputs & {
|
|
42
|
+
outputChanges?: PulumiOutputChange[];
|
|
43
|
+
};
|
|
37
44
|
/** The applied outputs a `pulumi stack export` records, secrets left out. */
|
|
38
45
|
export declare function pulumiExportedOutputValues(exported: unknown): Record<string, unknown>;
|
|
39
46
|
/** A Pulumi member's outputs for `member-outputs`, `kinds: ["pulumi"]`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"member-outputs.d.ts","sourceRoot":"","sources":["../src/member-outputs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"member-outputs.d.ts","sourceRoot":"","sources":["../src/member-outputs.ts"],"names":[],"mappings":"AA8CA,OAAO,KAAK,EAAmB,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,kDAAkD,CAAC;AAClI,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AACjE,OAAO,EAA8B,KAAK,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAE/F,OAAO,EAAqE,KAAK,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAItI,sDAAsD;AACtD,MAAM,MAAM,iBAAiB,GAAG,KAAK,GAAG,QAAQ,CAAC;AAEjD,sGAAsG;AACtG,eAAO,MAAM,0BAA0B,iCAAiC,CAAC;AAEzE,MAAM,WAAW,yBAAyB;IACxC,qHAAqH;IACrH,OAAO,CAAC,EAAE,iBAAiB,CAAC;IAC5B,oEAAoE;IACpE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAcD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAGjE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,GACtF,oBAAoB,GAAG;IAAE,aAAa,CAAC,EAAE,kBAAkB,EAAE,CAAA;CAAE,CAkBjE;AAED,6EAA6E;AAC7E,wBAAgB,0BAA0B,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAErF;AAED,2EAA2E;AAC3E,wBAAgB,kBAAkB,CAAC,OAAO,GAAE,yBAA8B,GAAG,kBAAkB,CAoB9F;AAED,8DAA8D;AAC9D,eAAO,MAAM,uBAAuB,EAAE,kBAAyC,CAAC"}
|
package/dist/member-outputs.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { pulumiPlannedOutputChanges } from "./planned-output-changes.js";
|
|
1
2
|
import { pulumiPlannedStackOutputs, pulumiExportedStackOutputs } from "./stack-outputs.js";
|
|
2
3
|
import { memberExportOf, previewPulumiMemberRead, pulumiMemberStackOutputs } from "./run.js";
|
|
3
4
|
import { isSecret } from "./values.js";
|
|
@@ -33,8 +34,11 @@ export function pulumiPartHasChanges(part) {
|
|
|
33
34
|
* the preview's error. A preview that plans no stack outputs (no stack step,
|
|
34
35
|
* or one without outputs, which is what a real `pulumi preview --json`
|
|
35
36
|
* prints, #4475) gives the export's outputs when it plans nothing to apply,
|
|
36
|
-
* since no apply will move them
|
|
37
|
-
*
|
|
37
|
+
* since no apply will move them. With changes, each output is traced to the
|
|
38
|
+
* export's resources (#4635, {@link pulumiPlannedOutputChanges}): the ones
|
|
39
|
+
* the preview leaves alone keep their value, and the rest are unknown, so
|
|
40
|
+
* nothing reads a value the preview may move. `outputChanges` lists each
|
|
41
|
+
* output's verdict and why.
|
|
38
42
|
*/
|
|
39
43
|
export function pulumiMemberPlannedOutputs(member, read) {
|
|
40
44
|
const { part } = read;
|
|
@@ -47,7 +51,11 @@ export function pulumiMemberPlannedOutputs(member, read) {
|
|
|
47
51
|
const exported = read.exported === undefined ? [] : pulumiExportedStackOutputs(read.exported);
|
|
48
52
|
if (!changes)
|
|
49
53
|
return { known: knownValues(exported), unknown: [], planDigest: part.member.planDigest, changes };
|
|
50
|
-
|
|
54
|
+
if (part.member.holes.length > 0 || read.exported === undefined) {
|
|
55
|
+
return { known: {}, unknown: exported.filter((o) => !o.secret).map((o) => o.name), planDigest: part.member.planDigest, changes };
|
|
56
|
+
}
|
|
57
|
+
const traced = pulumiPlannedOutputChanges({ part, exported: read.exported, ...(read.targeted ? { targeted: true } : {}) });
|
|
58
|
+
return { known: traced.known, unknown: traced.unknown, planDigest: part.member.planDigest, changes, outputChanges: traced.outputs };
|
|
51
59
|
}
|
|
52
60
|
const unknown = planned.filter((o) => o.unknown).map((o) => o.name);
|
|
53
61
|
return { known: knownValues(planned), unknown, planDigest: part.member.planDigest, changes: changes || unknown.length > 0 };
|
|
@@ -59,6 +59,11 @@ export interface PulumiAdoptExportResult {
|
|
|
59
59
|
export interface PulumiAdoptPreviewArgs extends PulumiAdoptStackArgs {
|
|
60
60
|
/** `--file`: the export to adopt, from the Export step when `adoptFromFile`. */
|
|
61
61
|
file?: string;
|
|
62
|
+
/**
|
|
63
|
+
* The plunge backend URL plunge adopts onto, passed as `PULUMI_BACKEND_URL`. Default, as the Check
|
|
64
|
+
* step resolves it: `plywood.yml`'s, `PULUMI_BACKEND_URL`, `Pulumi.yaml`'s.
|
|
65
|
+
*/
|
|
66
|
+
backend?: string;
|
|
62
67
|
}
|
|
63
68
|
export interface PulumiAdoptPreviewResult {
|
|
64
69
|
member: string;
|