@devramps/cli 0.1.7 → 0.1.8

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.
Files changed (2) hide show
  1. package/dist/index.js +50 -16
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -90,6 +90,8 @@ var MultiStackProgress = class {
90
90
  hasRenderedOnce = false;
91
91
  useAltScreen = true;
92
92
  // Use alternate screen buffer for clean display
93
+ maxStackNameLen = 40;
94
+ // Will be calculated dynamically
93
95
  constructor() {
94
96
  this.isTTY = process.stdout.isTTY ?? false;
95
97
  }
@@ -97,6 +99,11 @@ var MultiStackProgress = class {
97
99
  * Start the progress display (call after all stacks are registered)
98
100
  */
99
101
  start() {
102
+ this.maxStackNameLen = Math.max(
103
+ ...Array.from(this.stacks.values()).map((s) => s.stackName.length),
104
+ 20
105
+ // minimum width
106
+ );
100
107
  if (this.isTTY) {
101
108
  if (this.useAltScreen) {
102
109
  process.stdout.write("\x1B[?1049h");
@@ -114,13 +121,14 @@ var MultiStackProgress = class {
114
121
  /**
115
122
  * Register a stack to track
116
123
  */
117
- addStack(stackName, accountId, region, totalResources) {
124
+ addStack(stackName, stackType, accountId, region, totalResources) {
118
125
  const key = getStackKey(stackName, accountId, region);
119
126
  if (this.stacks.has(key)) {
120
127
  return;
121
128
  }
122
129
  this.stacks.set(key, {
123
130
  stackName,
131
+ stackType,
124
132
  accountId,
125
133
  region,
126
134
  completed: 0,
@@ -212,11 +220,26 @@ var MultiStackProgress = class {
212
220
  console.log(this.formatStackLine(stack, false));
213
221
  }
214
222
  }
223
+ /**
224
+ * Get a short label for stack type
225
+ */
226
+ getTypeLabel(stackType) {
227
+ switch (stackType) {
228
+ case "org":
229
+ return "ORG";
230
+ case "pipeline":
231
+ return "PIPE";
232
+ case "account":
233
+ return "ACCT";
234
+ case "stage":
235
+ return "STAGE";
236
+ }
237
+ }
215
238
  /**
216
239
  * Format a single stack line
217
240
  */
218
241
  formatStackLine(stack, withSpinner) {
219
- const { accountId, region, stackName, completed, total, status, cfnStatus, latestResourceId, failureReason } = stack;
242
+ const { accountId, region, stackName, stackType, completed, total, status, cfnStatus, latestResourceId, failureReason } = stack;
220
243
  let statusIndicator;
221
244
  let colorFn;
222
245
  switch (status) {
@@ -241,22 +264,28 @@ var MultiStackProgress = class {
241
264
  const filled = Math.round(this.barWidth * percentage);
242
265
  const empty = this.barWidth - filled;
243
266
  const bar = "\u2588".repeat(filled) + "\u2591".repeat(empty);
244
- const accountLabel = `${accountId} ${region}`;
267
+ const typeLabel = this.getTypeLabel(stackType).padEnd(5);
268
+ const accountLabel = `${accountId} ${region.padEnd(12)}`;
245
269
  const countLabel = `${completed}/${total}`;
246
- const maxStackNameLen = 35;
247
- const displayName = stackName.length > maxStackNameLen ? stackName.slice(0, maxStackNameLen - 3) + "..." : stackName.padEnd(maxStackNameLen);
270
+ const displayName = stackName.padEnd(this.maxStackNameLen);
248
271
  let rightInfo = "";
249
- if (status === "failed" && failureReason) {
250
- const maxLen = 40;
251
- rightInfo = failureReason.length > maxLen ? failureReason.slice(0, maxLen - 3) + "..." : failureReason;
272
+ if (status === "failed" || status === "rollback") {
273
+ const statusText = cfnStatus || "FAILED";
274
+ if (failureReason && failureReason !== cfnStatus) {
275
+ const maxLen = 50;
276
+ const fullReason = `${statusText}: ${failureReason}`;
277
+ rightInfo = fullReason.length > maxLen ? fullReason.slice(0, maxLen - 3) + "..." : fullReason;
278
+ } else {
279
+ rightInfo = statusText;
280
+ }
252
281
  } else if (status === "in_progress") {
253
282
  const cfnStatusDisplay = cfnStatus || "DEPLOYING";
254
- const resourceDisplay = latestResourceId ? latestResourceId.length > 20 ? latestResourceId.slice(0, 17) + "..." : latestResourceId : "";
283
+ const resourceDisplay = latestResourceId ? latestResourceId.length > 25 ? latestResourceId.slice(0, 22) + "..." : latestResourceId : "";
255
284
  rightInfo = resourceDisplay ? `${cfnStatusDisplay} \u2192 ${resourceDisplay}` : cfnStatusDisplay;
256
285
  } else if (status === "complete") {
257
- rightInfo = "COMPLETE";
286
+ rightInfo = cfnStatus || "COMPLETE";
258
287
  }
259
- const leftPart = `${statusIndicator} ${accountLabel} ${displayName}`;
288
+ const leftPart = `${statusIndicator} [${typeLabel}] ${accountLabel} ${displayName}`;
260
289
  const middlePart = `[${bar}] ${countLabel}`;
261
290
  const line = `${leftPart} ${middlePart} ${rightInfo}`;
262
291
  return colorFn(line);
@@ -611,6 +640,7 @@ async function waitForStackWithProgress(client, stackName, accountId, region, op
611
640
  const pollInterval = 2e3;
612
641
  const progress = getMultiStackProgress();
613
642
  let latestResourceId = "";
643
+ let latestFailureReason = "";
614
644
  verbose(`[${stackName}] Starting to wait for stack operation...`);
615
645
  try {
616
646
  while (true) {
@@ -646,6 +676,10 @@ async function waitForStackWithProgress(client, stackName, accountId, region, op
646
676
  if (isResourceComplete(status)) {
647
677
  completedResources.add(logicalId);
648
678
  }
679
+ if (status.includes("FAILED") && event.ResourceStatusReason) {
680
+ latestFailureReason = `${logicalId}: ${event.ResourceStatusReason}`;
681
+ verbose(`[${stackName}] Failure reason: ${latestFailureReason}`);
682
+ }
649
683
  }
650
684
  }
651
685
  let displayStatus = "in_progress";
@@ -657,7 +691,7 @@ async function waitForStackWithProgress(client, stackName, accountId, region, op
657
691
  progress.updateStack(stackName, accountId, region, completedResources.size, displayStatus, currentStatus, latestResourceId);
658
692
  if (TERMINAL_STATES.has(currentStatus)) {
659
693
  const success2 = SUCCESS_STATES.has(currentStatus);
660
- const failureReason = success2 ? void 0 : currentStatus;
694
+ const failureReason = success2 ? void 0 : latestFailureReason || currentStatus;
661
695
  progress.completeStack(stackName, accountId, region, success2, failureReason);
662
696
  verbose(`[${stackName}] Reached terminal state: ${currentStatus} (success: ${success2})`);
663
697
  if (success2) {
@@ -2770,17 +2804,17 @@ async function executeDeployment(plan, pipelines, pipelineArtifacts, authData, c
2770
2804
  info(`Deploying ${totalStacks} stack(s) in parallel...`);
2771
2805
  newline();
2772
2806
  const progress = getMultiStackProgress();
2773
- progress.addStack(plan.orgStack.stackName, plan.orgStack.accountId, plan.orgStack.region, 5);
2807
+ progress.addStack(plan.orgStack.stackName, "org", plan.orgStack.accountId, plan.orgStack.region, 5);
2774
2808
  for (const stack of plan.pipelineStacks) {
2775
2809
  const resourceCount = stack.dockerArtifacts.length + stack.bundleArtifacts.length;
2776
- progress.addStack(stack.stackName, stack.accountId, stack.region, Math.max(resourceCount, 1));
2810
+ progress.addStack(stack.stackName, "pipeline", stack.accountId, stack.region, Math.max(resourceCount, 1));
2777
2811
  }
2778
2812
  for (const stack of plan.accountStacks) {
2779
- progress.addStack(stack.stackName, stack.accountId, stack.region, 1);
2813
+ progress.addStack(stack.stackName, "account", stack.accountId, stack.region, 1);
2780
2814
  }
2781
2815
  for (const stack of plan.stageStacks) {
2782
2816
  const resourceCount = stack.dockerArtifacts.length + stack.bundleArtifacts.length + 2;
2783
- progress.addStack(stack.stackName, stack.accountId, stack.region, resourceCount);
2817
+ progress.addStack(stack.stackName, "stage", stack.accountId, stack.region, resourceCount);
2784
2818
  }
2785
2819
  progress.start();
2786
2820
  const orgPromise = (async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devramps/cli",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "DevRamps CLI - Bootstrap AWS infrastructure for CI/CD pipelines",
5
5
  "main": "dist/index.js",
6
6
  "bin": {