@devramps/cli 0.1.3 → 0.1.5
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/dist/index.js +226 -157
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -74,54 +74,85 @@ var CloudFormationError = class extends DevRampsError {
|
|
|
74
74
|
// src/utils/logger.ts
|
|
75
75
|
import chalk from "chalk";
|
|
76
76
|
var verboseMode = false;
|
|
77
|
-
var
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
78
|
+
function getStackKey(stackName, accountId, region) {
|
|
79
|
+
return `${stackName}:${accountId}:${region}`;
|
|
80
|
+
}
|
|
81
|
+
var MultiStackProgress = class {
|
|
82
|
+
stacks = /* @__PURE__ */ new Map();
|
|
83
|
+
stackOrder = [];
|
|
82
84
|
lastLineCount = 0;
|
|
83
|
-
inProgressResources = /* @__PURE__ */ new Map();
|
|
84
85
|
isTTY;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
spinnerFrame = 0;
|
|
87
|
+
spinnerInterval = null;
|
|
88
|
+
barWidth = 20;
|
|
89
|
+
constructor() {
|
|
88
90
|
this.isTTY = process.stdout.isTTY ?? false;
|
|
89
|
-
this.
|
|
91
|
+
if (this.isTTY) {
|
|
92
|
+
this.spinnerInterval = setInterval(() => {
|
|
93
|
+
this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER_FRAMES.length;
|
|
94
|
+
this.render();
|
|
95
|
+
}, 80);
|
|
96
|
+
}
|
|
90
97
|
}
|
|
91
98
|
/**
|
|
92
|
-
*
|
|
99
|
+
* Register a stack to track
|
|
93
100
|
*/
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (
|
|
97
|
-
|
|
98
|
-
this.inProgressResources.set(resourceStatus.logicalId, resourceStatus);
|
|
99
|
-
} else {
|
|
100
|
-
this.inProgressResources.delete(resourceStatus.logicalId);
|
|
101
|
-
}
|
|
101
|
+
addStack(stackName, accountId, region, totalResources) {
|
|
102
|
+
const key = getStackKey(stackName, accountId, region);
|
|
103
|
+
if (this.stacks.has(key)) {
|
|
104
|
+
return;
|
|
102
105
|
}
|
|
106
|
+
this.stacks.set(key, {
|
|
107
|
+
stackName,
|
|
108
|
+
accountId,
|
|
109
|
+
region,
|
|
110
|
+
completed: 0,
|
|
111
|
+
total: totalResources,
|
|
112
|
+
status: "pending"
|
|
113
|
+
});
|
|
114
|
+
this.stackOrder.push(key);
|
|
103
115
|
this.render();
|
|
104
116
|
}
|
|
105
117
|
/**
|
|
106
|
-
*
|
|
118
|
+
* Update a stack's progress
|
|
107
119
|
*/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
120
|
+
updateStack(stackName, accountId, region, completed, status, latestEvent, latestResourceId) {
|
|
121
|
+
const key = getStackKey(stackName, accountId, region);
|
|
122
|
+
const stack = this.stacks.get(key);
|
|
123
|
+
if (stack) {
|
|
124
|
+
stack.completed = completed;
|
|
125
|
+
stack.status = status;
|
|
126
|
+
if (latestEvent) stack.latestEvent = latestEvent;
|
|
127
|
+
if (latestResourceId) stack.latestResourceId = latestResourceId;
|
|
128
|
+
this.render();
|
|
129
|
+
}
|
|
115
130
|
}
|
|
116
131
|
/**
|
|
117
|
-
* Mark a
|
|
132
|
+
* Mark a stack as started
|
|
118
133
|
*/
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
this.
|
|
134
|
+
startStack(stackName, accountId, region) {
|
|
135
|
+
const key = getStackKey(stackName, accountId, region);
|
|
136
|
+
const stack = this.stacks.get(key);
|
|
137
|
+
if (stack) {
|
|
138
|
+
stack.status = "in_progress";
|
|
139
|
+
this.render();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Mark a stack as complete
|
|
144
|
+
*/
|
|
145
|
+
completeStack(stackName, accountId, region, success2) {
|
|
146
|
+
const key = getStackKey(stackName, accountId, region);
|
|
147
|
+
const stack = this.stacks.get(key);
|
|
148
|
+
if (stack) {
|
|
149
|
+
stack.status = success2 ? "complete" : "failed";
|
|
150
|
+
stack.completed = success2 ? stack.total : stack.completed;
|
|
151
|
+
this.render();
|
|
152
|
+
}
|
|
122
153
|
}
|
|
123
154
|
/**
|
|
124
|
-
* Clear the
|
|
155
|
+
* Clear the display
|
|
125
156
|
*/
|
|
126
157
|
clear() {
|
|
127
158
|
if (!this.isTTY) return;
|
|
@@ -131,56 +162,108 @@ var ProgressBar = class {
|
|
|
131
162
|
this.lastLineCount = 0;
|
|
132
163
|
}
|
|
133
164
|
/**
|
|
134
|
-
* Finish
|
|
165
|
+
* Finish and stop updates
|
|
135
166
|
*/
|
|
136
167
|
finish() {
|
|
168
|
+
if (this.spinnerInterval) {
|
|
169
|
+
clearInterval(this.spinnerInterval);
|
|
170
|
+
this.spinnerInterval = null;
|
|
171
|
+
}
|
|
137
172
|
this.clear();
|
|
138
|
-
this.
|
|
139
|
-
|
|
173
|
+
this.renderFinal();
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Render final state (no clearing, just print)
|
|
177
|
+
*/
|
|
178
|
+
renderFinal() {
|
|
179
|
+
for (const key of this.stackOrder) {
|
|
180
|
+
const stack = this.stacks.get(key);
|
|
181
|
+
if (!stack) continue;
|
|
182
|
+
console.log(this.formatStackLine(stack, false));
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Format a single stack line
|
|
187
|
+
*/
|
|
188
|
+
formatStackLine(stack, withSpinner) {
|
|
189
|
+
const { accountId, region, stackName, completed, total, status, latestEvent, latestResourceId } = stack;
|
|
190
|
+
let statusIndicator;
|
|
191
|
+
let colorFn;
|
|
192
|
+
switch (status) {
|
|
193
|
+
case "complete":
|
|
194
|
+
statusIndicator = "\u2714";
|
|
195
|
+
colorFn = chalk.green;
|
|
196
|
+
break;
|
|
197
|
+
case "failed":
|
|
198
|
+
case "rollback":
|
|
199
|
+
statusIndicator = "\u2716";
|
|
200
|
+
colorFn = chalk.red;
|
|
201
|
+
break;
|
|
202
|
+
case "in_progress":
|
|
203
|
+
statusIndicator = withSpinner ? SPINNER_FRAMES[this.spinnerFrame] : "\u22EF";
|
|
204
|
+
colorFn = chalk.blue;
|
|
205
|
+
break;
|
|
206
|
+
default:
|
|
207
|
+
statusIndicator = "\u25CB";
|
|
208
|
+
colorFn = chalk.gray;
|
|
209
|
+
}
|
|
210
|
+
const percentage = total > 0 ? completed / total : 0;
|
|
140
211
|
const filled = Math.round(this.barWidth * percentage);
|
|
141
212
|
const empty = this.barWidth - filled;
|
|
142
|
-
const bar =
|
|
143
|
-
const
|
|
144
|
-
const
|
|
145
|
-
|
|
213
|
+
const bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
|
|
214
|
+
const shortAccount = accountId.slice(-4);
|
|
215
|
+
const accountLabel = `[...${shortAccount}/${region}]`;
|
|
216
|
+
const countLabel = `(${completed}/${total})`;
|
|
217
|
+
let eventLabel = "";
|
|
218
|
+
if (status === "in_progress" && latestEvent && latestResourceId) {
|
|
219
|
+
const shortStatus = latestEvent.replace("CREATE_", "").replace("UPDATE_", "").replace("DELETE_", "");
|
|
220
|
+
const resourceIdTrunc = latestResourceId.length > 15 ? latestResourceId.slice(0, 12) + "..." : latestResourceId;
|
|
221
|
+
eventLabel = ` ${shortStatus} ${resourceIdTrunc}`;
|
|
222
|
+
}
|
|
223
|
+
const maxStackNameLen = 40;
|
|
224
|
+
const displayName = stackName.length > maxStackNameLen ? "..." + stackName.slice(-(maxStackNameLen - 3)) : stackName;
|
|
225
|
+
const line = `${statusIndicator} ${accountLabel} ${displayName} [${bar}] ${countLabel}${eventLabel}`;
|
|
226
|
+
return colorFn(line);
|
|
146
227
|
}
|
|
147
228
|
/**
|
|
148
|
-
* Render
|
|
229
|
+
* Render all stack progress bars
|
|
149
230
|
*/
|
|
150
231
|
render() {
|
|
151
|
-
this.
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
}
|
|
167
|
-
const remaining = this.inProgressResources.size - inProgress.length;
|
|
168
|
-
if (remaining > 0) {
|
|
169
|
-
lines.push(chalk.gray(` ... and ${remaining} more in progress`));
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
if (this.isTTY) {
|
|
173
|
-
for (const line of lines) {
|
|
174
|
-
process.stdout.write(line + "\n");
|
|
175
|
-
}
|
|
176
|
-
this.lastLineCount = lines.length;
|
|
177
|
-
} else {
|
|
178
|
-
if (this.completed === 0 || this.completed === this.total) {
|
|
179
|
-
console.log(lines[0]);
|
|
232
|
+
if (this.isRendering) return;
|
|
233
|
+
this.isRendering = true;
|
|
234
|
+
try {
|
|
235
|
+
if (this.isTTY) {
|
|
236
|
+
this.clear();
|
|
237
|
+
const lines = [];
|
|
238
|
+
for (const key of this.stackOrder) {
|
|
239
|
+
const stack = this.stacks.get(key);
|
|
240
|
+
if (!stack) continue;
|
|
241
|
+
lines.push(this.formatStackLine(stack, true));
|
|
242
|
+
}
|
|
243
|
+
for (const line of lines) {
|
|
244
|
+
process.stdout.write(line + "\n");
|
|
245
|
+
}
|
|
246
|
+
this.lastLineCount = lines.length;
|
|
180
247
|
}
|
|
248
|
+
} finally {
|
|
249
|
+
this.isRendering = false;
|
|
181
250
|
}
|
|
182
251
|
}
|
|
252
|
+
isRendering = false;
|
|
183
253
|
};
|
|
254
|
+
var globalProgress = null;
|
|
255
|
+
function getMultiStackProgress() {
|
|
256
|
+
if (!globalProgress) {
|
|
257
|
+
globalProgress = new MultiStackProgress();
|
|
258
|
+
}
|
|
259
|
+
return globalProgress;
|
|
260
|
+
}
|
|
261
|
+
function clearMultiStackProgress() {
|
|
262
|
+
if (globalProgress) {
|
|
263
|
+
globalProgress.finish();
|
|
264
|
+
globalProgress = null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
184
267
|
function setVerbose(enabled) {
|
|
185
268
|
verboseMode = enabled;
|
|
186
269
|
}
|
|
@@ -241,18 +324,6 @@ function table(rows) {
|
|
|
241
324
|
function newline() {
|
|
242
325
|
console.log();
|
|
243
326
|
}
|
|
244
|
-
function resourceProgress(stackName, resourceId, resourceType, status, reason) {
|
|
245
|
-
const stackLabel = chalk.cyan(`[${stackName}]`);
|
|
246
|
-
const typeLabel = chalk.gray(resourceType);
|
|
247
|
-
if (status === "in_progress") {
|
|
248
|
-
console.log(`${stackLabel} ${chalk.yellow("\u22EF")} ${resourceId} ${typeLabel}`);
|
|
249
|
-
} else if (status === "complete") {
|
|
250
|
-
console.log(`${stackLabel} ${chalk.green("\u2714")} ${resourceId} ${typeLabel}`);
|
|
251
|
-
} else if (status === "failed") {
|
|
252
|
-
const reasonText = reason ? ` - ${reason}` : "";
|
|
253
|
-
console.log(`${stackLabel} ${chalk.red("\u2716")} ${resourceId} ${typeLabel}${reasonText}`);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
327
|
|
|
257
328
|
// src/aws/credentials.ts
|
|
258
329
|
var DEFAULT_REGION = "us-east-1";
|
|
@@ -356,10 +427,12 @@ import {
|
|
|
356
427
|
DescribeStackEventsCommand,
|
|
357
428
|
CreateStackCommand,
|
|
358
429
|
UpdateStackCommand,
|
|
430
|
+
DeleteStackCommand,
|
|
359
431
|
CreateChangeSetCommand,
|
|
360
432
|
DescribeChangeSetCommand,
|
|
361
433
|
DeleteChangeSetCommand,
|
|
362
434
|
waitUntilChangeSetCreateComplete,
|
|
435
|
+
waitUntilStackDeleteComplete,
|
|
363
436
|
ChangeSetType
|
|
364
437
|
} from "@aws-sdk/client-cloudformation";
|
|
365
438
|
async function getStackStatus(stackName, credentials, region) {
|
|
@@ -499,13 +572,15 @@ function isResourceComplete(status) {
|
|
|
499
572
|
if (!status) return false;
|
|
500
573
|
return status.includes("_COMPLETE") && !status.includes("ROLLBACK");
|
|
501
574
|
}
|
|
502
|
-
async function waitForStackWithProgress(client, stackName, operationStartTime, totalResources, maxWaitTime = 600
|
|
575
|
+
async function waitForStackWithProgress(client, stackName, accountId, region, operationStartTime, totalResources, maxWaitTime = 600) {
|
|
503
576
|
const seenEventIds = /* @__PURE__ */ new Set();
|
|
504
577
|
const completedResources = /* @__PURE__ */ new Set();
|
|
505
|
-
const inProgressResources = /* @__PURE__ */ new Map();
|
|
506
578
|
const startTime = Date.now();
|
|
507
|
-
const pollInterval =
|
|
508
|
-
const
|
|
579
|
+
const pollInterval = 2e3;
|
|
580
|
+
const progress = getMultiStackProgress();
|
|
581
|
+
let latestEvent = "";
|
|
582
|
+
let latestResourceId = "";
|
|
583
|
+
verbose(`[${stackName}] Starting to wait for stack operation...`);
|
|
509
584
|
try {
|
|
510
585
|
while (true) {
|
|
511
586
|
if (Date.now() - startTime > maxWaitTime * 1e3) {
|
|
@@ -518,6 +593,8 @@ async function waitForStackWithProgress(client, stackName, operationStartTime, t
|
|
|
518
593
|
if (!stack) {
|
|
519
594
|
throw new Error(`Stack ${stackName} not found`);
|
|
520
595
|
}
|
|
596
|
+
const currentStatus = stack.StackStatus || "";
|
|
597
|
+
verbose(`[${stackName}] Current status: ${currentStatus}`);
|
|
521
598
|
const eventsResponse = await client.send(
|
|
522
599
|
new DescribeStackEventsCommand({ StackName: stackName })
|
|
523
600
|
);
|
|
@@ -531,56 +608,28 @@ async function waitForStackWithProgress(client, stackName, operationStartTime, t
|
|
|
531
608
|
seenEventIds.add(event.EventId);
|
|
532
609
|
}
|
|
533
610
|
const logicalId = event.LogicalResourceId;
|
|
534
|
-
const resourceType = event.ResourceType || "Unknown";
|
|
535
611
|
const status = event.ResourceStatus || "";
|
|
536
612
|
if (logicalId && logicalId !== stackName) {
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
logicalId,
|
|
542
|
-
resourceType,
|
|
543
|
-
status: "in_progress"
|
|
544
|
-
};
|
|
545
|
-
progressBar.update(completedResources.size, resourceStatus);
|
|
546
|
-
} else {
|
|
547
|
-
resourceProgress(stackName, logicalId, resourceType, "in_progress");
|
|
548
|
-
}
|
|
549
|
-
} else if (isResourceComplete(status)) {
|
|
613
|
+
latestEvent = status;
|
|
614
|
+
latestResourceId = logicalId;
|
|
615
|
+
verbose(`[${stackName}] Resource ${logicalId}: ${status}`);
|
|
616
|
+
if (isResourceComplete(status)) {
|
|
550
617
|
completedResources.add(logicalId);
|
|
551
|
-
inProgressResources.delete(logicalId);
|
|
552
|
-
if (progressBar) {
|
|
553
|
-
const resourceStatus = {
|
|
554
|
-
logicalId,
|
|
555
|
-
resourceType,
|
|
556
|
-
status: "complete"
|
|
557
|
-
};
|
|
558
|
-
progressBar.update(completedResources.size, resourceStatus);
|
|
559
|
-
} else {
|
|
560
|
-
resourceProgress(stackName, logicalId, resourceType, "complete");
|
|
561
|
-
}
|
|
562
|
-
} else if (status.includes("FAILED") || status.includes("ROLLBACK")) {
|
|
563
|
-
inProgressResources.delete(logicalId);
|
|
564
|
-
if (progressBar) {
|
|
565
|
-
const resourceStatus = {
|
|
566
|
-
logicalId,
|
|
567
|
-
resourceType,
|
|
568
|
-
status: "failed",
|
|
569
|
-
reason: event.ResourceStatusReason
|
|
570
|
-
};
|
|
571
|
-
progressBar.update(completedResources.size, resourceStatus);
|
|
572
|
-
} else {
|
|
573
|
-
resourceProgress(stackName, logicalId, resourceType, "failed", event.ResourceStatusReason);
|
|
574
|
-
}
|
|
575
618
|
}
|
|
576
619
|
}
|
|
577
620
|
}
|
|
578
|
-
|
|
621
|
+
let displayStatus = "in_progress";
|
|
622
|
+
if (currentStatus.includes("ROLLBACK")) {
|
|
623
|
+
displayStatus = "rollback";
|
|
624
|
+
} else if (currentStatus.includes("FAILED")) {
|
|
625
|
+
displayStatus = "failed";
|
|
626
|
+
}
|
|
627
|
+
progress.updateStack(stackName, accountId, region, completedResources.size, displayStatus, latestEvent, latestResourceId);
|
|
579
628
|
if (TERMINAL_STATES.has(currentStatus)) {
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
}
|
|
583
|
-
if (
|
|
629
|
+
const success2 = SUCCESS_STATES.has(currentStatus);
|
|
630
|
+
progress.completeStack(stackName, accountId, region, success2);
|
|
631
|
+
verbose(`[${stackName}] Reached terminal state: ${currentStatus} (success: ${success2})`);
|
|
632
|
+
if (success2) {
|
|
584
633
|
return;
|
|
585
634
|
}
|
|
586
635
|
throw new Error(`Stack operation failed with status: ${currentStatus}`);
|
|
@@ -588,39 +637,57 @@ async function waitForStackWithProgress(client, stackName, operationStartTime, t
|
|
|
588
637
|
await new Promise((resolve) => setTimeout(resolve, pollInterval));
|
|
589
638
|
}
|
|
590
639
|
} catch (error2) {
|
|
591
|
-
|
|
592
|
-
progressBar.finish();
|
|
593
|
-
}
|
|
640
|
+
progress.completeStack(stackName, accountId, region, false);
|
|
594
641
|
throw error2;
|
|
595
642
|
}
|
|
596
643
|
}
|
|
597
644
|
async function deployStack(options) {
|
|
598
|
-
const { stackName, template, accountId, region, credentials
|
|
645
|
+
const { stackName, template, accountId, region = "us-east-1", credentials } = options;
|
|
599
646
|
const client = new CloudFormationClient({
|
|
600
647
|
credentials,
|
|
601
648
|
region
|
|
602
649
|
});
|
|
603
650
|
const templateBody = JSON.stringify(template);
|
|
604
651
|
const resourceCount = Object.keys(template.Resources || {}).length;
|
|
652
|
+
const progress = getMultiStackProgress();
|
|
653
|
+
progress.startStack(stackName, accountId, region);
|
|
605
654
|
try {
|
|
606
655
|
const stackStatus = await getStackStatus(stackName, credentials, region);
|
|
607
|
-
if (stackStatus.exists) {
|
|
656
|
+
if (stackStatus.exists && stackStatus.status === "ROLLBACK_COMPLETE") {
|
|
657
|
+
verbose(`Stack ${stackName} is in ROLLBACK_COMPLETE state, deleting before recreating...`);
|
|
658
|
+
await deleteStack(client, stackName);
|
|
659
|
+
verbose(`Stack ${stackName} deleted, now creating...`);
|
|
660
|
+
await createStack(client, stackName, accountId, region, templateBody, resourceCount);
|
|
661
|
+
} else if (stackStatus.exists) {
|
|
608
662
|
verbose(`Stack ${stackName} exists, updating...`);
|
|
609
|
-
await updateStack(client, stackName,
|
|
663
|
+
await updateStack(client, stackName, accountId, region, templateBody, resourceCount);
|
|
610
664
|
} else {
|
|
611
665
|
verbose(`Stack ${stackName} does not exist, creating...`);
|
|
612
|
-
await createStack(client, stackName,
|
|
666
|
+
await createStack(client, stackName, accountId, region, templateBody, resourceCount);
|
|
613
667
|
}
|
|
614
668
|
} catch (error2) {
|
|
615
669
|
const errorMessage = error2 instanceof Error ? error2.message : String(error2);
|
|
616
670
|
if (errorMessage.includes("No updates are to be performed")) {
|
|
617
671
|
verbose(`Stack ${stackName} is already up to date`);
|
|
672
|
+
progress.completeStack(stackName, accountId, region, true);
|
|
618
673
|
return;
|
|
619
674
|
}
|
|
675
|
+
progress.completeStack(stackName, accountId, region, false);
|
|
620
676
|
throw new CloudFormationError(stackName, accountId, errorMessage);
|
|
621
677
|
}
|
|
622
678
|
}
|
|
623
|
-
async function
|
|
679
|
+
async function deleteStack(client, stackName) {
|
|
680
|
+
await client.send(
|
|
681
|
+
new DeleteStackCommand({
|
|
682
|
+
StackName: stackName
|
|
683
|
+
})
|
|
684
|
+
);
|
|
685
|
+
await waitUntilStackDeleteComplete(
|
|
686
|
+
{ client, maxWaitTime: 300 },
|
|
687
|
+
{ StackName: stackName }
|
|
688
|
+
);
|
|
689
|
+
}
|
|
690
|
+
async function createStack(client, stackName, accountId, region, templateBody, resourceCount) {
|
|
624
691
|
const operationStartTime = /* @__PURE__ */ new Date();
|
|
625
692
|
await client.send(
|
|
626
693
|
new CreateStackCommand({
|
|
@@ -633,11 +700,9 @@ async function createStack(client, stackName, templateBody, accountId, resourceC
|
|
|
633
700
|
]
|
|
634
701
|
})
|
|
635
702
|
);
|
|
636
|
-
|
|
637
|
-
await waitForStackWithProgress(client, stackName, operationStartTime, resourceCount, 600, showProgress);
|
|
638
|
-
success(`Stack ${stackName} created successfully in account ${accountId}`);
|
|
703
|
+
await waitForStackWithProgress(client, stackName, accountId, region, operationStartTime, resourceCount);
|
|
639
704
|
}
|
|
640
|
-
async function updateStack(client, stackName,
|
|
705
|
+
async function updateStack(client, stackName, accountId, region, templateBody, resourceCount) {
|
|
641
706
|
const operationStartTime = /* @__PURE__ */ new Date();
|
|
642
707
|
await client.send(
|
|
643
708
|
new UpdateStackCommand({
|
|
@@ -646,9 +711,7 @@ async function updateStack(client, stackName, templateBody, accountId, resourceC
|
|
|
646
711
|
Capabilities: ["CAPABILITY_NAMED_IAM"]
|
|
647
712
|
})
|
|
648
713
|
);
|
|
649
|
-
|
|
650
|
-
await waitForStackWithProgress(client, stackName, operationStartTime, resourceCount, 600, showProgress);
|
|
651
|
-
success(`Stack ${stackName} updated successfully in account ${accountId}`);
|
|
714
|
+
await waitForStackWithProgress(client, stackName, accountId, region, operationStartTime, resourceCount);
|
|
652
715
|
}
|
|
653
716
|
async function readExistingStack(stackName, accountId, region, credentials) {
|
|
654
717
|
const client = new CloudFormationClient({
|
|
@@ -2675,6 +2738,19 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
2675
2738
|
header("Deploying All Stacks");
|
|
2676
2739
|
info(`Deploying ${totalStacks} stack(s) in parallel...`);
|
|
2677
2740
|
newline();
|
|
2741
|
+
const progress = getMultiStackProgress();
|
|
2742
|
+
progress.addStack(plan.orgStack.stackName, plan.orgStack.accountId, plan.orgStack.region, 5);
|
|
2743
|
+
for (const stack of plan.pipelineStacks) {
|
|
2744
|
+
const resourceCount = stack.dockerArtifacts.length + stack.bundleArtifacts.length;
|
|
2745
|
+
progress.addStack(stack.stackName, stack.accountId, stack.region, Math.max(resourceCount, 1));
|
|
2746
|
+
}
|
|
2747
|
+
for (const stack of plan.accountStacks) {
|
|
2748
|
+
progress.addStack(stack.stackName, stack.accountId, stack.region, 1);
|
|
2749
|
+
}
|
|
2750
|
+
for (const stack of plan.stageStacks) {
|
|
2751
|
+
const resourceCount = stack.dockerArtifacts.length + stack.bundleArtifacts.length + 2;
|
|
2752
|
+
progress.addStack(stack.stackName, stack.accountId, stack.region, resourceCount);
|
|
2753
|
+
}
|
|
2678
2754
|
const orgPromise = (async () => {
|
|
2679
2755
|
try {
|
|
2680
2756
|
await deployOrgStack(plan, pipelines, authData, currentAccountId, options);
|
|
@@ -2702,10 +2778,10 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
2702
2778
|
const accountPromises = plan.accountStacks.map(async (stack) => {
|
|
2703
2779
|
try {
|
|
2704
2780
|
await deployAccountStack(stack, currentAccountId, options);
|
|
2705
|
-
return { stack:
|
|
2781
|
+
return { stack: stack.stackName, success: true };
|
|
2706
2782
|
} catch (error2) {
|
|
2707
2783
|
return {
|
|
2708
|
-
stack:
|
|
2784
|
+
stack: stack.stackName,
|
|
2709
2785
|
success: false,
|
|
2710
2786
|
error: error2 instanceof Error ? error2.message : String(error2)
|
|
2711
2787
|
};
|
|
@@ -2729,6 +2805,7 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
|
|
|
2729
2805
|
...accountPromises,
|
|
2730
2806
|
...stagePromises
|
|
2731
2807
|
]);
|
|
2808
|
+
clearMultiStackProgress();
|
|
2732
2809
|
newline();
|
|
2733
2810
|
for (const result of allResults) {
|
|
2734
2811
|
if (result.success) {
|
|
@@ -2784,9 +2861,7 @@ async function deployOrgStack(plan, pipelines, authData, currentAccountId, optio
|
|
|
2784
2861
|
template,
|
|
2785
2862
|
accountId: cicdAccountId,
|
|
2786
2863
|
region: cicdRegion,
|
|
2787
|
-
credentials
|
|
2788
|
-
showProgress: false
|
|
2789
|
-
// Disable progress bar for parallel deployment
|
|
2864
|
+
credentials
|
|
2790
2865
|
};
|
|
2791
2866
|
await previewStackChanges(deployOptions);
|
|
2792
2867
|
await deployStack(deployOptions);
|
|
@@ -2809,9 +2884,7 @@ async function deployPipelineStack(stack, authData, currentAccountId, options) {
|
|
|
2809
2884
|
template,
|
|
2810
2885
|
accountId: cicdAccountId,
|
|
2811
2886
|
region: cicdRegion,
|
|
2812
|
-
credentials
|
|
2813
|
-
showProgress: false
|
|
2814
|
-
// Disable progress bar for parallel deployment
|
|
2887
|
+
credentials
|
|
2815
2888
|
};
|
|
2816
2889
|
await previewStackChanges(deployOptions);
|
|
2817
2890
|
await deployStack(deployOptions);
|
|
@@ -2828,9 +2901,7 @@ async function deployAccountStack(stack, currentAccountId, options) {
|
|
|
2828
2901
|
template,
|
|
2829
2902
|
accountId: stack.accountId,
|
|
2830
2903
|
region: stack.region,
|
|
2831
|
-
credentials
|
|
2832
|
-
showProgress: false
|
|
2833
|
-
// Disable progress bar for parallel deployment
|
|
2904
|
+
credentials
|
|
2834
2905
|
};
|
|
2835
2906
|
await previewStackChanges(deployOptions);
|
|
2836
2907
|
await deployStack(deployOptions);
|
|
@@ -2856,9 +2927,7 @@ async function deployStageStack(stack, authData, currentAccountId, options) {
|
|
|
2856
2927
|
template,
|
|
2857
2928
|
accountId: stack.accountId,
|
|
2858
2929
|
region: stack.region,
|
|
2859
|
-
credentials
|
|
2860
|
-
showProgress: false
|
|
2861
|
-
// Disable progress bar for parallel deployment
|
|
2930
|
+
credentials
|
|
2862
2931
|
};
|
|
2863
2932
|
await previewStackChanges(deployOptions);
|
|
2864
2933
|
await deployStack(deployOptions);
|