@go-to-k/cdkd 0.228.0 → 0.229.1
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 +5 -2
- package/dist/cli.js +60 -8
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -589,14 +589,17 @@ cdkd events MyStack # list runs, newest first
|
|
|
589
589
|
cdkd events MyStack --run <runId> # one run's full event stream
|
|
590
590
|
cdkd events MyStack --format json # machine-readable (AI-agent hand-off)
|
|
591
591
|
cdkd events prune MyStack --all # purge event history (reclaim S3 space)
|
|
592
|
+
cdkd destroy MyStack --purge-events # destroy + purge events in one command
|
|
592
593
|
```
|
|
593
594
|
|
|
594
595
|
Events are persisted as JSONL under a `deployments/` key family separate
|
|
595
596
|
from `state.json` (no state schema bump), so a destroyed stack's failure
|
|
596
597
|
history stays readable. Recording is best-effort and never blocks the
|
|
597
598
|
run; events carry error + metadata only (never resource properties). The
|
|
598
|
-
store self-bounds to the last 20 runs,
|
|
599
|
-
history on demand (`--keep N` / `--older-than <dur>` / `--all`)
|
|
599
|
+
store self-bounds to the last 20 runs, `cdkd events prune` purges old
|
|
600
|
+
history on demand (`--keep N` / `--older-than <dur>` / `--all`), and
|
|
601
|
+
`cdkd destroy --purge-events` deletes a stack's history right after a clean
|
|
602
|
+
destroy so the bucket returns fully empty. See
|
|
600
603
|
**[docs/deployment-events.md](docs/deployment-events.md)** for the full
|
|
601
604
|
reference.
|
|
602
605
|
|
package/dist/cli.js
CHANGED
|
@@ -1556,7 +1556,7 @@ const FLUSH_INTERVAL_MS = 2e3;
|
|
|
1556
1556
|
const FLUSH_EVENT_THRESHOLD = 50;
|
|
1557
1557
|
/** Build-time cdkd version, with a dev fallback for non-built contexts. */
|
|
1558
1558
|
function getCdkdVersion() {
|
|
1559
|
-
return "0.
|
|
1559
|
+
return "0.229.1";
|
|
1560
1560
|
}
|
|
1561
1561
|
/**
|
|
1562
1562
|
* Generate a time-sortable unique run id, e.g.
|
|
@@ -2505,10 +2505,16 @@ var ExportIndexStore = class {
|
|
|
2505
2505
|
*
|
|
2506
2506
|
* @param stacks the stacks being deployed / destroyed together (the `--all`
|
|
2507
2507
|
* set, or the auto-include-dependency-expanded target set).
|
|
2508
|
+
* @param opts see {@link InferCrossStackStackDepsOptions}. `opts.kinds`
|
|
2509
|
+
* restricts which reference kinds count as edges (defaults to both). Pass
|
|
2510
|
+
* `['ImportValue']` for STRONG-only edges (deploy-closure expansion).
|
|
2508
2511
|
* @returns Map<consumerStackName, Set<producerStackName>>. Consumers with no
|
|
2509
2512
|
* inferred cross-stack producer get an empty set entry.
|
|
2510
2513
|
*/
|
|
2511
|
-
function inferCrossStackStackDeps(stacks) {
|
|
2514
|
+
function inferCrossStackStackDeps(stacks, opts) {
|
|
2515
|
+
const kinds = opts?.kinds ?? ["ImportValue", "GetStackOutput"];
|
|
2516
|
+
const wantImportValue = kinds.includes("ImportValue");
|
|
2517
|
+
const wantGetStackOutput = kinds.includes("GetStackOutput");
|
|
2512
2518
|
const exportOwner = /* @__PURE__ */ new Map();
|
|
2513
2519
|
for (const stack of stacks) {
|
|
2514
2520
|
const outputs = stack.template.Outputs;
|
|
@@ -2527,10 +2533,14 @@ function inferCrossStackStackDeps(stacks) {
|
|
|
2527
2533
|
collectCrossStackRefs(stack.template, (kind, value) => {
|
|
2528
2534
|
let producer;
|
|
2529
2535
|
if (kind === "ImportValue") {
|
|
2536
|
+
if (!wantImportValue) return;
|
|
2530
2537
|
if (typeof value === "string") producer = exportOwner.get(value);
|
|
2531
|
-
} else
|
|
2532
|
-
|
|
2533
|
-
if (typeof
|
|
2538
|
+
} else {
|
|
2539
|
+
if (!wantGetStackOutput) return;
|
|
2540
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
2541
|
+
const sn = value["StackName"];
|
|
2542
|
+
if (typeof sn === "string") producer = sn;
|
|
2543
|
+
}
|
|
2534
2544
|
}
|
|
2535
2545
|
if (producer && producer !== stack.stackName && stackNames.has(producer)) producers.add(producer);
|
|
2536
2546
|
});
|
|
@@ -36835,13 +36845,19 @@ async function deployCommand(stacks, options) {
|
|
|
36835
36845
|
for (const producer of inferredCrossStackDeps.get(stackName) ?? []) union.add(producer);
|
|
36836
36846
|
return union;
|
|
36837
36847
|
};
|
|
36848
|
+
const inferredStrongCrossStackDeps = inferCrossStackStackDeps(allStacks, { kinds: ["ImportValue"] });
|
|
36849
|
+
const effectiveStrongStackDeps = (stackName, deps) => {
|
|
36850
|
+
const union = new Set(deps);
|
|
36851
|
+
for (const producer of inferredStrongCrossStackDeps.get(stackName) ?? []) union.add(producer);
|
|
36852
|
+
return union;
|
|
36853
|
+
};
|
|
36838
36854
|
if (!options.exclusively) {
|
|
36839
36855
|
const targetNames = new Set(targetStacks.map((s) => s.stackName));
|
|
36840
36856
|
const allStackMap = new Map(allStacks.map((s) => [s.stackName, s]));
|
|
36841
36857
|
const addDependencies = (stackName) => {
|
|
36842
36858
|
const stack = allStackMap.get(stackName);
|
|
36843
36859
|
if (!stack) return;
|
|
36844
|
-
for (const depName of
|
|
36860
|
+
for (const depName of effectiveStrongStackDeps(stackName, stack.dependencyNames)) if (!targetNames.has(depName)) {
|
|
36845
36861
|
const depStack = allStackMap.get(depName);
|
|
36846
36862
|
if (depStack) {
|
|
36847
36863
|
targetNames.add(depName);
|
|
@@ -39418,6 +39434,37 @@ function orderConsumersBeforeProducers(stackNames, consumerToProducers) {
|
|
|
39418
39434
|
return ordered;
|
|
39419
39435
|
}
|
|
39420
39436
|
/**
|
|
39437
|
+
* Issue [#885] — apply `cdkd destroy --purge-events` for one stack.
|
|
39438
|
+
*
|
|
39439
|
+
* Purges the stack's deployment-event history (the post-mortem `deployments/`
|
|
39440
|
+
* store cdkd keeps by default) ONLY after a clean, non-interrupted destroy, so
|
|
39441
|
+
* the state bucket returns fully empty. Deliberately skipped on a failed /
|
|
39442
|
+
* interrupted destroy — those events ARE the post-mortem the user wants on the
|
|
39443
|
+
* retry — and a no-op when `--purge-events` was not passed.
|
|
39444
|
+
*
|
|
39445
|
+
* MUST be called AFTER the run's `eventRecorder.finalize()` (which writes this
|
|
39446
|
+
* run's own events + index): purging first would just be re-created by the
|
|
39447
|
+
* finalize. Best-effort — a purge failure warns but never fails the
|
|
39448
|
+
* already-successful destroy (the resources are gone regardless). The
|
|
39449
|
+
* equivalent for an already-destroyed stack is `cdkd events prune <stack> --all`.
|
|
39450
|
+
*
|
|
39451
|
+
* Returns the prune result when a purge ran, or `null` when it was skipped
|
|
39452
|
+
* (flag off / failed / interrupted) or the purge itself errored. Extracted
|
|
39453
|
+
* from the destroy loop so the gating is unit-testable without the full
|
|
39454
|
+
* synth / AWS-client harness.
|
|
39455
|
+
*/
|
|
39456
|
+
async function purgeEventsAfterDestroy(reader, stackName, region, opts, logger) {
|
|
39457
|
+
if (opts.purgeEvents !== true || opts.runResult !== "SUCCEEDED" || opts.interrupted) return null;
|
|
39458
|
+
try {
|
|
39459
|
+
const purge = await reader.pruneRuns(stackName, region, { all: true });
|
|
39460
|
+
if (purge.deletedRunIds.length > 0 || purge.indexDeleted) logger.info(` Purged deployment-event history for ${stackName} (${region}).`);
|
|
39461
|
+
return purge;
|
|
39462
|
+
} catch (purgeError) {
|
|
39463
|
+
logger.warn(` Failed to purge deployment-event history for ${stackName}: ${purgeError instanceof Error ? purgeError.message : String(purgeError)}`);
|
|
39464
|
+
return null;
|
|
39465
|
+
}
|
|
39466
|
+
}
|
|
39467
|
+
/**
|
|
39421
39468
|
* Destroy command implementation
|
|
39422
39469
|
*/
|
|
39423
39470
|
async function destroyCommand(stackArgs, options) {
|
|
@@ -39645,6 +39692,11 @@ async function destroyCommand(stackArgs, options) {
|
|
|
39645
39692
|
} finally {
|
|
39646
39693
|
await eventRecorder.finalize(destroyRunResult);
|
|
39647
39694
|
}
|
|
39695
|
+
await purgeEventsAfterDestroy(new DeploymentEventsReader(stateBackend), stackName, stackTargetRegion, {
|
|
39696
|
+
purgeEvents: options.purgeEvents,
|
|
39697
|
+
runResult: destroyRunResult,
|
|
39698
|
+
interrupted
|
|
39699
|
+
}, logger);
|
|
39648
39700
|
if (interrupted) break;
|
|
39649
39701
|
}
|
|
39650
39702
|
if (totalErrors > 0) throw new PartialFailureError(`Destroy completed with ${totalErrors} resource error(s). State preserved — inspect 'cdkd state show <stack>' and re-run 'cdkd destroy' to retry.`);
|
|
@@ -39657,7 +39709,7 @@ async function destroyCommand(stackArgs, options) {
|
|
|
39657
39709
|
* Create destroy command
|
|
39658
39710
|
*/
|
|
39659
39711
|
function createDestroyCommand() {
|
|
39660
|
-
const cmd = new Command("destroy").description("Destroy all resources in the stack").argument("[stacks...]", "Stack name(s) to destroy. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards (e.g. 'MyStage/*').").option("--all", "Destroy all stacks", false).action(withErrorHandling(destroyCommand));
|
|
39712
|
+
const cmd = new Command("destroy").description("Destroy all resources in the stack").argument("[stacks...]", "Stack name(s) to destroy. Accepts physical CloudFormation names (e.g. 'MyStage-Api') or CDK display paths (e.g. 'MyStage/Api'). Supports wildcards (e.g. 'MyStage/*').").option("--all", "Destroy all stacks", false).option("--purge-events", "After a clean destroy, also delete the stack's deployment-event history (issue #808 store) so the state bucket returns fully empty. By default events survive destroy as post-mortem context. Skipped when the destroy fails or is interrupted (those events aid the retry). Equivalent for an already-destroyed stack: 'cdkd events prune <stack> --all'.", false).action(withErrorHandling(destroyCommand));
|
|
39661
39713
|
[
|
|
39662
39714
|
...commonOptions,
|
|
39663
39715
|
...appOptions,
|
|
@@ -54952,7 +55004,7 @@ function reorderArgs(argv) {
|
|
|
54952
55004
|
async function main() {
|
|
54953
55005
|
installPipeCloseHandler();
|
|
54954
55006
|
const program = new Command();
|
|
54955
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.
|
|
55007
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.229.1");
|
|
54956
55008
|
program.addCommand(createBootstrapCommand());
|
|
54957
55009
|
program.addCommand(createSynthCommand());
|
|
54958
55010
|
program.addCommand(createListCommand());
|