Skip to content

Commit 42e5d08

Browse files
authored
fix(cli): stack monitor prints over error messages (#19859)
In #19742, we limited the amount of text that the status printer would produce, and tried to get rid of the empty lines at the end of the rewritable block as well. Unfortunately, we scrolled up too far, overwriting the error messages that may occur during resource provisioning. Since these were the only place where error messages were displayed, it is now not possible to see why a stack deployment fails. This PR fixes that. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 2c2bc0b commit 42e5d08

File tree

3 files changed

+40
-20
lines changed

3 files changed

+40
-20
lines changed

packages/aws-cdk/lib/api/util/cloudformation/stack-activity-monitor.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -682,7 +682,7 @@ export class CurrentActivityPrinter extends ActivityPrinterBase {
682682

683683
// Display in the same block space, otherwise we're going to have silly empty lines.
684684
this.block.displayLines(lines);
685-
this.block.removeEmptyLines(lines);
685+
this.block.removeEmptyLines();
686686
}
687687

688688
private progressBar(width: number) {
@@ -745,7 +745,7 @@ function colorFromStatusActivity(status?: string) {
745745
return chalk.red;
746746
}
747747

748-
if (status.startsWith('CREATE_') || status.startsWith('UPDATE_')) {
748+
if (status.startsWith('CREATE_') || status.startsWith('UPDATE_') || status.startsWith('IMPORT_')) {
749749
return chalk.green;
750750
}
751751
// For stacks, it may also be 'UPDDATE_ROLLBACK_IN_PROGRESS'

packages/aws-cdk/lib/api/util/display.ts

+15-18
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const wrapAnsi = require('wrap-ansi');
77
*/
88
export class RewritableBlock {
99
private lastHeight = 0;
10+
private trailingEmptyLines = 0;
1011

1112
constructor(private readonly stream: NodeJS.WriteStream) {
1213
}
@@ -22,23 +23,27 @@ export class RewritableBlock {
2223
}
2324

2425
public displayLines(lines: string[]) {
25-
lines = terminalWrap(this.width, expandNewlines(lines)).slice(0, getMaxBlockHeight(this.height, this.lastHeight, lines));
26+
lines = terminalWrap(this.width, expandNewlines(lines));
27+
lines = lines.slice(0, getMaxBlockHeight(this.height, this.lastHeight, lines));
2628

2729
this.stream.write(cursorUp(this.lastHeight));
2830
for (const line of lines) {
2931
this.stream.write(cll() + line + '\n');
3032
}
33+
34+
this.trailingEmptyLines = Math.max(0, this.lastHeight - lines.length);
35+
3136
// Clear remainder of unwritten lines
32-
for (let i = 0; i < this.lastHeight - lines.length; i++) {
37+
for (let i = 0; i < this.trailingEmptyLines; i++) {
3338
this.stream.write(cll() + '\n');
3439
}
3540

3641
// The block can only ever get bigger
3742
this.lastHeight = Math.max(this.lastHeight, lines.length);
3843
}
3944

40-
public removeEmptyLines(lines: string[]) {
41-
this.stream.write(cursorUp(this.lastHeight - lines.length));
45+
public removeEmptyLines() {
46+
this.stream.write(cursorUp(this.trailingEmptyLines));
4247
}
4348
}
4449

@@ -62,26 +67,18 @@ function cll() {
6267
function terminalWrap(width: number | undefined, lines: string[]) {
6368
if (width === undefined) { return lines; }
6469

65-
const ret = new Array<string>();
66-
for (const line of lines) {
67-
ret.push(...wrapAnsi(line, width - 1, {
68-
hard: true,
69-
trim: true,
70-
wordWrap: false,
71-
}).split('\n'));
72-
}
73-
return ret;
70+
return lines.flatMap(line => wrapAnsi(line, width - 1, {
71+
hard: true,
72+
trim: true,
73+
wordWrap: false,
74+
}).split('\n'));
7475
}
7576

7677
/**
7778
* Make sure there are no hidden newlines in the gin strings
7879
*/
7980
function expandNewlines(lines: string[]): string[] {
80-
const ret = new Array<string>();
81-
for (const line of lines) {
82-
ret.push(...line.split('\n'));
83-
}
84-
return ret;
81+
return lines.flatMap(line => line.split('\n'));
8582
}
8683

8784
function getMaxBlockHeight(windowHeight: number | undefined, lastHeight: number, lines: string[]): number {

packages/aws-cdk/test/api/util/display.test.ts

+23
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,27 @@ describe('Rewritable Block Tests', () => {
3636

3737
expect(output.length).toEqual(6);
3838
});
39+
40+
test('display accounts for newlines in output', () => {
41+
const output = stderr.inspectSync(() => {
42+
block.displayLines(['before\nafter']);
43+
});
44+
expect(output.length).toEqual(3); // cursorup + 2 lines
45+
});
46+
47+
test('removeEmptyLines only removes trailing lines', () => {
48+
stderr.inspectSync(() => {
49+
block.displayLines(Array.from(Array(5).keys()).map(x => `${x}`));
50+
});
51+
stderr.inspectSync(() => {
52+
// Leaves 3 empty lines
53+
block.displayLines(Array.from(Array(2).keys()).map(x => `${x}`));
54+
});
55+
56+
const output = stderr.inspectSync(() => {
57+
block.removeEmptyLines();
58+
});
59+
const expectedEmptyLines = 3;
60+
expect(JSON.stringify(output)).toEqual(JSON.stringify([`\u001b[${expectedEmptyLines}A`]));
61+
});
3962
});

0 commit comments

Comments
 (0)