Skip to content

Commit 586e1b3

Browse files
rix0rrrgithub-actions
and
github-actions
authored
feat(toolkit): add a return type for toolkit.deploy() (#317)
`toolkit.deploy()` now returns information about the stacks it deployed. Fixes aws/aws-cdk#33189 --- By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license --------- Signed-off-by: github-actions <[email protected]> Co-authored-by: github-actions <[email protected]>
1 parent 2df3633 commit 586e1b3

File tree

16 files changed

+672
-7
lines changed

16 files changed

+672
-7
lines changed

packages/@aws-cdk/cloud-assembly-schema/lib/cloud-assembly/schema.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,12 @@ export interface ArtifactManifest {
100100
readonly properties?: ArtifactProperties;
101101

102102
/**
103-
* A string that represents this artifact. Should only be used in user interfaces.
103+
* A string that can be shown to a user to uniquely identify this artifact inside a cloud assembly tree
104+
*
105+
* Is used by the CLI to present a list of stacks to the user in a way that
106+
* makes sense to them. Even though the property name "display name" doesn't
107+
* imply it, this field is used to select stacks as well, so all stacks should
108+
* have a unique display name.
104109
*
105110
* @default - no display name
106111
*/

packages/@aws-cdk/cloud-assembly-schema/schema/cloud-assembly.schema.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
]
8484
},
8585
"displayName": {
86-
"description": "A string that represents this artifact. Should only be used in user interfaces. (Default - no display name)",
86+
"description": "A string that can be shown to a user to uniquely identify this artifact inside a cloud assembly tree\n\nIs used by the CLI to present a list of stacks to the user in a way that\nmakes sense to them. Even though the property name \"display name\" doesn't\nimply it, this field is used to select stacks as well, so all stacks should\nhave a unique display name. (Default - no display name)",
8787
"type": "string"
8888
}
8989
},
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
2-
"schemaHash": "78936b0f9299bbe47497dd77f8065d71e65d8d739a0413ad7698ad03b22ef83e",
2+
"schemaHash": "96958a4c40e0a00e850f0c14dd6e9c0fc8db0b075f1f155cea41ab198c0514be",
33
"revision": 43
44
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
export * from './toolkit';
22
export * from './non-interactive-io-host';
3+
export * from './types';
4+
export * from '../api/shared-public';

packages/@aws-cdk/toolkit-lib/lib/toolkit/toolkit.ts

+21-3
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as fs from 'fs-extra';
66
import { NonInteractiveIoHost } from './non-interactive-io-host';
77
import type { ToolkitServices } from './private';
88
import { assemblyFromSource } from './private';
9+
import type { DeployResult } from './types';
910
import type { BootstrapEnvironments, BootstrapOptions, BootstrapResult, EnvironmentBootstrapResult } from '../actions/bootstrap';
1011
import { BootstrapSource } from '../actions/bootstrap';
1112
import { AssetBuildTime, type DeployOptions } from '../actions/deploy';
@@ -322,7 +323,7 @@ export class Toolkit extends CloudAssemblySourceBuilder {
322323
*
323324
* Deploys the selected stacks into an AWS account
324325
*/
325-
public async deploy(cx: ICloudAssemblySource, options: DeployOptions = {}): Promise<void> {
326+
public async deploy(cx: ICloudAssemblySource, options: DeployOptions = {}): Promise<DeployResult> {
326327
const ioHelper = asIoHelper(this.ioHost, 'deploy');
327328
const assembly = await assemblyFromSource(ioHelper, cx);
328329
return this._deploy(assembly, 'deploy', options);
@@ -331,17 +332,21 @@ export class Toolkit extends CloudAssemblySourceBuilder {
331332
/**
332333
* Helper to allow deploy being called as part of the watch action.
333334
*/
334-
private async _deploy(assembly: StackAssembly, action: 'deploy' | 'watch', options: ExtendedDeployOptions = {}) {
335+
private async _deploy(assembly: StackAssembly, action: 'deploy' | 'watch', options: ExtendedDeployOptions = {}): Promise<DeployResult> {
335336
const ioHelper = asIoHelper(this.ioHost, action);
336337
const selectStacks = options.stacks ?? ALL_STACKS;
337338
const synthSpan = await ioHelper.span(SPAN.SYNTH_ASSEMBLY).begin({ stacks: selectStacks });
338339
const stackCollection = await assembly.selectStacksV2(selectStacks);
339340
await this.validateStacksMetadata(stackCollection, ioHelper);
340341
const synthDuration = await synthSpan.end();
341342

343+
const ret: DeployResult = {
344+
stacks: [],
345+
};
346+
342347
if (stackCollection.stackCount === 0) {
343348
await ioHelper.notify(IO.CDK_TOOLKIT_E5001.msg('This app contains no stacks'));
344-
return;
349+
return ret;
345350
}
346351

347352
const deployments = await this.deploymentsForAction('deploy');
@@ -564,6 +569,17 @@ export class Toolkit extends CloudAssemblySourceBuilder {
564569
await ioHelper.notify(IO.CDK_TOOLKIT_I5901.msg(buffer.join('\n')));
565570
}
566571
await ioHelper.notify(IO.CDK_TOOLKIT_I5901.msg(`Stack ARN:\n${deployResult.stackArn}`));
572+
573+
ret.stacks.push({
574+
stackName: stack.stackName,
575+
environment: {
576+
account: stack.environment.account,
577+
region: stack.environment.region,
578+
},
579+
stackArn: deployResult.stackArn,
580+
outputs: deployResult.outputs,
581+
hierarchicalId: stack.hierarchicalId,
582+
});
567583
} catch (e: any) {
568584
// It has to be exactly this string because an integration test tests for
569585
// "bold(stackname) failed: ResourceNotReady: <error>"
@@ -624,6 +640,8 @@ export class Toolkit extends CloudAssemblySourceBuilder {
624640
buildAsset,
625641
publishAsset,
626642
});
643+
644+
return ret;
627645
}
628646

629647
/**
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/**
2+
* Result interface for toolkit.deploy operation
3+
*/
4+
export interface DeployResult {
5+
/**
6+
* Map of deployed stacks by artifact ID.
7+
*/
8+
readonly stacks: DeployedStack[];
9+
}
10+
11+
/**
12+
* Information about a deployed stack
13+
*/
14+
export interface DeployedStack {
15+
/**
16+
* The name of the deployed stack
17+
*
18+
* A stack name is unique inside its environment, but not unique globally.
19+
*/
20+
readonly stackName: string;
21+
22+
/**
23+
* The environment where the stack was deployed
24+
*
25+
* This environment is always concrete, because even though the CDK app's
26+
* stack may be region-agnostic, in order to be deployed it will have to have
27+
* been specialized.
28+
*/
29+
readonly environment: Environment;
30+
31+
/**
32+
* Hierarchical identifier
33+
*
34+
* This uniquely identifies the stack inside the CDK app.
35+
*
36+
* In practice this will be the stack's construct path, but unfortunately the
37+
* Cloud Assembly contract doesn't require or guarantee that.
38+
*/
39+
readonly hierarchicalId: string;
40+
41+
/**
42+
* The ARN of the deployed stack
43+
*/
44+
readonly stackArn: string;
45+
46+
/**
47+
* The outputs of the deployed CloudFormation stack
48+
*/
49+
readonly outputs: { [key: string]: string };
50+
}
51+
52+
/**
53+
* An environment, which is an (account, region) pair
54+
*/
55+
export interface Environment {
56+
/**
57+
* The account number
58+
*/
59+
readonly account: string;
60+
61+
/**
62+
* The region number
63+
*/
64+
readonly region: string;
65+
}
66+
/**
67+
* Result interface for toolkit.deploy operation
68+
*/
69+
export interface DeployResult {
70+
/**
71+
* List of stacks deployed by this operation
72+
*/
73+
readonly stacks: DeployedStack[];
74+
}
75+
76+
/**
77+
* Information about a deployed stack
78+
*/
79+
export interface DeployedStack {
80+
/**
81+
* The name of the deployed stack
82+
*
83+
* A stack name is unique inside its environment, but not unique globally.
84+
*/
85+
readonly stackName: string;
86+
87+
/**
88+
* The environment where the stack was deployed
89+
*
90+
* This environment is always concrete, because even though the CDK app's
91+
* stack may be region-agnostic, in order to be deployed it will have to have
92+
* been specialized.
93+
*/
94+
readonly environment: Environment;
95+
96+
/**
97+
* Hierarchical identifier
98+
*
99+
* This uniquely identifies the stack inside the CDK app.
100+
*
101+
* In practice this will be the stack's construct path, but unfortunately the
102+
* Cloud Assembly contract doesn't require or guarantee that.
103+
*/
104+
readonly hierarchicalId: string;
105+
106+
/**
107+
* The ARN of the deployed stack
108+
*/
109+
readonly stackArn: string;
110+
111+
/**
112+
* The outputs of the deployed CloudFormation stack
113+
*/
114+
readonly outputs: { [key: string]: string };
115+
}
116+
117+
/**
118+
* An environment, which is an (account, region) pair
119+
*/
120+
export interface Environment {
121+
/**
122+
* The account number
123+
*/
124+
readonly account: string;
125+
126+
/**
127+
* The region number
128+
*/
129+
readonly region: string;
130+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import * as cdk from 'aws-cdk-lib/core';
2+
3+
const app = new cdk.App({ autoSynth: false });
4+
const stage = new cdk.Stage(app, 'Stage');
5+
new cdk.Stack(stage, 'Stack1');
6+
7+
app.synth();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"app": "$(npx -c 'which tsx') app.ts"
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"version": "40.0.0",
3+
"files": {
4+
"7f4fb64a3afca08edbdbaa369e00317cb253697278406a83c78e849e89045f9d": {
5+
"source": {
6+
"path": "StageStack130339B27.template.json",
7+
"packaging": "file"
8+
},
9+
"destinations": {
10+
"current_account-current_region": {
11+
"bucketName": "cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}",
12+
"objectKey": "7f4fb64a3afca08edbdbaa369e00317cb253697278406a83c78e849e89045f9d.json",
13+
"assumeRoleArn": "arn:${AWS::Partition}:iam::${AWS::AccountId}:role/cdk-hnb659fds-file-publishing-role-${AWS::AccountId}-${AWS::Region}"
14+
}
15+
}
16+
}
17+
},
18+
"dockerImages": {}
19+
}

0 commit comments

Comments
 (0)