2021-02-21 11:53:02 +00:00
|
|
|
import * as core from '@actions/core';
|
|
|
|
|
import * as github from '@actions/github';
|
|
|
|
|
import * as fs from 'fs';
|
|
|
|
|
import * as xmljs from 'xml-js';
|
2021-02-21 13:15:54 +00:00
|
|
|
import path from 'path';
|
2021-02-21 11:53:02 +00:00
|
|
|
import Handlebars from 'handlebars';
|
|
|
|
|
import ReportConverter from './report-converter';
|
|
|
|
|
import { RunMeta } from './ts/meta.ts';
|
|
|
|
|
|
|
|
|
|
class ResultsCheck {
|
|
|
|
|
static async publishResults(artifactsPath, githubToken) {
|
|
|
|
|
// Parse all reports
|
|
|
|
|
const runs = [];
|
|
|
|
|
const files = fs.readdirSync(artifactsPath);
|
|
|
|
|
await Promise.all(
|
|
|
|
|
files.map(async filepath => {
|
2021-02-21 12:46:22 +00:00
|
|
|
if (!filepath.endsWith('.xml')) return;
|
2021-02-22 00:39:24 +00:00
|
|
|
core.info(`Processing file ${filepath}...`);
|
2021-02-21 13:15:54 +00:00
|
|
|
const fileData = await ResultsCheck.parseReport(path.join(artifactsPath, filepath));
|
2021-02-21 11:53:02 +00:00
|
|
|
core.info(fileData.summary);
|
|
|
|
|
runs.push(fileData);
|
|
|
|
|
}),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Prepare run summary
|
|
|
|
|
const runSummary = new RunMeta('Test Results');
|
2021-02-22 21:49:04 +00:00
|
|
|
runs.forEach(run => {
|
|
|
|
|
runSummary.total += run.total;
|
|
|
|
|
runSummary.passed += run.passed;
|
|
|
|
|
runSummary.skipped += run.skipped;
|
|
|
|
|
runSummary.failed += run.failed;
|
|
|
|
|
runSummary.duration += run.duration;
|
2021-02-23 01:03:43 +00:00
|
|
|
core.debug(`Run suites length ${run.suites.length}`);
|
2021-02-22 21:49:04 +00:00
|
|
|
run.suites.forEach(suite => {
|
|
|
|
|
runSummary.addTests(suite.tests);
|
2021-02-21 11:53:02 +00:00
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// Log run summary
|
|
|
|
|
core.info('=================');
|
|
|
|
|
core.info('Analyze result:');
|
|
|
|
|
core.info(runSummary.summary);
|
|
|
|
|
|
|
|
|
|
// Create check
|
|
|
|
|
await ResultsCheck.createCheck(githubToken, runs, runSummary, runSummary.extractAnnotations());
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-21 13:15:54 +00:00
|
|
|
static async parseReport(filepath) {
|
2021-02-21 12:46:22 +00:00
|
|
|
core.info(`Trying to open ${filepath}`);
|
2021-02-21 11:53:02 +00:00
|
|
|
const file = await fs.promises.readFile(filepath, 'utf8');
|
|
|
|
|
const report = xmljs.xml2js(file, { compact: true });
|
2021-02-21 12:46:22 +00:00
|
|
|
core.info(`File ${filepath} parsed...`);
|
2021-02-21 11:53:02 +00:00
|
|
|
|
2021-02-21 13:15:54 +00:00
|
|
|
return ReportConverter.convertReport(path.basename(filepath), report);
|
2021-02-21 11:53:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static async createCheck(githubToken, runs, runSummary, annotations) {
|
|
|
|
|
const pullRequest = github.context.payload.pull_request;
|
|
|
|
|
const headSha = (pullRequest && pullRequest.head.sha) || github.context.sha;
|
|
|
|
|
|
|
|
|
|
const summary = await ResultsCheck.renderSummary(runs);
|
|
|
|
|
const text = await ResultsCheck.renderText(runs);
|
|
|
|
|
const title = runSummary.summary;
|
2021-02-22 16:57:08 +00:00
|
|
|
|
|
|
|
|
core.info(`Posting results for ${headSha}`);
|
2021-02-21 11:53:02 +00:00
|
|
|
const createCheckRequest = {
|
|
|
|
|
...github.context.repo,
|
|
|
|
|
name: 'Test Results',
|
|
|
|
|
head_sha: headSha,
|
|
|
|
|
status: 'completed',
|
2021-02-22 16:57:08 +00:00
|
|
|
conclusion: 'neutral',
|
2021-02-21 11:53:02 +00:00
|
|
|
output: {
|
|
|
|
|
title,
|
|
|
|
|
summary,
|
|
|
|
|
text,
|
|
|
|
|
annotations: annotations.slice(0, 50),
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const octokit = github.getOctokit(githubToken);
|
|
|
|
|
await octokit.checks.create(createCheckRequest);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static async renderSummary(runMetas) {
|
|
|
|
|
return ResultsCheck.render(`${__dirname}/../views/summary.hbs`, runMetas);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static async renderText(runMetas) {
|
|
|
|
|
return ResultsCheck.render(`${__dirname}/../views/text.hbs`, runMetas);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static async render(viewPath, runMetas) {
|
|
|
|
|
const source = await fs.promises.readFile(viewPath, 'utf8');
|
|
|
|
|
Handlebars.registerHelper('indent', ResultsCheck.indentHelper);
|
|
|
|
|
const template = Handlebars.compile(source);
|
|
|
|
|
return template(
|
|
|
|
|
{ runs: runMetas },
|
|
|
|
|
{
|
|
|
|
|
allowProtoMethodsByDefault: true,
|
|
|
|
|
allowProtoPropertiesByDefault: true,
|
|
|
|
|
},
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static indentHelper(argument) {
|
|
|
|
|
return argument
|
|
|
|
|
.split('\n')
|
|
|
|
|
.map(s => ` ${s}`)
|
|
|
|
|
.join('\n');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default ResultsCheck;
|