Skip to content

Commit c05e058

Browse files
rix0rrrgithub-actions
andauthored
chore: log integ test output to the file system (#416)
Write the (huge) text logs of integ test files to the file system if configured to do so (with `$INTEG_LOGS`), and use that feature in the GitHub logs to publish the logs as an artifact. At the same time, also start playing with Markdown reports of GitHub actions by writing to `$GITHUB_STEP_SUMMARY` to see what that looks like. --- By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license --------- Signed-off-by: github-actions <github-actions@github.com> Co-authored-by: github-actions <github-actions@github.com>
1 parent f6bd7b9 commit c05e058

File tree

3 files changed

+81
-2
lines changed

3 files changed

+81
-2
lines changed

.github/workflows/integ.yml

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

packages/@aws-cdk-testing/cli-integ/lib/integ-test.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,20 +48,26 @@ export function integTest(
4848
throw new Error('FAIL_FAST requested and currently failing. Stopping test early.');
4949
}
5050

51-
return await callback({
51+
const ret = await callback({
5252
output,
5353
randomString: randomString(),
5454
name,
5555
log(s: string) {
5656
output.write(`${s}\n`);
5757
},
5858
});
59+
60+
await writeLog(name, true, output.toString());
61+
62+
return ret;
5963
} catch (e: any) {
64+
// Print the buffered output, only if the test fails.
6065
failed = true;
6166

62-
// Print the buffered output, only if the test fails.
6367
output.write(e.message);
6468
output.write(e.stack);
69+
70+
await writeLog(name, false, output.toString());
6571
process.stderr.write(`[INTEG TEST::${name}] Failed: ${e}\n`);
6672

6773
const isGitHub = !!process.env.GITHUB_RUN_ID;
@@ -108,3 +114,48 @@ export function randomString() {
108114
// Crazy
109115
return Math.random().toString(36).replace(/[^a-z0-9]+/g, '');
110116
}
117+
118+
/**
119+
* Write log files
120+
*
121+
* Write a text log to `${INTEG_LOGS}/[FAILED-]description-of-test.txt`, and a single
122+
* line of a Markdown table to `${INTEG_LOGS}/md/1-description-of-test.md`.
123+
*
124+
* The latter are designed to be globcatted to $GITHUB_STEP_SUMMARY after tests
125+
* (we don't write there directly to avoid concurrency issues with multiple processes
126+
* reading and mutating the same file).
127+
*
128+
* We do use `atomicWrite` to write files -- it's only necessary for the header file,
129+
* which gets overwritten by every test, just to make sure it properly exists (shouldn't
130+
* end up empty or with interleaved contents). The other writes are not
131+
* contended and don't need to be atomic, but the function is just ergonomic to use.
132+
*/
133+
async function writeLog(testName: string, success: boolean, output: string) {
134+
if (process.env.INTEG_LOGS) {
135+
const slug = slugify(testName);
136+
const logFileName = `${process.env.INTEG_LOGS}/${success ? '' : 'FAILED-'}${slug}.txt`;
137+
await atomicWrite(logFileName, output);
138+
139+
// Sort failures before successes, and the table header before all
140+
await atomicWrite(`${process.env.INTEG_LOGS}/md/0-header.md`, [
141+
'| Result | Test Name |',
142+
'|--------|-----------|',
143+
].map(x => `${x}\n`).join(''));
144+
145+
const mdFileName = `${process.env.INTEG_LOGS}/md/${success ? '2' : '1'}-${slug}.md`;
146+
const firstColumn = success ? 'pass ✅' : 'fail ❌';
147+
await atomicWrite(mdFileName, `| ${firstColumn} | ${testName} |\n`);
148+
}
149+
}
150+
151+
function slugify(x: string) {
152+
return x.replace(/[^a-zA-Z0-9_,]+/g, '-');
153+
}
154+
155+
async function atomicWrite(fileName: string, contents: string) {
156+
await fs.promises.mkdir(path.dirname(fileName), { recursive: true });
157+
158+
const tmp = `${fileName}.${process.pid}`;
159+
await fs.promises.writeFile(tmp, contents);
160+
await fs.promises.rename(tmp, fileName);
161+
}

projenrc/cdk-cli-integ-tests.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,23 @@ export class CdkCliIntegTestsWorkflow extends Component {
416416
CDK_MAJOR_VERSION: '2',
417417
RELEASE_TAG: 'latest',
418418
GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}',
419+
INTEG_LOGS: 'logs',
420+
},
421+
},
422+
{
423+
name: 'Set workflow summary',
424+
run: [
425+
'echo "## Test results" >> $GITHUB_STEP_SUMMARY',
426+
'cat logs/md/*.md >> $GITHUB_STEP_SUMMARY',
427+
].join('\n'),
428+
},
429+
{
430+
name: 'Upload logs',
431+
uses: 'actions/upload-artifact@v4.4.0',
432+
with: {
433+
name: 'logs',
434+
path: 'logs/',
435+
overwrite: 'true',
419436
},
420437
},
421438
],

0 commit comments

Comments
 (0)