sst 2.0.0-rc.38 → 2.0.0-rc.39

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.
@@ -1,2 +1,3 @@
1
- import { CloudFormationDeployments, DeployStackOptions } from "./cloudformation-deployments.js";
2
- export declare function publishAssets(deployment: CloudFormationDeployments, options: DeployStackOptions): Promise<void>;
1
+ import { SdkProvider } from "aws-cdk/lib/api/aws-auth/sdk-provider.js";
2
+ import { DeployStackOptions as PublishStackAssetsOptions } from "./cloudformation-deployments.js";
3
+ export declare function publishDeployAssets(sdkProvider: SdkProvider, options: PublishStackAssetsOptions): Promise<any>;
@@ -1,7 +1,14 @@
1
+ import { debug } from "aws-cdk/lib/logging.js";
2
+ import { CloudFormationStack, TemplateParameters, waitForStackDelete, } from "aws-cdk/lib/api/util/cloudformation.js";
1
3
  import { ToolkitInfo } from "aws-cdk/lib/api/toolkit-info.js";
4
+ import { addMetadataAssetsToManifest } from "aws-cdk/lib/assets.js";
5
+ import { publishAssets } from "aws-cdk/lib/util/asset-publishing.js";
6
+ import { AssetManifestBuilder } from "aws-cdk/lib/util/asset-manifest-builder.js";
7
+ import { CloudFormationDeployments, } from "./cloudformation-deployments.js";
8
+ import { makeBodyParameter } from "./deploy-stack.js";
2
9
  import { Context } from "../context/context.js";
3
- export async function publishAssets(deployment, options) {
4
- const toolkitInfo = await useToolkitInfo().lookup(deployment, options);
10
+ export async function publishDeployAssets(sdkProvider, options) {
11
+ const { deployment, toolkitInfo, stackSdk, resolvedEnvironment, cloudFormationRoleArn, } = await useDeployment().get(sdkProvider, options);
5
12
  await deployment.publishStackAssets(options.stack, toolkitInfo, {
6
13
  buildAssets: options.buildAssets ?? true,
7
14
  publishOptions: {
@@ -9,17 +16,97 @@ export async function publishAssets(deployment, options) {
9
16
  parallel: options.assetParallelism,
10
17
  },
11
18
  });
19
+ return deployStack({
20
+ stack: options.stack,
21
+ noMonitor: true,
22
+ resolvedEnvironment,
23
+ deployName: options.deployName,
24
+ notificationArns: options.notificationArns,
25
+ quiet: options.quiet,
26
+ sdk: stackSdk,
27
+ sdkProvider,
28
+ roleArn: cloudFormationRoleArn,
29
+ reuseAssets: options.reuseAssets,
30
+ toolkitInfo,
31
+ tags: options.tags,
32
+ deploymentMethod: options.deploymentMethod,
33
+ force: options.force,
34
+ parameters: options.parameters,
35
+ usePreviousParameters: options.usePreviousParameters,
36
+ progress: options.progress,
37
+ ci: options.ci,
38
+ rollback: options.rollback,
39
+ hotswap: options.hotswap,
40
+ extraUserAgent: options.extraUserAgent,
41
+ resourcesToImport: options.resourcesToImport,
42
+ overrideTemplate: options.overrideTemplate,
43
+ assetParallelism: options.assetParallelism,
44
+ });
12
45
  }
13
- const useToolkitInfo = Context.memo(() => {
46
+ const useDeployment = Context.memo(() => {
14
47
  const state = new Map();
15
48
  return {
16
- async lookup(deployment, options) {
17
- if (state.has(deployment))
18
- return state.get(deployment);
19
- const { stackSdk, resolvedEnvironment } = await deployment.prepareSdkFor(options.stack, options.roleArn);
20
- const toolkitInfo = await ToolkitInfo.lookup(resolvedEnvironment, stackSdk, options.toolkitStackName);
21
- state.set(deployment, toolkitInfo);
22
- return toolkitInfo;
49
+ async get(sdkProvider, options) {
50
+ if (!state.has(sdkProvider)) {
51
+ const deployment = new CloudFormationDeployments({ sdkProvider });
52
+ const { stackSdk, resolvedEnvironment, cloudFormationRoleArn } = await deployment.prepareSdkFor(options.stack, options.roleArn);
53
+ const toolkitInfo = await ToolkitInfo.lookup(resolvedEnvironment, stackSdk, options.toolkitStackName);
54
+ // Do a verification of the bootstrap stack version
55
+ await deployment.validateBootstrapStackVersion(options.stack.stackName, options.stack.requiresBootstrapStackVersion, options.stack.bootstrapStackVersionSsmParameter, toolkitInfo);
56
+ state.set(sdkProvider, {
57
+ deployment,
58
+ toolkitInfo,
59
+ stackSdk,
60
+ resolvedEnvironment,
61
+ cloudFormationRoleArn,
62
+ });
63
+ }
64
+ return state.get(sdkProvider);
23
65
  }
24
66
  };
25
67
  });
68
+ async function deployStack(options) {
69
+ const stackArtifact = options.stack;
70
+ const stackEnv = options.resolvedEnvironment;
71
+ options.sdk.appendCustomUserAgent(options.extraUserAgent);
72
+ const cfn = options.sdk.cloudFormation();
73
+ const deployName = options.deployName || stackArtifact.stackName;
74
+ let cloudFormationStack = await CloudFormationStack.lookup(cfn, deployName);
75
+ if (cloudFormationStack.stackStatus.isCreationFailure) {
76
+ debug(`Found existing stack ${deployName} that had previously failed creation. Deleting it before attempting to re-create it.`);
77
+ await cfn.deleteStack({ StackName: deployName }).promise();
78
+ const deletedStack = await waitForStackDelete(cfn, deployName);
79
+ if (deletedStack && deletedStack.stackStatus.name !== "DELETE_COMPLETE") {
80
+ throw new Error(`Failed deleting stack ${deployName} that had previously failed creation (current state: ${deletedStack.stackStatus})`);
81
+ }
82
+ // Update variable to mark that the stack does not exist anymore, but avoid
83
+ // doing an actual lookup in CloudFormation (which would be silly to do if
84
+ // we just deleted it).
85
+ cloudFormationStack = CloudFormationStack.doesNotExist(cfn, deployName);
86
+ }
87
+ // Detect "legacy" assets (which remain in the metadata) and publish them via
88
+ // an ad-hoc asset manifest, while passing their locations via template
89
+ // parameters.
90
+ const legacyAssets = new AssetManifestBuilder();
91
+ const assetParams = await addMetadataAssetsToManifest(stackArtifact, legacyAssets, options.toolkitInfo, options.reuseAssets);
92
+ const finalParameterValues = { ...options.parameters, ...assetParams };
93
+ const templateParams = TemplateParameters.fromTemplate(stackArtifact.template);
94
+ const stackParams = options.usePreviousParameters
95
+ ? templateParams.updateExisting(finalParameterValues, cloudFormationStack.parameters)
96
+ : templateParams.supplyAll(finalParameterValues);
97
+ const bodyParameter = await makeBodyParameter(stackArtifact, options.resolvedEnvironment, legacyAssets, options.toolkitInfo, options.sdk, options.overrideTemplate);
98
+ await publishAssets(legacyAssets.toManifest(stackArtifact.assembly.directory), options.sdkProvider, stackEnv, {
99
+ parallel: options.assetParallelism,
100
+ });
101
+ return {
102
+ isUpdate: cloudFormationStack.exists && cloudFormationStack.stackStatus.name !== 'REVIEW_IN_PROGRESS',
103
+ params: {
104
+ StackName: deployName,
105
+ TemplateBody: bodyParameter.TemplateBody,
106
+ TemplateURL: bodyParameter.TemplateURL,
107
+ Parameters: stackParams.apiParameters,
108
+ Capabilities: ['CAPABILITY_IAM', 'CAPABILITY_NAMED_IAM', 'CAPABILITY_AUTO_EXPAND'],
109
+ Tags: options.tags,
110
+ },
111
+ };
112
+ }
@@ -290,6 +290,6 @@ export declare class CloudFormationDeployments {
290
290
  /**
291
291
  * Validate that the bootstrap stack has the right version for this stack
292
292
  */
293
- private validateBootstrapStackVersion;
293
+ validateBootstrapStackVersion(stackName: string, requiresBootstrapStackVersion: number | undefined, bootstrapStackVersionSsmParameter: string | undefined, toolkitInfo: ToolkitInfo): Promise<void>;
294
294
  }
295
295
  export {};
@@ -1,5 +1,6 @@
1
1
  import * as cxapi from "@aws-cdk/cx-api";
2
2
  import { Tag } from "aws-cdk/lib/cdk-toolkit.js";
3
+ import { AssetManifestBuilder } from "aws-cdk/lib/util/asset-manifest-builder.js";
3
4
  import { ISDK, SdkProvider } from "aws-cdk/lib/api/aws-auth/index.js";
4
5
  import { ToolkitInfo } from "aws-cdk/lib/api/toolkit-info.js";
5
6
  import { ResourcesToImport } from "aws-cdk/lib/api/util/cloudformation.js";
@@ -185,6 +186,20 @@ export interface ChangeSetDeploymentMethod {
185
186
  readonly changeSetName?: string;
186
187
  }
187
188
  export declare function deployStack(options: DeployStackOptions): Promise<DeployStackResult | undefined>;
189
+ /**
190
+ * Prepares the body parameter for +CreateChangeSet+.
191
+ *
192
+ * If the template is small enough to be inlined into the API call, just return
193
+ * it immediately.
194
+ *
195
+ * Otherwise, add it to the asset manifest to get uploaded to the staging
196
+ * bucket and return its coordinates. If there is no staging bucket, an error
197
+ * is thrown.
198
+ *
199
+ * @param stack the synthesized stack that provides the CloudFormation template
200
+ * @param toolkitInfo information about the toolkit stack
201
+ */
202
+ export declare function makeBodyParameter(stack: cxapi.CloudFormationStackArtifact, resolvedEnvironment: cxapi.Environment, assetManifest: AssetManifestBuilder, toolkitInfo: ToolkitInfo, sdk: ISDK, overrideTemplate?: any): Promise<TemplateBodyParameter>;
188
203
  /**
189
204
  * Prepare a body parameter for CFN, performing the upload
190
205
  *
@@ -340,7 +340,7 @@ class FullCloudFormationDeployment {
340
340
  * @param stack the synthesized stack that provides the CloudFormation template
341
341
  * @param toolkitInfo information about the toolkit stack
342
342
  */
343
- async function makeBodyParameter(stack, resolvedEnvironment, assetManifest, toolkitInfo, sdk, overrideTemplate) {
343
+ export async function makeBodyParameter(stack, resolvedEnvironment, assetManifest, toolkitInfo, sdk, overrideTemplate) {
344
344
  // If the template has already been uploaded to S3, just use it from there.
345
345
  if (stack.stackTemplateAssetObjectUrl && !overrideTemplate) {
346
346
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sst",
3
- "version": "2.0.0-rc.38",
3
+ "version": "2.0.0-rc.39",
4
4
  "bin": {
5
5
  "sst": "cli/sst.js"
6
6
  },
package/sst.mjs CHANGED
@@ -2120,11 +2120,26 @@ var init_cloudformation_deployments = __esm({
2120
2120
  // src/cdk/cloudformation-deployments-wrapper.ts
2121
2121
  var cloudformation_deployments_wrapper_exports = {};
2122
2122
  __export(cloudformation_deployments_wrapper_exports, {
2123
- publishAssets: () => publishAssets3
2123
+ publishDeployAssets: () => publishDeployAssets
2124
2124
  });
2125
+ import { debug as debug3 } from "aws-cdk/lib/logging.js";
2126
+ import {
2127
+ CloudFormationStack as CloudFormationStack3,
2128
+ TemplateParameters as TemplateParameters2,
2129
+ waitForStackDelete as waitForStackDelete2
2130
+ } from "aws-cdk/lib/api/util/cloudformation.js";
2125
2131
  import { ToolkitInfo as ToolkitInfo2 } from "aws-cdk/lib/api/toolkit-info.js";
2126
- async function publishAssets3(deployment, options) {
2127
- const toolkitInfo = await useToolkitInfo().lookup(deployment, options);
2132
+ import { addMetadataAssetsToManifest as addMetadataAssetsToManifest2 } from "aws-cdk/lib/assets.js";
2133
+ import { publishAssets as publishAssets3 } from "aws-cdk/lib/util/asset-publishing.js";
2134
+ import { AssetManifestBuilder as AssetManifestBuilder2 } from "aws-cdk/lib/util/asset-manifest-builder.js";
2135
+ async function publishDeployAssets(sdkProvider, options) {
2136
+ const {
2137
+ deployment,
2138
+ toolkitInfo,
2139
+ stackSdk,
2140
+ resolvedEnvironment,
2141
+ cloudFormationRoleArn
2142
+ } = await useDeployment().get(sdkProvider, options);
2128
2143
  await deployment.publishStackAssets(options.stack, toolkitInfo, {
2129
2144
  buildAssets: options.buildAssets ?? true,
2130
2145
  publishOptions: {
@@ -2132,26 +2147,130 @@ async function publishAssets3(deployment, options) {
2132
2147
  parallel: options.assetParallelism
2133
2148
  }
2134
2149
  });
2150
+ return deployStack2({
2151
+ stack: options.stack,
2152
+ noMonitor: true,
2153
+ resolvedEnvironment,
2154
+ deployName: options.deployName,
2155
+ notificationArns: options.notificationArns,
2156
+ quiet: options.quiet,
2157
+ sdk: stackSdk,
2158
+ sdkProvider,
2159
+ roleArn: cloudFormationRoleArn,
2160
+ reuseAssets: options.reuseAssets,
2161
+ toolkitInfo,
2162
+ tags: options.tags,
2163
+ deploymentMethod: options.deploymentMethod,
2164
+ force: options.force,
2165
+ parameters: options.parameters,
2166
+ usePreviousParameters: options.usePreviousParameters,
2167
+ progress: options.progress,
2168
+ ci: options.ci,
2169
+ rollback: options.rollback,
2170
+ hotswap: options.hotswap,
2171
+ extraUserAgent: options.extraUserAgent,
2172
+ resourcesToImport: options.resourcesToImport,
2173
+ overrideTemplate: options.overrideTemplate,
2174
+ assetParallelism: options.assetParallelism
2175
+ });
2176
+ }
2177
+ async function deployStack2(options) {
2178
+ const stackArtifact = options.stack;
2179
+ const stackEnv = options.resolvedEnvironment;
2180
+ options.sdk.appendCustomUserAgent(options.extraUserAgent);
2181
+ const cfn = options.sdk.cloudFormation();
2182
+ const deployName = options.deployName || stackArtifact.stackName;
2183
+ let cloudFormationStack = await CloudFormationStack3.lookup(cfn, deployName);
2184
+ if (cloudFormationStack.stackStatus.isCreationFailure) {
2185
+ debug3(
2186
+ `Found existing stack ${deployName} that had previously failed creation. Deleting it before attempting to re-create it.`
2187
+ );
2188
+ await cfn.deleteStack({ StackName: deployName }).promise();
2189
+ const deletedStack = await waitForStackDelete2(cfn, deployName);
2190
+ if (deletedStack && deletedStack.stackStatus.name !== "DELETE_COMPLETE") {
2191
+ throw new Error(
2192
+ `Failed deleting stack ${deployName} that had previously failed creation (current state: ${deletedStack.stackStatus})`
2193
+ );
2194
+ }
2195
+ cloudFormationStack = CloudFormationStack3.doesNotExist(cfn, deployName);
2196
+ }
2197
+ const legacyAssets = new AssetManifestBuilder2();
2198
+ const assetParams = await addMetadataAssetsToManifest2(
2199
+ stackArtifact,
2200
+ legacyAssets,
2201
+ options.toolkitInfo,
2202
+ options.reuseAssets
2203
+ );
2204
+ const finalParameterValues = { ...options.parameters, ...assetParams };
2205
+ const templateParams = TemplateParameters2.fromTemplate(
2206
+ stackArtifact.template
2207
+ );
2208
+ const stackParams = options.usePreviousParameters ? templateParams.updateExisting(
2209
+ finalParameterValues,
2210
+ cloudFormationStack.parameters
2211
+ ) : templateParams.supplyAll(finalParameterValues);
2212
+ const bodyParameter = await makeBodyParameter(
2213
+ stackArtifact,
2214
+ options.resolvedEnvironment,
2215
+ legacyAssets,
2216
+ options.toolkitInfo,
2217
+ options.sdk,
2218
+ options.overrideTemplate
2219
+ );
2220
+ await publishAssets3(
2221
+ legacyAssets.toManifest(stackArtifact.assembly.directory),
2222
+ options.sdkProvider,
2223
+ stackEnv,
2224
+ {
2225
+ parallel: options.assetParallelism
2226
+ }
2227
+ );
2228
+ return {
2229
+ isUpdate: cloudFormationStack.exists && cloudFormationStack.stackStatus.name !== "REVIEW_IN_PROGRESS",
2230
+ params: {
2231
+ StackName: deployName,
2232
+ TemplateBody: bodyParameter.TemplateBody,
2233
+ TemplateURL: bodyParameter.TemplateURL,
2234
+ Parameters: stackParams.apiParameters,
2235
+ Capabilities: ["CAPABILITY_IAM", "CAPABILITY_NAMED_IAM", "CAPABILITY_AUTO_EXPAND"],
2236
+ Tags: options.tags
2237
+ }
2238
+ };
2135
2239
  }
2136
- var useToolkitInfo;
2240
+ var useDeployment;
2137
2241
  var init_cloudformation_deployments_wrapper = __esm({
2138
2242
  "src/cdk/cloudformation-deployments-wrapper.ts"() {
2139
2243
  "use strict";
2244
+ init_cloudformation_deployments();
2245
+ init_deploy_stack();
2140
2246
  init_context();
2141
- useToolkitInfo = Context.memo(() => {
2247
+ useDeployment = Context.memo(() => {
2142
2248
  const state2 = /* @__PURE__ */ new Map();
2143
2249
  return {
2144
- async lookup(deployment, options) {
2145
- if (state2.has(deployment))
2146
- return state2.get(deployment);
2147
- const { stackSdk, resolvedEnvironment } = await deployment.prepareSdkFor(options.stack, options.roleArn);
2148
- const toolkitInfo = await ToolkitInfo2.lookup(
2149
- resolvedEnvironment,
2150
- stackSdk,
2151
- options.toolkitStackName
2152
- );
2153
- state2.set(deployment, toolkitInfo);
2154
- return toolkitInfo;
2250
+ async get(sdkProvider, options) {
2251
+ if (!state2.has(sdkProvider)) {
2252
+ const deployment = new CloudFormationDeployments({ sdkProvider });
2253
+ const { stackSdk, resolvedEnvironment, cloudFormationRoleArn } = await deployment.prepareSdkFor(options.stack, options.roleArn);
2254
+ const toolkitInfo = await ToolkitInfo2.lookup(
2255
+ resolvedEnvironment,
2256
+ stackSdk,
2257
+ options.toolkitStackName
2258
+ );
2259
+ await deployment.validateBootstrapStackVersion(
2260
+ options.stack.stackName,
2261
+ options.stack.requiresBootstrapStackVersion,
2262
+ options.stack.bootstrapStackVersionSsmParameter,
2263
+ toolkitInfo
2264
+ );
2265
+ state2.set(sdkProvider, {
2266
+ deployment,
2267
+ toolkitInfo,
2268
+ stackSdk,
2269
+ resolvedEnvironment,
2270
+ cloudFormationRoleArn
2271
+ });
2272
+ }
2273
+ return state2.get(sdkProvider);
2155
2274
  }
2156
2275
  };
2157
2276
  });
@@ -2162,23 +2281,22 @@ var init_cloudformation_deployments_wrapper = __esm({
2162
2281
  async function publishAssets4(stacks) {
2163
2282
  Logger.debug("Publishing assets");
2164
2283
  const provider = await useAWSProvider();
2165
- const { CloudFormationDeployments: CloudFormationDeployments2 } = await Promise.resolve().then(() => (init_cloudformation_deployments(), cloudformation_deployments_exports));
2166
- const { publishAssets: publishAssets5 } = await Promise.resolve().then(() => (init_cloudformation_deployments_wrapper(), cloudformation_deployments_wrapper_exports));
2167
- const deployment = new CloudFormationDeployments2({
2168
- sdkProvider: provider
2169
- });
2284
+ const { publishDeployAssets: publishDeployAssets2 } = await Promise.resolve().then(() => (init_cloudformation_deployments_wrapper(), cloudformation_deployments_wrapper_exports));
2285
+ const results = {};
2170
2286
  for (const stack of stacks) {
2171
- await publishAssets5(
2172
- deployment,
2287
+ const result = await publishDeployAssets2(
2288
+ provider,
2173
2289
  {
2174
2290
  stack,
2175
- quiet: true,
2291
+ quiet: false,
2176
2292
  deploymentMethod: {
2177
2293
  method: "direct"
2178
2294
  }
2179
2295
  }
2180
2296
  );
2297
+ results[stack.stackName] = result;
2181
2298
  }
2299
+ return results;
2182
2300
  }
2183
2301
  async function deployMany(stacks) {
2184
2302
  Logger.debug(
@@ -1,6 +1,6 @@
1
1
  import type { CloudFormationStackArtifact } from "aws-cdk-lib/cx-api";
2
2
  import { StackDeploymentResult } from "./monitor.js";
3
- export declare function publishAssets(stacks: CloudFormationStackArtifact[]): Promise<void>;
3
+ export declare function publishAssets(stacks: CloudFormationStackArtifact[]): Promise<Record<string, any>>;
4
4
  export declare function deployMany(stacks: CloudFormationStackArtifact[]): Promise<Record<string, {
5
5
  status: string;
6
6
  outputs: Record<string, string>;
package/stacks/deploy.js CHANGED
@@ -3,23 +3,21 @@ import { useAWSProvider } from "../credentials.js";
3
3
  import { Logger } from "../logger.js";
4
4
  import { isFailed, monitor } from "./monitor.js";
5
5
  export async function publishAssets(stacks) {
6
- // TODO: use memo in cloudformation-deployments.ts
7
6
  Logger.debug("Publishing assets");
8
7
  const provider = await useAWSProvider();
9
- const { CloudFormationDeployments } = await import("../cdk/cloudformation-deployments.js");
10
- const { publishAssets } = await import("../cdk/cloudformation-deployments-wrapper.js");
11
- const deployment = new CloudFormationDeployments({
12
- sdkProvider: provider,
13
- });
8
+ const { publishDeployAssets } = await import("../cdk/cloudformation-deployments-wrapper.js");
9
+ const results = {};
14
10
  for (const stack of stacks) {
15
- await publishAssets(deployment, {
11
+ const result = await publishDeployAssets(provider, {
16
12
  stack: stack,
17
- quiet: true,
13
+ quiet: false,
18
14
  deploymentMethod: {
19
15
  method: "direct",
20
16
  },
21
17
  });
18
+ results[stack.stackName] = result;
22
19
  }
20
+ return results;
23
21
  }
24
22
  export async function deployMany(stacks) {
25
23
  Logger.debug("Deploying stacks", stacks.map((s) => s.stackName));