sst 2.48.4 → 2.49.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/credentials.d.ts +4 -4
- package/credentials.js +14 -3
- package/package.json +33 -33
- package/package.json.bak +33 -33
- package/stacks/deploy.d.ts +1 -1
- package/stacks/deploy.js +151 -51
- package/stacks/synth.js +5 -3
- package/support/base-site-archiver.mjs +9 -9
- package/support/bootstrap-metadata-function/index.mjs +35879 -61286
- package/support/bridge/live-lambda.mjs +54 -106
- package/support/custom-resources/index.mjs +49975 -89843
- package/support/event-bus-retrier/index.mjs +32 -85
- package/support/job-manager/index.mjs +8205 -29763
- package/support/rds-migrator/index.mjs +42 -26
- package/support/script-function/index.mjs +32065 -40311
- package/support/signing-function/index.mjs +2806 -1466
- package/support/ssr-site-function-archiver.mjs +7 -7
- package/support/ssr-warmer/index.mjs +22577 -27092
- package/util/user-configuration.d.ts +89 -0
- package/util/user-configuration.js +311 -0
- package/cdk/deploy-stack.d.ts +0 -180
- package/cdk/deploy-stack.js +0 -520
- package/cdk/deployments-wrapper.d.ts +0 -3
- package/cdk/deployments-wrapper.js +0 -117
- package/cdk/deployments.d.ts +0 -323
- package/cdk/deployments.js +0 -408
package/cdk/deployments.js
DELETED
|
@@ -1,408 +0,0 @@
|
|
|
1
|
-
// Copied from https://github.com/aws/aws-cdk/blob/main/packages/aws-cdk/lib/api/cloudformation-deployments.ts
|
|
2
|
-
import { randomUUID } from "crypto";
|
|
3
|
-
import * as cxapi from "@aws-cdk/cx-api";
|
|
4
|
-
import * as cdk_assets from "cdk-assets";
|
|
5
|
-
import { AssetManifestBuilder } from "sst-aws-cdk/lib/api/deployments/asset-manifest-builder.js";
|
|
6
|
-
import { EVENT_TO_LOGGER, PublishingAws, } from "sst-aws-cdk/lib/api/deployments/asset-publishing.js";
|
|
7
|
-
import { determineAllowCrossAccountAssetPublishing } from "sst-aws-cdk/lib/api/deployments/checks.js";
|
|
8
|
-
import { CloudFormationStack, stabilizeStack, uploadStackTemplateAssets, } from "sst-aws-cdk/lib/api/deployments/cloudformation.js";
|
|
9
|
-
import { deployStack, destroyStack } from "./deploy-stack.js";
|
|
10
|
-
import { loadCurrentTemplate, loadCurrentTemplateWithNestedStacks, } from "sst-aws-cdk/lib/api/deployments/nested-stack-helpers.js";
|
|
11
|
-
import { debug, warning } from "sst-aws-cdk/lib/logging.js";
|
|
12
|
-
import { ToolkitError } from "sst-aws-cdk/lib/toolkit/error.js";
|
|
13
|
-
import { formatErrorMessage } from "sst-aws-cdk/lib/util/error.js";
|
|
14
|
-
import { EnvironmentAccess } from "sst-aws-cdk/lib/api/environment-access.js";
|
|
15
|
-
import { DEFAULT_TOOLKIT_STACK_NAME } from "sst-aws-cdk/lib/api/toolkit-info.js";
|
|
16
|
-
import { StackActivityMonitor, } from "sst-aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.js";
|
|
17
|
-
import { StackEventPoller } from "sst-aws-cdk/lib/api/util/cloudformation/stack-event-poller.js";
|
|
18
|
-
import { RollbackChoice } from "sst-aws-cdk/lib/api/util/cloudformation/stack-status.js";
|
|
19
|
-
import { makeBodyParameter } from "sst-aws-cdk/lib/api/util/template-body-parameter.js";
|
|
20
|
-
import { AssetManifest } from "cdk-assets";
|
|
21
|
-
const BOOTSTRAP_STACK_VERSION_FOR_ROLLBACK = 23;
|
|
22
|
-
/**
|
|
23
|
-
* Scope for a single set of deployments from a set of Cloud Assembly Artifacts
|
|
24
|
-
*
|
|
25
|
-
* Manages lookup of SDKs, Bootstrap stacks, etc.
|
|
26
|
-
*/
|
|
27
|
-
export class Deployments {
|
|
28
|
-
props;
|
|
29
|
-
envs;
|
|
30
|
-
/**
|
|
31
|
-
* SDK provider for asset publishing (do not use for anything else).
|
|
32
|
-
*
|
|
33
|
-
* This SDK provider is only allowed to be used for that purpose, nothing else.
|
|
34
|
-
*
|
|
35
|
-
* It's not a different object, but the field name should imply that this
|
|
36
|
-
* object should not be used directly, except to pass to asset handling routines.
|
|
37
|
-
*/
|
|
38
|
-
assetSdkProvider;
|
|
39
|
-
/**
|
|
40
|
-
* SDK provider for passing to deployStack
|
|
41
|
-
*
|
|
42
|
-
* This SDK provider is only allowed to be used for that purpose, nothing else.
|
|
43
|
-
*
|
|
44
|
-
* It's not a different object, but the field name should imply that this
|
|
45
|
-
* object should not be used directly, except to pass to `deployStack`.
|
|
46
|
-
*/
|
|
47
|
-
deployStackSdkProvider;
|
|
48
|
-
publisherCache = new Map();
|
|
49
|
-
_allowCrossAccountAssetPublishing;
|
|
50
|
-
constructor(props) {
|
|
51
|
-
this.props = props;
|
|
52
|
-
this.assetSdkProvider = props.sdkProvider;
|
|
53
|
-
this.deployStackSdkProvider = props.sdkProvider;
|
|
54
|
-
this.envs = new EnvironmentAccess(props.sdkProvider, props.toolkitStackName ?? DEFAULT_TOOLKIT_STACK_NAME);
|
|
55
|
-
}
|
|
56
|
-
/**
|
|
57
|
-
* Resolves the environment for a stack.
|
|
58
|
-
*/
|
|
59
|
-
async resolveEnvironment(stack) {
|
|
60
|
-
return this.envs.resolveStackEnvironment(stack);
|
|
61
|
-
}
|
|
62
|
-
async readCurrentTemplateWithNestedStacks(rootStackArtifact, retrieveProcessedTemplate = false) {
|
|
63
|
-
const env = await this.envs.accessStackForLookupBestEffort(rootStackArtifact);
|
|
64
|
-
return loadCurrentTemplateWithNestedStacks(rootStackArtifact, env.sdk, retrieveProcessedTemplate);
|
|
65
|
-
}
|
|
66
|
-
async readCurrentTemplate(stackArtifact) {
|
|
67
|
-
debug(`Reading existing template for stack ${stackArtifact.displayName}.`);
|
|
68
|
-
const env = await this.envs.accessStackForLookupBestEffort(stackArtifact);
|
|
69
|
-
return loadCurrentTemplate(stackArtifact, env.sdk);
|
|
70
|
-
}
|
|
71
|
-
async resourceIdentifierSummaries(stackArtifact) {
|
|
72
|
-
debug(`Retrieving template summary for stack ${stackArtifact.displayName}.`);
|
|
73
|
-
// Currently, needs to use `deploy-role` since it may need to read templates in the staging
|
|
74
|
-
// bucket which have been encrypted with a KMS key (and lookup-role may not read encrypted things)
|
|
75
|
-
const env = await this.envs.accessStackForReadOnlyStackOperations(stackArtifact);
|
|
76
|
-
const cfn = env.sdk.cloudFormation();
|
|
77
|
-
// @ts-ignore
|
|
78
|
-
await uploadStackTemplateAssets(stackArtifact, this);
|
|
79
|
-
// Upload the template, if necessary, before passing it to CFN
|
|
80
|
-
const builder = new AssetManifestBuilder();
|
|
81
|
-
const cfnParam = await makeBodyParameter(stackArtifact, env.resolvedEnvironment, builder, env.resources);
|
|
82
|
-
// If the `makeBodyParameter` before this added assets, make sure to publish them before
|
|
83
|
-
// calling the API.
|
|
84
|
-
const addedAssets = builder.toManifest(stackArtifact.assembly.directory);
|
|
85
|
-
for (const entry of addedAssets.entries) {
|
|
86
|
-
await this.buildSingleAsset("no-version-validation", addedAssets, entry, {
|
|
87
|
-
stack: stackArtifact,
|
|
88
|
-
});
|
|
89
|
-
await this.publishSingleAsset(addedAssets, entry, {
|
|
90
|
-
stack: stackArtifact,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
const response = await cfn.getTemplateSummary(cfnParam);
|
|
94
|
-
if (!response.ResourceIdentifierSummaries) {
|
|
95
|
-
debug('GetTemplateSummary API call did not return "ResourceIdentifierSummaries"');
|
|
96
|
-
}
|
|
97
|
-
return response.ResourceIdentifierSummaries ?? [];
|
|
98
|
-
}
|
|
99
|
-
async deployStack(options) {
|
|
100
|
-
let deploymentMethod = options.deploymentMethod;
|
|
101
|
-
if (options.changeSetName || options.execute !== undefined) {
|
|
102
|
-
if (deploymentMethod) {
|
|
103
|
-
throw new ToolkitError("You cannot supply both 'deploymentMethod' and 'changeSetName/execute'. Supply one or the other.");
|
|
104
|
-
}
|
|
105
|
-
deploymentMethod = {
|
|
106
|
-
method: "change-set",
|
|
107
|
-
changeSetName: options.changeSetName,
|
|
108
|
-
execute: options.execute,
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
const env = await this.envs.accessStackForMutableStackOperations(options.stack);
|
|
112
|
-
// Do a verification of the bootstrap stack version
|
|
113
|
-
await this.validateBootstrapStackVersion(options.stack.stackName, options.stack.requiresBootstrapStackVersion, options.stack.bootstrapStackVersionSsmParameter, env.resources);
|
|
114
|
-
const executionRoleArn = await env.replacePlaceholders(options.roleArn ?? options.stack.cloudFormationExecutionRoleArn);
|
|
115
|
-
// Deploy assets
|
|
116
|
-
const assetArtifacts = options.stack.dependencies.filter(cxapi.AssetManifestArtifact.isAssetManifestArtifact);
|
|
117
|
-
for (const asset of assetArtifacts) {
|
|
118
|
-
const manifest = AssetManifest.fromFile(asset.file);
|
|
119
|
-
await publishAssets(manifest, this.deployStackSdkProvider, env.resolvedEnvironment, { quiet: options.quiet });
|
|
120
|
-
}
|
|
121
|
-
return deployStack({
|
|
122
|
-
stack: options.stack,
|
|
123
|
-
noMonitor: true,
|
|
124
|
-
resolvedEnvironment: env.resolvedEnvironment,
|
|
125
|
-
deployName: options.deployName,
|
|
126
|
-
notificationArns: options.notificationArns,
|
|
127
|
-
quiet: options.quiet,
|
|
128
|
-
sdk: env.sdk,
|
|
129
|
-
sdkProvider: this.deployStackSdkProvider,
|
|
130
|
-
roleArn: executionRoleArn,
|
|
131
|
-
reuseAssets: options.reuseAssets,
|
|
132
|
-
envResources: env.resources,
|
|
133
|
-
tags: options.tags,
|
|
134
|
-
deploymentMethod,
|
|
135
|
-
force: options.force,
|
|
136
|
-
parameters: options.parameters,
|
|
137
|
-
usePreviousParameters: options.usePreviousParameters,
|
|
138
|
-
progress: options.progress,
|
|
139
|
-
ci: options.ci,
|
|
140
|
-
rollback: options.rollback,
|
|
141
|
-
hotswap: options.hotswap,
|
|
142
|
-
hotswapPropertyOverrides: options.hotswapPropertyOverrides,
|
|
143
|
-
extraUserAgent: options.extraUserAgent,
|
|
144
|
-
resourcesToImport: options.resourcesToImport,
|
|
145
|
-
overrideTemplate: options.overrideTemplate,
|
|
146
|
-
assetParallelism: options.assetParallelism,
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
async rollbackStack(options) {
|
|
150
|
-
let resourcesToSkip = options.orphanLogicalIds ?? [];
|
|
151
|
-
if (options.force && resourcesToSkip.length > 0) {
|
|
152
|
-
throw new ToolkitError("Cannot combine --force with --orphan");
|
|
153
|
-
}
|
|
154
|
-
const env = await this.envs.accessStackForMutableStackOperations(options.stack);
|
|
155
|
-
if (options.validateBootstrapStackVersion ?? true) {
|
|
156
|
-
// Do a verification of the bootstrap stack version
|
|
157
|
-
await this.validateBootstrapStackVersion(options.stack.stackName, BOOTSTRAP_STACK_VERSION_FOR_ROLLBACK, options.stack.bootstrapStackVersionSsmParameter, env.resources);
|
|
158
|
-
}
|
|
159
|
-
const cfn = env.sdk.cloudFormation();
|
|
160
|
-
const deployName = options.stack.stackName;
|
|
161
|
-
// We loop in case of `--force` and the stack ends up in `CONTINUE_UPDATE_ROLLBACK`.
|
|
162
|
-
let maxLoops = 10;
|
|
163
|
-
while (maxLoops--) {
|
|
164
|
-
let cloudFormationStack = await CloudFormationStack.lookup(cfn, deployName);
|
|
165
|
-
const executionRoleArn = await env.replacePlaceholders(options.roleArn ?? options.stack.cloudFormationExecutionRoleArn);
|
|
166
|
-
switch (cloudFormationStack.stackStatus.rollbackChoice) {
|
|
167
|
-
case RollbackChoice.NONE:
|
|
168
|
-
warning(`Stack ${deployName} does not need a rollback: ${cloudFormationStack.stackStatus}`);
|
|
169
|
-
return { notInRollbackableState: true };
|
|
170
|
-
case RollbackChoice.START_ROLLBACK:
|
|
171
|
-
debug(`Initiating rollback of stack ${deployName}`);
|
|
172
|
-
await cfn.rollbackStack({
|
|
173
|
-
StackName: deployName,
|
|
174
|
-
RoleARN: executionRoleArn,
|
|
175
|
-
ClientRequestToken: randomUUID(),
|
|
176
|
-
// Enabling this is just the better overall default, the only reason it isn't the upstream default is backwards compatibility
|
|
177
|
-
RetainExceptOnCreate: true,
|
|
178
|
-
});
|
|
179
|
-
break;
|
|
180
|
-
case RollbackChoice.CONTINUE_UPDATE_ROLLBACK:
|
|
181
|
-
if (options.force) {
|
|
182
|
-
// Find the failed resources from the deployment and automatically skip them
|
|
183
|
-
// (Using deployment log because we definitely have `DescribeStackEvents` permissions, and we might not have
|
|
184
|
-
// `DescribeStackResources` permissions).
|
|
185
|
-
const poller = new StackEventPoller(cfn, {
|
|
186
|
-
stackName: deployName,
|
|
187
|
-
stackStatuses: [
|
|
188
|
-
"ROLLBACK_IN_PROGRESS",
|
|
189
|
-
"UPDATE_ROLLBACK_IN_PROGRESS",
|
|
190
|
-
],
|
|
191
|
-
});
|
|
192
|
-
await poller.poll();
|
|
193
|
-
resourcesToSkip = poller.resourceErrors
|
|
194
|
-
.filter((r) => !r.isStackEvent && r.parentStackLogicalIds.length === 0)
|
|
195
|
-
.map((r) => r.event.LogicalResourceId ?? "");
|
|
196
|
-
}
|
|
197
|
-
const skipDescription = resourcesToSkip.length > 0
|
|
198
|
-
? ` (orphaning: ${resourcesToSkip.join(", ")})`
|
|
199
|
-
: "";
|
|
200
|
-
warning(`Continuing rollback of stack ${deployName}${skipDescription}`);
|
|
201
|
-
await cfn.continueUpdateRollback({
|
|
202
|
-
StackName: deployName,
|
|
203
|
-
ClientRequestToken: randomUUID(),
|
|
204
|
-
RoleARN: executionRoleArn,
|
|
205
|
-
ResourcesToSkip: resourcesToSkip,
|
|
206
|
-
});
|
|
207
|
-
break;
|
|
208
|
-
case RollbackChoice.ROLLBACK_FAILED:
|
|
209
|
-
warning(`Stack ${deployName} failed creation and rollback. This state cannot be rolled back. You can recreate this stack by running 'cdk deploy'.`);
|
|
210
|
-
return { notInRollbackableState: true };
|
|
211
|
-
default:
|
|
212
|
-
throw new ToolkitError(`Unexpected rollback choice: ${cloudFormationStack.stackStatus.rollbackChoice}`);
|
|
213
|
-
}
|
|
214
|
-
const monitor = options.quiet
|
|
215
|
-
? undefined
|
|
216
|
-
: StackActivityMonitor.withDefaultPrinter(cfn, deployName, options.stack, {
|
|
217
|
-
ci: options.ci,
|
|
218
|
-
}).start();
|
|
219
|
-
let stackErrorMessage = undefined;
|
|
220
|
-
let finalStackState = cloudFormationStack;
|
|
221
|
-
try {
|
|
222
|
-
const successStack = await stabilizeStack(cfn, deployName);
|
|
223
|
-
// This shouldn't really happen, but catch it anyway. You never know.
|
|
224
|
-
if (!successStack) {
|
|
225
|
-
throw new ToolkitError("Stack deploy failed (the stack disappeared while we were rolling it back)");
|
|
226
|
-
}
|
|
227
|
-
finalStackState = successStack;
|
|
228
|
-
const errors = monitor?.errors?.join(", ");
|
|
229
|
-
if (errors) {
|
|
230
|
-
stackErrorMessage = errors;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
catch (e) {
|
|
234
|
-
stackErrorMessage = suffixWithErrors(formatErrorMessage(e), monitor?.errors);
|
|
235
|
-
}
|
|
236
|
-
finally {
|
|
237
|
-
await monitor?.stop();
|
|
238
|
-
}
|
|
239
|
-
if (finalStackState.stackStatus.isRollbackSuccess || !stackErrorMessage) {
|
|
240
|
-
return { success: true };
|
|
241
|
-
}
|
|
242
|
-
// Either we need to ignore some resources to continue the rollback, or something went wrong
|
|
243
|
-
if (finalStackState.stackStatus.rollbackChoice ===
|
|
244
|
-
RollbackChoice.CONTINUE_UPDATE_ROLLBACK &&
|
|
245
|
-
options.force) {
|
|
246
|
-
// Do another loop-de-loop
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
throw new ToolkitError(`${stackErrorMessage} (fix problem and retry, or orphan these resources using --orphan or --force)`);
|
|
250
|
-
}
|
|
251
|
-
throw new ToolkitError("Rollback did not finish after a large number of iterations; stopping because it looks like we're not making progress anymore. You can retry if rollback was progressing as expected.");
|
|
252
|
-
}
|
|
253
|
-
async destroyStack(options) {
|
|
254
|
-
const env = await this.envs.accessStackForMutableStackOperations(options.stack);
|
|
255
|
-
const executionRoleArn = await env.replacePlaceholders(options.roleArn ?? options.stack.cloudFormationExecutionRoleArn);
|
|
256
|
-
return destroyStack({
|
|
257
|
-
sdk: env.sdk,
|
|
258
|
-
roleArn: executionRoleArn,
|
|
259
|
-
stack: options.stack,
|
|
260
|
-
deployName: options.deployName,
|
|
261
|
-
quiet: options.quiet,
|
|
262
|
-
ci: options.ci,
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
async stackExists(options) {
|
|
266
|
-
let env;
|
|
267
|
-
if (options.tryLookupRole) {
|
|
268
|
-
env = await this.envs.accessStackForLookupBestEffort(options.stack);
|
|
269
|
-
}
|
|
270
|
-
else {
|
|
271
|
-
env = await this.envs.accessStackForReadOnlyStackOperations(options.stack);
|
|
272
|
-
}
|
|
273
|
-
const stack = await CloudFormationStack.lookup(env.sdk.cloudFormation(), options.deployName ?? options.stack.stackName);
|
|
274
|
-
return stack.exists;
|
|
275
|
-
}
|
|
276
|
-
/**
|
|
277
|
-
* Build a single asset from an asset manifest
|
|
278
|
-
*
|
|
279
|
-
* If an assert manifest artifact is given, the bootstrap stack version
|
|
280
|
-
* will be validated according to the constraints in that manifest artifact.
|
|
281
|
-
* If that is not necessary, `'no-version-validation'` can be passed.
|
|
282
|
-
*/
|
|
283
|
-
// eslint-disable-next-line max-len
|
|
284
|
-
async buildSingleAsset(assetArtifact, assetManifest, asset, options) {
|
|
285
|
-
if (assetArtifact !== "no-version-validation") {
|
|
286
|
-
const env = await this.envs.accessStackForReadOnlyStackOperations(options.stack);
|
|
287
|
-
await this.validateBootstrapStackVersion(options.stack.stackName, assetArtifact.requiresBootstrapStackVersion, assetArtifact.bootstrapStackVersionSsmParameter, env.resources);
|
|
288
|
-
}
|
|
289
|
-
const resolvedEnvironment = await this.envs.resolveStackEnvironment(options.stack);
|
|
290
|
-
const publisher = this.cachedPublisher(assetManifest, resolvedEnvironment, options.stackName);
|
|
291
|
-
await publisher.buildEntry(asset);
|
|
292
|
-
}
|
|
293
|
-
/**
|
|
294
|
-
* Publish a single asset from an asset manifest
|
|
295
|
-
*/
|
|
296
|
-
async publishSingleAsset(assetManifest, asset, options) {
|
|
297
|
-
const stackEnv = await this.envs.resolveStackEnvironment(options.stack);
|
|
298
|
-
// No need to validate anymore, we already did that during build
|
|
299
|
-
const publisher = this.cachedPublisher(assetManifest, stackEnv, options.stackName);
|
|
300
|
-
await publisher.publishEntry(asset, {
|
|
301
|
-
allowCrossAccount: await this.allowCrossAccountAssetPublishingForEnv(options.stack),
|
|
302
|
-
});
|
|
303
|
-
if (publisher.hasFailures) {
|
|
304
|
-
throw new ToolkitError(`Failed to publish asset ${asset.id}`);
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
async allowCrossAccountAssetPublishingForEnv(stack) {
|
|
308
|
-
if (this._allowCrossAccountAssetPublishing === undefined) {
|
|
309
|
-
const env = await this.envs.accessStackForReadOnlyStackOperations(stack);
|
|
310
|
-
this._allowCrossAccountAssetPublishing =
|
|
311
|
-
await determineAllowCrossAccountAssetPublishing(env.sdk, this.props.toolkitStackName);
|
|
312
|
-
}
|
|
313
|
-
return this._allowCrossAccountAssetPublishing;
|
|
314
|
-
}
|
|
315
|
-
/**
|
|
316
|
-
* Return whether a single asset has been published already
|
|
317
|
-
*/
|
|
318
|
-
async isSingleAssetPublished(assetManifest, asset, options) {
|
|
319
|
-
const stackEnv = await this.envs.resolveStackEnvironment(options.stack);
|
|
320
|
-
const publisher = this.cachedPublisher(assetManifest, stackEnv, options.stackName);
|
|
321
|
-
return publisher.isEntryPublished(asset);
|
|
322
|
-
}
|
|
323
|
-
/**
|
|
324
|
-
* Validate that the bootstrap stack has the right version for this stack
|
|
325
|
-
*
|
|
326
|
-
* Call into envResources.validateVersion, but prepend the stack name in case of failure.
|
|
327
|
-
*/
|
|
328
|
-
async validateBootstrapStackVersion(stackName, requiresBootstrapStackVersion, bootstrapStackVersionSsmParameter, envResources) {
|
|
329
|
-
try {
|
|
330
|
-
await envResources.validateVersion(requiresBootstrapStackVersion, bootstrapStackVersionSsmParameter);
|
|
331
|
-
}
|
|
332
|
-
catch (e) {
|
|
333
|
-
throw new ToolkitError(`${stackName}: ${formatErrorMessage(e)}`);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
cachedPublisher(assetManifest, env, stackName) {
|
|
337
|
-
const existing = this.publisherCache.get(assetManifest);
|
|
338
|
-
if (existing) {
|
|
339
|
-
return existing;
|
|
340
|
-
}
|
|
341
|
-
const prefix = stackName ? `${stackName}: ` : "";
|
|
342
|
-
const publisher = new cdk_assets.AssetPublishing(assetManifest, {
|
|
343
|
-
// The AssetPublishing class takes care of role assuming etc, so it's okay to
|
|
344
|
-
// give it a direct `SdkProvider`.
|
|
345
|
-
aws: new PublishingAws(this.assetSdkProvider, env),
|
|
346
|
-
progressListener: new ParallelSafeAssetProgress(prefix, this.props.quiet ?? false),
|
|
347
|
-
});
|
|
348
|
-
this.publisherCache.set(assetManifest, publisher);
|
|
349
|
-
return publisher;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* Asset progress that doesn't do anything with percentages (currently)
|
|
354
|
-
*/
|
|
355
|
-
class ParallelSafeAssetProgress {
|
|
356
|
-
prefix;
|
|
357
|
-
quiet;
|
|
358
|
-
constructor(prefix, quiet) {
|
|
359
|
-
this.prefix = prefix;
|
|
360
|
-
this.quiet = quiet;
|
|
361
|
-
}
|
|
362
|
-
onPublishEvent(type, event) {
|
|
363
|
-
const handler = this.quiet && type !== "fail" ? debug : EVENT_TO_LOGGER[type];
|
|
364
|
-
handler(`${this.prefix}${type}: ${event.message}`);
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
function suffixWithErrors(msg, errors) {
|
|
368
|
-
return errors && errors.length > 0 ? `${msg}: ${errors.join(", ")}` : msg;
|
|
369
|
-
}
|
|
370
|
-
//////////////////////
|
|
371
|
-
// Manually copied over functions
|
|
372
|
-
//////////////////////
|
|
373
|
-
/*
|
|
374
|
-
* Copy over deprecated `publishAssets` from `lib/api/deployments/asset-publishing.ts`
|
|
375
|
-
* to be used in `deployments-wrapper.ts`
|
|
376
|
-
*/
|
|
377
|
-
class PublishingProgressListener {
|
|
378
|
-
constructor() { }
|
|
379
|
-
onPublishEvent(type, event) {
|
|
380
|
-
const handler = EVENT_TO_LOGGER[type];
|
|
381
|
-
handler(`[${event.percentComplete}%] ${type}: ${event.message}`);
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
export async function publishAssets(manifest, sdk, targetEnv, options) {
|
|
385
|
-
// This shouldn't really happen (it's a programming error), but we don't have
|
|
386
|
-
// the types here to guide us. Do an runtime validation to be super super sure.
|
|
387
|
-
if (targetEnv.account === undefined ||
|
|
388
|
-
targetEnv.account === cxapi.UNKNOWN_ACCOUNT ||
|
|
389
|
-
targetEnv.region === undefined ||
|
|
390
|
-
targetEnv.account === cxapi.UNKNOWN_REGION) {
|
|
391
|
-
throw new ToolkitError(`Asset publishing requires resolved account and region, got ${JSON.stringify(targetEnv)}`);
|
|
392
|
-
}
|
|
393
|
-
const publisher = new cdk_assets.AssetPublishing(manifest, {
|
|
394
|
-
aws: new PublishingAws(sdk, targetEnv),
|
|
395
|
-
progressListener: options.quiet
|
|
396
|
-
? undefined
|
|
397
|
-
: new PublishingProgressListener(),
|
|
398
|
-
throwOnError: false,
|
|
399
|
-
publishInParallel: true,
|
|
400
|
-
buildAssets: true,
|
|
401
|
-
publishAssets: true,
|
|
402
|
-
quiet: options.quiet,
|
|
403
|
-
});
|
|
404
|
-
await publisher.publish({ allowCrossAccount: true });
|
|
405
|
-
if (publisher.hasFailures) {
|
|
406
|
-
throw new ToolkitError("Failed to publish one or more assets. See the error messages above for more information.");
|
|
407
|
-
}
|
|
408
|
-
}
|