@intentius/chant 0.18.1 → 0.18.3
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/cli/handlers/lifecycle.d.ts.map +1 -1
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/registry.d.ts +4 -0
- package/dist/cli/registry.d.ts.map +1 -1
- package/dist/discovery/collect.d.ts.map +1 -1
- package/dist/lifecycle/git.d.ts +9 -0
- package/dist/lifecycle/git.d.ts.map +1 -1
- package/dist/lifecycle/live-diff.d.ts +18 -0
- package/dist/lifecycle/live-diff.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli/handlers/lifecycle.ts +79 -2
- package/src/cli/main.ts +4 -0
- package/src/cli/registry.ts +4 -0
- package/src/discovery/collect.test.ts +22 -0
- package/src/discovery/collect.ts +15 -1
- package/src/lifecycle/git.test.ts +16 -0
- package/src/lifecycle/git.ts +21 -0
- package/src/lifecycle/live-diff.test.ts +28 -1
- package/src/lifecycle/live-diff.ts +40 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../../../src/cli/handlers/lifecycle.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAoBlD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAwE/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoC3E;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":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAoBlD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAwE/E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAoC3E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA+C3E;AA2SD;;;;;;;GAOG;AACH,wBAAsB,gBAAgB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CA6G3E;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/dist/cli/main.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAmC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAiB9E;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,
|
|
1
|
+
{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/cli/main.ts"],"names":[],"mappings":";AAKA,OAAO,EAAmC,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAiB9E;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CA2LpD"}
|
package/dist/cli/registry.d.ts
CHANGED
|
@@ -60,6 +60,10 @@ export interface ParsedArgs {
|
|
|
60
60
|
/** `chant graph --live --overlay` — classify the provisioned graph against
|
|
61
61
|
* declared source: managed / foreign / pending (#780). */
|
|
62
62
|
overlay?: boolean;
|
|
63
|
+
/** `chant lifecycle diff <env> --between <refA> <refB>` (#822) — diff two saved
|
|
64
|
+
* snapshots (orphan-branch commits from `lifecycle log`) against each other. */
|
|
65
|
+
betweenA?: string;
|
|
66
|
+
betweenB?: string;
|
|
63
67
|
/** `chant graph --live --overlay --overlay-anchor <source|live>` (#821) — which
|
|
64
68
|
* graph is the canvas. `source` (default) keeps the declared edges (the
|
|
65
69
|
* cross-substrate topology) and joins live status per node; `live` keeps the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/cli/registry.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/cli/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/discovery/collect.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/discovery/collect.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,eAAe,CAAC;AAkB9D;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAAC,GACjE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAqEzB"}
|
package/dist/lifecycle/git.d.ts
CHANGED
|
@@ -46,6 +46,15 @@ export declare function writeSnapshot(environment: string, lexicon: string, json
|
|
|
46
46
|
export declare function readSnapshot(environment: string, lexicon: string, opts?: {
|
|
47
47
|
cwd?: string;
|
|
48
48
|
}): Promise<string | null>;
|
|
49
|
+
/**
|
|
50
|
+
* Read a snapshot at a specific orphan-branch commit (#822). `readSnapshot` reads
|
|
51
|
+
* the branch tip; this reads `<ref>:<env>/<lexicon>.json` for any commit `ref`
|
|
52
|
+
* (as listed by {@link listSnapshots}), so two historical snapshots can be diffed.
|
|
53
|
+
* Returns null if that env/lexicon wasn't captured at `ref`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function readSnapshotAt(environment: string, lexicon: string, ref: string, opts?: {
|
|
56
|
+
cwd?: string;
|
|
57
|
+
}): Promise<string | null>;
|
|
49
58
|
/**
|
|
50
59
|
* Append one immutable release record line to `<environment>/releases.jsonl`
|
|
51
60
|
* on the orphan branch (#568, epic #551 "Build & deploy observability"). Same
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lifecycle/git.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lifecycle/git.ts"],"names":[],"mappings":"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"}
|
|
@@ -46,6 +46,24 @@ export interface DiffLiveInput {
|
|
|
46
46
|
/** Resources captured by the previous snapshot, if any. */
|
|
47
47
|
observedThen: Record<string, ResourceMetadata> | undefined;
|
|
48
48
|
}
|
|
49
|
+
/** The delta between two saved snapshots (#822): a two-way observed diff. */
|
|
50
|
+
export interface SnapshotDiffResult {
|
|
51
|
+
/** In `next`, not in `prev`. */
|
|
52
|
+
added: string[];
|
|
53
|
+
/** In `prev`, not in `next`. */
|
|
54
|
+
removed: string[];
|
|
55
|
+
/** In both; metadata differs (with the attribute-level changes). */
|
|
56
|
+
changed: ResourceDrift[];
|
|
57
|
+
/** In both; metadata identical. */
|
|
58
|
+
unchanged: string[];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Diff two **observed** snapshots (#822) — `prev` vs `next`, each a resources map
|
|
62
|
+
* read from the orphan branch. A two-way diff (no "declared" axis), so it answers
|
|
63
|
+
* "what changed in the cloud between two points" independent of source. Pure and
|
|
64
|
+
* deterministic (results sorted). Feeds the deployment-lanes frame-pair diff.
|
|
65
|
+
*/
|
|
66
|
+
export declare function diffSnapshots(prev: Record<string, ResourceMetadata>, next: Record<string, ResourceMetadata>): SnapshotDiffResult;
|
|
49
67
|
export declare function diffLive(input: DiffLiveInput): LiveDiffResult;
|
|
50
68
|
export interface LiveArtifactDiffResult {
|
|
51
69
|
/** Observed now, not in previous snapshot. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"live-diff.d.ts","sourceRoot":"","sources":["../../src/lifecycle/live-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qDAAqD;IACrD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,mDAAmD;IACnD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mEAAmE;IACnE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,oDAAoD;IACpD,oBAAoB,EAAE,aAAa,EAAE,CAAC;IACtC,sDAAsD;IACtD,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC9C,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS,CAAC;CAC5D;AAyCD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CAiE7D;AAID,MAAM,WAAW,sBAAsB;IACrC,8CAA8C;IAC9C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iCAAiC;IACjC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,mCAAmC;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC9C,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS,CAAC;CAC5D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,sBAAsB,CAmCvF"}
|
|
1
|
+
{"version":3,"file":"live-diff.d.ts","sourceRoot":"","sources":["../../src/lifecycle/live-diff.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,WAAW,eAAe;IAC9B,2EAA2E;IAC3E,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,eAAe,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,cAAc;IAC7B,sEAAsE;IACtE,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qDAAqD;IACrD,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,mDAAmD;IACnD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mEAAmE;IACnE,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,oDAAoD;IACpD,oBAAoB,EAAE,aAAa,EAAE,CAAC;IACtC,sDAAsD;IACtD,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACtB,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC9C,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS,CAAC;CAC5D;AAyCD,6EAA6E;AAC7E,MAAM,WAAW,kBAAkB;IACjC,gCAAgC;IAChC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gCAAgC;IAChC,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oEAAoE;IACpE,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,mCAAmC;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,EACtC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GACrC,kBAAkB,CAiBpB;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,GAAG,cAAc,CAiE7D;AAID,MAAM,WAAW,sBAAsB;IACrC,8CAA8C;IAC9C,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,iCAAiC;IACjC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,mCAAmC;IACnC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,sBAAsB;IACrC,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAC9C,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,GAAG,SAAS,CAAC;CAC5D;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,sBAAsB,CAmCvF"}
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { resolve } from "node:path";
|
|
2
2
|
import { build } from "../../build";
|
|
3
3
|
import { takeSnapshot } from "../../lifecycle/snapshot";
|
|
4
|
-
import { readSnapshot, readEnvironmentSnapshots, listSnapshots, fetchLifecycle, StaleLifecycleBranchError } from "../../lifecycle/git";
|
|
4
|
+
import { readSnapshot, readSnapshotAt, readEnvironmentSnapshots, listSnapshots, fetchLifecycle, StaleLifecycleBranchError } from "../../lifecycle/git";
|
|
5
5
|
import { computeBuildDigest, diffDigests } from "../../lifecycle/digest";
|
|
6
|
-
import { diffLive, diffLiveArtifacts, type LiveDiffResult, type LiveArtifactDiffResult } from "../../lifecycle/live-diff";
|
|
6
|
+
import { diffLive, diffLiveArtifacts, diffSnapshots, type LiveDiffResult, type LiveArtifactDiffResult, type SnapshotDiffResult } from "../../lifecycle/live-diff";
|
|
7
7
|
import { buildChangeSet, renderChangeSet, gitlabMrReport, type ChangeSet } from "../../lifecycle/change-set";
|
|
8
8
|
import { affectedStacks } from "../../lifecycle/affected";
|
|
9
9
|
import { loadChantConfig } from "../../config";
|
|
@@ -159,6 +159,18 @@ export async function runLifecycleDiff(ctx: CommandContext): Promise<number> {
|
|
|
159
159
|
return 1;
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
// `--between <refA> <refB>` (#822): diff two saved snapshots against each other.
|
|
163
|
+
// Purely historical — no build, no cloud query; reads the orphan branch.
|
|
164
|
+
if (args.betweenA && args.betweenB) {
|
|
165
|
+
return runLifecycleDiffBetween({
|
|
166
|
+
environment,
|
|
167
|
+
lexiconFilter,
|
|
168
|
+
refA: args.betweenA,
|
|
169
|
+
refB: args.betweenB,
|
|
170
|
+
json: !!args.json,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
162
174
|
// Filter serializers to target lexicon before building
|
|
163
175
|
const targetSerializers = lexiconFilter
|
|
164
176
|
? plugins.filter((p) => p.name === lexiconFilter).map((p) => p.serializer)
|
|
@@ -186,6 +198,71 @@ export async function runLifecycleDiff(ctx: CommandContext): Promise<number> {
|
|
|
186
198
|
return runLifecycleDiffDigest({ environment, lexicons, buildResult });
|
|
187
199
|
}
|
|
188
200
|
|
|
201
|
+
interface BetweenDiffArgs {
|
|
202
|
+
environment: string;
|
|
203
|
+
lexiconFilter?: string;
|
|
204
|
+
refA: string;
|
|
205
|
+
refB: string;
|
|
206
|
+
json: boolean;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* `chant lifecycle diff <env> --between <refA> <refB>` (#822). Diffs two saved
|
|
211
|
+
* snapshots against each other — read-only, no build, no cloud query. Reads
|
|
212
|
+
* `<ref>:<env>/<lexicon>.json` from the orphan branch at each ref and reports the
|
|
213
|
+
* two-way delta per lexicon.
|
|
214
|
+
*/
|
|
215
|
+
async function runLifecycleDiffBetween(args: BetweenDiffArgs): Promise<number> {
|
|
216
|
+
await fetchLifecycle();
|
|
217
|
+
const { config } = await loadChantConfig(resolve("."));
|
|
218
|
+
const lexicons = args.lexiconFilter ? [args.lexiconFilter] : config.lexicons ?? [];
|
|
219
|
+
if (lexicons.length === 0) {
|
|
220
|
+
console.error(formatError({ message: "No lexicons to diff — pass a lexicon or declare `lexicons` in chant.config." }));
|
|
221
|
+
return 1;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
const parseResources = (content: string | null): Record<string, ResourceMetadata> | null => {
|
|
225
|
+
if (content === null) return null;
|
|
226
|
+
try {
|
|
227
|
+
return (JSON.parse(content) as LifecycleSnapshot).resources ?? {};
|
|
228
|
+
} catch {
|
|
229
|
+
return null;
|
|
230
|
+
}
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const byLexicon: Record<string, SnapshotDiffResult> = {};
|
|
234
|
+
for (const lexicon of lexicons) {
|
|
235
|
+
const prev = parseResources(await readSnapshotAt(args.environment, lexicon, args.refA));
|
|
236
|
+
const next = parseResources(await readSnapshotAt(args.environment, lexicon, args.refB));
|
|
237
|
+
if (prev === null && next === null) {
|
|
238
|
+
if (!args.json) console.error(formatWarning({ message: `${lexicon}: not captured at either ref — skipping` }));
|
|
239
|
+
continue;
|
|
240
|
+
}
|
|
241
|
+
byLexicon[lexicon] = diffSnapshots(prev ?? {}, next ?? {});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if (args.json) {
|
|
245
|
+
console.log(JSON.stringify({ environment: args.environment, refA: args.refA, refB: args.refB, lexicons: byLexicon }, null, 2));
|
|
246
|
+
return 0;
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
if (Object.keys(byLexicon).length === 0) {
|
|
250
|
+
console.log(`No snapshots for ${args.environment} at ${args.refA} / ${args.refB}.`);
|
|
251
|
+
return 0;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
console.log(formatBold(`Snapshot diff — ${args.environment}: ${args.refA} → ${args.refB}`));
|
|
255
|
+
for (const [lexicon, d] of Object.entries(byLexicon)) {
|
|
256
|
+
console.log(
|
|
257
|
+
`\n${formatBold(lexicon)} — ${d.added.length} added, ${d.removed.length} removed, ${d.changed.length} changed, ${d.unchanged.length} unchanged`,
|
|
258
|
+
);
|
|
259
|
+
for (const name of d.added) console.log(` + ${name}`);
|
|
260
|
+
for (const name of d.removed) console.log(` - ${name}`);
|
|
261
|
+
for (const drift of d.changed) console.log(` ~ ${drift.name} (${drift.changes.map((c) => c.path).join(", ")})`);
|
|
262
|
+
}
|
|
263
|
+
return 0;
|
|
264
|
+
}
|
|
265
|
+
|
|
189
266
|
interface DigestDiffArgs {
|
|
190
267
|
environment: string;
|
|
191
268
|
lexicons: string[];
|
package/src/cli/main.ts
CHANGED
|
@@ -94,6 +94,10 @@ export function parseArgs(args: string[]): ParsedArgs {
|
|
|
94
94
|
result.live = true;
|
|
95
95
|
} else if (arg === "--overlay") {
|
|
96
96
|
result.overlay = true;
|
|
97
|
+
} else if (arg === "--between") {
|
|
98
|
+
result.betweenA = args[++i];
|
|
99
|
+
result.betweenB = args[++i];
|
|
100
|
+
if (!result.betweenA || !result.betweenB) throw new Error("--between needs two snapshot refs: --between <refA> <refB>");
|
|
97
101
|
} else if (arg === "--overlay-anchor") {
|
|
98
102
|
const v = args[++i];
|
|
99
103
|
if (v !== "source" && v !== "live") throw new Error(`--overlay-anchor must be 'source' or 'live', got '${v}'`);
|
package/src/cli/registry.ts
CHANGED
|
@@ -61,6 +61,10 @@ export interface ParsedArgs {
|
|
|
61
61
|
/** `chant graph --live --overlay` — classify the provisioned graph against
|
|
62
62
|
* declared source: managed / foreign / pending (#780). */
|
|
63
63
|
overlay?: boolean;
|
|
64
|
+
/** `chant lifecycle diff <env> --between <refA> <refB>` (#822) — diff two saved
|
|
65
|
+
* snapshots (orphan-branch commits from `lifecycle log`) against each other. */
|
|
66
|
+
betweenA?: string;
|
|
67
|
+
betweenB?: string;
|
|
64
68
|
/** `chant graph --live --overlay --overlay-anchor <source|live>` (#821) — which
|
|
65
69
|
* graph is the canvas. `source` (default) keeps the declared edges (the
|
|
66
70
|
* cross-substrate topology) and joins live status per node; `live` keeps the
|
|
@@ -301,3 +301,25 @@ describe("collectEntities with composites", () => {
|
|
|
301
301
|
expect(entities.has("myComp")).toBe(false);
|
|
302
302
|
});
|
|
303
303
|
});
|
|
304
|
+
|
|
305
|
+
describe("collectEntities — default exports (op files)", () => {
|
|
306
|
+
test("two files with `export default` do not collide (keyed per file)", () => {
|
|
307
|
+
const apply = createMockEntity("Temporal::Op");
|
|
308
|
+
const reconcile = createMockEntity("Temporal::Op");
|
|
309
|
+
const result = collectEntities([
|
|
310
|
+
{ file: "ops/apply.op.ts", exports: { default: apply } },
|
|
311
|
+
{ file: "ops/reconcile.op.ts", exports: { default: reconcile } },
|
|
312
|
+
]);
|
|
313
|
+
expect(result.size).toBe(2);
|
|
314
|
+
// keyed by file basename (sans .op.ts), not the literal "default"
|
|
315
|
+
expect(result.get("apply")).toBe(apply);
|
|
316
|
+
expect(result.get("reconcile")).toBe(reconcile);
|
|
317
|
+
expect(result.has("default")).toBe(false);
|
|
318
|
+
});
|
|
319
|
+
|
|
320
|
+
test("a single default export is collected (not dropped)", () => {
|
|
321
|
+
const op = createMockEntity("Temporal::Op");
|
|
322
|
+
const result = collectEntities([{ file: "ops/deploy.op.ts", exports: { default: op } }]);
|
|
323
|
+
expect(result.get("deploy")).toBe(op);
|
|
324
|
+
});
|
|
325
|
+
});
|
package/src/discovery/collect.ts
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
1
2
|
import { isDeclarable, type Declarable } from "../declarable";
|
|
2
3
|
import { isCompositeInstance, expandComposite } from "../composite";
|
|
3
4
|
import { isLexiconOutput } from "../lexicon-output";
|
|
4
5
|
import { DiscoveryError } from "../errors";
|
|
5
6
|
import { setProvenance } from "../provenance";
|
|
6
7
|
|
|
8
|
+
/**
|
|
9
|
+
* The entity key for an export. `export default` is per-module — the `Op` pattern
|
|
10
|
+
* (`export default op`) uses it, and two op files must not collide on the literal
|
|
11
|
+
* name "default". Key a default export by the file's basename so distinct files
|
|
12
|
+
* stay distinct; named exports keep their name. (Serializers that care about the
|
|
13
|
+
* declared name — e.g. the Op serializer — read it from the entity, not this key.)
|
|
14
|
+
*/
|
|
15
|
+
function exportKey(rawName: string, file: string): string {
|
|
16
|
+
if (rawName !== "default") return rawName;
|
|
17
|
+
return basename(file).replace(/\.ts$/, "").replace(/\.op$/, "");
|
|
18
|
+
}
|
|
19
|
+
|
|
7
20
|
/**
|
|
8
21
|
* Collects all declarable entities from imported modules.
|
|
9
22
|
* CompositeInstance exports are expanded into individual entities
|
|
@@ -21,7 +34,8 @@ export function collectEntities(
|
|
|
21
34
|
const entities = new Map<string, Declarable>();
|
|
22
35
|
|
|
23
36
|
for (const { file, exports } of modules) {
|
|
24
|
-
for (const [
|
|
37
|
+
for (const [rawName, value] of Object.entries(exports)) {
|
|
38
|
+
const name = exportKey(rawName, file);
|
|
25
39
|
if (isDeclarable(value)) {
|
|
26
40
|
if (entities.has(name)) {
|
|
27
41
|
// Same object re-exported from multiple files (e.g. re-exports from multiple files) is fine
|
|
@@ -6,6 +6,7 @@ import { join } from "node:path";
|
|
|
6
6
|
import {
|
|
7
7
|
writeSnapshot,
|
|
8
8
|
readSnapshot,
|
|
9
|
+
readSnapshotAt,
|
|
9
10
|
readEnvironmentSnapshots,
|
|
10
11
|
listSnapshots,
|
|
11
12
|
getHeadCommit,
|
|
@@ -56,6 +57,21 @@ describe("lifecycle/git", () => {
|
|
|
56
57
|
});
|
|
57
58
|
});
|
|
58
59
|
|
|
60
|
+
test("readSnapshotAt reads a snapshot at a historical orphan-branch commit (#822)", async () => {
|
|
61
|
+
await withTestDir(async (dir) => {
|
|
62
|
+
await initRepo(dir);
|
|
63
|
+
await writeSnapshot("prod", "aws", JSON.stringify({ resources: { vpc: { type: "T", status: "OK" } } }), { cwd: dir });
|
|
64
|
+
await writeSnapshot("prod", "aws", JSON.stringify({ resources: { vpc: { type: "T", status: "OK" }, subnet: { type: "S", status: "OK" } } }), { cwd: dir });
|
|
65
|
+
const snaps = await listSnapshots({ cwd: dir }); // newest-first
|
|
66
|
+
expect(snaps.length).toBeGreaterThanOrEqual(2);
|
|
67
|
+
const older = await readSnapshotAt("prod", "aws", snaps[1].commit, { cwd: dir });
|
|
68
|
+
const newer = await readSnapshotAt("prod", "aws", snaps[0].commit, { cwd: dir });
|
|
69
|
+
expect(Object.keys(JSON.parse(older!).resources)).toEqual(["vpc"]);
|
|
70
|
+
expect(Object.keys(JSON.parse(newer!).resources).sort()).toEqual(["subnet", "vpc"]);
|
|
71
|
+
expect(await readSnapshotAt("prod", "gcp", snaps[0].commit, { cwd: dir })).toBeNull();
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
|
|
59
75
|
test("subsequent writes preserve other env+lexicon entries", async () => {
|
|
60
76
|
await withTestDir(async (dir) => {
|
|
61
77
|
await initRepo(dir);
|
package/src/lifecycle/git.ts
CHANGED
|
@@ -166,6 +166,27 @@ export async function readSnapshot(
|
|
|
166
166
|
return readBlobFromPath(environment, `${lexicon}.json`, opts);
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
+
/**
|
|
170
|
+
* Read a snapshot at a specific orphan-branch commit (#822). `readSnapshot` reads
|
|
171
|
+
* the branch tip; this reads `<ref>:<env>/<lexicon>.json` for any commit `ref`
|
|
172
|
+
* (as listed by {@link listSnapshots}), so two historical snapshots can be diffed.
|
|
173
|
+
* Returns null if that env/lexicon wasn't captured at `ref`.
|
|
174
|
+
*/
|
|
175
|
+
export async function readSnapshotAt(
|
|
176
|
+
environment: string,
|
|
177
|
+
lexicon: string,
|
|
178
|
+
ref: string,
|
|
179
|
+
opts?: { cwd?: string },
|
|
180
|
+
): Promise<string | null> {
|
|
181
|
+
const rt = getRuntime();
|
|
182
|
+
const result = await rt.spawn(
|
|
183
|
+
["git", "show", `${ref}:${environment}/${lexicon}.json`],
|
|
184
|
+
{ cwd: opts?.cwd },
|
|
185
|
+
);
|
|
186
|
+
if (result.exitCode !== 0) return null;
|
|
187
|
+
return result.stdout;
|
|
188
|
+
}
|
|
189
|
+
|
|
169
190
|
/**
|
|
170
191
|
* Append one immutable release record line to `<environment>/releases.jsonl`
|
|
171
192
|
* on the orphan branch (#568, epic #551 "Build & deploy observability"). Same
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, test, expect } from "vitest";
|
|
2
|
-
import { diffLive, diffLiveArtifacts } from "./live-diff";
|
|
2
|
+
import { diffLive, diffLiveArtifacts, diffSnapshots } from "./live-diff";
|
|
3
3
|
import type { ResourceMetadata, ArtifactMetadata } from "../lexicon";
|
|
4
4
|
|
|
5
5
|
const meta = (overrides: Partial<ResourceMetadata> = {}): ResourceMetadata => ({
|
|
@@ -182,3 +182,30 @@ describe("diffLiveArtifacts", () => {
|
|
|
182
182
|
expect(result.unchanged).toEqual(["release/default/b"]);
|
|
183
183
|
});
|
|
184
184
|
});
|
|
185
|
+
|
|
186
|
+
describe("diffSnapshots (#822)", () => {
|
|
187
|
+
test("classifies added / removed / changed / unchanged between two snapshots", () => {
|
|
188
|
+
const prev = {
|
|
189
|
+
vpc: meta({ physicalId: "vpc-1" }),
|
|
190
|
+
subnet: meta({ physicalId: "subnet-1", status: "CREATE_COMPLETE" }),
|
|
191
|
+
gone: meta({ physicalId: "old" }),
|
|
192
|
+
};
|
|
193
|
+
const next = {
|
|
194
|
+
vpc: meta({ physicalId: "vpc-1" }), // unchanged
|
|
195
|
+
subnet: meta({ physicalId: "subnet-1", status: "UPDATE_COMPLETE" }), // changed (status)
|
|
196
|
+
fresh: meta({ physicalId: "new" }), // added
|
|
197
|
+
};
|
|
198
|
+
const d = diffSnapshots(prev, next);
|
|
199
|
+
expect(d.added).toEqual(["fresh"]);
|
|
200
|
+
expect(d.removed).toEqual(["gone"]);
|
|
201
|
+
expect(d.unchanged).toEqual(["vpc"]);
|
|
202
|
+
expect(d.changed.map((c) => c.name)).toEqual(["subnet"]);
|
|
203
|
+
expect(d.changed[0].changes.map((c) => c.path)).toContain("status");
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
test("empty vs empty is all-unchanged-empty; results are sorted", () => {
|
|
207
|
+
expect(diffSnapshots({}, {})).toEqual({ added: [], removed: [], changed: [], unchanged: [] });
|
|
208
|
+
const d = diffSnapshots({}, { b: meta(), a: meta() });
|
|
209
|
+
expect(d.added).toEqual(["a", "b"]);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
@@ -90,6 +90,46 @@ function shallowEqual(a: unknown, b: unknown): boolean {
|
|
|
90
90
|
return JSON.stringify(a) === JSON.stringify(b);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
/** The delta between two saved snapshots (#822): a two-way observed diff. */
|
|
94
|
+
export interface SnapshotDiffResult {
|
|
95
|
+
/** In `next`, not in `prev`. */
|
|
96
|
+
added: string[];
|
|
97
|
+
/** In `prev`, not in `next`. */
|
|
98
|
+
removed: string[];
|
|
99
|
+
/** In both; metadata differs (with the attribute-level changes). */
|
|
100
|
+
changed: ResourceDrift[];
|
|
101
|
+
/** In both; metadata identical. */
|
|
102
|
+
unchanged: string[];
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Diff two **observed** snapshots (#822) — `prev` vs `next`, each a resources map
|
|
107
|
+
* read from the orphan branch. A two-way diff (no "declared" axis), so it answers
|
|
108
|
+
* "what changed in the cloud between two points" independent of source. Pure and
|
|
109
|
+
* deterministic (results sorted). Feeds the deployment-lanes frame-pair diff.
|
|
110
|
+
*/
|
|
111
|
+
export function diffSnapshots(
|
|
112
|
+
prev: Record<string, ResourceMetadata>,
|
|
113
|
+
next: Record<string, ResourceMetadata>,
|
|
114
|
+
): SnapshotDiffResult {
|
|
115
|
+
const added: string[] = [];
|
|
116
|
+
const removed: string[] = [];
|
|
117
|
+
const changed: ResourceDrift[] = [];
|
|
118
|
+
const unchanged: string[] = [];
|
|
119
|
+
for (const name of [...new Set([...Object.keys(prev), ...Object.keys(next)])].sort()) {
|
|
120
|
+
const a = prev[name];
|
|
121
|
+
const b = next[name];
|
|
122
|
+
if (!a && b) added.push(name);
|
|
123
|
+
else if (a && !b) removed.push(name);
|
|
124
|
+
else if (a && b) {
|
|
125
|
+
const changes = compareMetadata(a, b);
|
|
126
|
+
if (changes.length > 0) changed.push({ name, type: b.type ?? a.type, changes });
|
|
127
|
+
else unchanged.push(name);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return { added, removed, changed, unchanged };
|
|
131
|
+
}
|
|
132
|
+
|
|
93
133
|
export function diffLive(input: DiffLiveInput): LiveDiffResult {
|
|
94
134
|
const { declared, observedNow, observedThen } = input;
|
|
95
135
|
const observedThenMap = observedThen ?? {};
|