Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { integTest, withDefaultFixture } from '../../../lib';

integTest(
'cdk ls --json in CI does not print synthesis time to stdout',
'cdk ls in CI prints only the stack listing to stdout',
withDefaultFixture(async (fixture) => {
// `cdk ls --json` stdout is a machine-readable contract and is often piped (e.g. to `jq`),
// so it must be only the stack listing, not status lines like "✨ Synthesis time: ...".
const listing = await fixture.cdk(['ls', '--json'], {
// In CI, non-error output goes to stdout. `cdk ls` stdout must be only the stack listing,
// not status lines like "✨ Synthesis time: ..." or "Including dependency stacks: ...".
const listing = await fixture.cdk(['ls'], {
verbose: false, // fixture defaults verbose on; turn it off so stdout is just the listing
captureStderr: false, // capture stdout only; stderr is folded into the result by default
modEnv: { CI: 'true' }, // CI routes non-error output to stdout (default is stderr)
});

const lines = listing.trim().split('\n').filter(line => line.length > 0);

// every line should be a stack; a synth-time line would not carry the prefix
// every line should be a stack; a status line would not carry the stack name prefix
expect(lines.length).toBeGreaterThan(0);
for (const line of lines) {
expect(line).toContain(fixture.stackNamePrefix);
Expand Down
8 changes: 4 additions & 4 deletions packages/aws-cdk/lib/cli/cdk-toolkit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -967,10 +967,10 @@ export class CdkToolkit {
): Promise<number> {
this.ioHost.rewriteOnce(IO.CDK_TOOLKIT_I2901, (msg) => formatStackList(msg.data.stacks, options));

// With `--json`, stdout must stay machine-parsable, so suppress the synth-time line (I1000).
if (options.json) {
this.ioHost.once(IO.CDK_TOOLKIT_I1000, () => ({ preventDefault: true }));
}
// cdk ls stdout is the stack listing only. Suppress the info status lines synthesis emits next
// to it: the synth-time line (I1000) and the dependency-expansion note (I1002).
this.ioHost.once(IO.CDK_TOOLKIT_I1000, () => ({ preventDefault: true }));
this.ioHost.once(IO.CDK_TOOLKIT_I1002, () => ({ preventDefault: true }));

await this.toolkit.list(this.props.cloudExecutable, {
stacks: selectors.length > 0
Expand Down
30 changes: 10 additions & 20 deletions packages/aws-cdk/test/cli/cdk-toolkit.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,33 +220,23 @@ describe('list', () => {
]);
});

test('with --json, suppresses the synthesis-time line so stdout stays machine-parsable', async () => {
// `cdk ls --json` stdout is a machine-readable contract; the "Synthesis time" line
// (CDK_TOOLKIT_I1000) must not be written (in CI mode non-error output goes to stdout).
const toolkit = defaultToolkitSetup();
const onceSpy = jest.spyOn(ioHost, 'once');

// WHEN
await toolkit.list([], { json: true });

// THEN - a one-shot suppressor for I1000 was registered that prevents default handling.
const i1000Call = onceSpy.mock.calls.find(([code]) => (code as any)?.code === 'CDK_TOOLKIT_I1000');
expect(i1000Call).toBeDefined();
const listener = i1000Call![1] as (msg: any) => any;
expect(listener({ code: 'CDK_TOOLKIT_I1000' })).toEqual({ preventDefault: true });
});

test('without --json, does not suppress the synthesis-time line', async () => {
// Plain `cdk ls` is not a machine-readable contract, so the line is left alone.
test('suppresses the synth-time (I1000) and dependency-expansion (I1002) lines on the list path', async () => {
// Both are info-level lines emitted next to the listing; in CI they would land on stdout and
// pollute the parseable output. The list path registers a one-shot suppressor for each so they
// are dropped before being written. (End-to-end stdout behavior is covered by the integ test.)
const toolkit = defaultToolkitSetup();
const onceSpy = jest.spyOn(ioHost, 'once');

// WHEN
await toolkit.list([]);

// THEN
const i1000Call = onceSpy.mock.calls.find(([code]) => (code as any)?.code === 'CDK_TOOLKIT_I1000');
expect(i1000Call).toBeUndefined();
for (const code of ['CDK_TOOLKIT_I1000', 'CDK_TOOLKIT_I1002']) {
const call = onceSpy.mock.calls.find(([sel]) => (sel as any)?.code === code);
expect(call).toBeDefined();
const listener = call![1] as (msg: any) => any;
expect(listener({ code })).toEqual({ preventDefault: true });
}
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{"seq":0,"type":"notify","action":"list","level":"trace","code":"CDK_TOOLKIT_I1001","message":"Starting Synthesis ..."}
{"seq":1,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1000","message":"Starting Synthesis ..."}
{"seq":2,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1001","message":"\n✨ Synthesis time: <DURATION>\n"}
{"seq":3,"type":"notify","action":"list","level":"info","code":"CDK_TOOLKIT_I1000","message":"✨ Synthesis time: <DURATION>"}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{"seq":0,"type":"notify","action":"list","level":"trace","code":"CDK_TOOLKIT_I1001","message":"Starting Synthesis ..."}
{"seq":1,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1000","message":"Starting Synthesis ..."}
{"seq":2,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1001","message":"\n✨ Synthesis time: <DURATION>\n"}
{"seq":3,"type":"notify","action":"list","level":"info","code":"CDK_TOOLKIT_I1000","message":"✨ Synthesis time: <DURATION>"}
{"seq":4,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-C\n dependencies:\n - id: Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n"}
{"seq":3,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-C\n dependencies:\n - id: Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n"}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{"seq":0,"type":"notify","action":"list","level":"trace","code":"CDK_TOOLKIT_I1001","message":"Starting Synthesis ..."}
{"seq":1,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1000","message":"Starting Synthesis ..."}
{"seq":2,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1001","message":"\n✨ Synthesis time: <DURATION>\n"}
{"seq":3,"type":"notify","action":"list","level":"info","code":"CDK_TOOLKIT_I1000","message":"✨ Synthesis time: <DURATION>"}
{"seq":4,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-A\n name: Test-Stack-A\n environment:\n account: \"123456789012\"\n region: bermuda-triangle-1\n name: aws://123456789012/bermuda-triangle-1\n- id: Test-Stack-B\n name: Test-Stack-B\n environment:\n account: \"123456789012\"\n region: bermuda-triangle-1\n name: aws://123456789012/bermuda-triangle-1\n"}
{"seq":3,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-A\n name: Test-Stack-A\n environment:\n account: \"123456789012\"\n region: bermuda-triangle-1\n name: aws://123456789012/bermuda-triangle-1\n- id: Test-Stack-B\n name: Test-Stack-B\n environment:\n account: \"123456789012\"\n region: bermuda-triangle-1\n name: aws://123456789012/bermuda-triangle-1\n"}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{"seq":0,"type":"notify","action":"list","level":"trace","code":"CDK_TOOLKIT_I1001","message":"Starting Synthesis ..."}
{"seq":1,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1000","message":"Starting Synthesis ..."}
{"seq":2,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1001","message":"\n✨ Synthesis time: <DURATION>\n"}
{"seq":3,"type":"notify","action":"list","level":"info","code":"CDK_TOOLKIT_I1000","message":"✨ Synthesis time: <DURATION>"}
{"seq":4,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"Test-Stack-A\nTest-Stack-B"}
{"seq":3,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"Test-Stack-A\nTest-Stack-B"}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{"seq":0,"type":"notify","action":"list","level":"trace","code":"CDK_TOOLKIT_I1001","message":"Starting Synthesis ..."}
{"seq":1,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1000","message":"Starting Synthesis ..."}
{"seq":2,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1001","message":"\n✨ Synthesis time: <DURATION>\n"}
{"seq":3,"type":"notify","action":"list","level":"info","code":"CDK_TOOLKIT_I1000","message":"✨ Synthesis time: <DURATION>"}
{"seq":4,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-C\n dependencies: []\n- id: Test-Stack-A\n dependencies:\n - id: Test-Stack-C\n dependencies: []\n"}
{"seq":3,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-C\n dependencies: []\n- id: Test-Stack-A\n dependencies:\n - id: Test-Stack-C\n dependencies: []\n"}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{"seq":0,"type":"notify","action":"list","level":"trace","code":"CDK_TOOLKIT_I1001","message":"Starting Synthesis ..."}
{"seq":1,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1000","message":"Starting Synthesis ..."}
{"seq":2,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1001","message":"\n✨ Synthesis time: <DURATION>\n"}
{"seq":3,"type":"notify","action":"list","level":"info","code":"CDK_TOOLKIT_I1000","message":"✨ Synthesis time: <DURATION>"}
{"seq":4,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-A/Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-A/Test-Stack-B/Test-Stack-C\n dependencies:\n - id: Test-Stack-A/Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n"}
{"seq":3,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-A/Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-A/Test-Stack-B/Test-Stack-C\n dependencies:\n - id: Test-Stack-A/Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n"}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{"seq":0,"type":"notify","action":"list","level":"trace","code":"CDK_TOOLKIT_I1001","message":"Starting Synthesis ..."}
{"seq":1,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1000","message":"Starting Synthesis ..."}
{"seq":2,"type":"notify","action":"list","level":"trace","code":"CDK_CLI_I1001","message":"\n✨ Synthesis time: <DURATION>\n"}
{"seq":3,"type":"notify","action":"list","level":"info","code":"CDK_TOOLKIT_I1000","message":"✨ Synthesis time: <DURATION>"}
{"seq":4,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n"}
{"seq":3,"type":"notify","action":"list","level":"result","code":"CDK_TOOLKIT_I2901","message":"- id: Test-Stack-A\n dependencies: []\n- id: Test-Stack-B\n dependencies:\n - id: Test-Stack-A\n dependencies: []\n"}
Loading