@go-to-k/cdkd 0.283.7 → 0.283.8

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.
@@ -13971,7 +13971,7 @@ var CloudControlProvider = class {
13971
13971
  if (context?.finalSnapshotIdentifier !== void 0) throw new ProvisioningError(`${logicalId} (${resourceType}) requires a final snapshot (DeletionPolicy: Snapshot), but the Cloud Control API delete route has no final-snapshot parameter. Re-run with --skip-final-snapshot after snapshotting manually, or retain the resource.`, resourceType, logicalId, physicalId);
13972
13972
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
13973
13973
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
13974
- const { ASGProvider } = await import("./asg-provider-o7QsopaI.js").then((n) => n.n);
13974
+ const { ASGProvider } = await import("./asg-provider-Tu4sDbhu.js").then((n) => n.n);
13975
13975
  return await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
13976
13976
  }
13977
13977
  const isProtectedEc2Instance = context?.removeProtection === true && resourceType === "AWS::EC2::Instance";
@@ -14655,7 +14655,7 @@ const CR_NO_SERVICE_TOKEN_SKIP_REASON = "no ServiceToken in state — Delete han
14655
14655
  * torn down by hand. Mirrors the caveat `compositeIdFormatMessage` already
14656
14656
  * carries for the composite-id family.
14657
14657
  */
14658
- const DEPLOY_SKIP_CAVEAT = "NOTE this arm is ALSO reached from cdkd deploy (the DELETE of a resource removed from the template, plus the replacement / rollback deletes), which DROP the state record and report success (https://github.com/go-to-k/cdkd/issues/1762) — there, tear the resource down by hand.";
14658
+ const DEPLOY_SKIP_CAVEAT = "NOTE this arm is ALSO reached from cdkd deploy. Since issue 1762 the DELETE of a resource removed from the template behaves like destroy — the record is KEPT and the next deploy re-attempts it — but a REPLACEMENT / rollback delete FAILS the resource instead (https://github.com/go-to-k/cdkd/issues/1762), leaving the old one untracked; there, tear the resource down by hand.";
14659
14659
  /**
14660
14660
  * Type guard to validate Lambda response payload structure
14661
14661
  */
@@ -20086,8 +20086,98 @@ async function withResourceDeadline(operation, opts) {
20086
20086
  });
20087
20087
  }
20088
20088
 
20089
+ //#endregion
20090
+ //#region src/deployment/delete-outcome.ts
20091
+ /**
20092
+ * Deploy-side consumption of {@link ResourceDeleteResult} (issue
20093
+ * [#1762](https://github.com/go-to-k/cdkd/issues/1762)) — the twin of what
20094
+ * `src/cli/commands/destroy-runner.ts` does for `cdkd destroy`.
20095
+ *
20096
+ * Issue [#1752](https://github.com/go-to-k/cdkd/issues/1752) gave
20097
+ * `ResourceProvider.delete` an optional return value whose `'skipped'` arm
20098
+ * means **the resource this result names was NOT destroyed and may still be
20099
+ * ALIVE**, and taught the destroy runner to report it. Every OTHER
20100
+ * `provider.delete(...)` call site — the deploy engine's template-DELETE
20101
+ * branch, its four replacement / recreate delete sites, and the five
20102
+ * `rollback-executor.ts` delete arms — discarded the value, so the same skip
20103
+ * printed as `deleted`, counted as `deleted`, and dropped the state record.
20104
+ *
20105
+ * **The module must stay a LEAF — no imports beyond the type, ever.** Same
20106
+ * reason as `src/provisioning/nested-stack-messages.ts`: both the deploy
20107
+ * engine and the rollback executor consume it, and those two already sit on a
20108
+ * dense import ring (engine -> executor -> provider registry -> every
20109
+ * provider). A helper that pulled anything else in would close it.
20110
+ */
20111
+ /**
20112
+ * The `reason` of a `'skipped'` delete outcome, or `undefined` when the
20113
+ * provider reported a delete (`{ outcome: 'deleted' }` or the back-compat
20114
+ * `void` return ~80 providers still use).
20115
+ *
20116
+ * A function rather than an inline `result?.outcome === 'skipped'` test at
20117
+ * ten call sites so the back-compat `void` reading lives in ONE place: the
20118
+ * signature is `Promise<void | ResourceDeleteResult>`, so a caller that awaits
20119
+ * it holds `void | ResourceDeleteResult`, which TypeScript will happily let
20120
+ * you compare against nothing useful.
20121
+ */
20122
+ function deleteSkipReason(result) {
20123
+ if (!result || result.outcome !== "skipped") return void 0;
20124
+ if (typeof result.reason !== "string") return UNSPECIFIED_SKIP_REASON;
20125
+ const trimmed = result.reason.trim();
20126
+ return trimmed === "" ? UNSPECIFIED_SKIP_REASON : trimmed;
20127
+ }
20128
+ /**
20129
+ * Stand-in for a `'skipped'` outcome whose producer supplied no `reason`.
20130
+ *
20131
+ * Deliberately says the cause is unknown rather than inventing one: the line
20132
+ * it renders on is the user's only signal that the resource survived, and a
20133
+ * fabricated cause would send them looking in the wrong place.
20134
+ */
20135
+ const UNSPECIFIED_SKIP_REASON = "no reason reported by the provider";
20136
+ /**
20137
+ * The sentence every deploy-side skip renders, in the log line AND in the
20138
+ * `Error` the sites that must FAIL the resource throw.
20139
+ *
20140
+ * Wording rules, both load-bearing:
20141
+ *
20142
+ * 1. It says the resource was NOT deleted and MAY STILL EXIST. A skip issued
20143
+ * no AWS call at every producer but `NestedStackProvider.delete`, so the
20144
+ * old resource is presumed alive — which is the whole reason a replacement
20145
+ * site cannot proceed to create its replacement beside it.
20146
+ * 2. It must NOT contain any phrase the callers' already-deleted classifiers
20147
+ * substring-match (`does not exist` / `was not found` / `not found` /
20148
+ * `No policy found` / `NoSuchEntity` / `NotFoundException` /
20149
+ * `ResourceNotFoundException`). Reading a skip as "already gone" is exactly
20150
+ * the mis-accounting this change exists to remove, and the deploy engine's
20151
+ * DELETE branch and its update-not-supported fallback each carry such a
20152
+ * classifier. The call sites additionally handle the skip OUTSIDE their
20153
+ * `catch`, so a future `reason` carrying one of those phrases still cannot
20154
+ * reach a classifier — belt and braces, because `reason` is provider text.
20155
+ */
20156
+ function deleteSkippedMessage(logicalId, physicalId, reason, duringClause) {
20157
+ return `cdkd could not address ${logicalId} (${physicalId}) ${duringClause}, so it was NOT deleted and may still exist: ${reason}`;
20158
+ }
20159
+
20089
20160
  //#endregion
20090
20161
  //#region src/deployment/rollback-executor.ts
20162
+ /**
20163
+ * Issue [#1762](https://github.com/go-to-k/cdkd/issues/1762): turn a
20164
+ * `{ outcome: 'skipped' }` delete into a thrown error at every rollback delete
20165
+ * arm.
20166
+ *
20167
+ * A skip means the resource was NOT deleted, so the rollback op did not
20168
+ * happen. Throwing routes it into the per-op accounting each arm already has —
20169
+ * `result.failures++` plus a `ROLLBACK_RESOURCE_FAILED` event and a kept
20170
+ * journal segment for the shared catch, or the local warn + `result.warnings++`
20171
+ * at the one arm whose delete is already best-effort. Both are correct and
20172
+ * neither needs a second code path; what is NOT correct is the pre-#1762
20173
+ * behavior, where every arm read a skip as a successful revert, dropped the
20174
+ * state record, and popped the segment.
20175
+ */
20176
+ function throwIfDeleteSkipped(result, logicalId, physicalId, duringClause) {
20177
+ const reason = deleteSkipReason(result);
20178
+ if (reason === void 0) return;
20179
+ throw new Error(deleteSkippedMessage(logicalId, physicalId, reason, duringClause));
20180
+ }
20091
20181
  /** The `--skip-final-snapshot` flag name cited by every refusal below. */
20092
20182
  const SKIP_FINAL_SNAPSHOT_FLAG = "--skip-final-snapshot";
20093
20183
  /**
@@ -20517,10 +20607,10 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
20517
20607
  resourceType: op.resourceType,
20518
20608
  provisionedBy: deleteProvisionedBy
20519
20609
  });
20520
- await provider.delete(op.logicalId, op.physicalId, op.resourceType, op.properties, {
20610
+ throwIfDeleteSkipped(await provider.delete(op.logicalId, op.physicalId, op.resourceType, op.properties, {
20521
20611
  expectedRegion: ctx.region,
20522
20612
  ...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
20523
- });
20613
+ }), op.logicalId, op.physicalId, "while rolling back its CREATE");
20524
20614
  delete stateResources[op.logicalId];
20525
20615
  logger.info(` Rollback: ${op.logicalId} deleted successfully`);
20526
20616
  await afterOp?.(op.logicalId);
@@ -20544,10 +20634,10 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
20544
20634
  });
20545
20635
  {
20546
20636
  const finalSnapshotIdentifier = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
20547
- await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
20637
+ throwIfDeleteSkipped(await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
20548
20638
  expectedRegion: ctx.region,
20549
20639
  ...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
20550
- });
20640
+ }), op.logicalId, current.physicalId, "while reversing its replacement (re-adopting the retained old resource)");
20551
20641
  }
20552
20642
  stateResources[op.logicalId] = prev;
20553
20643
  logger.info(` Rollback: ${op.logicalId} restored to the retained old resource`);
@@ -20592,10 +20682,10 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
20592
20682
  logger.info(` Rollback: re-create collided with the new resource's name — deleting the new resource (${current.physicalId}) first...`);
20593
20683
  {
20594
20684
  const finalSnapshotIdentifier = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
20595
- await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
20685
+ throwIfDeleteSkipped(await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
20596
20686
  expectedRegion: ctx.region,
20597
20687
  ...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
20598
- });
20688
+ }), op.logicalId, current.physicalId, "while clearing the new resource so the old one could be re-created");
20599
20689
  }
20600
20690
  deletedNewFirst = true;
20601
20691
  delete stateResources[op.logicalId];
@@ -20629,10 +20719,10 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
20629
20719
  await afterOp?.(op.logicalId);
20630
20720
  if (!deletedNewFirst && !adoptedLiveNewResource) try {
20631
20721
  const finalSnapshotIdentifier = rollbackFinalSnapshotId(op.resourceType, current, op.provisionedBy);
20632
- await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
20722
+ throwIfDeleteSkipped(await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, {
20633
20723
  expectedRegion: ctx.region,
20634
20724
  ...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
20635
- });
20725
+ }), op.logicalId, current.physicalId, "while deleting the new resource after re-creating the old one");
20636
20726
  } catch (deleteError) {
20637
20727
  logger.warn(` Rollback: old ${op.logicalId} re-created, but deleting the new resource (${current.physicalId}) failed: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}. Delete it manually — it is no longer tracked in state.`);
20638
20728
  result.warnings++;
@@ -20778,10 +20868,10 @@ async function replayFailedOperations(failedOps, stateResources, stackName, ctx,
20778
20868
  resourceType: op.resourceType,
20779
20869
  provisionedBy: deleteProvisionedBy
20780
20870
  });
20781
- await provider.delete(op.logicalId, op.physicalId, op.resourceType, op.attemptedProperties, {
20871
+ throwIfDeleteSkipped(await provider.delete(op.logicalId, op.physicalId, op.resourceType, op.attemptedProperties, {
20782
20872
  expectedRegion: ctx.region,
20783
20873
  ...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
20784
- });
20874
+ }), op.logicalId, op.physicalId, "while deleting the partially-created resource (--revert-failed)");
20785
20875
  delete stateResources[op.logicalId];
20786
20876
  await options.afterOp?.(op.logicalId);
20787
20877
  ctx.recordEvent?.({
@@ -20935,7 +21025,7 @@ const FLUSH_INTERVAL_MS = 2e3;
20935
21025
  const FLUSH_EVENT_THRESHOLD = 50;
20936
21026
  /** Build-time cdkd version, with a dev fallback for non-built contexts. */
20937
21027
  function getCdkdVersion() {
20938
- return "0.283.7";
21028
+ return "0.283.8";
20939
21029
  }
20940
21030
  /**
20941
21031
  * Generate a time-sortable unique run id, e.g.
@@ -21902,6 +21992,7 @@ var DeployEngine = class {
21902
21992
  created: 0,
21903
21993
  updated: 0,
21904
21994
  deleted: 0,
21995
+ deleteSkipped: 0,
21905
21996
  unchanged: Object.keys(currentState.resources).length,
21906
21997
  durationMs: Date.now() - startTime,
21907
21998
  outputs: this.buildDisplayOutputs(template, persistedOutputs),
@@ -21919,6 +22010,7 @@ var DeployEngine = class {
21919
22010
  created: createChanges.length,
21920
22011
  updated: updateChanges.length,
21921
22012
  deleted: deleteChanges.length,
22013
+ deleteSkipped: 0,
21922
22014
  unchanged: this.diffCalculator.filterByType(changes, "NO_CHANGE").length,
21923
22015
  durationMs: Date.now() - startTime,
21924
22016
  attributeFallbackCount: this.resolver.getPhysicalIdFallbackCount()
@@ -21941,6 +22033,7 @@ var DeployEngine = class {
21941
22033
  created: actualCounts.created,
21942
22034
  updated: actualCounts.updated,
21943
22035
  deleted: actualCounts.deleted,
22036
+ deleteSkipped: actualCounts.deleteSkipped,
21944
22037
  unchanged: unchangedCount,
21945
22038
  durationMs,
21946
22039
  outputs: this.buildDisplayOutputs(template, newState.outputs ?? {}),
@@ -21974,7 +22067,8 @@ var DeployEngine = class {
21974
22067
  created: 0,
21975
22068
  updated: 0,
21976
22069
  deleted: 0,
21977
- skipped: 0
22070
+ skipped: 0,
22071
+ deleteSkipped: 0
21978
22072
  };
21979
22073
  const completedOperations = [];
21980
22074
  const failedOperations = [];
@@ -22081,8 +22175,9 @@ var DeployEngine = class {
22081
22175
  const logicalId = node.id;
22082
22176
  const change = node.data;
22083
22177
  const previousState = currentState.resources[logicalId] ? { ...currentState.resources[logicalId] } : void 0;
22178
+ let deleteOutcome;
22084
22179
  try {
22085
- await this.provisionResource(logicalId, change, newResources, stackName, template, parameterValues, conditions, actualCounts, progress);
22180
+ deleteOutcome = await this.provisionResource(logicalId, change, newResources, stackName, template, parameterValues, conditions, actualCounts, progress);
22086
22181
  } catch (provisionError) {
22087
22182
  this.interrupted = true;
22088
22183
  this.interruptCause ??= "sibling-failure";
@@ -22096,6 +22191,7 @@ var DeployEngine = class {
22096
22191
  });
22097
22192
  throw provisionError;
22098
22193
  }
22194
+ if (deleteOutcome) return;
22099
22195
  completedOperations.push({
22100
22196
  logicalId,
22101
22197
  changeType: "DELETE",
@@ -22387,9 +22483,10 @@ var DeployEngine = class {
22387
22483
  resourceType,
22388
22484
  ...labelRouting && { provisionedBy: labelRouting }
22389
22485
  });
22486
+ let deleteSkipped;
22390
22487
  try {
22391
22488
  await withResourceDeadline(async () => {
22392
- await this.provisionResourceBody(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress);
22489
+ deleteSkipped = (await this.provisionResourceBody(logicalId, change, stateResources, stackName, template, parameterValues, conditions, counts, progress))?.deleteSkipped;
22393
22490
  }, {
22394
22491
  warnAfterMs,
22395
22492
  timeoutMs,
@@ -22403,6 +22500,20 @@ var DeployEngine = class {
22403
22500
  },
22404
22501
  onTimeout: (elapsedMs) => new ResourceTimeoutError(logicalId, resourceType, this.stackRegion, elapsedMs, operationKind, timeoutMs)
22405
22502
  });
22503
+ if (deleteSkipped !== void 0) {
22504
+ this.recordEvent({
22505
+ eventType: "RESOURCE_SKIPPED",
22506
+ stackName,
22507
+ operation: eventOp,
22508
+ logicalId,
22509
+ resourceType,
22510
+ ...stateResources[logicalId]?.provisionedBy ? { provisionedBy: stateResources[logicalId]?.provisionedBy } : labelRouting && { provisionedBy: labelRouting },
22511
+ ...stateResources[logicalId]?.physicalId && { physicalId: stateResources[logicalId]?.physicalId },
22512
+ reason: deleteSkipped,
22513
+ durationMs: Date.now() - resourceStartedAt
22514
+ });
22515
+ return { deleteSkipped };
22516
+ }
22406
22517
  this.recordEvent({
22407
22518
  eventType: "RESOURCE_SUCCEEDED",
22408
22519
  stackName,
@@ -22499,8 +22610,9 @@ var DeployEngine = class {
22499
22610
  */
22500
22611
  async replaceDeleteFirstAndRecreate(logicalId, resourceType, currentResource, oldDeleteProvider, replaceProvider, replaceProps, updateReplacePolicy) {
22501
22612
  const finalSnapshotIdentifier = await this.prepareFinalSnapshotForDelete(logicalId, resourceType, currentResource, updateReplacePolicy);
22613
+ let deleteResult;
22502
22614
  try {
22503
- await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
22615
+ deleteResult = await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
22504
22616
  expectedRegion: this.stackRegion,
22505
22617
  forceDataDelete: this.options.forceStatefulRecreation === true,
22506
22618
  ...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
@@ -22508,6 +22620,8 @@ var DeployEngine = class {
22508
22620
  } catch (deleteError) {
22509
22621
  throw new Error(`Failed to delete old resource ${logicalId} (${currentResource.physicalId}) during the --replace delete-first fallback: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
22510
22622
  }
22623
+ const replaceSkipReason = deleteSkipReason(deleteResult);
22624
+ if (replaceSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, replaceSkipReason, "during the --replace delete-first fallback"));
22511
22625
  this.logger.info(` ${green("✓")} Old resource deleted`);
22512
22626
  this.logger.info(` Re-creating ${logicalId}...`);
22513
22627
  try {
@@ -22645,16 +22759,19 @@ var DeployEngine = class {
22645
22759
  else {
22646
22760
  this.logger.info(` Destroying old ${logicalId} (${currentResource.physicalId}) before recreate...`);
22647
22761
  const recreateFinalSnapshotId = await this.prepareFinalSnapshotForDelete(logicalId, resourceType, currentResource, updateReplacePolicy);
22762
+ let recreateDeleteResult;
22648
22763
  try {
22649
- await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
22764
+ recreateDeleteResult = await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
22650
22765
  expectedRegion: this.stackRegion,
22651
22766
  forceDataDelete: this.options.forceStatefulRecreation === true,
22652
22767
  ...recreateFinalSnapshotId !== void 0 && { finalSnapshotIdentifier: recreateFinalSnapshotId }
22653
22768
  });
22654
- this.logger.info(` ${green("✓")} Old resource deleted`);
22655
22769
  } catch (deleteError) {
22656
22770
  throw new Error(`Failed to destroy old resource ${logicalId} (${currentResource.physicalId}) during ${recreateFlagName}: ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
22657
22771
  }
22772
+ const recreateSkipReason = deleteSkipReason(recreateDeleteResult);
22773
+ if (recreateSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, recreateSkipReason, `during ${recreateFlagName}`));
22774
+ this.logger.info(` ${green("✓")} Old resource deleted`);
22658
22775
  }
22659
22776
  this.logger.info(` Creating new ${logicalId}...`);
22660
22777
  createResult = await withRetry(() => this.withRetry(() => replaceProvider.create(logicalId, resourceType, replaceProps), logicalId, void 0, void 0, replaceProvider), logicalId, {
@@ -22702,15 +22819,22 @@ var DeployEngine = class {
22702
22819
  snapshotBlockedDelete = true;
22703
22820
  this.logger.warn(` ⚠ Final snapshot for old ${logicalId} (${currentResource.physicalId}) failed: ${snapshotError instanceof Error ? snapshotError.message : String(snapshotError)}. The old resource was NOT deleted (UpdateReplacePolicy: Snapshot) — delete it manually once you have a snapshot; it is no longer tracked in state.`);
22704
22821
  }
22705
- if (!snapshotBlockedDelete) try {
22706
- await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
22707
- expectedRegion: this.stackRegion,
22708
- forceDataDelete: this.options.forceStatefulRecreation === true,
22709
- ...cleanupFinalSnapshotId !== void 0 && { finalSnapshotIdentifier: cleanupFinalSnapshotId }
22710
- });
22711
- this.logger.info(` ${green("✓")} Old resource deleted`);
22712
- } catch (deleteError) {
22713
- this.logger.warn(` ⚠ Failed to delete old resource ${logicalId} (${currentResource.physicalId}): ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
22822
+ if (!snapshotBlockedDelete) {
22823
+ let cleanupDeleteResult = void 0;
22824
+ let cleanupDeleteFailed = false;
22825
+ try {
22826
+ cleanupDeleteResult = await oldDeleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
22827
+ expectedRegion: this.stackRegion,
22828
+ forceDataDelete: this.options.forceStatefulRecreation === true,
22829
+ ...cleanupFinalSnapshotId !== void 0 && { finalSnapshotIdentifier: cleanupFinalSnapshotId }
22830
+ });
22831
+ } catch (deleteError) {
22832
+ this.logger.warn(` ⚠ Failed to delete old resource ${logicalId} (${currentResource.physicalId}): ${deleteError instanceof Error ? deleteError.message : String(deleteError)}`);
22833
+ cleanupDeleteFailed = true;
22834
+ }
22835
+ const cleanupSkipReason = deleteSkipReason(cleanupDeleteResult);
22836
+ if (cleanupSkipReason !== void 0) this.logger.warn(` ⚠ ${deleteSkippedMessage(logicalId, currentResource.physicalId, cleanupSkipReason, "while cleaning up the replaced resource")}. Delete it manually — it is no longer tracked in state.`);
22837
+ else if (!cleanupDeleteFailed) this.logger.info(` ${green("✓")} Old resource deleted`);
22714
22838
  }
22715
22839
  }
22716
22840
  }
@@ -22753,8 +22877,9 @@ var DeployEngine = class {
22753
22877
  }
22754
22878
  this.logger.info(`UPDATE not supported for ${logicalId} (${resourceType}), replacing (DELETE → CREATE)`);
22755
22879
  const fallbackFinalSnapshotId = await this.prepareFinalSnapshotForDelete(logicalId, resourceType, currentResource, template?.Resources?.[logicalId]?.UpdateReplacePolicy ?? currentResource.updateReplacePolicy);
22880
+ let fallbackDeleteResult = void 0;
22756
22881
  try {
22757
- await updateProvider.delete(logicalId, currentResource.physicalId, resourceType, currentProps, {
22882
+ fallbackDeleteResult = await updateProvider.delete(logicalId, currentResource.physicalId, resourceType, currentProps, {
22758
22883
  expectedRegion: this.stackRegion,
22759
22884
  forceDataDelete: this.options.forceStatefulRecreation === true,
22760
22885
  ...fallbackFinalSnapshotId !== void 0 && { finalSnapshotIdentifier: fallbackFinalSnapshotId }
@@ -22764,6 +22889,8 @@ var DeployEngine = class {
22764
22889
  if (deleteMsg.includes("does not exist") || deleteMsg.includes("not found") || deleteMsg.includes("NotFound")) this.logger.debug(`Old resource ${logicalId} already gone, proceeding with CREATE`);
22765
22890
  else throw deleteError;
22766
22891
  }
22892
+ const fallbackSkipReason = deleteSkipReason(fallbackDeleteResult);
22893
+ if (fallbackSkipReason !== void 0) throw new Error(deleteSkippedMessage(logicalId, currentResource.physicalId, fallbackSkipReason, "during the UPDATE-not-supported replacement"));
22767
22894
  const replDecision = this.providerRegistry.getProviderFor({
22768
22895
  resourceType,
22769
22896
  properties: resolvedProps
@@ -22817,8 +22944,9 @@ var DeployEngine = class {
22817
22944
  provisionedBy: currentResource.provisionedBy
22818
22945
  }).provider;
22819
22946
  this.logger.debug(`Deleting ${logicalId} (${resourceType})`);
22947
+ let deleteResult = void 0;
22820
22948
  try {
22821
- await this.withRetry(() => deleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
22949
+ deleteResult = await this.withRetry(() => deleteProvider.delete(logicalId, currentResource.physicalId, resourceType, currentResource.properties, {
22822
22950
  expectedRegion: this.stackRegion,
22823
22951
  ...finalSnapshotIdentifier !== void 0 && { finalSnapshotIdentifier }
22824
22952
  }), logicalId, 3, 5e3, deleteProvider);
@@ -22827,6 +22955,16 @@ var DeployEngine = class {
22827
22955
  if (msg.includes("does not exist") || msg.includes("was not found") || msg.includes("not found") || msg.includes("No policy found") || msg.includes("NoSuchEntity") || msg.includes("NotFoundException") || msg.includes("ResourceNotFoundException")) this.logger.debug(`Resource ${logicalId} already deleted (${msg}), removing from state`);
22828
22956
  else throw deleteError;
22829
22957
  }
22958
+ const deleteSkipped = deleteSkipReason(deleteResult);
22959
+ if (deleteSkipped !== void 0) {
22960
+ if (progress) progress.current++;
22961
+ const skipPrefix = progress ? `[${progress.current}/${progress.total}] ` : " ";
22962
+ renderer.removeTask(logicalId);
22963
+ this.logger.info(`${skipPrefix}${formatResourceLine("skipped", logicalId, resourceType, `skipped (${deleteSkipped})`)}`);
22964
+ this.logger.warn(deleteSkippedMessage(logicalId, currentResource.physicalId, deleteSkipped, "while removing it from the template") + `. Its cdkd state record was KEPT, so the next 'cdkd deploy' re-attempts the delete. Repair the record first ('cdkd state show ${stackName}' to inspect; for a nested stack it is the CHILD's own state, whose other resources may already be gone), or delete the resource by hand and drop the record with 'cdkd state orphan ${stackName}'.`);
22965
+ if (counts) counts.deleteSkipped++;
22966
+ return { deleteSkipped };
22967
+ }
22830
22968
  delete stateResources[logicalId];
22831
22969
  if (counts) counts.deleted++;
22832
22970
  if (progress) progress.current++;
@@ -23103,5 +23241,5 @@ var DeployEngine = class {
23103
23241
  };
23104
23242
 
23105
23243
  //#endregion
23106
- export { configStringRefusal as $, resolveSkipPrefix as $t, green as A, LockError as An, rewriteTemplateAssetReferences as At, slowCcOperationTimeoutMs as B, SynthesisError as Bn, formatDockerLoginError as Bt, MULTI_REGION_RECREATE_BLOCKED_TYPES as C, CdkdError as Cn, shouldRetainResource as Ct, bold as D, LocalInvokeBuildError as Dn, buildAssetRedirectMap as Dt, formatResourceLine as E, DeployCancelledError as En, WorkGraph as Et, clearOnUpdateRemoval as F, ResourceTimeoutError as Fn, parseBootstrapMarker as Ft, getAccountInfo as G, __exportAll as Gn, getDockerImageBySourceHash as Gt, isTerminationProtectionPropagationError as H, isCdkdError as Hn, runDockerForeground as Ht, ProviderRegistry as I, ResourceUpdateNotSupportedError as In, validateAssetBucketName as It, normalizeAwsTagsToCfn as J, getDefaultStateBucketName as Jt, refStateLookupFromResource as K, Synthesizer as Kt, findActionableSilentDrops as L, StackHasActiveImportsError as Ln, validateContainerRepoName as Lt, yellow as M, NestedStackChildDirectDestroyError as Mn, BOOTSTRAP_MARKER_PREFIX as Mt, IAMRoleProvider as N, PartialFailureError as Nn, ensureAssetStorage as Nt, cyan as O, LocalMigrateError as On, createAssetRedirectResolver as Ot, collectInlinePolicyNamesManagedBySiblings as P, ProvisioningError as Pn, getBootstrapMarkerKey as Pt, configBooleanRefusal as Q, resolveCaptureObservedState as Qt, findSilentDropProperties as R, StackTerminationProtectionError as Rn, buildDenyExternalAccessPolicy as Rt, extractDeploymentEventError as S, AssetError as Sn, rebuildClientForBucketRegion as St, renderStatefulReason as T, DependencyError as Tn, stringifyValue as Tt, IntrinsicFunctionResolver as U, normalizeAwsError as Un, runDockerStreaming as Ut, disableInstanceApiTermination as V, formatError as Vn, getDockerCmd as Vt, cfnRefValueFromPhysicalId as W, withErrorHandling as Wn, AssetManifestLoader as Wt, assertRegionMatch as X, resolveApp as Xt, resolveExplicitPhysicalId as Y, getLegacyStateBucketName as Yt, coerceCfnBoolean as Z, resolveAutoAssetStorage as Zt, createPreDeleteFinalSnapshot as _, resolveBucketRegion as _n, markNonRetryable as _t, DeploymentEventsStore as a, CFN_TEMPLATE_BODY_LIMIT as an, s3BucketArn as at, unsupportedFinalSnapshotError as b, resetAwsClients as bn, LockManager as bt, replayFailedOperations as c, findLargeInlineResources as cn, s3BucketRegionalDomainName as ct, IMPLICIT_DELETE_DEPENDENCIES as d, PARTITION_TABLE as dn, DiffCalculator as dt, resolveStateBucketWithDefault as en, readConfigString as et, computeImplicitDeleteEdges as f, canonicalizeRegion as fn, describeTypeWithThrottleRetry as ft, ccRoutedFinalSnapshotError as g, clearBucketRegionCache as gn, isThrottlingError as gt, buildFinalSnapshotIdentifier as h, processStackMessages as hn, isRetryableTransientError as ht, DeploymentEventsReader as i, warnDeprecatedNoPrefixCliFlag as in, requireConfigString as it, red as j, MissingCdkCliError as jn, AssetModeResolver as jt, gray as k, LocalStartServiceError as kn, loadPublishableAssetManifest as kt, replayRollback as l, uploadCfnTemplate as ln, s3BucketWebsiteUrl as lt, PRE_DELETE_SNAPSHOT_TYPES as m, AssemblyReader as mn, isMarkedNonRetryable as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, resolveUseCdkBootstrapAssets as nn, requireConfigArray as nt, planFailedOps as o, CFN_TEMPLATE_URL_LIMIT as on, s3BucketDomainName as ot, ATOMIC_FINAL_SNAPSHOT_TYPES as p, derivePartitionAndUrlSuffix as pn, withRetry as pt, WAFv2WebACLProvider as q, synthesisStatusMessage as qt, DeployEngine as r, stateBucketExistenceConfirmed as rn, requireConfigObject as rt, planRollback as s, MIGRATE_TMP_PREFIX as sn, s3BucketDualStackDomainName as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, resolveStateBucketWithDefaultAndSource as tn, replayWarn as tt, withResourceDeadline as u, expectedOwnerParam as un, applyRoleArnIfSet as ut, isFinalSnapshotError as v, AwsClients as vn, DagBuilder as vt, isStatefulRecreateTargetSync as w, ConfigError as wn, AssetPublisher as wt, makeCanonicalizePropertiesFn as x, setAwsClients as xn, S3StateBackend as xt, refusesFinalSnapshot as y, getAwsClients as yn, TemplateParser as yt, CloudControlProvider as z, StateError as zn, buildDockerImage as zt };
23107
- //# sourceMappingURL=deploy-engine-CKpBSlde.js.map
23244
+ export { coerceCfnBoolean as $, resolveAutoAssetStorage as $t, cyan as A, LocalMigrateError as An, createAssetRedirectResolver as At, findSilentDropProperties as B, StackTerminationProtectionError as Bn, buildDenyExternalAccessPolicy as Bt, makeCanonicalizePropertiesFn as C, setAwsClients as Cn, S3StateBackend as Ct, renderStatefulReason as D, DependencyError as Dn, stringifyValue as Dt, isStatefulRecreateTargetSync as E, ConfigError as En, AssetPublisher as Et, IAMRoleProvider as F, PartialFailureError as Fn, ensureAssetStorage as Ft, IntrinsicFunctionResolver as G, normalizeAwsError as Gn, runDockerStreaming as Gt, slowCcOperationTimeoutMs as H, SynthesisError as Hn, formatDockerLoginError as Ht, collectInlinePolicyNamesManagedBySiblings as I, ProvisioningError as In, getBootstrapMarkerKey as It, refStateLookupFromResource as J, Synthesizer as Jt, cfnRefValueFromPhysicalId as K, withErrorHandling as Kn, AssetManifestLoader as Kt, clearOnUpdateRemoval as L, ResourceTimeoutError as Ln, parseBootstrapMarker as Lt, green as M, LockError as Mn, rewriteTemplateAssetReferences as Mt, red as N, MissingCdkCliError as Nn, AssetModeResolver as Nt, formatResourceLine as O, DeployCancelledError as On, WorkGraph as Ot, yellow as P, NestedStackChildDirectDestroyError as Pn, BOOTSTRAP_MARKER_PREFIX as Pt, assertRegionMatch as Q, resolveApp as Qt, ProviderRegistry as R, ResourceUpdateNotSupportedError as Rn, validateAssetBucketName as Rt, unsupportedFinalSnapshotError as S, resetAwsClients as Sn, LockManager as St, MULTI_REGION_RECREATE_BLOCKED_TYPES as T, CdkdError as Tn, shouldRetainResource as Tt, disableInstanceApiTermination as U, formatError as Un, getDockerCmd as Ut, CloudControlProvider as V, StateError as Vn, buildDockerImage as Vt, isTerminationProtectionPropagationError as W, isCdkdError as Wn, runDockerForeground as Wt, normalizeAwsTagsToCfn as X, getDefaultStateBucketName as Xt, WAFv2WebACLProvider as Y, synthesisStatusMessage as Yt, resolveExplicitPhysicalId as Z, getLegacyStateBucketName as Zt, buildFinalSnapshotIdentifier as _, processStackMessages as _n, isRetryableTransientError as _t, DeploymentEventsStore as a, stateBucketExistenceConfirmed as an, requireConfigObject as at, isFinalSnapshotError as b, AwsClients as bn, DagBuilder as bt, replayFailedOperations as c, CFN_TEMPLATE_URL_LIMIT as cn, s3BucketDomainName as ct, deleteSkipReason as d, uploadCfnTemplate as dn, s3BucketWebsiteUrl as dt, resolveCaptureObservedState as en, configBooleanRefusal as et, withResourceDeadline as f, expectedOwnerParam as fn, applyRoleArnIfSet as ft, PRE_DELETE_SNAPSHOT_TYPES as g, AssemblyReader as gn, isMarkedNonRetryable as gt, ATOMIC_FINAL_SNAPSHOT_TYPES as h, derivePartitionAndUrlSuffix as hn, withRetry as ht, DeploymentEventsReader as i, resolveUseCdkBootstrapAssets as in, requireConfigArray as it, gray as j, LocalStartServiceError as jn, loadPublishableAssetManifest as jt, bold as k, LocalInvokeBuildError as kn, buildAssetRedirectMap as kt, replayRollback as l, MIGRATE_TMP_PREFIX as ln, s3BucketDualStackDomainName as lt, computeImplicitDeleteEdges as m, canonicalizeRegion as mn, describeTypeWithThrottleRetry as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, resolveStateBucketWithDefault as nn, readConfigString as nt, planFailedOps as o, warnDeprecatedNoPrefixCliFlag as on, requireConfigString as ot, IMPLICIT_DELETE_DEPENDENCIES as p, PARTITION_TABLE as pn, DiffCalculator as pt, getAccountInfo as q, __exportAll as qn, getDockerImageBySourceHash as qt, DeployEngine as r, resolveStateBucketWithDefaultAndSource as rn, replayWarn as rt, planRollback as s, CFN_TEMPLATE_BODY_LIMIT as sn, s3BucketArn as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, resolveSkipPrefix as tn, configStringRefusal as tt, UNSPECIFIED_SKIP_REASON as u, findLargeInlineResources as un, s3BucketRegionalDomainName as ut, ccRoutedFinalSnapshotError as v, clearBucketRegionCache as vn, isThrottlingError as vt, extractDeploymentEventError as w, AssetError as wn, rebuildClientForBucketRegion as wt, refusesFinalSnapshot as x, getAwsClients as xn, TemplateParser as xt, createPreDeleteFinalSnapshot as y, resolveBucketRegion as yn, markNonRetryable as yt, findActionableSilentDrops as z, StackHasActiveImportsError as zn, validateContainerRepoName as zt };
23245
+ //# sourceMappingURL=deploy-engine-D95wmKN8.js.map