feat: when failed to wrote the results, and having failed tests, make sure the build fails

This commit is contained in:
A. J. Kaptijn 2024-01-17 12:43:53 +01:00
parent 39a2ecbea2
commit a3bd4352e9
3 changed files with 94 additions and 14 deletions

49
dist/index.js generated vendored
View file

@ -129,6 +129,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
const core = __importStar(__nccwpck_require__(2186)); const core = __importStar(__nccwpck_require__(2186));
const github = __importStar(__nccwpck_require__(5438)); const github = __importStar(__nccwpck_require__(5438));
const local_file_provider_1 = __nccwpck_require__(9399); const local_file_provider_1 = __nccwpck_require__(9399);
const test_results_1 = __nccwpck_require__(2768);
const get_annotations_1 = __nccwpck_require__(5867); const get_annotations_1 = __nccwpck_require__(5867);
const get_report_1 = __nccwpck_require__(3737); const get_report_1 = __nccwpck_require__(3737);
const dart_json_parser_1 = __nccwpck_require__(4528); const dart_json_parser_1 = __nccwpck_require__(4528);
@ -236,13 +237,15 @@ class TestReporter {
try { try {
core.startGroup(`Creating test report ${reportName}`); core.startGroup(`Creating test report ${reportName}`);
const tr = yield this.createReport(parser, reportName, files); const tr = yield this.createReport(parser, reportName, files);
results.push(...tr); if (tr != null) {
results.push(tr);
}
} }
finally { finally {
core.endGroup(); core.endGroup();
} }
} }
const isFailed = results.some(tr => tr.result === 'failed'); const isFailed = results.some(tr => tr.results.some(r => r.isFailed));
const conclusion = isFailed ? 'failure' : 'success'; const conclusion = isFailed ? 'failure' : 'success';
const passed = results.reduce((sum, tr) => sum + tr.passed, 0); const passed = results.reduce((sum, tr) => sum + tr.passed, 0);
const failed = results.reduce((sum, tr) => sum + tr.failed, 0); const failed = results.reduce((sum, tr) => sum + tr.failed, 0);
@ -253,6 +256,10 @@ class TestReporter {
core.setOutput('failed', failed); core.setOutput('failed', failed);
core.setOutput('skipped', skipped); core.setOutput('skipped', skipped);
core.setOutput('time', time); core.setOutput('time', time);
if (results.some(r => r.shouldFail)) {
core.setFailed(`Failed test were found and the results could not be written to github, so fail this step.`);
return;
}
if (this.failOnError && isFailed) { if (this.failOnError && isFailed) {
core.setFailed(`Failed test were found and 'fail-on-error' option is set to ${this.failOnError}`); core.setFailed(`Failed test were found and 'fail-on-error' option is set to ${this.failOnError}`);
return; return;
@ -267,10 +274,11 @@ class TestReporter {
return __awaiter(this, void 0, void 0, function* () { return __awaiter(this, void 0, void 0, function* () {
if (files.length === 0) { if (files.length === 0) {
core.warning(`No file matches path ${this.path}`); core.warning(`No file matches path ${this.path}`);
return []; return null;
} }
core.info(`Processing test results for check run ${name}`); core.info(`Processing test results for check run ${name}`);
const results = []; const results = [];
const result = new test_results_1.TestRunResultWithUrl(results, null);
for (const { file, content } of files) { for (const { file, content } of files) {
try { try {
core.info(`Processing test results from ${file}`); core.info(`Processing test results from ${file}`);
@ -309,6 +317,7 @@ class TestReporter {
core.setOutput('url', resp.data.url); core.setOutput('url', resp.data.url);
core.setOutput('url_html', resp.data.html_url); core.setOutput('url_html', resp.data.html_url);
core.info(`Check run details: ${resp.data.details_url}`); core.info(`Check run details: ${resp.data.details_url}`);
result.checkUrl = resp.data.html_url;
if (this.slackWebhook && this.context.branch === 'master') { if (this.slackWebhook && this.context.branch === 'master') {
const webhook = new webhook_1.IncomingWebhook(this.slackWebhook); const webhook = new webhook_1.IncomingWebhook(this.slackWebhook);
const passed = results.reduce((sum, tr) => sum + tr.passed, 0); const passed = results.reduce((sum, tr) => sum + tr.passed, 0);
@ -343,7 +352,7 @@ class TestReporter {
catch (error) { catch (error) {
core.error(`Could not create check to store the results`); core.error(`Could not create check to store the results`);
} }
return results; return result;
}); });
} }
getParser(reporter, options) { getParser(reporter, options) {
@ -1686,8 +1695,33 @@ function getResultIcon(result) {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.TestCaseResult = exports.TestGroupResult = exports.TestSuiteResult = exports.TestRunResult = void 0; exports.TestCaseResult = exports.TestGroupResult = exports.TestSuiteResult = exports.TestRunResult = exports.TestRunResultWithUrl = void 0;
const node_utils_1 = __nccwpck_require__(5824); const node_utils_1 = __nccwpck_require__(5824);
class TestRunResultWithUrl {
constructor(results, checkUrl) {
this.results = results;
this.checkUrl = checkUrl;
}
get hasCheck() {
return !!this.checkUrl;
}
get shouldFail() {
return !this.hasCheck && this.results.some(r => r.isFailed);
}
get passed() {
return this.results.reduce((sum, g) => sum + g.passed, 0);
}
get failed() {
return this.results.reduce((sum, g) => sum + g.failed, 0);
}
get skipped() {
return this.results.reduce((sum, g) => sum + g.skipped, 0);
}
get time() {
return this.results.reduce((sum, g) => sum + g.time, 0);
}
}
exports.TestRunResultWithUrl = TestRunResultWithUrl;
class TestRunResult { class TestRunResult {
constructor(path, suites, totalTime) { constructor(path, suites, totalTime) {
this.path = path; this.path = path;
@ -1710,8 +1744,11 @@ class TestRunResult {
var _a; var _a;
return (_a = this.totalTime) !== null && _a !== void 0 ? _a : this.suites.reduce((sum, g) => sum + g.time, 0); return (_a = this.totalTime) !== null && _a !== void 0 ? _a : this.suites.reduce((sum, g) => sum + g.time, 0);
} }
get isFailed() {
return this.suites.some(t => t.result === 'failed');
}
get result() { get result() {
return this.suites.some(t => t.result === 'failed') ? 'failed' : 'success'; return this.isFailed ? 'failed' : 'success';
} }
get failedSuites() { get failedSuites() {
return this.suites.filter(s => s.result === 'failed'); return this.suites.filter(s => s.result === 'failed');

View file

@ -5,7 +5,7 @@ import {GitHub} from '@actions/github/lib/utils'
import {LocalFileProvider} from './input-providers/local-file-provider' import {LocalFileProvider} from './input-providers/local-file-provider'
import {FileContent} from './input-providers/input-provider' import {FileContent} from './input-providers/input-provider'
import {ParseOptions, TestParser} from './test-parser' import {ParseOptions, TestParser} from './test-parser'
import {TestRunResult} from './test-results' import {TestRunResult, TestRunResultWithUrl} from './test-results'
import {getAnnotations} from './report/get-annotations' import {getAnnotations} from './report/get-annotations'
import {getReport} from './report/get-report' import {getReport} from './report/get-report'
@ -102,7 +102,7 @@ class TestReporter {
core.info(`Using test report parser '${this.reporter}'`) core.info(`Using test report parser '${this.reporter}'`)
const parser = this.getParser(this.reporter, options) const parser = this.getParser(this.reporter, options)
const results: TestRunResult[] = [] const results: TestRunResultWithUrl[] = []
const input = await inputProvider.load() const input = await inputProvider.load()
try { try {
@ -134,13 +134,15 @@ class TestReporter {
try { try {
core.startGroup(`Creating test report ${reportName}`) core.startGroup(`Creating test report ${reportName}`)
const tr = await this.createReport(parser, reportName, files) const tr = await this.createReport(parser, reportName, files)
results.push(...tr) if (tr != null) {
results.push(tr)
}
} finally { } finally {
core.endGroup() core.endGroup()
} }
} }
const isFailed = results.some(tr => tr.result === 'failed') const isFailed = results.some(tr => tr.results.some(r => r.isFailed))
const conclusion = isFailed ? 'failure' : 'success' const conclusion = isFailed ? 'failure' : 'success'
const passed = results.reduce((sum, tr) => sum + tr.passed, 0) const passed = results.reduce((sum, tr) => sum + tr.passed, 0)
const failed = results.reduce((sum, tr) => sum + tr.failed, 0) const failed = results.reduce((sum, tr) => sum + tr.failed, 0)
@ -153,6 +155,11 @@ class TestReporter {
core.setOutput('skipped', skipped) core.setOutput('skipped', skipped)
core.setOutput('time', time) core.setOutput('time', time)
if (results.some(r => r.shouldFail)) {
core.setFailed(`Failed test were found and the results could not be written to github, so fail this step.`)
return
}
if (this.failOnError && isFailed) { if (this.failOnError && isFailed) {
core.setFailed(`Failed test were found and 'fail-on-error' option is set to ${this.failOnError}`) core.setFailed(`Failed test were found and 'fail-on-error' option is set to ${this.failOnError}`)
return return
@ -164,14 +171,17 @@ class TestReporter {
} }
} }
async createReport(parser: TestParser, name: string, files: FileContent[]): Promise<TestRunResult[]> { async createReport(parser: TestParser, name: string, files: FileContent[]): Promise<TestRunResultWithUrl | null> {
if (files.length === 0) { if (files.length === 0) {
core.warning(`No file matches path ${this.path}`) core.warning(`No file matches path ${this.path}`)
return [] return null
} }
core.info(`Processing test results for check run ${name}`) core.info(`Processing test results for check run ${name}`)
const results: TestRunResult[] = [] const results: TestRunResult[] = []
const result: TestRunResultWithUrl = new TestRunResultWithUrl(results, null)
for (const {file, content} of files) { for (const {file, content} of files) {
try { try {
core.info(`Processing test results from ${file}`) core.info(`Processing test results from ${file}`)
@ -226,6 +236,7 @@ class TestReporter {
core.setOutput('url', resp.data.url) core.setOutput('url', resp.data.url)
core.setOutput('url_html', resp.data.html_url) core.setOutput('url_html', resp.data.html_url)
core.info(`Check run details: ${resp.data.details_url}`) core.info(`Check run details: ${resp.data.details_url}`)
result.checkUrl = resp.data.html_url
if (this.slackWebhook && this.context.branch === 'master') { if (this.slackWebhook && this.context.branch === 'master') {
const webhook = new IncomingWebhook(this.slackWebhook) const webhook = new IncomingWebhook(this.slackWebhook)
@ -264,7 +275,7 @@ class TestReporter {
core.error(`Could not create check to store the results`) core.error(`Could not create check to store the results`)
} }
return results return result
} }
getParser(reporter: string, options: ParseOptions): TestParser { getParser(reporter: string, options: ParseOptions): TestParser {

View file

@ -1,5 +1,33 @@
import {DEFAULT_LOCALE} from './utils/node-utils' import {DEFAULT_LOCALE} from './utils/node-utils'
export class TestRunResultWithUrl {
constructor(
public results: TestRunResult[],
public checkUrl: string | null
) {}
get hasCheck(): boolean {
return !!this.checkUrl
}
get shouldFail(): boolean {
return !this.hasCheck && this.results.some(r => r.isFailed)
}
get passed(): number {
return this.results.reduce((sum, g) => sum + g.passed, 0)
}
get failed(): number {
return this.results.reduce((sum, g) => sum + g.failed, 0)
}
get skipped(): number {
return this.results.reduce((sum, g) => sum + g.skipped, 0)
}
get time(): number {
return this.results.reduce((sum, g) => sum + g.time, 0)
}
}
export class TestRunResult { export class TestRunResult {
constructor( constructor(
readonly path: string, readonly path: string,
@ -25,8 +53,12 @@ export class TestRunResult {
return this.totalTime ?? this.suites.reduce((sum, g) => sum + g.time, 0) return this.totalTime ?? this.suites.reduce((sum, g) => sum + g.time, 0)
} }
get isFailed(): boolean {
return this.suites.some(t => t.result === 'failed')
}
get result(): TestExecutionResult { get result(): TestExecutionResult {
return this.suites.some(t => t.result === 'failed') ? 'failed' : 'success' return this.isFailed ? 'failed' : 'success'
} }
get failedSuites(): TestSuiteResult[] { get failedSuites(): TestSuiteResult[] {