@go-to-k/cdkd 0.268.1 → 0.268.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/README.md +21 -9
- package/dist/{asg-provider-_vnp1pfL.js → asg-provider-bxS6B6Ja.js} +2 -2
- package/dist/{asg-provider-_vnp1pfL.js.map → asg-provider-bxS6B6Ja.js.map} +1 -1
- package/dist/cli.js +152 -40
- package/dist/cli.js.map +1 -1
- package/dist/{deploy-engine-A2CeJkZr.js → deploy-engine-DEi5-8x-.js} +117 -41
- package/dist/deploy-engine-DEi5-8x-.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/dist/deploy-engine-A2CeJkZr.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { $ as WorkGraph,
|
|
2
|
+
import { $ as WorkGraph, A as slowCcOperationTimeoutMs, At as warnDeprecatedNoPrefixCliFlag, B as applyRoleArnIfSet, Bt as resolveBucketRegion, C as yellow, Ct as resolveAutoAssetStorage, D as ProviderRegistry, Dt as resolveStateBucketWithDefaultAndSource, E as clearOnUpdateRemoval, Et as resolveStateBucketWithDefault, F as refStateLookupFromResource, Ft as uploadCfnTemplate, G as DagBuilder, H as describeTypeWithThrottleRetry, Ht as getAwsClients, I as WAFv2WebACLProvider, It as expectedOwnerParam, J as S3StateBackend, K as TemplateParser, Kt as CdkdError, L as normalizeAwsTagsToCfn, Lt as AssemblyReader, M as isTerminationProtectionPropagationError, Mt as CFN_TEMPLATE_URL_LIMIT, N as IntrinsicFunctionResolver, Nt as MIGRATE_TMP_PREFIX, O as findActionableSilentDrops, Ot as resolveUseCdkBootstrapAssets, P as cfnRefValueFromPhysicalId, Pt as findLargeInlineResources, Q as stringifyValue, Qt as LocalStartServiceError, R as resolveExplicitPhysicalId, Rt as processStackMessages, S as red, St as resolveApp, T as collectInlinePolicyNamesManagedBySiblings, Tt as resolveSkipPrefix, U as withRetry, Ut as resetAwsClients, V as DiffCalculator, Vt as AwsClients, W as isRetryableTransientError, Wt as setAwsClients, X as shouldRetainResource, Xt as LocalInvokeBuildError$1, Y as rebuildClientForBucketRegion, Yt as DeployCancelledError, Z as AssetPublisher, Zt as LocalMigrateError, _ as formatResourceLine, _t as getDockerImageBySourceHash, a as DeploymentEventsStore, an as ResourceUpdateNotSupportedError, at as BOOTSTRAP_MARKER_PREFIX, b as gray, bt as getDefaultStateBucketName, c as replayFailedOperations, ct as parseBootstrapMarker, d as IMPLICIT_DELETE_DEPENDENCIES, dt as buildDockerImage, en as MissingCdkCliError, et as buildAssetRedirectMap, f as computeImplicitDeleteEdges, fn as normalizeAwsError, ft as formatDockerLoginError, g as renderStatefulReason, gt as AssetManifestLoader, h as isStatefulRecreateTargetSync, ht as runDockerStreaming, i as DeploymentEventsReader, in as ResourceTimeoutError, it as AssetModeResolver, j as disableInstanceApiTermination, jt as CFN_TEMPLATE_BODY_LIMIT, k as CloudControlProvider, kt as stateBucketExistenceConfirmed, l as replayRollback, lt as validateAssetBucketName, m as MULTI_REGION_RECREATE_BLOCKED_TYPES, mt as runDockerForeground, n as DEFAULT_RESOURCE_WARN_AFTER_MS, nn as PartialFailureError, nt as loadPublishableAssetManifest, o as planFailedOps, on as StackHasActiveImportsError, ot as ensureAssetStorage, p as extractDeploymentEventError, pn as withErrorHandling, pt as getDockerCmd, q as LockManager, r as DeployEngine, rn as ProvisioningError, rt as rewriteTemplateAssetReferences, s as planRollback, sn as StackTerminationProtectionError, st as getBootstrapMarkerKey, t as DEFAULT_RESOURCE_TIMEOUT_MS, tn as NestedStackChildDirectDestroyError, tt as createAssetRedirectResolver, u as withResourceDeadline, ut as validateContainerRepoName, v as bold, vt as Synthesizer, w as IAMRoleProvider, wt as resolveCaptureObservedState, x as green, xt as getLegacyStateBucketName, y as cyan, yt as synthesisStatusMessage, z as assertRegionMatch } from "./deploy-engine-DEi5-8x-.js";
|
|
3
3
|
import { a as getLiveRenderer, c as PATTERN_B_RESOURCE_TYPES, d as generateResourceNameWithFallback, f as withSkipPrefix, i as runStackBuffered, n as getLogger, o as PATTERN_B_NAME_OPTIONS, p as withStackName, s as PATTERN_B_NAME_PROPERTIES, u as generateResourceName } from "./logger-BYMEE-BS.js";
|
|
4
|
-
import { t as ASGProvider } from "./asg-provider-
|
|
4
|
+
import { t as ASGProvider } from "./asg-provider-bxS6B6Ja.js";
|
|
5
5
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
6
6
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
7
7
|
import { CopyObjectCommand, CreateBucketCommand, DeleteBucketAnalyticsConfigurationCommand, DeleteBucketCommand, DeleteBucketCorsCommand, DeleteBucketIntelligentTieringConfigurationCommand, DeleteBucketInventoryConfigurationCommand, DeleteBucketLifecycleCommand, DeleteBucketMetricsConfigurationCommand, DeleteBucketPolicyCommand, DeleteBucketReplicationCommand, DeleteBucketTaggingCommand, DeleteBucketWebsiteCommand, DeleteObjectsCommand, GetBucketAccelerateConfigurationCommand, GetBucketCorsCommand, GetBucketEncryptionCommand, GetBucketLifecycleConfigurationCommand, GetBucketLocationCommand, GetBucketLoggingCommand, GetBucketNotificationConfigurationCommand, GetBucketPolicyCommand, GetBucketReplicationCommand, GetBucketTaggingCommand, GetBucketVersioningCommand, GetBucketWebsiteCommand, GetObjectCommand, GetObjectLockConfigurationCommand, GetPublicAccessBlockCommand, HeadBucketCommand, ListBucketAnalyticsConfigurationsCommand, ListBucketIntelligentTieringConfigurationsCommand, ListBucketInventoryConfigurationsCommand, ListBucketMetricsConfigurationsCommand, ListObjectVersionsCommand, ListObjectsV2Command, NoSuchBucket, PutBucketAccelerateConfigurationCommand, PutBucketAnalyticsConfigurationCommand, PutBucketCorsCommand, PutBucketEncryptionCommand, PutBucketIntelligentTieringConfigurationCommand, PutBucketInventoryConfigurationCommand, PutBucketLifecycleConfigurationCommand, PutBucketLoggingCommand, PutBucketMetricsConfigurationCommand, PutBucketNotificationConfigurationCommand, PutBucketOwnershipControlsCommand, PutBucketPolicyCommand, PutBucketReplicationCommand, PutBucketTaggingCommand, PutBucketVersioningCommand, PutBucketWebsiteCommand, PutObjectCommand, PutObjectLockConfigurationCommand, PutPublicAccessBlockCommand, S3Client, S3ServiceException } from "@aws-sdk/client-s3";
|
|
@@ -15617,30 +15617,14 @@ var EC2Provider = class {
|
|
|
15617
15617
|
VpcId: properties["VpcId"] ?? void 0
|
|
15618
15618
|
}))).GroupId;
|
|
15619
15619
|
try {
|
|
15620
|
-
await this.applyTags(groupId, properties, logicalId);
|
|
15621
15620
|
const ingressRules = properties["SecurityGroupIngress"];
|
|
15622
|
-
if (ingressRules && Array.isArray(ingressRules)) for (const rule of ingressRules) await this.ec2Client.send(new AuthorizeSecurityGroupIngressCommand({
|
|
15623
|
-
GroupId: groupId,
|
|
15624
|
-
IpPermissions: [this.buildIpPermission(rule)]
|
|
15625
|
-
}));
|
|
15626
15621
|
const egressRules = properties["SecurityGroupEgress"];
|
|
15627
|
-
|
|
15628
|
-
|
|
15629
|
-
|
|
15630
|
-
|
|
15631
|
-
|
|
15632
|
-
|
|
15633
|
-
IpRanges: [{ CidrIp: "0.0.0.0/0" }]
|
|
15634
|
-
}]
|
|
15635
|
-
}));
|
|
15636
|
-
} catch (error) {
|
|
15637
|
-
if (!this.isNotFoundError(error)) throw error;
|
|
15638
|
-
}
|
|
15639
|
-
for (const rule of egressRules) await this.ec2Client.send(new AuthorizeSecurityGroupEgressCommand({
|
|
15640
|
-
GroupId: groupId,
|
|
15641
|
-
IpPermissions: [this.buildIpPermission(rule, "egress")]
|
|
15642
|
-
}));
|
|
15643
|
-
}
|
|
15622
|
+
const firstRejection = (await Promise.allSettled([
|
|
15623
|
+
this.applyTags(groupId, properties, logicalId),
|
|
15624
|
+
this.authorizeInlineIngress(groupId, ingressRules),
|
|
15625
|
+
this.applyInlineEgress(groupId, egressRules)
|
|
15626
|
+
])).find((r) => r.status === "rejected");
|
|
15627
|
+
if (firstRejection) throw firstRejection.reason;
|
|
15644
15628
|
} catch (innerError) {
|
|
15645
15629
|
try {
|
|
15646
15630
|
await this.ec2Client.send(new DeleteSecurityGroupCommand({ GroupId: groupId }));
|
|
@@ -15663,6 +15647,79 @@ var EC2Provider = class {
|
|
|
15663
15647
|
throw new ProvisioningError(`Failed to create SecurityGroup ${logicalId}: ${error instanceof Error ? error.message : String(error)}`, resourceType, logicalId, void 0, cause);
|
|
15664
15648
|
}
|
|
15665
15649
|
}
|
|
15650
|
+
/**
|
|
15651
|
+
* Authorize a freshly-created security group's inline
|
|
15652
|
+
* `SecurityGroupIngress` rules in a SINGLE `AuthorizeSecurityGroupIngress`
|
|
15653
|
+
* call.
|
|
15654
|
+
*
|
|
15655
|
+
* The API takes an `IpPermissions` ARRAY; the previous per-rule loop paid
|
|
15656
|
+
* one round trip per rule for no benefit. AWS applies the whole list
|
|
15657
|
+
* atomically, so the resulting rule set is byte-identical — the only
|
|
15658
|
+
* behavior difference is that a bad rule now rejects the batch instead of
|
|
15659
|
+
* being preceded by its already-applied siblings, and the caller deletes
|
|
15660
|
+
* the half-wired group in either case.
|
|
15661
|
+
*/
|
|
15662
|
+
async authorizeInlineIngress(groupId, ingressRules) {
|
|
15663
|
+
if (!Array.isArray(ingressRules) || ingressRules.length === 0) return;
|
|
15664
|
+
await this.ec2Client.send(new AuthorizeSecurityGroupIngressCommand({
|
|
15665
|
+
GroupId: groupId,
|
|
15666
|
+
IpPermissions: ingressRules.map((rule) => this.buildIpPermission(rule))
|
|
15667
|
+
}));
|
|
15668
|
+
}
|
|
15669
|
+
/**
|
|
15670
|
+
* Apply a freshly-created security group's inline `SecurityGroupEgress`
|
|
15671
|
+
* rules.
|
|
15672
|
+
*
|
|
15673
|
+
* When a template specifies egress explicitly, CloudFormation replaces the
|
|
15674
|
+
* AWS-default "allow all egress" rule (`-1` / `0.0.0.0/0`) with the
|
|
15675
|
+
* supplied set, so cdkd revokes the default first and then authorizes the
|
|
15676
|
+
* template's rules. Both steps are preserved, including for an EMPTY
|
|
15677
|
+
* `SecurityGroupEgress: []` — that is a deliberate "no egress at all",
|
|
15678
|
+
* which requires the revoke and no authorize.
|
|
15679
|
+
*
|
|
15680
|
+
* Two round trips are saved where they are provably redundant:
|
|
15681
|
+
*
|
|
15682
|
+
* - The whole revoke+authorize pair is SKIPPED when the templated egress
|
|
15683
|
+
* is exactly the rule AWS already created by default. `isDefaultEgressRule`
|
|
15684
|
+
* is the exact comparator (protocol `-1`, `CidrIp 0.0.0.0/0`, no IPv6
|
|
15685
|
+
* range / peer group / prefix list / description, ports absent or `-1`)
|
|
15686
|
+
* and is the SAME predicate the drift reverse-mapper uses to recognize
|
|
15687
|
+
* the AWS default, so the two cannot disagree about what "default" means.
|
|
15688
|
+
* AWS creates exactly ONE default egress rule and it is IPv4-only (there
|
|
15689
|
+
* is no `::/0` default), which is why a single-element match is the right
|
|
15690
|
+
* shape. NOTE this deliberately does NOT fire for the CDK L2
|
|
15691
|
+
* `allowAllOutbound: true` shape, which stamps
|
|
15692
|
+
* `Description: 'Allow all outbound traffic by default'` — the AWS
|
|
15693
|
+
* default rule carries no description, so skipping there would leave the
|
|
15694
|
+
* group in a state CloudFormation would not produce AND would surface as
|
|
15695
|
+
* permanent phantom drift (`readCurrentState` would report no
|
|
15696
|
+
* Description while state records one).
|
|
15697
|
+
* - The remaining authorize is a SINGLE batched call rather than one per
|
|
15698
|
+
* rule (see {@link authorizeInlineIngress}).
|
|
15699
|
+
*/
|
|
15700
|
+
async applyInlineEgress(groupId, egressRules) {
|
|
15701
|
+
if (!Array.isArray(egressRules)) return;
|
|
15702
|
+
if (egressRules.length === 1 && isDefaultEgressRule(egressRules[0])) {
|
|
15703
|
+
this.logger.debug(`SecurityGroup ${groupId} egress equals the AWS default allow-all rule; skipping the redundant revoke + re-authorize`);
|
|
15704
|
+
return;
|
|
15705
|
+
}
|
|
15706
|
+
try {
|
|
15707
|
+
await this.ec2Client.send(new RevokeSecurityGroupEgressCommand({
|
|
15708
|
+
GroupId: groupId,
|
|
15709
|
+
IpPermissions: [{
|
|
15710
|
+
IpProtocol: "-1",
|
|
15711
|
+
IpRanges: [{ CidrIp: "0.0.0.0/0" }]
|
|
15712
|
+
}]
|
|
15713
|
+
}));
|
|
15714
|
+
} catch (error) {
|
|
15715
|
+
if (!this.isNotFoundError(error)) throw error;
|
|
15716
|
+
}
|
|
15717
|
+
if (egressRules.length === 0) return;
|
|
15718
|
+
await this.ec2Client.send(new AuthorizeSecurityGroupEgressCommand({
|
|
15719
|
+
GroupId: groupId,
|
|
15720
|
+
IpPermissions: egressRules.map((rule) => this.buildIpPermission(rule, "egress"))
|
|
15721
|
+
}));
|
|
15722
|
+
}
|
|
15666
15723
|
async updateSecurityGroup(logicalId, physicalId, resourceType, properties, previousProperties) {
|
|
15667
15724
|
this.logger.debug(`Updating SecurityGroup ${logicalId}: ${physicalId}`);
|
|
15668
15725
|
try {
|
|
@@ -19991,6 +20048,14 @@ var CloudFrontOACProvider = class {
|
|
|
19991
20048
|
* `assertRegionMatch()` confirms the client is pointed at the region the
|
|
19992
20049
|
* resource was created in (a region mismatch would otherwise silently
|
|
19993
20050
|
* "succeed" while leaving the real resource behind).
|
|
20051
|
+
*
|
|
20052
|
+
* A `Get` that succeeds but carries no `ETag` is a hard error here for the
|
|
20053
|
+
* same reason it is in {@link update}: `IfMatch: undefined` reaches AWS as
|
|
20054
|
+
* a missing required parameter, and the resulting SDK/AWS rejection says
|
|
20055
|
+
* nothing about the `Get` being what came back short. On the DELETE path
|
|
20056
|
+
* that opacity is worse than on update — the failure surfaces during
|
|
20057
|
+
* `cdkd destroy`, where the user's next question is "is the OAC still
|
|
20058
|
+
* there?", so the message has to name the actual cause.
|
|
19994
20059
|
*/
|
|
19995
20060
|
async delete(logicalId, physicalId, resourceType, _properties, context) {
|
|
19996
20061
|
this.logger.debug(`Deleting CloudFront Origin Access Control ${logicalId}: ${physicalId}`);
|
|
@@ -20006,6 +20071,7 @@ var CloudFrontOACProvider = class {
|
|
|
20006
20071
|
}
|
|
20007
20072
|
throw error;
|
|
20008
20073
|
}
|
|
20074
|
+
if (!etag) throw new Error("GetOriginAccessControl did not return ETag");
|
|
20009
20075
|
await this.cloudFrontClient.send(new DeleteOriginAccessControlCommand({
|
|
20010
20076
|
Id: physicalId,
|
|
20011
20077
|
IfMatch: etag
|
|
@@ -20099,6 +20165,18 @@ var CloudFrontOACProvider = class {
|
|
|
20099
20165
|
* copy that exists to (a) fail loudly when a required field is missing
|
|
20100
20166
|
* rather than letting the SDK reject with an opaque serialization error,
|
|
20101
20167
|
* and (b) keep unknown extra keys out of the request.
|
|
20168
|
+
*
|
|
20169
|
+
* All four required fields are checked for a NON-EMPTY string, not merely
|
|
20170
|
+
* for `typeof === 'string'`. `''` is the shape an unresolved intrinsic or a
|
|
20171
|
+
* `Fn::Sub` over a missing value most often collapses into, and CloudFront
|
|
20172
|
+
* rejects it just as surely as it rejects an absent field — so letting it
|
|
20173
|
+
* through would defeat the whole point of (a): the user would get AWS's
|
|
20174
|
+
* `InvalidArgument` instead of a message naming the field cdkd could see
|
|
20175
|
+
* was blank. The three type/behavior fields are additionally CFn enums
|
|
20176
|
+
* (`s3` / `mediastore` / `lambda` / `mediapackagev2`; `always` / `never` /
|
|
20177
|
+
* `no-override`; `sigv4`), for which the empty string is never a member.
|
|
20178
|
+
* `Description` is deliberately not in this set — it is genuinely optional
|
|
20179
|
+
* and `''` is a legitimate value that clears it.
|
|
20102
20180
|
*/
|
|
20103
20181
|
toSdkConfig(value, logicalId, resourceType, physicalId) {
|
|
20104
20182
|
const config = value ?? {};
|
|
@@ -20106,11 +20184,12 @@ var CloudFrontOACProvider = class {
|
|
|
20106
20184
|
const originType = config["OriginAccessControlOriginType"];
|
|
20107
20185
|
const signingBehavior = config["SigningBehavior"];
|
|
20108
20186
|
const signingProtocol = config["SigningProtocol"];
|
|
20187
|
+
const nonEmpty = (value) => typeof value === "string" && value.length > 0;
|
|
20109
20188
|
const missing = [
|
|
20110
|
-
|
|
20111
|
-
|
|
20112
|
-
|
|
20113
|
-
|
|
20189
|
+
nonEmpty(name) ? void 0 : "Name",
|
|
20190
|
+
nonEmpty(originType) ? void 0 : "OriginAccessControlOriginType",
|
|
20191
|
+
nonEmpty(signingBehavior) ? void 0 : "SigningBehavior",
|
|
20192
|
+
nonEmpty(signingProtocol) ? void 0 : "SigningProtocol"
|
|
20114
20193
|
].filter((field) => field !== void 0);
|
|
20115
20194
|
if (missing.length > 0) throw new ProvisioningError(`CloudFront Origin Access Control ${logicalId}: OriginAccessControlConfig is missing required field(s): ${missing.join(", ")}`, resourceType, logicalId, physicalId);
|
|
20116
20195
|
const description = config["Description"];
|
|
@@ -22393,19 +22472,19 @@ var ECSProvider = class {
|
|
|
22393
22472
|
try {
|
|
22394
22473
|
await this.settleService(logicalId, service.serviceName ?? service.serviceArn, properties["Cluster"]);
|
|
22395
22474
|
} catch (waitError) {
|
|
22475
|
+
const cleanupCluster = properties["Cluster"];
|
|
22476
|
+
const clusterArg = cleanupCluster ? ` --cluster ${cleanupCluster}` : "";
|
|
22396
22477
|
try {
|
|
22397
22478
|
await client.send(new DeleteServiceCommand({
|
|
22398
22479
|
cluster: properties["Cluster"],
|
|
22399
22480
|
service: service.serviceArn,
|
|
22400
22481
|
force: true
|
|
22401
22482
|
}));
|
|
22402
|
-
this.logger.
|
|
22483
|
+
this.logger.warn(`Deleted partially-created ECS service ${logicalId} (${service.serviceArn}) after the steady-state wait failed, so the next deploy's CreateService does not collide on the name. Its stopped tasks remain inspectable for about an hour: aws ecs list-tasks${clusterArg} --desired-status STOPPED`);
|
|
22403
22484
|
} catch (cleanupError) {
|
|
22404
|
-
const cleanupCluster = properties["Cluster"];
|
|
22405
|
-
const clusterArg = cleanupCluster ? ` --cluster ${cleanupCluster}` : "";
|
|
22406
22485
|
this.logger.warn(`Failed to clean up partially-created ECS service ${logicalId} (${service.serviceArn}): ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}. Manual deletion may be required before the next deploy: aws ecs delete-service${clusterArg} --service ${service.serviceArn} --force`);
|
|
22407
22486
|
}
|
|
22408
|
-
throw waitError;
|
|
22487
|
+
throw new Error(`ECS service ${logicalId} did not reach steady state under --full-wait: ${waitError instanceof Error ? waitError.message : String(waitError)}. Inspect why its tasks stopped (stopped tasks stay visible for about an hour): aws ecs list-tasks${clusterArg} --desired-status STOPPED, then aws ecs describe-tasks${clusterArg} --tasks <task-arn> --query 'tasks[].[stoppedReason,containers[].reason]'`, { cause: waitError });
|
|
22409
22488
|
}
|
|
22410
22489
|
return {
|
|
22411
22490
|
physicalId: service.serviceArn,
|
|
@@ -42953,6 +43032,39 @@ async function promptMigrationConfirm(renames, opts) {
|
|
|
42953
43032
|
rl.close();
|
|
42954
43033
|
}
|
|
42955
43034
|
}
|
|
43035
|
+
/**
|
|
43036
|
+
* Build the `DeployEngineOptions.onCurrentStateLoaded` gate that runs the
|
|
43037
|
+
* prefix-migration check, or `undefined` when the check is inactive
|
|
43038
|
+
* (`skipPrefix === false`, i.e. the user opted back in to legacy prefixing).
|
|
43039
|
+
*
|
|
43040
|
+
* Why a gate rather than a pre-lock `getState`: prefix-skipping has been the
|
|
43041
|
+
* default since v0.94.0, so the previous shape issued an S3 GET on EVERY
|
|
43042
|
+
* deploy of EVERY stack — including brand-new stacks with no state at all —
|
|
43043
|
+
* and the deploy engine then read the very same object again immediately
|
|
43044
|
+
* after taking the lock. Running as the engine's post-lock gate reuses that
|
|
43045
|
+
* read. The contract the check actually depends on ("surface this before any
|
|
43046
|
+
* provider call runs") is preserved: the engine invokes the gate immediately
|
|
43047
|
+
* after loading state and before parsing, diffing, or provisioning anything.
|
|
43048
|
+
* Reading under the lock is also strictly more authoritative — no concurrent
|
|
43049
|
+
* deploy can mutate the state between the check and the diff it predicts.
|
|
43050
|
+
*
|
|
43051
|
+
* Declining the prompt raises {@link DeployCancelledError}, which the deploy
|
|
43052
|
+
* CLI unwinds quietly (no error output, no FAILED run event) — matching the
|
|
43053
|
+
* plain early `return` the pre-lock version used.
|
|
43054
|
+
*
|
|
43055
|
+
* The gate is scoped to `stackName`: nested-stack children inherit the parent
|
|
43056
|
+
* engine's option object, and the check is deliberately top-level-only (it was
|
|
43057
|
+
* never applied to children).
|
|
43058
|
+
*/
|
|
43059
|
+
function createPrefixMigrationGate(opts) {
|
|
43060
|
+
if (!opts.skipPrefix) return void 0;
|
|
43061
|
+
return async (gateStackName, state) => {
|
|
43062
|
+
if (gateStackName !== opts.stackName) return;
|
|
43063
|
+
const pending = findPendingPrefixRenames(opts.stackName, state);
|
|
43064
|
+
if (pending.length === 0) return;
|
|
43065
|
+
if (!await promptMigrationConfirm(pending, { ...opts.yes !== void 0 && { yes: opts.yes } })) throw new DeployCancelledError();
|
|
43066
|
+
};
|
|
43067
|
+
}
|
|
42956
43068
|
|
|
42957
43069
|
//#endregion
|
|
42958
43070
|
//#region src/cli/commands/deploy.ts
|
|
@@ -43190,13 +43302,11 @@ async function deployCommand(stacks, options) {
|
|
|
43190
43302
|
});
|
|
43191
43303
|
let runResult = "SUCCEEDED";
|
|
43192
43304
|
try {
|
|
43193
|
-
|
|
43194
|
-
|
|
43195
|
-
|
|
43196
|
-
|
|
43197
|
-
|
|
43198
|
-
}
|
|
43199
|
-
}
|
|
43305
|
+
const migrationGate = createPrefixMigrationGate({
|
|
43306
|
+
stackName: stackInfo.stackName,
|
|
43307
|
+
skipPrefix,
|
|
43308
|
+
yes: options.yes
|
|
43309
|
+
});
|
|
43200
43310
|
let recreateViaCcApiTargets;
|
|
43201
43311
|
let recreateViaSdkProviderTargets;
|
|
43202
43312
|
if (options.recreateViaCcApi?.length || options.recreateViaSdkProvider?.length) {
|
|
@@ -43248,6 +43358,7 @@ async function deployCommand(stacks, options) {
|
|
|
43248
43358
|
...options.roleArn && { roleArn: options.roleArn },
|
|
43249
43359
|
...assetRedirect && { assetRedirect },
|
|
43250
43360
|
...eventRecorder && { eventRecorder },
|
|
43361
|
+
...migrationGate && { onCurrentStateLoaded: migrationGate },
|
|
43251
43362
|
...recreateViaCcApiTargets && recreateViaCcApiTargets.size > 0 && { recreateViaCcApiTargets },
|
|
43252
43363
|
...recreateViaSdkProviderTargets && recreateViaSdkProviderTargets.size > 0 && { recreateViaSdkProviderTargets },
|
|
43253
43364
|
...options.replace && { replace: true },
|
|
@@ -43296,6 +43407,7 @@ async function deployCommand(stacks, options) {
|
|
|
43296
43407
|
deleted: deployResult.deleted
|
|
43297
43408
|
}, deployResult.durationMs);
|
|
43298
43409
|
} catch (deployError) {
|
|
43410
|
+
if (deployError instanceof DeployCancelledError) return;
|
|
43299
43411
|
runResult = "FAILED";
|
|
43300
43412
|
recordRunFailed(eventRecorder, stackInfo.stackName, deployError);
|
|
43301
43413
|
throw deployError;
|
|
@@ -62613,7 +62725,7 @@ function createMigrateCommand() {
|
|
|
62613
62725
|
*/
|
|
62614
62726
|
function buildProgram() {
|
|
62615
62727
|
const program = new Command();
|
|
62616
|
-
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.268.
|
|
62728
|
+
program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.268.3");
|
|
62617
62729
|
program.hook("preAction", (_thisCommand, actionCommand) => {
|
|
62618
62730
|
const { profile } = actionCommand.optsWithGlobals();
|
|
62619
62731
|
if (profile !== void 0) process.env["AWS_PROFILE"] = profile;
|