-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
Co-authored-by: Brian Seeders <brian.seeders@elastic.co>
- Loading branch information
1 parent
52113fb
commit ffe549c
Showing
8 changed files
with
203 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
const { TestFailures } = require('kibana-buildkite-library'); | ||
|
||
(async () => { | ||
try { | ||
await TestFailures.annotateTestFailures(); | ||
} catch (ex) { | ||
console.error('Annotate test failures error', ex.message); | ||
if (ex.response) { | ||
console.error('HTTP Error Response Status', ex.response.status); | ||
console.error('HTTP Error Response Body', ex.response.data); | ||
} | ||
process.exit(1); | ||
} | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
138 changes: 138 additions & 0 deletions
138
packages/kbn-test/src/failed_tests_reporter/report_failures_to_file.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { createHash } from 'crypto'; | ||
import { mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from 'fs'; | ||
import { join, basename, resolve } from 'path'; | ||
|
||
import { ToolingLog } from '@kbn/dev-utils'; | ||
import { REPO_ROOT } from '@kbn/utils'; | ||
import { escape } from 'he'; | ||
|
||
import { TestFailure } from './get_failures'; | ||
|
||
const findScreenshots = (dirPath: string, allScreenshots: string[] = []) => { | ||
const files = readdirSync(dirPath); | ||
|
||
for (const file of files) { | ||
if (statSync(join(dirPath, file)).isDirectory()) { | ||
if (file.match(/node_modules/)) { | ||
continue; | ||
} | ||
|
||
allScreenshots = findScreenshots(join(dirPath, file), allScreenshots); | ||
} else { | ||
const fullPath = join(dirPath, file); | ||
if (fullPath.match(/screenshots\/failure\/.+\.png$/)) { | ||
allScreenshots.push(fullPath); | ||
} | ||
} | ||
} | ||
|
||
return allScreenshots; | ||
}; | ||
|
||
export function reportFailuresToFile(log: ToolingLog, failures: TestFailure[]) { | ||
if (!failures?.length) { | ||
return; | ||
} | ||
|
||
let screenshots: string[]; | ||
try { | ||
screenshots = [ | ||
...findScreenshots(join(REPO_ROOT, 'test', 'functional')), | ||
...findScreenshots(join(REPO_ROOT, 'x-pack', 'test', 'functional')), | ||
]; | ||
} catch (e) { | ||
log.error(e as Error); | ||
screenshots = []; | ||
} | ||
|
||
const screenshotsByName: Record<string, string> = {}; | ||
for (const screenshot of screenshots) { | ||
const [name] = basename(screenshot).split('.'); | ||
screenshotsByName[name] = screenshot; | ||
} | ||
|
||
// Jest could, in theory, fail 1000s of tests and write 1000s of failures | ||
// So let's just write files for the first 20 | ||
for (const failure of failures.slice(0, 20)) { | ||
const hash = createHash('md5').update(failure.name).digest('hex'); | ||
const filenameBase = `${ | ||
process.env.BUILDKITE_JOB_ID ? process.env.BUILDKITE_JOB_ID + '_' : '' | ||
}${hash}`; | ||
const dir = join('target', 'test_failures'); | ||
|
||
const failureLog = [ | ||
['Test:', '-----', failure.classname, failure.name, ''], | ||
['Failure:', '--------', failure.failure], | ||
failure['system-out'] ? ['', 'Standard Out:', '-------------', failure['system-out']] : [], | ||
] | ||
.flat() | ||
.join('\n'); | ||
|
||
const failureJSON = JSON.stringify( | ||
{ | ||
...failure, | ||
hash, | ||
buildId: process.env.BUJILDKITE_BUILD_ID || '', | ||
jobId: process.env.BUILDKITE_JOB_ID || '', | ||
url: process.env.BUILDKITE_BUILD_URL || '', | ||
jobName: process.env.BUILDKITE_LABEL | ||
? `${process.env.BUILDKITE_LABEL}${ | ||
process.env.BUILDKITE_PARALLEL_JOB ? ` #${process.env.BUILDKITE_PARALLEL_JOB}` : '' | ||
}` | ||
: '', | ||
}, | ||
null, | ||
2 | ||
); | ||
|
||
let screenshot = ''; | ||
const screenshotName = `${failure.name.replace(/([^ a-zA-Z0-9-]+)/g, '_')}`; | ||
if (screenshotsByName[screenshotName]) { | ||
try { | ||
screenshot = readFileSync(screenshotsByName[screenshotName]).toString('base64'); | ||
} catch (e) { | ||
log.error(e as Error); | ||
} | ||
} | ||
|
||
const screenshotHtml = screenshot | ||
? `<img class="screenshot img-fluid img-thumbnail" src="data:image/png;base64,${screenshot}" />` | ||
: ''; | ||
|
||
const failureHTML = readFileSync( | ||
resolve( | ||
REPO_ROOT, | ||
'packages/kbn-test/src/failed_tests_reporter/report_failures_to_file_html_template.html' | ||
) | ||
) | ||
.toString() | ||
.replace('$TITLE', escape(failure.name)) | ||
.replace( | ||
'$MAIN', | ||
` | ||
${failure.classname | ||
.split('.') | ||
.map((part) => `<h5>${escape(part.replace('·', '.'))}</h5>`) | ||
.join('')} | ||
<hr /> | ||
<p><strong>${escape(failure.name)}</strong></p> | ||
<pre>${escape(failure.failure)}</pre> | ||
${screenshotHtml} | ||
<pre>${escape(failure['system-out'] || '')}</pre> | ||
` | ||
); | ||
|
||
mkdirSync(dir, { recursive: true }); | ||
writeFileSync(join(dir, `${filenameBase}.log`), failureLog, 'utf8'); | ||
writeFileSync(join(dir, `${filenameBase}.html`), failureHTML, 'utf8'); | ||
writeFileSync(join(dir, `${filenameBase}.json`), failureJSON, 'utf8'); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
packages/kbn-test/src/failed_tests_reporter/report_failures_to_file_html_template.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="utf-8" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1" /> | ||
<link | ||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" | ||
rel="stylesheet" | ||
integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" | ||
crossorigin="anonymous" | ||
/> | ||
<style type="text/css"> | ||
pre { | ||
font-size: 0.75em !important; | ||
} | ||
|
||
img.screenshot { | ||
cursor: pointer; | ||
height: 200px; | ||
margin: 5px 0; | ||
} | ||
|
||
img.screenshot.expanded { | ||
height: auto; | ||
} | ||
</style> | ||
<title>$TITLE</title> | ||
</head> | ||
<body> | ||
<div class="col-lg-10 mx-auto p-3 py-md-5"> | ||
<main>$MAIN</main> | ||
</div> | ||
<script type="text/javascript"> | ||
for (const img of document.getElementsByTagName('img')) { | ||
img.addEventListener('click', () => { | ||
img.classList.toggle('expanded'); | ||
}); | ||
} | ||
</script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters