@intentius/chant 0.18.34 → 0.18.36
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/lifecycle.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAgDlD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAqF/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoC3E;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/lifecycle.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAgDlD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAqF/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoC3E;AAED;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuB/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAuG3E;AA0UD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAsI3E;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB1E;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAM9E;AAkBD;;;;;;GAMG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA+C/E"}
|
package/package.json
CHANGED
|
@@ -280,7 +280,21 @@ export async function runLifecycleDiff(ctx: CommandContext): Promise<number> {
|
|
|
280
280
|
: Array.from(buildResult.manifest.lexicons);
|
|
281
281
|
|
|
282
282
|
if (args.live) {
|
|
283
|
-
|
|
283
|
+
// Multi-stack component projects: observe each component's own cfn stack
|
|
284
|
+
// and union (same fix runGraphLive / plan use), so a deployed resource
|
|
285
|
+
// isn't reported "missing". Only when this target has no explicit stack.
|
|
286
|
+
let componentStacks: string[] = [];
|
|
287
|
+
if (!target.stack) {
|
|
288
|
+
try {
|
|
289
|
+
const disc = await discoverComponents(target.root);
|
|
290
|
+
const set = new Set<string>();
|
|
291
|
+
for (const { component } of disc.components.values()) for (const s of cfnDeployStacks(component.deploy)) set.add(s);
|
|
292
|
+
componentStacks = [...set];
|
|
293
|
+
} catch {
|
|
294
|
+
// no components / discovery failed → single-stack observe path
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
const r = await runLifecycleDiffLive({ environment, lexicons, plugins, buildResult, json, stack: target.stack, componentStacks });
|
|
284
298
|
totalDrift += r.totalDrift;
|
|
285
299
|
totalChecked += r.totalLexiconsChecked;
|
|
286
300
|
if (json) {
|
|
@@ -434,6 +448,10 @@ interface LiveDiffArgs {
|
|
|
434
448
|
/** Deployed stack name for a multi-stack project (#932); scopes the live
|
|
435
449
|
* observation (which CloudFormation stack to query) and the snapshot read. */
|
|
436
450
|
stack?: string;
|
|
451
|
+
/** Component projects deploy one CFN stack per component; observe them all and
|
|
452
|
+
* union (the same fix graph/plan use), else every deployed resource reads as
|
|
453
|
+
* "missing". Empty → the single-stack observe path. */
|
|
454
|
+
componentStacks?: string[];
|
|
437
455
|
}
|
|
438
456
|
|
|
439
457
|
interface LiveDiffOutcome {
|
|
@@ -497,15 +515,25 @@ async function runLifecycleDiffLive(args: LiveDiffArgs): Promise<LiveDiffOutcome
|
|
|
497
515
|
|
|
498
516
|
// ── Resources path (entity-keyed) ──────────────────────────────────────
|
|
499
517
|
if (plugin.describeResources) {
|
|
500
|
-
let observedNow: Record<string, ResourceMetadata
|
|
518
|
+
let observedNow: Record<string, ResourceMetadata> = {};
|
|
501
519
|
try {
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
520
|
+
if (args.componentStacks && args.componentStacks.length > 0) {
|
|
521
|
+
// Observe each component's own stack and union — the multi-stack fix.
|
|
522
|
+
for (const stack of args.componentStacks) {
|
|
523
|
+
Object.assign(
|
|
524
|
+
observedNow,
|
|
525
|
+
await plugin.describeResources({ environment: args.environment, buildOutput, entityNames: Array.from(declared), entities, stack }),
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
} else {
|
|
529
|
+
observedNow = await plugin.describeResources({
|
|
530
|
+
environment: args.environment,
|
|
531
|
+
buildOutput,
|
|
532
|
+
entityNames: Array.from(declared),
|
|
533
|
+
entities,
|
|
534
|
+
stack: args.stack,
|
|
535
|
+
});
|
|
536
|
+
}
|
|
509
537
|
} catch (err) {
|
|
510
538
|
console.error(formatError({
|
|
511
539
|
message: `${lexiconName}: describeResources failed — ${err instanceof Error ? err.message : String(err)}`,
|
package/src/graph-detail.test.ts
CHANGED
|
@@ -57,6 +57,19 @@ describe("applyDetail", () => {
|
|
|
57
57
|
expect(ir.edges).toContainEqual({ from: "subnet", to: "vpc", kind: "ref", viaAttr: "network" });
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
+
test("T1 (composites) carries the cross-stack imports forward (survive the collapse as plain nodes)", () => {
|
|
61
|
+
const withImports: GraphIR = {
|
|
62
|
+
...base,
|
|
63
|
+
nodes: [...base.nodes, { id: "pClusterArn", kind: "AWS::CloudFormation::Parameter", lexicon: "aws", attrs: {} }],
|
|
64
|
+
imports: [{ name: "pClusterArn", node: "pClusterArn" }],
|
|
65
|
+
};
|
|
66
|
+
const ir = applyDetail(withImports, DETAIL.COMPOSITES);
|
|
67
|
+
// The import node isn't a composite, so it survives — and `imports` rides
|
|
68
|
+
// along so a viewer can hide/match it at this tier too (not just base + T3).
|
|
69
|
+
expect(ir.nodes.some((n) => n.id === "pClusterArn")).toBe(true);
|
|
70
|
+
expect(ir.imports).toEqual([{ name: "pClusterArn", node: "pClusterArn" }]);
|
|
71
|
+
});
|
|
72
|
+
|
|
60
73
|
test("T1 node count is between T0 and T2", () => {
|
|
61
74
|
const t0 = applyDetail(base, DETAIL.STACKS).nodes.length;
|
|
62
75
|
const t1 = applyDetail(base, DETAIL.COMPOSITES).nodes.length;
|
package/src/graph-detail.ts
CHANGED
|
@@ -111,7 +111,18 @@ function toComposites(ir: GraphIR): GraphIR {
|
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
nodes.sort((a, b) => a.id.localeCompare(b.id));
|
|
114
|
-
|
|
114
|
+
// Carry the cross-stack import list forward: parameter/import nodes aren't
|
|
115
|
+
// composites, so they survive the collapse as plain nodes — a viewer that
|
|
116
|
+
// hides imports (or matches them across stacks) needs `imports` at every tier,
|
|
117
|
+
// not just the base + ATTRIBUTES. Filter to handles whose node survived.
|
|
118
|
+
const surviving = new Set(nodes.map((n) => n.id));
|
|
119
|
+
const imports = ir.imports?.filter((i) => surviving.has(i.node));
|
|
120
|
+
return {
|
|
121
|
+
nodes,
|
|
122
|
+
edges: sortEdges([...seen.values()]),
|
|
123
|
+
groups: { byLexicon: byLexiconOf(nodes) },
|
|
124
|
+
...(imports && imports.length ? { imports } : {}),
|
|
125
|
+
};
|
|
115
126
|
}
|
|
116
127
|
|
|
117
128
|
/** T3 — annotate each edge with the producer attribute it references. */
|