@go-to-k/cdkd 0.5.0 → 0.6.0
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 +19 -0
- package/dist/cli.js +402 -31
- package/dist/cli.js.map +4 -4
- package/dist/go-to-k-cdkd-0.6.0.tgz +0 -0
- package/dist/index.js +65 -27
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
- package/dist/go-to-k-cdkd-0.5.0.tgz +0 -0
|
Binary file
|
package/dist/index.js
CHANGED
|
@@ -3024,6 +3024,18 @@ var LockManager = class {
|
|
|
3024
3024
|
);
|
|
3025
3025
|
}
|
|
3026
3026
|
}
|
|
3027
|
+
/**
|
|
3028
|
+
* Check whether a lock currently exists for a stack
|
|
3029
|
+
*
|
|
3030
|
+
* Returns true if a lock file is present in S3 (regardless of expiry).
|
|
3031
|
+
* This is intended for read-only inspection (e.g. `cdkd state list --long`),
|
|
3032
|
+
* not for acquisition decisions — use `acquireLock` for that, which has its
|
|
3033
|
+
* own expired-lock cleanup logic.
|
|
3034
|
+
*/
|
|
3035
|
+
async isLocked(stackName) {
|
|
3036
|
+
const lockInfo = await this.getLockInfo(stackName);
|
|
3037
|
+
return lockInfo !== null;
|
|
3038
|
+
}
|
|
3027
3039
|
/**
|
|
3028
3040
|
* Release a lock for a stack
|
|
3029
3041
|
*/
|
|
@@ -7388,7 +7400,12 @@ var RETRYABLE_ERROR_MESSAGE_PATTERNS = [
|
|
|
7388
7400
|
// or SubscriptionFilter role propagation. CW Logs probes the destination
|
|
7389
7401
|
// by delivering a test message; if the stream is freshly ACTIVE or the
|
|
7390
7402
|
// assumed role hasn't propagated, the probe fails with "Invalid request".
|
|
7391
|
-
"Could not deliver test message"
|
|
7403
|
+
"Could not deliver test message",
|
|
7404
|
+
// SQS: same-name queue can't be re-created until 60s after a delete.
|
|
7405
|
+
// Hits when a stack is destroyed and re-deployed in quick succession
|
|
7406
|
+
// (a common dev / iteration loop). Retry recovers within ~60s instead
|
|
7407
|
+
// of failing the whole deploy.
|
|
7408
|
+
"wait 60 seconds"
|
|
7392
7409
|
];
|
|
7393
7410
|
var RETRYABLE_HTTP_STATUS_CODES = /* @__PURE__ */ new Set([429, 503]);
|
|
7394
7411
|
function isRetryableTransientError(error, message) {
|
|
@@ -7403,6 +7420,39 @@ function isRetryableTransientError(error, message) {
|
|
|
7403
7420
|
return RETRYABLE_ERROR_MESSAGE_PATTERNS.some((p) => message.includes(p));
|
|
7404
7421
|
}
|
|
7405
7422
|
|
|
7423
|
+
// src/deployment/retry.ts
|
|
7424
|
+
var defaultSleep = (ms) => new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
7425
|
+
async function withRetry(operation, logicalId, opts = {}) {
|
|
7426
|
+
const maxRetries = opts.maxRetries ?? 8;
|
|
7427
|
+
const initialDelayMs = opts.initialDelayMs ?? 1e3;
|
|
7428
|
+
const maxDelayMs = opts.maxDelayMs ?? 8e3;
|
|
7429
|
+
const sleep = opts.sleep ?? defaultSleep;
|
|
7430
|
+
let lastError;
|
|
7431
|
+
for (let attempt = 0; attempt <= maxRetries; attempt++) {
|
|
7432
|
+
try {
|
|
7433
|
+
return await operation();
|
|
7434
|
+
} catch (error) {
|
|
7435
|
+
lastError = error;
|
|
7436
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7437
|
+
const retryable = isRetryableTransientError(error, message);
|
|
7438
|
+
if (!retryable || attempt >= maxRetries) {
|
|
7439
|
+
throw error;
|
|
7440
|
+
}
|
|
7441
|
+
const delay = Math.min(initialDelayMs * Math.pow(2, attempt), maxDelayMs);
|
|
7442
|
+
opts.logger?.debug(
|
|
7443
|
+
` \u23F3 Retrying ${logicalId} in ${delay / 1e3}s (attempt ${attempt + 1}/${maxRetries}) - ${message}`
|
|
7444
|
+
);
|
|
7445
|
+
for (let waited = 0; waited < delay; waited += 1e3) {
|
|
7446
|
+
if (opts.isInterrupted?.()) {
|
|
7447
|
+
throw opts.onInterrupted ? opts.onInterrupted() : new Error("Interrupted");
|
|
7448
|
+
}
|
|
7449
|
+
await sleep(Math.min(1e3, delay - waited));
|
|
7450
|
+
}
|
|
7451
|
+
}
|
|
7452
|
+
}
|
|
7453
|
+
throw lastError;
|
|
7454
|
+
}
|
|
7455
|
+
|
|
7406
7456
|
// src/deployment/deploy-engine.ts
|
|
7407
7457
|
var InterruptedError = class extends Error {
|
|
7408
7458
|
constructor() {
|
|
@@ -8389,32 +8439,20 @@ var DeployEngine = class {
|
|
|
8389
8439
|
);
|
|
8390
8440
|
}
|
|
8391
8441
|
/**
|
|
8392
|
-
* Execute an operation with retry for transient IAM propagation errors
|
|
8393
|
-
|
|
8394
|
-
|
|
8395
|
-
|
|
8396
|
-
|
|
8397
|
-
|
|
8398
|
-
|
|
8399
|
-
|
|
8400
|
-
|
|
8401
|
-
|
|
8402
|
-
|
|
8403
|
-
|
|
8404
|
-
|
|
8405
|
-
|
|
8406
|
-
const delay = initialDelayMs * Math.pow(2, attempt);
|
|
8407
|
-
this.logger.debug(
|
|
8408
|
-
` \u23F3 Retrying ${logicalId} in ${delay / 1e3}s (attempt ${attempt + 1}/${maxRetries}) - ${message}`
|
|
8409
|
-
);
|
|
8410
|
-
for (let waited = 0; waited < delay; waited += 1e3) {
|
|
8411
|
-
if (this.interrupted)
|
|
8412
|
-
throw new InterruptedError();
|
|
8413
|
-
await new Promise((resolve4) => setTimeout(resolve4, Math.min(1e3, delay - waited)));
|
|
8414
|
-
}
|
|
8415
|
-
}
|
|
8416
|
-
}
|
|
8417
|
-
throw lastError;
|
|
8442
|
+
* Execute an operation with retry for transient IAM propagation errors.
|
|
8443
|
+
*
|
|
8444
|
+
* Thin wrapper over `withRetry` from ./retry.js that injects this engine's
|
|
8445
|
+
* SIGINT-aware interrupt check and logger. The actual backoff schedule
|
|
8446
|
+
* lives there.
|
|
8447
|
+
*/
|
|
8448
|
+
async withRetry(operation, logicalId, maxRetries, initialDelayMs) {
|
|
8449
|
+
return withRetry(operation, logicalId, {
|
|
8450
|
+
...maxRetries !== void 0 && { maxRetries },
|
|
8451
|
+
...initialDelayMs !== void 0 && { initialDelayMs },
|
|
8452
|
+
logger: this.logger,
|
|
8453
|
+
isInterrupted: () => this.interrupted,
|
|
8454
|
+
onInterrupted: () => new InterruptedError()
|
|
8455
|
+
});
|
|
8418
8456
|
}
|
|
8419
8457
|
/**
|
|
8420
8458
|
* Resolve stack outputs from template and resource attributes
|