@intentius/chant-lexicon-pulumi 0.124.59 → 0.124.60
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/change-set.d.ts +38 -4
- package/dist/change-set.d.ts.map +1 -1
- package/dist/change-set.js +85 -13
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/integrity.json +2 -2
- package/dist/manifest.json +1 -1
- package/dist/pulumi-up.d.ts +2 -0
- package/dist/pulumi-up.d.ts.map +1 -1
- package/dist/pulumi-up.js +5 -1
- package/package.json +2 -2
- package/src/change-set.ts +93 -16
- package/src/index.ts +3 -0
- package/src/preview-generated.test.ts +113 -0
- package/src/pulumi-up.test.ts +12 -1
- package/src/pulumi-up.ts +5 -1
package/dist/change-set.d.ts
CHANGED
|
@@ -68,7 +68,11 @@
|
|
|
68
68
|
* each step's op, URN, provider, id, inputs before and after, `diffReasons`,
|
|
69
69
|
* `replaceReasons` and `detailedDiff`, sorted by URN and op. It leaves out
|
|
70
70
|
* `config`, `duration`, `diagnostics` and `changeSummary`, and the states'
|
|
71
|
-
* outputs, which at preview are the last deployment's or unknown.
|
|
71
|
+
* outputs, which at preview are the last deployment's or unknown. It also
|
|
72
|
+
* leaves out what the engine makes up while planning a create or a
|
|
73
|
+
* replacement (plywood#56): an autoname such as `events-3f45941` is drawn
|
|
74
|
+
* again by every preview, so it reads as {@link PULUMI_GENERATED}. See
|
|
75
|
+
* {@link pulumiPlannedInputs}. Unknowns already print as one fixed string. For a
|
|
72
76
|
* member on the resource lock grain the `pulumi-up` capability passes
|
|
73
77
|
* `changedOnly` (#4541, ruling B), which leaves `same` and `read` steps out.
|
|
74
78
|
*
|
|
@@ -140,14 +144,44 @@ export interface PulumiPreviewDigestOptions {
|
|
|
140
144
|
*/
|
|
141
145
|
changedOnly?: boolean;
|
|
142
146
|
}
|
|
147
|
+
/** What stands in a digest for an input the engine made up while planning (plywood#56). */
|
|
148
|
+
export declare const PULUMI_GENERATED = "<generated at plan time>";
|
|
149
|
+
/**
|
|
150
|
+
* The inputs a step would write, with the values the engine made up while
|
|
151
|
+
* planning replaced by {@link PULUMI_GENERATED} (plywood#56). Two previews of
|
|
152
|
+
* one create draw different autonames (`events-3f45941`, then
|
|
153
|
+
* `events-9c01d2e`), and a digest over them could never match a later plan of
|
|
154
|
+
* the same change.
|
|
155
|
+
*
|
|
156
|
+
* Only a create or a replacement draws a name: an update's inputs keep the one
|
|
157
|
+
* the resource was created with, and that stays in `before` and `after`. A
|
|
158
|
+
* value counts as generated when the engine lists its key in `__defaults`
|
|
159
|
+
* (the inputs the provider filled in, not the program) and it reads as an
|
|
160
|
+
* autoname of this resource: its logical name, or the start of it when the
|
|
161
|
+
* provider shortened it, then a dash and seven hex characters. An engine that
|
|
162
|
+
* prints no `__defaults` is held to the exact logical name. Every other input
|
|
163
|
+
* stays in, the defaults that are plain values included, so a changed input
|
|
164
|
+
* still changes the digest. `before` is the recorded state and is never masked.
|
|
165
|
+
*/
|
|
166
|
+
export declare function pulumiPlannedInputs(step: PulumiStep): Json | null;
|
|
143
167
|
/**
|
|
144
168
|
* The member's plan digest: `computePlanDigest("pulumi-preview", …)` over
|
|
145
169
|
* what each step proposes, sorted by URN and op, so two renderings of one
|
|
146
|
-
* preview agree. See the module comment for what it leaves out
|
|
147
|
-
*
|
|
148
|
-
* `
|
|
170
|
+
* preview agree. See the module comment for what it leaves out, and
|
|
171
|
+
* {@link pulumiPlannedInputs} for the values the engine made up that it leaves
|
|
172
|
+
* out of a create. With `changedOnly`, `same` and `read` steps are left out
|
|
173
|
+
* too, under the label `pulumi-preview-changed`, so the two digests never
|
|
174
|
+
* collide.
|
|
149
175
|
*/
|
|
150
176
|
export declare function pulumiPreviewDigest(preview: unknown, opts?: PulumiPreviewDigestOptions): string;
|
|
177
|
+
/**
|
|
178
|
+
* The digest of each resource the preview changes, by URN (plywood#55): the
|
|
179
|
+
* steps of that URN (a replace is several), as {@link pulumiPreviewDigest}
|
|
180
|
+
* reads them, with the values the engine made up left out. A `same` or `read` step is not in it whatever the lock grain,
|
|
181
|
+
* so what a pull request left alone never makes its plan differ from a plan
|
|
182
|
+
* made after another change landed on it.
|
|
183
|
+
*/
|
|
184
|
+
export declare function pulumiResourceDigests(preview: unknown): Record<string, string>;
|
|
151
185
|
/** The action and disruption one URN's steps mean, or undefined for an op the change set has no action for. */
|
|
152
186
|
export declare function pulumiStepsAction(steps: PulumiStep[]): {
|
|
153
187
|
action: ChangeSetAction;
|
package/dist/change-set.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"change-set.d.ts","sourceRoot":"","sources":["../src/change-set.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"change-set.d.ts","sourceRoot":"","sources":["../src/change-set.ts"],"names":[],"mappings":"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"}
|
package/dist/change-set.js
CHANGED
|
@@ -68,7 +68,11 @@
|
|
|
68
68
|
* each step's op, URN, provider, id, inputs before and after, `diffReasons`,
|
|
69
69
|
* `replaceReasons` and `detailedDiff`, sorted by URN and op. It leaves out
|
|
70
70
|
* `config`, `duration`, `diagnostics` and `changeSummary`, and the states'
|
|
71
|
-
* outputs, which at preview are the last deployment's or unknown.
|
|
71
|
+
* outputs, which at preview are the last deployment's or unknown. It also
|
|
72
|
+
* leaves out what the engine makes up while planning a create or a
|
|
73
|
+
* replacement (plywood#56): an autoname such as `events-3f45941` is drawn
|
|
74
|
+
* again by every preview, so it reads as {@link PULUMI_GENERATED}. See
|
|
75
|
+
* {@link pulumiPlannedInputs}. Unknowns already print as one fixed string. For a
|
|
72
76
|
* member on the resource lock grain the `pulumi-up` capability passes
|
|
73
77
|
* `changedOnly` (#4541, ruling B), which leaves `same` and `read` steps out.
|
|
74
78
|
*
|
|
@@ -108,30 +112,98 @@ export function pulumiExportResources(doc) {
|
|
|
108
112
|
const byString = (a, b) => (a < b ? -1 : a > b ? 1 : 0);
|
|
109
113
|
/** Step ops that change nothing: what {@link PulumiPreviewDigestOptions.changedOnly} leaves out of the digest. */
|
|
110
114
|
export const PULUMI_UNCHANGED_OPS = new Set(["same", "read"]);
|
|
115
|
+
/** What stands in a digest for an input the engine made up while planning (plywood#56). */
|
|
116
|
+
export const PULUMI_GENERATED = "<generated at plan time>";
|
|
117
|
+
/** Pulumi's autonaming: the logical name, a dash and seven random hex characters. */
|
|
118
|
+
const AUTONAME = /^(.+)-[0-9a-f]{7}$/;
|
|
119
|
+
/** The step's resource name: the last part of its URN. */
|
|
120
|
+
function logicalName(urn) {
|
|
121
|
+
const at = urn?.lastIndexOf("::") ?? -1;
|
|
122
|
+
return urn && at >= 0 ? urn.slice(at + 2) : (urn ?? "");
|
|
123
|
+
}
|
|
111
124
|
/**
|
|
112
|
-
* The
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* `
|
|
116
|
-
*
|
|
125
|
+
* The inputs a step would write, with the values the engine made up while
|
|
126
|
+
* planning replaced by {@link PULUMI_GENERATED} (plywood#56). Two previews of
|
|
127
|
+
* one create draw different autonames (`events-3f45941`, then
|
|
128
|
+
* `events-9c01d2e`), and a digest over them could never match a later plan of
|
|
129
|
+
* the same change.
|
|
130
|
+
*
|
|
131
|
+
* Only a create or a replacement draws a name: an update's inputs keep the one
|
|
132
|
+
* the resource was created with, and that stays in `before` and `after`. A
|
|
133
|
+
* value counts as generated when the engine lists its key in `__defaults`
|
|
134
|
+
* (the inputs the provider filled in, not the program) and it reads as an
|
|
135
|
+
* autoname of this resource: its logical name, or the start of it when the
|
|
136
|
+
* provider shortened it, then a dash and seven hex characters. An engine that
|
|
137
|
+
* prints no `__defaults` is held to the exact logical name. Every other input
|
|
138
|
+
* stays in, the defaults that are plain values included, so a changed input
|
|
139
|
+
* still changes the digest. `before` is the recorded state and is never masked.
|
|
117
140
|
*/
|
|
118
|
-
export function
|
|
119
|
-
const
|
|
120
|
-
|
|
121
|
-
|
|
141
|
+
export function pulumiPlannedInputs(step) {
|
|
142
|
+
const inputs = step.newState?.inputs;
|
|
143
|
+
if (!isObject(inputs))
|
|
144
|
+
return inputs ?? null;
|
|
145
|
+
const draws = step.oldState === undefined || step.op === "create" || step.op === "create-replacement" || step.op === "replace";
|
|
146
|
+
if (!draws)
|
|
147
|
+
return inputs;
|
|
148
|
+
const name = logicalName(step.urn).toLowerCase();
|
|
149
|
+
const filled = Array.isArray(inputs.__defaults) ? new Set(inputs.__defaults.filter((k) => typeof k === "string")) : undefined;
|
|
150
|
+
const out = {};
|
|
151
|
+
for (const [key, value] of Object.entries(inputs)) {
|
|
152
|
+
const stem = typeof value === "string" ? AUTONAME.exec(value)?.[1]?.toLowerCase() : undefined;
|
|
153
|
+
const generated = stem !== undefined && name !== "" && (filled ? filled.has(key) && (name.startsWith(stem) || stem.startsWith(name)) : stem === name);
|
|
154
|
+
out[key] = generated ? PULUMI_GENERATED : value;
|
|
155
|
+
}
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
/** One step as a digest sees it: what it proposes, without the values the engine made up. */
|
|
159
|
+
function digestStep(s) {
|
|
160
|
+
return {
|
|
122
161
|
op: s.op ?? null,
|
|
123
162
|
urn: s.urn ?? null,
|
|
124
163
|
provider: s.provider ?? null,
|
|
125
164
|
id: s.newState?.id ?? s.oldState?.id ?? null,
|
|
126
165
|
before: s.oldState?.inputs ?? null,
|
|
127
|
-
after: s
|
|
166
|
+
after: pulumiPlannedInputs(s),
|
|
128
167
|
diffReasons: [...(s.diffReasons ?? [])].sort(),
|
|
129
168
|
replaceReasons: [...(s.replaceReasons ?? [])].sort(),
|
|
130
169
|
detailedDiff: s.detailedDiff ?? null,
|
|
131
|
-
}
|
|
132
|
-
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
const byStep = (a, b) => byString(`${a.urn}\u0000${a.op}`, `${b.urn}\u0000${b.op}`);
|
|
173
|
+
/**
|
|
174
|
+
* The member's plan digest: `computePlanDigest("pulumi-preview", …)` over
|
|
175
|
+
* what each step proposes, sorted by URN and op, so two renderings of one
|
|
176
|
+
* preview agree. See the module comment for what it leaves out, and
|
|
177
|
+
* {@link pulumiPlannedInputs} for the values the engine made up that it leaves
|
|
178
|
+
* out of a create. With `changedOnly`, `same` and `read` steps are left out
|
|
179
|
+
* too, under the label `pulumi-preview-changed`, so the two digests never
|
|
180
|
+
* collide.
|
|
181
|
+
*/
|
|
182
|
+
export function pulumiPreviewDigest(preview, opts = {}) {
|
|
183
|
+
const steps = (pulumiSteps(preview) ?? [])
|
|
184
|
+
.filter((s) => !opts.changedOnly || !PULUMI_UNCHANGED_OPS.has(s.op ?? ""))
|
|
185
|
+
.map(digestStep)
|
|
186
|
+
.sort(byStep);
|
|
133
187
|
return computePlanDigest(opts.changedOnly ? "pulumi-preview-changed" : "pulumi-preview", steps);
|
|
134
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* The digest of each resource the preview changes, by URN (plywood#55): the
|
|
191
|
+
* steps of that URN (a replace is several), as {@link pulumiPreviewDigest}
|
|
192
|
+
* reads them, with the values the engine made up left out. A `same` or `read` step is not in it whatever the lock grain,
|
|
193
|
+
* so what a pull request left alone never makes its plan differ from a plan
|
|
194
|
+
* made after another change landed on it.
|
|
195
|
+
*/
|
|
196
|
+
export function pulumiResourceDigests(preview) {
|
|
197
|
+
const byUrn = new Map();
|
|
198
|
+
for (const s of pulumiSteps(preview) ?? []) {
|
|
199
|
+
if (PULUMI_UNCHANGED_OPS.has(s.op ?? ""))
|
|
200
|
+
continue;
|
|
201
|
+
const list = byUrn.get(s.urn) ?? [];
|
|
202
|
+
list.push(digestStep(s));
|
|
203
|
+
byUrn.set(s.urn, list);
|
|
204
|
+
}
|
|
205
|
+
return Object.fromEntries([...byUrn].sort(([a], [b]) => byString(a, b)).map(([urn, steps]) => [urn, computePlanDigest("pulumi-resource", steps.sort(byStep))]));
|
|
206
|
+
}
|
|
135
207
|
const REPLACE_OPS = new Set(["replace", "create-replacement", "delete-replaced"]);
|
|
136
208
|
/** The action and disruption one URN's steps mean, or undefined for an op the change set has no action for. */
|
|
137
209
|
export function pulumiStepsAction(steps) {
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { pulumiPlugin } from "./plugin.js";
|
|
|
2
2
|
export { pulumiSerializer } from "./serializer.js";
|
|
3
3
|
export { pulumiConfigSchema, pulumiMemberConfigSchema, type PulumiConfig } from "./config.js";
|
|
4
4
|
export { readPulumiMember, PULUMI_EXPORT_FILE, type PulumiMemberConfig, type PulumiMemberReport } from "./workspace-member.js";
|
|
5
|
-
export { pulumiPreviewPart, pulumiPreviewDigest, pulumiSteps, pulumiExportResources, type PulumiPreviewPartInput, type PulumiStep, type PulumiStepState, type PulumiExportedResource, } from "./change-set.js";
|
|
5
|
+
export { pulumiPreviewPart, pulumiPreviewDigest, pulumiResourceDigests, pulumiPlannedInputs, PULUMI_GENERATED, pulumiSteps, pulumiExportResources, type PulumiPreviewPartInput, type PulumiStep, type PulumiStepState, type PulumiExportedResource, } from "./change-set.js";
|
|
6
6
|
export { pulumiRefreshArgs, pulumiRefreshDriftRecords, pulumiRefreshDocumentRecords, type PulumiRefreshRead, type PulumiRefreshDriftInput, type PulumiRefreshDocumentInput, } from "./drift-record.js";
|
|
7
7
|
export { previewPulumiMember, previewPulumiMemberRead, refreshPulumiMember, pulumiMemberEngine, pulumiMemberStackOutputs, pulumiPreviewArgs, pulumiStackOutputArgs, runAllowedPlunge, runAllowedPulumi, readMemberExport, defaultPulumiRunner, PULUMI_ALLOWED_COMMANDS, PULUMI_APPLY_COMMANDS, runApplyPulumi, runApplyPlunge, pulumiUpArgs, plungeUpArgs, pulumiUpPreviewArgs, PULUMI_REVIEW_STACK_COMMANDS, REVIEW_STACK_NAME, isReviewStackName, reviewStackInitArgs, reviewStackDestroyArgs, reviewStackRmArgs, runReviewStackPulumi, runReviewStackPlunge, type PulumiPolicyPack, type PulumiApplyTail, type PulumiRunner, type PreviewPulumiMemberOptions, type PulumiMemberPreview, type PulumiMemberEngine, type PulumiMemberStackOutputsOptions, type RefreshPulumiMemberOptions, } from "./run.js";
|
|
8
8
|
export { pulumiExportedStackOutputs, pulumiPlannedStackOutputs, type PulumiStackOutput } from "./stack-outputs.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@ export { pulumiPlugin } from "./plugin.js";
|
|
|
2
2
|
export { pulumiSerializer } from "./serializer.js";
|
|
3
3
|
export { pulumiConfigSchema, pulumiMemberConfigSchema } from "./config.js";
|
|
4
4
|
export { readPulumiMember, PULUMI_EXPORT_FILE } from "./workspace-member.js";
|
|
5
|
-
export { pulumiPreviewPart, pulumiPreviewDigest, pulumiSteps, pulumiExportResources, } from "./change-set.js";
|
|
5
|
+
export { pulumiPreviewPart, pulumiPreviewDigest, pulumiResourceDigests, pulumiPlannedInputs, PULUMI_GENERATED, pulumiSteps, pulumiExportResources, } from "./change-set.js";
|
|
6
6
|
export { pulumiRefreshArgs, pulumiRefreshDriftRecords, pulumiRefreshDocumentRecords, } from "./drift-record.js";
|
|
7
7
|
export { previewPulumiMember, previewPulumiMemberRead, refreshPulumiMember, pulumiMemberEngine, pulumiMemberStackOutputs, pulumiPreviewArgs, pulumiStackOutputArgs, runAllowedPlunge, runAllowedPulumi, readMemberExport, defaultPulumiRunner, PULUMI_ALLOWED_COMMANDS, PULUMI_APPLY_COMMANDS, runApplyPulumi, runApplyPlunge, pulumiUpArgs, plungeUpArgs, pulumiUpPreviewArgs, PULUMI_REVIEW_STACK_COMMANDS, REVIEW_STACK_NAME, isReviewStackName, reviewStackInitArgs, reviewStackDestroyArgs, reviewStackRmArgs, runReviewStackPulumi, runReviewStackPlunge, } from "./run.js";
|
|
8
8
|
export { pulumiExportedStackOutputs, pulumiPlannedStackOutputs } from "./stack-outputs.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": "6066d06e053b59c3170661488757ef2e85187346d1d3e6e5e69f126a38dd4913",
|
|
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": "d6d6dfcd5c8b2e4908518689e3727e4ca7e761bf6a407f7d6dc9bbb116ea9ac3"
|
|
29
29
|
}
|
package/dist/manifest.json
CHANGED
package/dist/pulumi-up.d.ts
CHANGED
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
* through `DeployContext.lockGrain`, else `resource` on plunge and
|
|
27
27
|
* `target` on stock Pulumi, #4552) the digest leaves `same` and `read`
|
|
28
28
|
* steps out (ruling B);
|
|
29
|
+
* - `resourceDigests`: one digest per resource the preview changes, by URN,
|
|
30
|
+
* whatever the grain (plywood#55);
|
|
29
31
|
* - `outputs` from the stack step's planned outputs;
|
|
30
32
|
* - `shape` from `pulumiPlanShape` (`./plan-shape.ts`);
|
|
31
33
|
* - `artifact`: the engine, the shape, the digest, CrossGuard's findings,
|
package/dist/pulumi-up.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pulumi-up.d.ts","sourceRoot":"","sources":["../src/pulumi-up.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pulumi-up.d.ts","sourceRoot":"","sources":["../src/pulumi-up.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwIG;AAMH,OAAO,KAAK,EACV,UAAU,EAEV,YAAY,EACZ,kBAAkB,EAClB,oBAAoB,EAEpB,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAuB,KAAK,SAAS,EAAE,MAAM,2CAA2C,CAAC;AAChG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAEvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAG/E,OAAO,EAWL,KAAK,kBAAkB,EACxB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,wBAAwB,EAAE,MAAM,iBAAiB,CAAC;AAG7G,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAKnE,OAAO,EAcL,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAClB,MAAM,OAAO,CAAC;AAEf,OAAO,EAA6B,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAM5F,kEAAkE;AAClE,MAAM,MAAM,eAAe,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAE7D,oCAAoC;AACpC,MAAM,WAAW,iBAAiB;IAChC,2FAA2F;IAC3F,GAAG,EAAE,MAAM,CAAC;IACZ,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,uGAAuG;IACvG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oGAAoG;IACpG,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,sDAAsD;IACtD,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;OAOG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,4HAA4H;IAC5H,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,0IAA0I;IAC1I,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B;;;;OAIG;IACH,WAAW,CAAC,EAAE,gBAAgB,EAAE,CAAC;IACjC;;;;;;OAMG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAC1D;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,0BAA0B;AAC1B,MAAM,WAAW,kBAAkB;IACjC,0BAA0B;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,yFAAyF;IACzF,YAAY,EAAE,OAAO,CAAC;IACtB,oFAAoF;IACpF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,6EAA6E;IAC7E,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAC7B,kEAAkE;IAClE,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,yFAAyF;IACzF,cAAc,CAAC,EAAE,iBAAiB,CAAC;CACpC;AAED,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,WAAW,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,kBAAkB,CAAC;IAC3B,gFAAgF;IAChF,YAAY,EAAE,wBAAwB,CAAC;IACvC,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,mEAAmE;IACnE,OAAO,EAAE,MAAM,CAAC;IAChB,wCAAwC;IACxC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qDAAqD;IACrD,MAAM,EAAE,kBAAkB,CAAC;IAC3B;;;;;OAKG;IACH,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC;;;;;;;OAOG;IACH,eAAe,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACpG;;;;;OAKG;IACH,cAAc,CAAC,EAAE,kBAAkB,EAAE,CAAC;CACvC;AAED,wDAAwD;AACxD,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC3F,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,MAAM,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;CACtE;AAgCD,yHAAyH;AACzH,qBAAa,oBAAqB,SAAQ,KAAK;aAG3B,MAAM,EAAE,MAAM;IAFhC,QAAQ,CAAC,SAAS,QAAQ;IAC1B,YACkB,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM,EAIhB;CACF;AAED,qGAAqG;AACrG,qBAAa,uBAAwB,SAAQ,KAAK;aAK9B,MAAM,EAAE,MAAM;aACd,QAAQ,EAAE,kBAAkB;IAL9C,QAAQ,CAAC,YAAY,QAAQ;IAC7B,+DAA+D;IAC/D,QAAQ,CAAC,QAAQ,IAAqB;IACtC,YACkB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,kBAAkB,EAC5C,MAAM,CAAC,EAAE,MAAM,EAKhB;CACF;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;aAE9B,MAAM,EAAE,MAAM;aACd,WAAW,EAAE,MAAM,EAAE;aACrB,OAAO,CAAC,EAAE,kBAAkB;IAH9C,YACkB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,MAAM,EAAE,EACrB,OAAO,CAAC,EAAE,kBAAkB,YAAA,EAI7C;CACF;AAED;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;aAE1B,MAAM,EAAE,MAAM;aAEd,OAAO,CAAC,EAAE,kBAAkB;IAH9C,YACkB,MAAM,EAAE,MAAM,EAC9B,OAAO,EAAE,MAAM,EACC,OAAO,CAAC,EAAE,kBAAkB,YAAA,EAI7C;CACF;AAED,oHAAoH;AACpH,qBAAa,+BAAgC,SAAQ,KAAK;aAC5B,MAAM,EAAE,MAAM;IAA1C,YAA4B,MAAM,EAAE,MAAM,EAGzC;CACF;AAED,qHAAqH;AACrH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,kBAAkB,GAAG,eAAe,CAElF;AAED,kEAAkE;AAClE,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,4FAA4F;IAC5F,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,YAAY,CAAC;IACtC,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,8DAA8D;IAC9D,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,uLAAuL;IACvL,SAAS,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;CAClC;AA0BD,sEAAsE;AACtE,wBAAgB,cAAc,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,CAI/D;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAkBvG;AAED,mGAAmG;AACnG,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAE7D;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,MAAM,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,cAAc,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAOvL;AA+DD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,IAAI,CAAC,iBAAiB,EAAE,eAAe,GAAG,YAAY,CAAC,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM,GAAG,SAAS,CAWhJ;AA8ND,mGAAmG;AACnG,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAIrE;AAED;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,GAAG,EAAE,oBAAoB,EACzB,OAAO,EAAE,SAAS,kBAAkB,EAAE,EACtC,IAAI,GAAE;IAAE,WAAW,CAAC,EAAE,aAAa,GAAG,IAAI,CAAA;CAAO,GAChD,OAAO,CAAC,YAAY,EAAE,CAAC,CAuBzB;AAyBD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS,CAK9E;AAgHD,0GAA0G;AAC1G,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,oBAAoB,GAAG,aAAa,GAAG,oBAAoB,GAAG,IAAI,CAqBpI;AAED,qEAAqE;AACrE,wBAAgB,wBAAwB,CAAC,IAAI,GAAE,eAAoB,GAAG,UAAU,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAwDtH;AAED,eAAO,MAAM,kBAAkB,mDAA6B,CAAC"}
|
package/dist/pulumi-up.js
CHANGED
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
* through `DeployContext.lockGrain`, else `resource` on plunge and
|
|
27
27
|
* `target` on stock Pulumi, #4552) the digest leaves `same` and `read`
|
|
28
28
|
* steps out (ruling B);
|
|
29
|
+
* - `resourceDigests`: one digest per resource the preview changes, by URN,
|
|
30
|
+
* whatever the grain (plywood#55);
|
|
29
31
|
* - `outputs` from the stack step's planned outputs;
|
|
30
32
|
* - `shape` from `pulumiPlanShape` (`./plan-shape.ts`);
|
|
31
33
|
* - `artifact`: the engine, the shape, the digest, CrossGuard's findings,
|
|
@@ -139,7 +141,7 @@ import { basename, isAbsolute, join, relative, resolve } from "node:path";
|
|
|
139
141
|
import { PlanShapeMovedError } from "@intentius/chant/components/covered-round";
|
|
140
142
|
import { computePlanDigest } from "@intentius/chant/lifecycle/plan-digest";
|
|
141
143
|
import { parseYAML } from "@intentius/chant/yaml";
|
|
142
|
-
import { pulumiPreviewPart } from "./change-set.js";
|
|
144
|
+
import { pulumiPreviewPart, pulumiResourceDigests } from "./change-set.js";
|
|
143
145
|
import { PULUMI_STREAMING_PREVIEW_ENV, pulumiAppliedSteps, pulumiFailedUrns, pulumiLandedUrns, pulumiPolicyEvents, pulumiPolicyFindings, pulumiStreamError, pulumiStreamPreview, pulumiStreamSummary, pulumiStreamTimings, } from "./engine-events.js";
|
|
144
146
|
import { CHANT_EXIT } from "@intentius/chant/exit-codes";
|
|
145
147
|
import { pulumiExitOf } from "./exit-codes.js";
|
|
@@ -565,6 +567,8 @@ async function planStack(ctx, original, opts) {
|
|
|
565
567
|
planDigest,
|
|
566
568
|
artifact,
|
|
567
569
|
changeSet: read.part,
|
|
570
|
+
// plywood#55: each changed resource's own digest, which a merged wave compares with the pull request's per resource.
|
|
571
|
+
resourceDigests: pulumiResourceDigests(read.preview),
|
|
568
572
|
outputs: { known: planned.known, unknown: planned.unknown },
|
|
569
573
|
shape: read.shape,
|
|
570
574
|
...(ctx.targets?.length ? { targets: ctx.targets } : {}),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intentius/chant-lexicon-pulumi",
|
|
3
|
-
"version": "0.124.
|
|
3
|
+
"version": "0.124.60",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"files": [
|
|
6
6
|
"src/",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
56
|
"peerDependencies": {
|
|
57
|
-
"@intentius/chant": "^0.124.
|
|
57
|
+
"@intentius/chant": "^0.124.60",
|
|
58
58
|
"zod": "^4.3.6"
|
|
59
59
|
},
|
|
60
60
|
"description": "pulumi lexicon for chant: a Pulumi program as a workspace member, its preview in the change set and its refresh as drift records",
|
package/src/change-set.ts
CHANGED
|
@@ -68,7 +68,11 @@
|
|
|
68
68
|
* each step's op, URN, provider, id, inputs before and after, `diffReasons`,
|
|
69
69
|
* `replaceReasons` and `detailedDiff`, sorted by URN and op. It leaves out
|
|
70
70
|
* `config`, `duration`, `diagnostics` and `changeSummary`, and the states'
|
|
71
|
-
* outputs, which at preview are the last deployment's or unknown.
|
|
71
|
+
* outputs, which at preview are the last deployment's or unknown. It also
|
|
72
|
+
* leaves out what the engine makes up while planning a create or a
|
|
73
|
+
* replacement (plywood#56): an autoname such as `events-3f45941` is drawn
|
|
74
|
+
* again by every preview, so it reads as {@link PULUMI_GENERATED}. See
|
|
75
|
+
* {@link pulumiPlannedInputs}. Unknowns already print as one fixed string. For a
|
|
72
76
|
* member on the resource lock grain the `pulumi-up` capability passes
|
|
73
77
|
* `changedOnly` (#4541, ruling B), which leaves `same` and `read` steps out.
|
|
74
78
|
*
|
|
@@ -164,31 +168,104 @@ export interface PulumiPreviewDigestOptions {
|
|
|
164
168
|
changedOnly?: boolean;
|
|
165
169
|
}
|
|
166
170
|
|
|
171
|
+
/** What stands in a digest for an input the engine made up while planning (plywood#56). */
|
|
172
|
+
export const PULUMI_GENERATED = "<generated at plan time>";
|
|
173
|
+
|
|
174
|
+
/** Pulumi's autonaming: the logical name, a dash and seven random hex characters. */
|
|
175
|
+
const AUTONAME = /^(.+)-[0-9a-f]{7}$/;
|
|
176
|
+
|
|
177
|
+
/** The step's resource name: the last part of its URN. */
|
|
178
|
+
function logicalName(urn: string | undefined): string {
|
|
179
|
+
const at = urn?.lastIndexOf("::") ?? -1;
|
|
180
|
+
return urn && at >= 0 ? urn.slice(at + 2) : (urn ?? "");
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* The inputs a step would write, with the values the engine made up while
|
|
185
|
+
* planning replaced by {@link PULUMI_GENERATED} (plywood#56). Two previews of
|
|
186
|
+
* one create draw different autonames (`events-3f45941`, then
|
|
187
|
+
* `events-9c01d2e`), and a digest over them could never match a later plan of
|
|
188
|
+
* the same change.
|
|
189
|
+
*
|
|
190
|
+
* Only a create or a replacement draws a name: an update's inputs keep the one
|
|
191
|
+
* the resource was created with, and that stays in `before` and `after`. A
|
|
192
|
+
* value counts as generated when the engine lists its key in `__defaults`
|
|
193
|
+
* (the inputs the provider filled in, not the program) and it reads as an
|
|
194
|
+
* autoname of this resource: its logical name, or the start of it when the
|
|
195
|
+
* provider shortened it, then a dash and seven hex characters. An engine that
|
|
196
|
+
* prints no `__defaults` is held to the exact logical name. Every other input
|
|
197
|
+
* stays in, the defaults that are plain values included, so a changed input
|
|
198
|
+
* still changes the digest. `before` is the recorded state and is never masked.
|
|
199
|
+
*/
|
|
200
|
+
export function pulumiPlannedInputs(step: PulumiStep): Json | null {
|
|
201
|
+
const inputs = step.newState?.inputs;
|
|
202
|
+
if (!isObject(inputs)) return inputs ?? null;
|
|
203
|
+
const draws = step.oldState === undefined || step.op === "create" || step.op === "create-replacement" || step.op === "replace";
|
|
204
|
+
if (!draws) return inputs;
|
|
205
|
+
const name = logicalName(step.urn).toLowerCase();
|
|
206
|
+
const filled = Array.isArray(inputs.__defaults) ? new Set(inputs.__defaults.filter((k): k is string => typeof k === "string")) : undefined;
|
|
207
|
+
const out: Json = {};
|
|
208
|
+
for (const [key, value] of Object.entries(inputs)) {
|
|
209
|
+
const stem = typeof value === "string" ? AUTONAME.exec(value)?.[1]?.toLowerCase() : undefined;
|
|
210
|
+
const generated = stem !== undefined && name !== "" && (filled ? filled.has(key) && (name.startsWith(stem) || stem.startsWith(name)) : stem === name);
|
|
211
|
+
out[key] = generated ? PULUMI_GENERATED : value;
|
|
212
|
+
}
|
|
213
|
+
return out;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/** One step as a digest sees it: what it proposes, without the values the engine made up. */
|
|
217
|
+
function digestStep(s: PulumiStep) {
|
|
218
|
+
return {
|
|
219
|
+
op: s.op ?? null,
|
|
220
|
+
urn: s.urn ?? null,
|
|
221
|
+
provider: s.provider ?? null,
|
|
222
|
+
id: s.newState?.id ?? s.oldState?.id ?? null,
|
|
223
|
+
before: s.oldState?.inputs ?? null,
|
|
224
|
+
after: pulumiPlannedInputs(s),
|
|
225
|
+
diffReasons: [...(s.diffReasons ?? [])].sort(),
|
|
226
|
+
replaceReasons: [...(s.replaceReasons ?? [])].sort(),
|
|
227
|
+
detailedDiff: s.detailedDiff ?? null,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const byStep = (a: { urn: string | null; op: string | null }, b: { urn: string | null; op: string | null }): number =>
|
|
232
|
+
byString(`${a.urn}\u0000${a.op}`, `${b.urn}\u0000${b.op}`);
|
|
233
|
+
|
|
167
234
|
/**
|
|
168
235
|
* The member's plan digest: `computePlanDigest("pulumi-preview", …)` over
|
|
169
236
|
* what each step proposes, sorted by URN and op, so two renderings of one
|
|
170
|
-
* preview agree. See the module comment for what it leaves out
|
|
171
|
-
*
|
|
172
|
-
* `
|
|
237
|
+
* preview agree. See the module comment for what it leaves out, and
|
|
238
|
+
* {@link pulumiPlannedInputs} for the values the engine made up that it leaves
|
|
239
|
+
* out of a create. With `changedOnly`, `same` and `read` steps are left out
|
|
240
|
+
* too, under the label `pulumi-preview-changed`, so the two digests never
|
|
241
|
+
* collide.
|
|
173
242
|
*/
|
|
174
243
|
export function pulumiPreviewDigest(preview: unknown, opts: PulumiPreviewDigestOptions = {}): string {
|
|
175
244
|
const steps = (pulumiSteps(preview) ?? [])
|
|
176
245
|
.filter((s) => !opts.changedOnly || !PULUMI_UNCHANGED_OPS.has(s.op ?? ""))
|
|
177
|
-
.map(
|
|
178
|
-
|
|
179
|
-
urn: s.urn ?? null,
|
|
180
|
-
provider: s.provider ?? null,
|
|
181
|
-
id: s.newState?.id ?? s.oldState?.id ?? null,
|
|
182
|
-
before: s.oldState?.inputs ?? null,
|
|
183
|
-
after: s.newState?.inputs ?? null,
|
|
184
|
-
diffReasons: [...(s.diffReasons ?? [])].sort(),
|
|
185
|
-
replaceReasons: [...(s.replaceReasons ?? [])].sort(),
|
|
186
|
-
detailedDiff: s.detailedDiff ?? null,
|
|
187
|
-
}))
|
|
188
|
-
.sort((a, b) => byString(`${a.urn}\u0000${a.op}`, `${b.urn}\u0000${b.op}`));
|
|
246
|
+
.map(digestStep)
|
|
247
|
+
.sort(byStep);
|
|
189
248
|
return computePlanDigest(opts.changedOnly ? "pulumi-preview-changed" : "pulumi-preview", steps);
|
|
190
249
|
}
|
|
191
250
|
|
|
251
|
+
/**
|
|
252
|
+
* The digest of each resource the preview changes, by URN (plywood#55): the
|
|
253
|
+
* steps of that URN (a replace is several), as {@link pulumiPreviewDigest}
|
|
254
|
+
* reads them, with the values the engine made up left out. A `same` or `read` step is not in it whatever the lock grain,
|
|
255
|
+
* so what a pull request left alone never makes its plan differ from a plan
|
|
256
|
+
* made after another change landed on it.
|
|
257
|
+
*/
|
|
258
|
+
export function pulumiResourceDigests(preview: unknown): Record<string, string> {
|
|
259
|
+
const byUrn = new Map<string, ReturnType<typeof digestStep>[]>();
|
|
260
|
+
for (const s of pulumiSteps(preview) ?? []) {
|
|
261
|
+
if (PULUMI_UNCHANGED_OPS.has(s.op ?? "")) continue;
|
|
262
|
+
const list = byUrn.get(s.urn!) ?? [];
|
|
263
|
+
list.push(digestStep(s));
|
|
264
|
+
byUrn.set(s.urn!, list);
|
|
265
|
+
}
|
|
266
|
+
return Object.fromEntries([...byUrn].sort(([a], [b]) => byString(a, b)).map(([urn, steps]) => [urn, computePlanDigest("pulumi-resource", steps.sort(byStep))]));
|
|
267
|
+
}
|
|
268
|
+
|
|
192
269
|
const REPLACE_OPS = new Set(["replace", "create-replacement", "delete-replaced"]);
|
|
193
270
|
|
|
194
271
|
/** The action and disruption one URN's steps mean, or undefined for an op the change set has no action for. */
|
package/src/index.ts
CHANGED
|
@@ -5,6 +5,9 @@ export { readPulumiMember, PULUMI_EXPORT_FILE, type PulumiMemberConfig, type Pul
|
|
|
5
5
|
export {
|
|
6
6
|
pulumiPreviewPart,
|
|
7
7
|
pulumiPreviewDigest,
|
|
8
|
+
pulumiResourceDigests,
|
|
9
|
+
pulumiPlannedInputs,
|
|
10
|
+
PULUMI_GENERATED,
|
|
8
11
|
pulumiSteps,
|
|
9
12
|
pulumiExportResources,
|
|
10
13
|
type PulumiPreviewPartInput,
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Values the engine makes up while planning stay out of the digest (plywood#56).
|
|
3
|
+
* `testdata/pulumi-preview/preview-create.json` is a recorded first preview:
|
|
4
|
+
* its queues carry autonames (`events-3f45941`, `worker-0-84f29f5`) the
|
|
5
|
+
* provider filled in, listed in each step's `__defaults`.
|
|
6
|
+
*/
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import { describe, expect, test } from "vitest";
|
|
10
|
+
import { PULUMI_GENERATED, pulumiPlannedInputs, pulumiPreviewDigest, pulumiResourceDigests, type PulumiStep } from "./change-set";
|
|
11
|
+
|
|
12
|
+
const created = JSON.parse(readFileSync(join(import.meta.dirname, "testdata", "pulumi-preview", "preview-create.json"), "utf-8")) as { steps: PulumiStep[] };
|
|
13
|
+
const copy = () => JSON.parse(JSON.stringify(created)) as typeof created;
|
|
14
|
+
const stepOf = (doc: typeof created, name: string) => doc.steps.find((s) => s.urn?.endsWith(`::${name}`))!;
|
|
15
|
+
const inputsOf = (doc: typeof created, name: string) => stepOf(doc, name).newState!.inputs as Record<string, unknown>;
|
|
16
|
+
|
|
17
|
+
/** The same preview drawn again: every autoname gets another suffix. */
|
|
18
|
+
function replanned(): typeof created {
|
|
19
|
+
const doc = copy();
|
|
20
|
+
for (const s of doc.steps) {
|
|
21
|
+
const inputs = s.newState?.inputs as Record<string, unknown> | undefined;
|
|
22
|
+
if (!inputs || !Array.isArray(inputs.__defaults)) continue;
|
|
23
|
+
for (const key of inputs.__defaults as string[]) {
|
|
24
|
+
const v = inputs[key];
|
|
25
|
+
if (typeof v === "string" && /-[0-9a-f]{7}$/.test(v)) inputs[key] = v.replace(/[0-9a-f]{7}$/, "0123abc");
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return doc;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
describe("a create's digest leaves out what the engine drew while planning", () => {
|
|
32
|
+
test("the recorded preview holds autonames, and a second draw gives the same digest", () => {
|
|
33
|
+
expect(inputsOf(created, "events").name).toBe("events-3f45941");
|
|
34
|
+
expect(inputsOf(replanned(), "events").name).toBe("events-0123abc");
|
|
35
|
+
expect(pulumiPreviewDigest(replanned())).toBe(pulumiPreviewDigest(created));
|
|
36
|
+
expect(pulumiPreviewDigest(replanned(), { changedOnly: true })).toBe(pulumiPreviewDigest(created, { changedOnly: true }));
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test("the name is replaced by one marker, and the rest of the inputs are kept", () => {
|
|
40
|
+
const planned = pulumiPlannedInputs(stepOf(created, "events")) as Record<string, unknown>;
|
|
41
|
+
expect(planned.name).toBe(PULUMI_GENERATED);
|
|
42
|
+
expect(planned.messageRetentionSeconds).toBe(3600);
|
|
43
|
+
expect(planned.maxMessageSize).toBe(262144);
|
|
44
|
+
expect(planned.tags).toEqual({ "corpus-owner": "plunge", "corpus-program": "aws-ts" });
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
test("two creates that differ in an input a reviewer saw still differ", () => {
|
|
48
|
+
for (const change of [
|
|
49
|
+
(d: typeof created) => { inputsOf(d, "events").messageRetentionSeconds = 7200; },
|
|
50
|
+
(d: typeof created) => { (inputsOf(d, "worker-0").tags as Record<string, string>)["corpus-index"] = "9"; },
|
|
51
|
+
// a default that is a plain value counts: it decides what gets applied
|
|
52
|
+
(d: typeof created) => { inputsOf(d, "events").maxMessageSize = 1024; },
|
|
53
|
+
// a name the program set is not a draw, and a changed one is a change
|
|
54
|
+
(d: typeof created) => { inputsOf(d, "app-role").name = "rec-ts-other"; },
|
|
55
|
+
]) {
|
|
56
|
+
const other = replanned();
|
|
57
|
+
change(other);
|
|
58
|
+
expect(pulumiPreviewDigest(other)).not.toBe(pulumiPreviewDigest(created));
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
test("a different logical name or a new resource changes the digest", () => {
|
|
63
|
+
const renamed = replanned();
|
|
64
|
+
stepOf(renamed, "events").urn = stepOf(renamed, "events").urn!.replace("::events", "::journal");
|
|
65
|
+
expect(pulumiPreviewDigest(renamed)).not.toBe(pulumiPreviewDigest(created));
|
|
66
|
+
const extra = replanned();
|
|
67
|
+
extra.steps.push({ ...stepOf(extra, "docs-notify"), urn: stepOf(extra, "docs-notify").urn!.replace("::docs-notify", "::more-notify") });
|
|
68
|
+
expect(pulumiPreviewDigest(extra)).not.toBe(pulumiPreviewDigest(created));
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("a string that only looks like a suffix is kept unless the engine filled it in", () => {
|
|
72
|
+
const doc = copy();
|
|
73
|
+
const step = stepOf(doc, "events");
|
|
74
|
+
(step.newState!.inputs as Record<string, unknown>).description = "events-3f45941";
|
|
75
|
+
expect((pulumiPlannedInputs(step) as Record<string, unknown>).description).toBe("events-3f45941");
|
|
76
|
+
// a name the program wrote is not listed in __defaults
|
|
77
|
+
(step.newState!.inputs as Record<string, unknown>).__defaults = [];
|
|
78
|
+
expect((pulumiPlannedInputs(step) as Record<string, unknown>).name).toBe("events-3f45941");
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("an engine that prints no __defaults is held to the exact logical name", () => {
|
|
82
|
+
const step: PulumiStep = { op: "create", urn: "urn:pulumi:dev::p::aws:sqs/queue:Queue::events", newState: { inputs: { name: "events-3f45941", other: "worker-3f45941" } } };
|
|
83
|
+
expect(pulumiPlannedInputs(step)).toEqual({ name: PULUMI_GENERATED, other: "worker-3f45941" });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("an update keeps its inputs, since it draws no name", () => {
|
|
87
|
+
const update: PulumiStep = {
|
|
88
|
+
op: "update",
|
|
89
|
+
urn: "urn:pulumi:dev::p::aws:sqs/queue:Queue::events",
|
|
90
|
+
oldState: { inputs: { name: "events-3f45941", messageRetentionSeconds: 60 } },
|
|
91
|
+
newState: { inputs: { __defaults: ["name"], name: "events-3f45941", messageRetentionSeconds: 7200 } },
|
|
92
|
+
};
|
|
93
|
+
expect(pulumiPlannedInputs(update)).toBe(update.newState!.inputs);
|
|
94
|
+
const other = JSON.parse(JSON.stringify(update)) as PulumiStep;
|
|
95
|
+
(other.oldState!.inputs as Record<string, unknown>).name = "events-aaaaaaa";
|
|
96
|
+
(other.newState!.inputs as Record<string, unknown>).name = "events-aaaaaaa";
|
|
97
|
+
expect(pulumiPreviewDigest({ steps: [other] })).not.toBe(pulumiPreviewDigest({ steps: [update] }));
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("a replacement draws a new name too", () => {
|
|
101
|
+
const replace = (suffix: string): PulumiStep => ({
|
|
102
|
+
op: "replace",
|
|
103
|
+
urn: "urn:pulumi:dev::p::aws:sqs/queue:Queue::events",
|
|
104
|
+
oldState: { inputs: { name: "events-1111111", fifoQueue: false } },
|
|
105
|
+
newState: { inputs: { __defaults: ["name"], name: `events-${suffix}`, fifoQueue: true } },
|
|
106
|
+
replaceReasons: ["fifoQueue"],
|
|
107
|
+
});
|
|
108
|
+
expect(pulumiPreviewDigest({ steps: [replace("2222222")] })).toBe(pulumiPreviewDigest({ steps: [replace("3333333")] }));
|
|
109
|
+
const flipped = replace("2222222");
|
|
110
|
+
(flipped.newState!.inputs as Record<string, unknown>).fifoQueue = false;
|
|
111
|
+
expect(pulumiPreviewDigest({ steps: [flipped] })).not.toBe(pulumiPreviewDigest({ steps: [replace("2222222")] }));
|
|
112
|
+
});
|
|
113
|
+
});
|
package/src/pulumi-up.test.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { join, relative } from "node:path";
|
|
|
18
18
|
import { describe, expect, test } from "vitest";
|
|
19
19
|
import { isPlanMovedError, type DeployContext } from "@intentius/chant/components/capability";
|
|
20
20
|
import { PlanShapeMovedError } from "@intentius/chant/components/covered-round";
|
|
21
|
-
import { pulumiPreviewDigest } from "./change-set";
|
|
21
|
+
import { pulumiPreviewDigest, pulumiResourceDigests } from "./change-set";
|
|
22
22
|
import { pulumiStreamPreview, PULUMI_STREAMING_PREVIEW_ENV } from "./engine-events";
|
|
23
23
|
import {
|
|
24
24
|
createPulumiUpCapability,
|
|
@@ -111,6 +111,17 @@ describe("plan on plunge", () => {
|
|
|
111
111
|
expect(artifact.policy.warnings).toHaveLength(1);
|
|
112
112
|
});
|
|
113
113
|
|
|
114
|
+
test("answers a digest for each resource the preview changes, on either grain (plywood#55)", async () => {
|
|
115
|
+
const cap = createPulumiUpCapability({ plunge: engine().run, env: {}, tmp: tmp(), snapshots: null });
|
|
116
|
+
const resource = await cap.plan!(ctx, step({ engine: "plunge" }));
|
|
117
|
+
const stack = await cap.plan!(ctx, step({ engine: "plunge", lockGrain: "target" }));
|
|
118
|
+
expect(resource.resourceDigests).toEqual(pulumiResourceDigests(pulumiStreamPreview(stream)));
|
|
119
|
+
expect(stack.resourceDigests).toEqual(resource.resourceDigests);
|
|
120
|
+
const changed = (pulumiStreamPreview(stream) as { steps: { op: string }[] }).steps.filter((x) => x.op !== "same" && x.op !== "read");
|
|
121
|
+
expect(Object.keys(resource.resourceDigests!).length).toBeGreaterThan(0);
|
|
122
|
+
expect(Object.keys(resource.resourceDigests!).length).toBeLessThanOrEqual(changed.length);
|
|
123
|
+
});
|
|
124
|
+
|
|
114
125
|
test("the target grain keeps every step in the digest", async () => {
|
|
115
126
|
const cap = createPulumiUpCapability({ plunge: engine().run, env: {}, tmp: tmp(), snapshots: null });
|
|
116
127
|
const planned = await cap.plan!(ctx, step({ engine: "plunge", lockGrain: "target" }));
|
package/src/pulumi-up.ts
CHANGED
|
@@ -26,6 +26,8 @@
|
|
|
26
26
|
* through `DeployContext.lockGrain`, else `resource` on plunge and
|
|
27
27
|
* `target` on stock Pulumi, #4552) the digest leaves `same` and `read`
|
|
28
28
|
* steps out (ruling B);
|
|
29
|
+
* - `resourceDigests`: one digest per resource the preview changes, by URN,
|
|
30
|
+
* whatever the grain (plywood#55);
|
|
29
31
|
* - `outputs` from the stack step's planned outputs;
|
|
30
32
|
* - `shape` from `pulumiPlanShape` (`./plan-shape.ts`);
|
|
31
33
|
* - `artifact`: the engine, the shape, the digest, CrossGuard's findings,
|
|
@@ -154,7 +156,7 @@ import type { GatePolicyFindings } from "@intentius/chant/gate-policy";
|
|
|
154
156
|
import { computePlanDigest } from "@intentius/chant/lifecycle/plan-digest";
|
|
155
157
|
import type { SnapshotStore } from "@intentius/chant/lifecycle/snapshot-store";
|
|
156
158
|
import { parseYAML } from "@intentius/chant/yaml";
|
|
157
|
-
import { pulumiPreviewPart } from "./change-set";
|
|
159
|
+
import { pulumiPreviewPart, pulumiResourceDigests } from "./change-set";
|
|
158
160
|
import {
|
|
159
161
|
PULUMI_STREAMING_PREVIEW_ENV,
|
|
160
162
|
pulumiAppliedSteps,
|
|
@@ -795,6 +797,8 @@ async function planStack(ctx: DeployContext, original: PulumiUpStepInput, opts:
|
|
|
795
797
|
planDigest,
|
|
796
798
|
artifact,
|
|
797
799
|
changeSet: read.part,
|
|
800
|
+
// plywood#55: each changed resource's own digest, which a merged wave compares with the pull request's per resource.
|
|
801
|
+
resourceDigests: pulumiResourceDigests(read.preview),
|
|
798
802
|
outputs: { known: planned.known, unknown: planned.unknown },
|
|
799
803
|
shape: read.shape,
|
|
800
804
|
...(ctx.targets?.length ? { targets: ctx.targets } : {}),
|