Skip to content

Commit b08571e

Browse files
committed
fix: add consistent profile/region prefixes and improved output filtering for multi-account deployments
1 parent 4cbf612 commit b08571e

11 files changed

Lines changed: 381 additions & 238 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,4 @@ CLAUDE.local.md
4040
temp/
4141
tmp/
4242
IDEAS.local.md
43+
*.local.md

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cli/index.ts

Lines changed: 43 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -99,60 +99,64 @@ async function main() {
9999
process.exit(1);
100100
}
101101

102-
console.log();
103-
const modeMessages = {
104-
diff: "Showing differences",
105-
changeset: "Creating changesets",
106-
execute: "Deploying stacks",
107-
};
108-
logger.info(
109-
modeMessages[args.mode as keyof typeof modeMessages] || "Processing stacks",
110-
);
111-
112102
const results = await deployToAllRegions(regions, args, controller.signal);
113103

114104
displayResults(args, results);
115105
}
116106

117107
function displayHeader(args: ParsedArgs, regions: string[]) {
118-
console.log(`
119-
Multi-Region CDK Deployment
120-
${Object.entries({
121-
Profile: args.profile,
122-
Stack: args.stackPattern,
123-
Regions: regions.join(" "),
124-
Mode: args.mode,
125-
Deployment: args.sequential ? "sequential" : "parallel",
126-
Dependencies: args.includeDeps ? "included" : "excluded",
127-
Timeout: process.env.CDK_TIMEOUT || "not set",
128-
})
129-
.map(([k, v]) => `${logger.dim(k + ":")} ${v}`)
130-
.join("\n")}`);
108+
logger.header("CDKO: Multi-Region Deployment");
109+
console.log();
110+
111+
logger.subheader("Configuration:");
112+
const config = [
113+
` Profile: ${args.profile}`,
114+
` Stack: ${args.stackPattern}`,
115+
` Regions: ${regions.join(", ")}`,
116+
` Mode: ${args.mode}`,
117+
` Deployment: ${args.sequential ? "sequential" : "parallel"}`,
118+
` Dependencies: ${args.includeDeps ? "included" : "excluded"}`,
119+
` Timeout: ${process.env.CDK_TIMEOUT || "not set"}`,
120+
];
121+
console.log(config.join("\n"));
131122
}
132123

133124
function displayResults(args: ParsedArgs, results: DeploymentResult[]) {
134-
const failedRegions = results.filter((r) => !r.success);
125+
const successful = results.filter((r) => r.success);
126+
const failed = results.filter((r) => !r.success);
135127

136-
if (failedRegions.length > 0) {
137-
console.log();
138-
logger.error(`${failedRegions.length} region(s) failed`);
139-
process.exit(1);
128+
console.log();
129+
logger.phase("Summary", "");
130+
131+
const status = failed.length > 0 ? "FAILURE" : "SUCCESS";
132+
133+
console.log(
134+
` Status: ${failed.length > 0 ? logger.dim("❌") : logger.dim("✅")} ${status}`,
135+
);
136+
console.log(` Stacks processed: ${results.length}`);
137+
console.log(` Successful: ${successful.length}`);
138+
139+
if (args.mode === "diff") {
140+
console.log(` With changes: ${successful.length}`);
140141
}
141142

142-
console.log();
143+
if (failed.length > 0) {
144+
console.log(` Failed: ${failed.length}`);
145+
}
143146

144-
if (args.dryRun) {
145-
logger.success("Dry run completed - no actual changes made");
146-
} else if (args.mode === "changeset") {
147-
logger.success("Changesets created for review in CloudFormation console");
148-
logger.info("Execute changesets manually after review");
149-
} else if (args.mode === "execute") {
150-
const totalDuration = results
147+
if (successful.length > 0 && successful.some((r) => r.duration)) {
148+
const totalDuration = successful
151149
.filter((r) => r.duration)
152150
.reduce((sum, r) => sum + parseFloat(r.duration!), 0);
153-
logger.success(`All deployments completed in ${totalDuration.toFixed(1)}s`);
154-
} else {
155-
logger.success("Differences shown for all regions");
151+
152+
const minutes = Math.floor(totalDuration / 60);
153+
const seconds = Math.floor(totalDuration % 60);
154+
const timeStr = minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
155+
console.log(` Total time: ${timeStr}`);
156+
}
157+
158+
if (failed.length > 0) {
159+
process.exit(1);
156160
}
157161
}
158162

src/core/account-manager.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ export class AccountManager {
7272
return patterns;
7373
}
7474

75-
logger.info(
76-
`Found ${
77-
matchedProfiles.length
78-
} profile(s) matching pattern: ${matchedProfiles.join(", ")}`,
79-
);
75+
if (matchedProfiles.length > 1) {
76+
logger.info(
77+
`Found ${matchedProfiles.length} profile(s) matching pattern: ${matchedProfiles.join(", ")}`,
78+
);
79+
}
8080
return matchedProfiles;
8181
}
8282

@@ -86,8 +86,6 @@ export class AccountManager {
8686
}
8787

8888
try {
89-
logger.info(`Discovering account for profile: ${profile}`);
90-
9189
const result =
9290
await $`aws sts get-caller-identity --profile ${profile} --output json`.quiet();
9391
const identity = JSON.parse(result.stdout);
@@ -100,7 +98,6 @@ export class AccountManager {
10098
};
10199

102100
this.accountCache.set(profile, accountInfo);
103-
logger.info(`Profile ${profile} → Account ${identity.Account}`);
104101

105102
return accountInfo;
106103
} catch (error) {
@@ -120,8 +117,6 @@ export class AccountManager {
120117
}
121118

122119
async getMultiAccountInfo(profiles: string[]): Promise<AccountInfo[]> {
123-
logger.info(`Discovering accounts for ${profiles.length} profile(s)...`);
124-
125120
const accountPromises = profiles.map((profile: string) =>
126121
this.getAccountInfo(profile).catch(
127122
(error): FailedAccountInfo => ({

src/core/cloud-assembly.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,11 @@ export class CloudAssemblyManager {
2828

2929
try {
3030
if (existsSync(cloudAssemblyPath)) {
31-
logger.info(`Cleaning existing cloud assembly at ${cloudAssemblyPath}`);
3231
rmSync(cloudAssemblyPath, { recursive: true, force: true });
3332
}
3433

3534
mkdirSync(cloudAssemblyPath, { recursive: true });
3635

37-
logger.info("Synthesizing cloud assembly...");
38-
3936
const cdkArgs = ["synth"];
4037

4138
if (process.env.CDK_CLI_NOTICES !== "true") {
@@ -55,7 +52,6 @@ export class CloudAssemblyManager {
5552
const result = await $({ quiet: true })`cdk ${cdkArgs}`;
5653

5754
if (result.exitCode === 0) {
58-
logger.success(`Cloud assembly synthesized to ${cloudAssemblyPath}`);
5955
this.cloudAssemblyPath = cloudAssemblyPath;
6056
return cloudAssemblyPath;
6157
} else {

0 commit comments

Comments
 (0)