feat: allows to generate the summary only.

This commit is contained in:
Giuseppe Lippolis 2021-06-03 10:41:08 +02:00
parent e8f4fdfec7
commit 17e793242c
6 changed files with 189 additions and 129 deletions

View file

@ -53,6 +53,10 @@ inputs:
working-directory: working-directory:
description: Relative path under $GITHUB_WORKSPACE where the repository was checked out description: Relative path under $GITHUB_WORKSPACE where the repository was checked out
required: false required: false
only-summary:
description: allows you to generate the summary only.
default: 'false'
required: false
token: token:
description: GitHub Access Token description: GitHub Access Token
required: false required: false

255
dist/index.js generated vendored
View file

@ -245,6 +245,7 @@ class TestReporter {
this.maxAnnotations = parseInt(core.getInput('max-annotations', { required: true })); this.maxAnnotations = parseInt(core.getInput('max-annotations', { required: true }));
this.failOnError = core.getInput('fail-on-error', { required: true }) === 'true'; this.failOnError = core.getInput('fail-on-error', { required: true }) === 'true';
this.workDirInput = core.getInput('working-directory', { required: false }); this.workDirInput = core.getInput('working-directory', { required: false });
this.onlySummary = core.getInput('only-summary', { required: false }) === 'true';
this.token = core.getInput('token', { required: true }); this.token = core.getInput('token', { required: true });
this.context = github_utils_1.getCheckRunContext(); this.context = github_utils_1.getCheckRunContext();
this.octokit = github.getOctokit(this.token); this.octokit = github.getOctokit(this.token);
@ -337,9 +338,9 @@ class TestReporter {
...github.context.repo ...github.context.repo
}); });
core.info('Creating report summary'); core.info('Creating report summary');
const { listSuites, listTests } = this; const { listSuites, listTests, onlySummary } = this;
const baseUrl = createResp.data.html_url; const baseUrl = createResp.data.html_url;
const summary = get_report_1.getReport(results, { listSuites, listTests, baseUrl }); const summary = get_report_1.getReport(results, { listSuites, listTests, baseUrl, onlySummary });
core.info('Creating annotations'); core.info('Creating annotations');
const annotations = get_annotations_1.getAnnotations(results, this.maxAnnotations); const annotations = get_annotations_1.getAnnotations(results, this.maxAnnotations);
const isFailed = results.some(tr => tr.result === 'failed'); const isFailed = results.some(tr => tr.result === 'failed');
@ -947,7 +948,7 @@ class JavaJunitParser {
return undefined; return undefined;
} }
const failure = failures[0]; const failure = failures[0];
const details = typeof (failure) === 'object' ? failure._ : failure; const details = typeof failure === 'object' ? failure._ : failure;
let filePath; let filePath;
let line; let line;
const src = this.exceptionThrowSource(details); const src = this.exceptionThrowSource(details);
@ -959,7 +960,7 @@ class JavaJunitParser {
path: filePath, path: filePath,
line, line,
details, details,
message: typeof (failure) === 'object' ? failure.message : undefined message: typeof failure === 'object' ? failure.message : undefined
}; };
} }
exceptionThrowSource(stackTrace) { exceptionThrowSource(stackTrace) {
@ -1350,7 +1351,8 @@ const MAX_REPORT_LENGTH = 65535;
const defaultOptions = { const defaultOptions = {
listSuites: 'all', listSuites: 'all',
listTests: 'all', listTests: 'all',
baseUrl: '' baseUrl: '',
onlySummary: false
}; };
function getReport(results, options = defaultOptions) { function getReport(results, options = defaultOptions) {
core.info('Generating check run summary'); core.info('Generating check run summary');
@ -1462,8 +1464,10 @@ function getTestRunsReport(testRuns, options) {
const resultsTable = markdown_utils_1.table(['Report', 'Passed', 'Failed', 'Skipped', 'Time'], [markdown_utils_1.Align.Left, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right], ...tableData); const resultsTable = markdown_utils_1.table(['Report', 'Passed', 'Failed', 'Skipped', 'Time'], [markdown_utils_1.Align.Left, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right, markdown_utils_1.Align.Right], ...tableData);
sections.push(resultsTable); sections.push(resultsTable);
} }
const suitesReports = testRuns.map((tr, i) => getSuitesReport(tr, i, options)).flat(); if (options.onlySummary === false) {
sections.push(...suitesReports); const suitesReports = testRuns.map((tr, i) => getSuitesReport(tr, i, options)).flat();
sections.push(...suitesReports);
}
return sections; return sections;
} }
function getSuitesReport(tr, runIndex, options) { function getSuitesReport(tr, runIndex, options) {
@ -8346,13 +8350,12 @@ module.exports = function (/**String*/input) {
} }
function fixPath(zipPath){ function fixPath(zipPath){
// convert windows file separators // convert windows file separators and normalize
zipPath = zipPath.split("\\").join("/"); zipPath = pth.posix.normalize(zipPath.split("\\").join("/"));
// add separator if it wasnt given // cleanup, remove invalid folder names
if (zipPath.charAt(zipPath.length - 1) !== "/") { var names = zipPath.split("/").filter((c) => c !== "" && c !== "." && c !== "..");
zipPath += "/"; // if we have name we return it
} return names.length ? names.join("/") + "/" : "";
return zipPath;
} }
return { return {
@ -8565,10 +8568,11 @@ module.exports = function (/**String*/input) {
items.forEach(function (filepath) { items.forEach(function (filepath) {
var p = pth.relative(localPath, filepath).split("\\").join("/"); //windows fix var p = pth.relative(localPath, filepath).split("\\").join("/"); //windows fix
if (filter(p)) { if (filter(p)) {
if (filepath.charAt(filepath.length - 1) !== pth.sep) { var stats = fs.statSync(filepath);
self.addFile(zipPath + p, fs.readFileSync(filepath), "", fs.statSync(filepath)); if (stats.isFile()) {
self.addFile(zipPath + p, fs.readFileSync(filepath), "", stats);
} else { } else {
self.addFile(zipPath + p + '/', Buffer.alloc(0), "", 0); self.addFile(zipPath + p + '/', Buffer.alloc(0), "", stats);
} }
} }
}); });
@ -8586,75 +8590,83 @@ module.exports = function (/**String*/input) {
* @param filter optional RegExp or Function if files match will * @param filter optional RegExp or Function if files match will
* be included. * be included.
*/ */
addLocalFolderAsync: function (/*String*/localPath, /*Function*/callback, /*String*/zipPath, /*RegExp|Function*/filter) { addLocalFolderAsync: function (/*String*/localPath, /*Function*/callback, /*String*/zipPath, /*RegExp|Function*/filter) {
if (filter === undefined) { if (filter instanceof RegExp) {
filter = function () { filter = (function (rx) {
return true; return function (filename) {
}; return rx.test(filename);
} else if (filter instanceof RegExp) { };
filter = function (filter) { })(filter);
return function (filename) { } else if ("function" !== typeof filter) {
return filter.test(filename); filter = function () {
} return true;
}(filter); };
} }
if (zipPath) { // fix ZipPath
zipPath = zipPath.split("\\").join("/"); zipPath = zipPath ? fixPath(zipPath) : "";
if (zipPath.charAt(zipPath.length - 1) !== "/") {
zipPath += "/";
}
} else {
zipPath = "";
}
// normalize the path first
localPath = pth.normalize(localPath);
localPath = localPath.split("\\").join("/"); //windows fix
if (localPath.charAt(localPath.length - 1) !== "/")
localPath += "/";
var self = this; // normalize the path first
fs.open(localPath, 'r', function (err, fd) { localPath = pth.normalize(localPath);
if (err && err.code === 'ENOENT') {
callback(undefined, Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
} else if (err) {
callback(undefined, err);
} else {
var items = Utils.findFiles(localPath);
var i = -1;
var next = function () { var self = this;
i += 1; fs.open(localPath, 'r', function (err) {
if (i < items.length) { if (err && err.code === 'ENOENT') {
var p = items[i].split("\\").join("/").replace(new RegExp(localPath.replace(/(\(|\))/g, '\\$1'), 'i'), ""); //windows fix callback(undefined, Utils.Errors.FILE_NOT_FOUND.replace("%s", localPath));
p = p.normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^\x20-\x7E]/g, '') // accent fix } else if (err) {
if (filter(p)) { callback(undefined, err);
if (p.charAt(p.length - 1) !== "/") { } else {
fs.readFile(items[i], function (err, data) { var items = Utils.findFiles(localPath);
if (err) { var i = -1;
callback(undefined, err);
} else {
self.addFile(zipPath + p, data, '', 0);
next();
}
})
} else {
self.addFile(zipPath + p, Buffer.alloc(0), "", 0);
next();
}
} else {
next();
}
} else { var next = function () {
callback(true, undefined); i += 1;
} if (i < items.length) {
} var filepath = items[i];
var p = pth.relative(localPath, filepath).split("\\").join("/"); //windows fix
p = p.normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^\x20-\x7E]/g, '') // accent fix
if (filter(p)) {
fs.stat(filepath, function (er0, stats) {
if (er0) callback(undefined, er0);
if (stats.isFile()) {
fs.readFile(filepath, function (er1, data) {
if (er1) {
callback(undefined, er1);
} else {
self.addFile(zipPath + p, data, "", stats);
next();
}
});
} else {
self.addFile(zipPath + p + "/", Buffer.alloc(0), "", stats);
next();
}
});
} else {
next();
}
next(); } else {
} callback(true, undefined);
}); }
}, }
next();
}
});
},
addLocalFolderPromise: function (/*String*/ localPath, /* object */ options) {
return new Promise((resolve, reject) => {
const { filter, zipPath } = Object.assign({}, options);
this.addLocalFolderAsync(localPath,
(done, err) => {
if (err) reject(err);
if (done) resolve(this);
}, zipPath, filter
);
});
},
/** /**
* Allows you to create a entry (file or directory) in the zip file. * Allows you to create a entry (file or directory) in the zip file.
@ -8688,7 +8700,7 @@ module.exports = function (/**String*/input) {
var unix = (entry.isDirectory) ? 0x4000 : 0x8000; var unix = (entry.isDirectory) ? 0x4000 : 0x8000;
if (isStat) { // File attributes from file stats if (isStat) { // File attributes from file stats
unix |= (0xfff & attr.mode) unix |= (0xfff & attr.mode);
}else if ('number' === typeof attr){ // attr from given attr values }else if ('number' === typeof attr){ // attr from given attr values
unix |= (0xfff & attr); unix |= (0xfff & attr);
}else{ // Default values: }else{ // Default values:
@ -8773,8 +8785,9 @@ module.exports = function (/**String*/input) {
} }
var name = canonical(child.entryName) var name = canonical(child.entryName)
var childName = sanitize(targetPath, maintainEntryPath ? name : pth.basename(name)); var childName = sanitize(targetPath, maintainEntryPath ? name : pth.basename(name));
// The reverse operation for attr depend on method addFile()
Utils.writeFileTo(childName, content, overwrite); var fileAttr = child.attr ? (((child.attr >>> 0) | 0) >> 16) & 0xfff : 0;
Utils.writeFileTo(childName, content, overwrite, fileAttr);
}); });
return true; return true;
} }
@ -8785,7 +8798,9 @@ module.exports = function (/**String*/input) {
if (fs.existsSync(target) && !overwrite) { if (fs.existsSync(target) && !overwrite) {
throw new Error(Utils.Errors.CANT_OVERRIDE); throw new Error(Utils.Errors.CANT_OVERRIDE);
} }
Utils.writeFileTo(target, content, overwrite); // The reverse operation for attr depend on method addFile()
var fileAttr = item.attr ? (((item.attr >>> 0) | 0) >> 16) & 0xfff : 0;
Utils.writeFileTo(target, content, overwrite, fileAttr);
return true; return true;
}, },
@ -8837,7 +8852,9 @@ module.exports = function (/**String*/input) {
if (!content) { if (!content) {
throw new Error(Utils.Errors.CANT_EXTRACT_FILE); throw new Error(Utils.Errors.CANT_EXTRACT_FILE);
} }
Utils.writeFileTo(entryName, content, overwrite); // The reverse operation for attr depend on method addFile()
var fileAttr = entry.attr ? (((entry.attr >>> 0) | 0) >> 16) & 0xfff : 0;
Utils.writeFileTo(entryName, content, overwrite, fileAttr);
try { try {
fs.utimesSync(entryName, entry.header.time, entry.header.time) fs.utimesSync(entryName, entry.header.time, entry.header.time)
} catch (err) { } catch (err) {
@ -8889,7 +8906,9 @@ module.exports = function (/**String*/input) {
return; return;
} }
Utils.writeFileToAsync(sanitize(targetPath, entryName), content, overwrite, function (succ) { // The reverse operation for attr depend on method addFile()
var fileAttr = entry.attr ? (((entry.attr >>> 0) | 0) >> 16) & 0xfff : 0;
Utils.writeFileToAsync(sanitize(targetPath, entryName), content, overwrite, fileAttr, function (succ) {
try { try {
fs.utimesSync(pth.resolve(targetPath, entryName), entry.header.time, entry.header.time); fs.utimesSync(pth.resolve(targetPath, entryName), entry.header.time, entry.header.time);
} catch (err) { } catch (err) {
@ -8934,6 +8953,27 @@ module.exports = function (/**String*/input) {
} }
}, },
writeZipPromise: function (/**String*/ targetFileName, /* object */ options) {
const { overwrite, perm } = Object.assign({ overwrite: true }, options);
return new Promise((resolve, reject) => {
// find file name
if (!targetFileName && _filename) targetFileName = _filename;
if (!targetFileName) reject("ADM-ZIP: ZIP File Name Missing");
this.toBufferPromise().then((zipData) => {
const ret = (done) => (done ? resolve(done) : reject("ADM-ZIP: Wasn't able to write zip file"));
Utils.writeFileToAsync(targetFileName, zipData, overwrite, perm, ret);
}, reject);
});
},
toBufferPromise: function () {
return new Promise((resolve, reject) => {
_zip.toAsyncBuffer(resolve, reject);
});
},
/** /**
* Returns the content of the entire zip file as a Buffer object * Returns the content of the entire zip file as a Buffer object
* *
@ -10298,17 +10338,17 @@ module.exports = function (/*Buffer*/input) {
getData : function(pass) { getData : function(pass) {
if (_entryHeader.changed) { if (_entryHeader.changed) {
return uncompressedData; return uncompressedData;
} else { } else {
return decompress(false, null, pass); return decompress(false, null, pass);
} }
}, },
getDataAsync : function(/*Function*/callback, pass) { getDataAsync : function(/*Function*/callback, pass) {
if (_entryHeader.changed) { if (_entryHeader.changed) {
callback(uncompressedData) callback(uncompressedData);
} else { } else {
decompress(true, callback, pass) decompress(true, callback, pass);
} }
}, },
@ -10324,14 +10364,20 @@ module.exports = function (/*Buffer*/input) {
}, },
packHeader : function() { packHeader : function() {
// 1. create header (buffer)
var header = _entryHeader.entryHeaderToBinary(); var header = _entryHeader.entryHeaderToBinary();
// add var addpos = Utils.Constants.CENHDR;
_entryName.copy(header, Utils.Constants.CENHDR); // 2. add file name
_entryName.copy(header, addpos);
addpos += _entryName.length;
// 3. add extra data
if (_entryHeader.extraLength) { if (_entryHeader.extraLength) {
_extra.copy(header, Utils.Constants.CENHDR + _entryName.length) _extra.copy(header, addpos);
addpos += _entryHeader.extraLength;
} }
// 4. add file comment
if (_entryHeader.commentLength) { if (_entryHeader.commentLength) {
_comment.copy(header, Utils.Constants.CENHDR + _entryName.length + _entryHeader.extraLength, _comment.length); _comment.copy(header, addpos);
} }
return header; return header;
}, },
@ -11952,12 +11998,14 @@ module.exports = (fromStream, toStream) => {
/***/ }), /***/ }),
/***/ 6214: /***/ 6214:
/***/ ((module, exports, __nccwpck_require__) => { /***/ ((module, exports) => {
"use strict"; "use strict";
Object.defineProperty(exports, "__esModule", ({ value: true })); Object.defineProperty(exports, "__esModule", ({ value: true }));
const tls_1 = __nccwpck_require__(4016); function isTLSSocket(socket) {
return socket.encrypted;
}
const deferToConnect = (socket, fn) => { const deferToConnect = (socket, fn) => {
let listeners; let listeners;
if (typeof fn === 'function') { if (typeof fn === 'function') {
@ -11974,7 +12022,7 @@ const deferToConnect = (socket, fn) => {
if (hasConnectListener) { if (hasConnectListener) {
listeners.connect(); listeners.connect();
} }
if (socket instanceof tls_1.TLSSocket && hasSecureConnectListener) { if (isTLSSocket(socket) && hasSecureConnectListener) {
if (socket.authorized) { if (socket.authorized) {
listeners.secureConnect(); listeners.secureConnect();
} }
@ -15984,7 +16032,7 @@ const is_response_ok_1 = __nccwpck_require__(9298);
const deprecation_warning_1 = __nccwpck_require__(397); const deprecation_warning_1 = __nccwpck_require__(397);
const normalize_arguments_1 = __nccwpck_require__(1048); const normalize_arguments_1 = __nccwpck_require__(1048);
const calculate_retry_delay_1 = __nccwpck_require__(3462); const calculate_retry_delay_1 = __nccwpck_require__(3462);
const globalDnsCache = new cacheable_lookup_1.default(); let globalDnsCache;
const kRequest = Symbol('request'); const kRequest = Symbol('request');
const kResponse = Symbol('response'); const kResponse = Symbol('response');
const kResponseSize = Symbol('responseSize'); const kResponseSize = Symbol('responseSize');
@ -16541,6 +16589,9 @@ class Request extends stream_1.Duplex {
options.cacheOptions = { ...options.cacheOptions }; options.cacheOptions = { ...options.cacheOptions };
// `options.dnsCache` // `options.dnsCache`
if (options.dnsCache === true) { if (options.dnsCache === true) {
if (!globalDnsCache) {
globalDnsCache = new cacheable_lookup_1.default();
}
options.dnsCache = globalDnsCache; options.dnsCache = globalDnsCache;
} }
else if (!is_1.default.undefined(options.dnsCache) && !options.dnsCache.lookup) { else if (!is_1.default.undefined(options.dnsCache) && !options.dnsCache.lookup) {

2
dist/index.js.map generated vendored

File diff suppressed because one or more lines are too long

36
dist/licenses.txt generated vendored
View file

@ -341,27 +341,27 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
adm-zip adm-zip
MIT MIT
Copyright (c) 2012 Another-D-Mention Software and other contributors, MIT License
http://www.another-d-mention.ro/
Permission is hereby granted, free of charge, to any person obtaining Copyright (c) 2012 Another-D-Mention Software and other contributors
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be Permission is hereby granted, free of charge, to any person obtaining a copy
included in all copies or substantial portions of the Software. of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, The above copyright notice and this permission notice shall be included in all
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF copies or substantial portions of the Software.
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
before-after-hook before-after-hook

View file

@ -39,6 +39,7 @@ class TestReporter {
readonly maxAnnotations = parseInt(core.getInput('max-annotations', {required: true})) readonly maxAnnotations = parseInt(core.getInput('max-annotations', {required: true}))
readonly failOnError = core.getInput('fail-on-error', {required: true}) === 'true' readonly failOnError = core.getInput('fail-on-error', {required: true}) === 'true'
readonly workDirInput = core.getInput('working-directory', {required: false}) readonly workDirInput = core.getInput('working-directory', {required: false})
readonly onlySummary = core.getInput('only-summary', {required: false}) === 'true'
readonly token = core.getInput('token', {required: true}) readonly token = core.getInput('token', {required: true})
readonly octokit: InstanceType<typeof GitHub> readonly octokit: InstanceType<typeof GitHub>
readonly context = getCheckRunContext() readonly context = getCheckRunContext()
@ -160,9 +161,9 @@ class TestReporter {
}) })
core.info('Creating report summary') core.info('Creating report summary')
const {listSuites, listTests} = this const {listSuites, listTests, onlySummary} = this
const baseUrl = createResp.data.html_url const baseUrl = createResp.data.html_url
const summary = getReport(results, {listSuites, listTests, baseUrl}) const summary = getReport(results, {listSuites, listTests, baseUrl, onlySummary})
core.info('Creating annotations') core.info('Creating annotations')
const annotations = getAnnotations(results, this.maxAnnotations) const annotations = getAnnotations(results, this.maxAnnotations)

View file

@ -10,12 +10,14 @@ export interface ReportOptions {
listSuites: 'all' | 'failed' listSuites: 'all' | 'failed'
listTests: 'all' | 'failed' | 'none' listTests: 'all' | 'failed' | 'none'
baseUrl: string baseUrl: string
onlySummary: boolean
} }
const defaultOptions: ReportOptions = { const defaultOptions: ReportOptions = {
listSuites: 'all', listSuites: 'all',
listTests: 'all', listTests: 'all',
baseUrl: '' baseUrl: '',
onlySummary: false
} }
export function getReport(results: TestRunResult[], options: ReportOptions = defaultOptions): string { export function getReport(results: TestRunResult[], options: ReportOptions = defaultOptions): string {
@ -152,8 +154,10 @@ function getTestRunsReport(testRuns: TestRunResult[], options: ReportOptions): s
sections.push(resultsTable) sections.push(resultsTable)
} }
const suitesReports = testRuns.map((tr, i) => getSuitesReport(tr, i, options)).flat() if (options.onlySummary === false) {
sections.push(...suitesReports) const suitesReports = testRuns.map((tr, i) => getSuitesReport(tr, i, options)).flat()
sections.push(...suitesReports)
}
return sections return sections
} }