@go-to-k/cdkd 0.264.0 → 0.264.2

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.
@@ -11260,7 +11260,7 @@ var CloudControlProvider = class {
11260
11260
  this.logger.debug(`Deleting resource ${logicalId} (${resourceType}), physical ID: ${physicalId}`);
11261
11261
  if (context?.removeProtection === true && resourceType === "AWS::AutoScaling::AutoScalingGroup") {
11262
11262
  this.logger.debug(`Delegating protected AutoScalingGroup ${logicalId} delete to the SDK ASGProvider (Cloud Control cannot force-delete a protected ASG)`);
11263
- const { ASGProvider } = await import("./asg-provider-B5N9p1vq.js").then((n) => n.n);
11263
+ const { ASGProvider } = await import("./asg-provider-Bxida3ei.js").then((n) => n.n);
11264
11264
  await new ASGProvider().delete(logicalId, physicalId, resourceType, _properties, context);
11265
11265
  return;
11266
11266
  }
@@ -11934,10 +11934,10 @@ var CustomResourceProvider = class CustomResourceProvider {
11934
11934
  responseClientResolveInFlight = null;
11935
11935
  responseClientGeneration = 0;
11936
11936
  /**
11937
- * Whether `this.s3Client` is a provider-OWNED client (built from the
11938
- * `setResponseBucket` region hint or by a region-correction rebuild)
11939
- * vs the shared `AwsClients.s3` instance from the constructor. Owned
11940
- * clients are `destroy()`ed when replaced; the shared one never is.
11937
+ * Whether `this.s3Client` is a provider-OWNED client (built by a
11938
+ * region-correction rebuild) vs the shared `AwsClients.s3` instance
11939
+ * from the constructor. Owned clients are `destroy()`ed when replaced;
11940
+ * the shared one never is.
11941
11941
  */
11942
11942
  ownsS3Client = false;
11943
11943
  /**
@@ -12015,12 +12015,20 @@ var CustomResourceProvider = class CustomResourceProvider {
12015
12015
  return this.asyncResponseTimeoutMs;
12016
12016
  }
12017
12017
  /**
12018
- * Set the S3 bucket for custom resource responses
12019
- * Called by ProviderRegistry when state bucket is configured
12020
- */
12021
- setResponseBucket(bucket, bucketRegion) {
12018
+ * Set the S3 bucket for custom resource responses.
12019
+ * Called by ProviderRegistry when the state bucket is configured.
12020
+ *
12021
+ * There is deliberately NO region parameter (issue #1202): the bucket's
12022
+ * ACTUAL region is resolved lazily via `ensureResponseClient()` before
12023
+ * the first S3 operation (issue #1195), starting from the shared
12024
+ * `AwsClients.s3` client so `--profile` / static credentials carry into
12025
+ * both the `GetBucketLocation` probe and the rebuilt client. The former
12026
+ * deploy-region hint parameter built a default-credential-chain client
12027
+ * (dropping `--profile`) and added nothing — the probe resolves the
12028
+ * bucket's real region regardless of the starting client's region.
12029
+ */
12030
+ setResponseBucket(bucket) {
12022
12031
  this.responseBucket = bucket;
12023
- if (bucketRegion) this.replaceS3Client(new S3Client({ region: bucketRegion }));
12024
12032
  this.responseClientGeneration++;
12025
12033
  this.responseClientResolved = false;
12026
12034
  this.responseClientResolveInFlight = null;
@@ -14893,8 +14901,8 @@ var ProviderRegistry = class {
14893
14901
  * Configure the response bucket for custom resources
14894
14902
  * This allows Lambda handlers using cfn-response to send responses via S3
14895
14903
  */
14896
- setCustomResourceResponseBucket(bucket, bucketRegion) {
14897
- this.customResourceProvider.setResponseBucket(bucket, bucketRegion);
14904
+ setCustomResourceResponseBucket(bucket) {
14905
+ this.customResourceProvider.setResponseBucket(bucket);
14898
14906
  this.logger.debug(`Custom resource response bucket set to: ${bucket}`);
14899
14907
  }
14900
14908
  /**
@@ -16387,6 +16395,53 @@ function isRetryableTransientError(error, message) {
16387
16395
  if (isThrottlingError(error)) return true;
16388
16396
  return RETRYABLE_ERROR_MESSAGE_PATTERNS.some((p) => message.includes(p));
16389
16397
  }
16398
+ /**
16399
+ * Match the "already exists" name-collision signature raised when a create
16400
+ * targets a physical name still held by another resource (or by the same
16401
+ * name's not-yet-released tombstone after an async delete).
16402
+ *
16403
+ * Deliberately NOT part of {@link RETRYABLE_ERROR_MESSAGE_PATTERNS}: a name
16404
+ * collision is only worth retrying at the specific re-create sites that just
16405
+ * deleted the old holder (the deploy engine's --replace delete-first fallback
16406
+ * and the rollback executor's reverse-replacement) — everywhere else it is a
16407
+ * genuine conflict that must fail fast. Shared by those sites' collision
16408
+ * detection + retry filters so a signature extension lands in one place.
16409
+ */
16410
+ function isNameCollisionError(message) {
16411
+ return /already exists/i.test(message) || message.includes("AlreadyExists");
16412
+ }
16413
+ /**
16414
+ * Match the SQS same-name re-creation cooldown: after `DeleteQueue`, creating
16415
+ * a queue with the SAME name inside ~60s fails with
16416
+ * `AWS.SimpleQueueService.QueueDeletedRecently` ("You must wait 60 seconds
16417
+ * after deleting a queue before you can create another with the same name").
16418
+ *
16419
+ * The generic transient table above already carries 'wait 60 seconds' for
16420
+ * plain CREATEs (rapid destroy → redeploy loops), but the delete-then-re-create
16421
+ * sites (the deploy engine's --replace delete-first fallback and the rollback
16422
+ * executor's reverse-replacement) override the retry filter with
16423
+ * {@link isNameCollisionError}, which this signature does NOT match — so a
16424
+ * replacement revert used to fail fast mid-flight with the resource absent
16425
+ * from both AWS and state (issue #1206). Those sites now OR this matcher into
16426
+ * their retry filter, with a schedule long enough to cover the 60s window.
16427
+ *
16428
+ * Kept separate from {@link isNameCollisionError} on purpose: a cooldown at a
16429
+ * create-first site must NOT be treated as a collision (deleting the new
16430
+ * resource would not release the cooldown on the old name).
16431
+ */
16432
+ function isNameCooldownError(message) {
16433
+ return message.includes("QueueDeletedRecently") || message.includes("wait 60 seconds");
16434
+ }
16435
+ /**
16436
+ * Retry filter for the delete-then-re-create sites: the old name holder was
16437
+ * just deleted, so both the late name release ("already exists" from an async
16438
+ * delete) and the SQS 60s name cooldown are worth waiting out. Pair with a
16439
+ * schedule that covers the full cooldown window (maxRetries 8, delays
16440
+ * 2s/4s/8s then capped at 10s ≈ 64s total sleep).
16441
+ */
16442
+ function isRecreateRetryableError(message) {
16443
+ return isNameCollisionError(message) || isNameCooldownError(message);
16444
+ }
16390
16445
 
16391
16446
  //#endregion
16392
16447
  //#region src/deployment/retry.ts
@@ -16506,6 +16561,17 @@ async function withResourceDeadline(operation, opts) {
16506
16561
  //#endregion
16507
16562
  //#region src/deployment/rollback-executor.ts
16508
16563
  /**
16564
+ * Retry schedule for a re-create that must wait out a name-release delay:
16565
+ * an async delete's late name release ("already exists") or the SQS 60s
16566
+ * same-name cooldown (issue #1206). 2s/4s/8s then capped at 10s over 8
16567
+ * retries ≈ 64s of total sleep — enough to cover the full cooldown window.
16568
+ */
16569
+ const RECREATE_RETRY_SCHEDULE = {
16570
+ maxRetries: 8,
16571
+ initialDelayMs: 2e3,
16572
+ maxDelayMs: 1e4
16573
+ };
16574
+ /**
16509
16575
  * True when the op recorded a replacement (old physical id differs from the
16510
16576
  * new one). The old physical resource is already gone / orphaned, so an
16511
16577
  * in-place revert is best-effort — the plan labels these explicitly.
@@ -16775,10 +16841,17 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
16775
16841
  let deletedNewFirst = false;
16776
16842
  let createResult;
16777
16843
  try {
16778
- createResult = await createProvider.create(op.logicalId, op.resourceType, { ...prev.properties });
16844
+ createResult = await withRetry(() => createProvider.create(op.logicalId, op.resourceType, { ...prev.properties }), op.logicalId, {
16845
+ ...RECREATE_RETRY_SCHEDULE,
16846
+ logger,
16847
+ ...isInterrupted && {
16848
+ isInterrupted,
16849
+ onInterrupted: () => /* @__PURE__ */ new Error("Rollback interrupted while waiting out the name cooldown")
16850
+ },
16851
+ isRetryable: isNameCooldownError
16852
+ });
16779
16853
  } catch (createError) {
16780
- const msg = createError instanceof Error ? createError.message : String(createError);
16781
- if (!(/already exists/i.test(msg) || msg.includes("AlreadyExists"))) throw createError;
16854
+ if (!isNameCollisionError(createError instanceof Error ? createError.message : String(createError))) throw createError;
16782
16855
  logger.info(` Rollback: re-create collided with the new resource's name — deleting the new resource (${current.physicalId}) first...`);
16783
16856
  await newDeleteProvider.delete(op.logicalId, current.physicalId, op.resourceType, current.properties, { expectedRegion: ctx.region });
16784
16857
  deletedNewFirst = true;
@@ -16786,15 +16859,13 @@ async function replaySingle(op, stateResources, stackName, ctx, orphanLogicalIds
16786
16859
  await afterOp?.(op.logicalId);
16787
16860
  try {
16788
16861
  createResult = await withRetry(() => createProvider.create(op.logicalId, op.resourceType, { ...prev.properties }), op.logicalId, {
16789
- maxRetries: 5,
16790
- initialDelayMs: 2e3,
16791
- maxDelayMs: 1e4,
16862
+ ...RECREATE_RETRY_SCHEDULE,
16792
16863
  logger,
16793
16864
  ...isInterrupted && {
16794
16865
  isInterrupted,
16795
16866
  onInterrupted: () => /* @__PURE__ */ new Error("Rollback interrupted while waiting for the old name to release")
16796
16867
  },
16797
- isRetryable: (message) => /already exists/i.test(message) || message.includes("AlreadyExists")
16868
+ isRetryable: isRecreateRetryableError
16798
16869
  });
16799
16870
  } catch (recreateError) {
16800
16871
  throw new Error(`Failed to re-create the old ${op.logicalId} after the new resource (${current.physicalId}) was already deleted: ${recreateError instanceof Error ? recreateError.message : String(recreateError)}. The resource is now absent — fix forward with 'cdkd deploy'.`);
@@ -17072,7 +17143,7 @@ const FLUSH_INTERVAL_MS = 2e3;
17072
17143
  const FLUSH_EVENT_THRESHOLD = 50;
17073
17144
  /** Build-time cdkd version, with a dev fallback for non-built contexts. */
17074
17145
  function getCdkdVersion() {
17075
- return "0.264.0";
17146
+ return "0.264.2";
17076
17147
  }
17077
17148
  /**
17078
17149
  * Generate a time-sortable unique run id, e.g.
@@ -18643,7 +18714,7 @@ var DeployEngine = class {
18643
18714
  createResult = await this.withRetry(() => replaceProvider.create(logicalId, resourceType, replaceProps), logicalId, void 0, void 0, replaceProvider);
18644
18715
  } catch (createError) {
18645
18716
  const createMsg = createError instanceof Error ? createError.message : String(createError);
18646
- if (!(/already exists/i.test(createMsg) || createMsg.includes("AlreadyExists"))) throw createError;
18717
+ if (!isNameCollisionError(createMsg)) throw createError;
18647
18718
  if (updateReplacePolicy === "Retain") throw new CdkdError(`${logicalId} (${resourceType}) requires replacement, but its user-supplied physical name is still held by the existing resource AND UpdateReplacePolicy: Retain pins that resource in place. Rename the resource in your CDK code — with Retain, the old resource keeps the name, so a same-name replacement can never proceed.`, "NAMED_REPLACEMENT_COLLISION");
18648
18719
  if (this.options.replace !== true) throw new CdkdError(`${logicalId} (${resourceType}) requires replacement, but the create-first attempt collided with the existing resource: ${createMsg}. The resource has a user-supplied physical name, so the CloudFormation-style safe replacement order (create the new resource before deleting the old) cannot reuse the occupied name — CloudFormation refuses this shape with "cannot update a stack when a custom-named resource requires replacing". Either rename the resource in your CDK code (a fresh name lets the safe create-first order proceed), or re-run with \`cdkd deploy --replace\` to delete the old resource FIRST and recreate it under the same name (the resource is briefly unavailable while it is recreated).`, "NAMED_REPLACEMENT_COLLISION");
18649
18720
  this.logger.info(` Create-first collided with the custom-named resource and --replace is set — deleting old ${logicalId} (${currentResource.physicalId}) first...`);
@@ -18657,13 +18728,13 @@ var DeployEngine = class {
18657
18728
  this.logger.info(` Re-creating ${logicalId}...`);
18658
18729
  try {
18659
18730
  createResult = await withRetry(() => this.withRetry(() => replaceProvider.create(logicalId, resourceType, replaceProps), logicalId, void 0, void 0, replaceProvider), logicalId, {
18660
- maxRetries: 5,
18731
+ maxRetries: 8,
18661
18732
  initialDelayMs: 2e3,
18662
18733
  maxDelayMs: 1e4,
18663
18734
  logger: this.logger,
18664
18735
  isInterrupted: () => this.interrupted,
18665
18736
  onInterrupted: () => new InterruptedError(this.interruptCause ?? "user"),
18666
- isRetryable: (message) => /already exists/i.test(message) || message.includes("AlreadyExists")
18737
+ isRetryable: isRecreateRetryableError
18667
18738
  });
18668
18739
  } catch (recreateError) {
18669
18740
  throw new Error(`Failed to re-create ${logicalId} after the --replace delete-first fallback already deleted the old resource (${currentResource.physicalId}): ${recreateError instanceof Error ? recreateError.message : String(recreateError)}. Re-run the deploy to create it fresh.`);
@@ -19009,4 +19080,4 @@ var DeployEngine = class {
19009
19080
 
19010
19081
  //#endregion
19011
19082
  export { createAssetRedirectResolver as $, ResourceTimeoutError as $t, CloudControlProvider as A, MIGRATE_TMP_PREFIX as At, assertRegionMatch as B, setAwsClients as Bt, green as C, resolveSkipPrefix as Ct, collectInlinePolicyNamesManagedBySiblings as D, warnDeprecatedNoPrefixCliFlag as Dt, IAMRoleProvider as E, resolveUseCdkBootstrapAssets as Et, cfnRefValueFromPhysicalId as F, clearBucketRegionCache as Ft, LockManager as G, LocalInvokeBuildError as Gt, DiffCalculator as H, CdkdError as Ht, refStateLookupFromResource as I, resolveBucketRegion as It, shouldRetainResource as J, LockError as Jt, S3StateBackend as K, LocalMigrateError as Kt, WAFv2WebACLProvider as L, AwsClients as Lt, disableInstanceApiTermination as M, uploadCfnTemplate as Mt, isTerminationProtectionPropagationError as N, expectedOwnerParam as Nt, ProviderRegistry as O, CFN_TEMPLATE_BODY_LIMIT as Ot, IntrinsicFunctionResolver as P, AssemblyReader as Pt, buildAssetRedirectMap as Q, ProvisioningError as Qt, normalizeAwsTagsToCfn as R, getAwsClients as Rt, gray as S, resolveCaptureObservedState as St, yellow as T, resolveStateBucketWithDefaultAndSource as Tt, DagBuilder as U, ConfigError as Ut, applyRoleArnIfSet as V, AssetError as Vt, TemplateParser as W, DependencyError as Wt, stringifyValue as X, NestedStackChildDirectDestroyError as Xt, AssetPublisher as Y, MissingCdkCliError as Yt, WorkGraph as Z, PartialFailureError as Zt, isStatefulRecreateTargetSync as _, synthesisStatusMessage as _t, DeploymentEventsStore as a, formatError as an, getBootstrapMarkerKey as at, bold as b, resolveApp as bt, replayFailedOperations as c, withErrorHandling as cn, validateContainerRepoName as ct, withRetry as d, getDockerCmd as dt, ResourceUpdateNotSupportedError as en, loadPublishableAssetManifest as et, isRetryableTransientError as f, runDockerForeground as ft, MULTI_REGION_RECREATE_BLOCKED_TYPES as g, Synthesizer as gt, extractDeploymentEventError as h, getDockerImageBySourceHash as ht, DeploymentEventsReader as i, SynthesisError as in, ensureAssetStorage as it, slowCcOperationTimeoutMs as j, findLargeInlineResources as jt, findActionableSilentDrops as k, CFN_TEMPLATE_URL_LIMIT as kt, replayRollback as l, __exportAll as ln, buildDockerImage as lt, computeImplicitDeleteEdges as m, AssetManifestLoader as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, StackTerminationProtectionError as nn, AssetModeResolver as nt, planFailedOps as o, isCdkdError as on, parseBootstrapMarker as ot, IMPLICIT_DELETE_DEPENDENCIES as p, runDockerStreaming as pt, rebuildClientForBucketRegion as q, LocalStartServiceError as qt, DeployEngine as r, StateError as rn, BOOTSTRAP_MARKER_PREFIX as rt, planRollback as s, normalizeAwsError as sn, validateAssetBucketName as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, StackHasActiveImportsError as tn, rewriteTemplateAssetReferences as tt, withResourceDeadline as u, formatDockerLoginError as ut, renderStatefulReason as v, getDefaultStateBucketName as vt, red as w, resolveStateBucketWithDefault as wt, cyan as x, resolveAutoAssetStorage as xt, formatResourceLine as y, getLegacyStateBucketName as yt, resolveExplicitPhysicalId as z, resetAwsClients as zt };
19012
- //# sourceMappingURL=deploy-engine-hlS6y_-0.js.map
19083
+ //# sourceMappingURL=deploy-engine-CaquB01e.js.map