@microsoft.azure/autorest.testserver
Version:
This project contains a set of OpenAPI definitions and a server implementing the corresponding API. Use this to test compliance of AutoRest generators.
128 lines (112 loc) • 6.07 kB
JavaScript
const { createBlobService } = require("azure-storage");
const { readFileSync, readdirSync } = require('fs');
const { join } = require("path");
const { GitHubCiClient } = require("./github");
const commentIndicatorPublish = "<!--AUTO-GENERATED PUBLISH JOB COMMENT-->\n";
const commentIndicatorCoverage = "<!--AUTO-GENERATED TESTSERVER COVERAGE COMMENT-->\n";
async function collectCoverage() {
// search for reports
const coverageFolder = __dirname;
const report = {};
const getMergedReport = (category) => {
const reports = readdirSync(coverageFolder).filter(f => f.startsWith(`report-${category}`) && f.endsWith(".json")).map(f => require(join(coverageFolder, f)));
const result = {};
for (const feature of [].concat.apply([], reports.map(r => Object.keys(r)))) {
result[feature] = Math.max(...reports.map(r => r[feature] || 0));
}
return result;
};
report.General = getMergedReport("vanilla");
report.Azure = getMergedReport("azure");
if (Object.keys(report).every(cat => Object.keys(report[cat]).length === 0)) throw "no report";
// post report
let comment = "";
for (const category of Object.keys(report)) {
const categoryObject = report[category];
const features = Object.keys(categoryObject).sort().map(x => [x, categoryObject[x] > 0]);
const countTotal = features.length;
const countCovered = features.filter(x => x[1]).length;
const countMissing = countTotal - countCovered;
const percentCoverage = countCovered / (countTotal || 1) * 100 | 0;
comment += `## ${percentCoverage === 100 ? "✔️" : "❌️"} ${category}: ${percentCoverage}%\n\n`;
if (countMissing > 0) {
comment += `<details><summary>${countMissing} out of ${countTotal} features are not covered by tests</summary><p>\n\n`;
let first = true;
for (const feature of features.filter(x => !x[1])) {
if (!first) comment += `, `;
first = false;
const f = feature[0];
comment += `[\`${f}\`](https://github.com/Azure/autorest.testserver/search?q=${f})`;
}
comment += "</p></details>";
} else if (countTotal === 0) {
comment += `no tests were run for this category\n`;
}
comment += "\n\n";
}
const testServerVersion = require(join(coverageFolder, "..", "..", "package.json")).version;
return `${commentIndicatorCoverage}# 🤖 AutoRest automatic feature coverage report 🤖\n*feature set version ${testServerVersion}*\n\n${comment}`;
}
function getPublishedPackageVersion() {
return require(join(__dirname, "..", "..", "..", "..", "..", "package.json")).version;
}
async function pushCoverage(repo, ref, azStorageAccount, azStorageAccessKey, comment, version) {
if (!version) {
version = getPublishedPackageVersion();
}
const blobSvc = createBlobService(azStorageAccount, azStorageAccessKey);
const container = await new Promise((res, rej) => blobSvc.createContainerIfNotExists(
`autorest-ci-coverage-report`,
{ publicAccessLevel: "blob" },
(error, result) => error ? rej(error) : res(result.name)));
await new Promise((res, rej) =>
blobSvc.createBlockBlobFromText(
container,
`${repo.split('/')[1]}_${version}.md`,
`<!-- ${ref} -->\n` + comment,
{ contentSettings: { contentType: "text/markdown; charset=utf-8" } },
(error, result) => error ? rej(error) : res(result.name)));
}
async function show(repo, pr, token) {
const comment = await collectCoverage();
const ghClient = new GitHubCiClient(repo, token);
// try cleaning up previous auto-comments
try {
const comments = await ghClient.getCommentsWithIndicator(pr, commentIndicatorCoverage);
for (const comment of comments) await ghClient.tryDeleteComment(comment.id);
} catch (_) { }
// send comment
await ghClient.createComment(pr, comment);
}
async function push(repo, pr, token, azStorageAccount, azStorageAccessKey, version) {
const ghClient = new GitHubCiClient(repo, token);
// try pushing coverage
const coverageComment = (await ghClient.getCommentsWithIndicator(pr, commentIndicatorCoverage))[0];
if (coverageComment) await pushCoverage(repo, pr, azStorageAccount, azStorageAccessKey, coverageComment.message, version);
}
async function immediatePush(repo, ref, githubToken, azStorageAccount, azStorageAccessKey, version) {
const postComment = githubToken && githubToken !== "skip";
if (postComment) {
// try posting "published" comment on GitHub (IMPORTANT: this assumes that this script is only run after successful publish!)
try {
// try deriving PR associated with last commit
const lastCommitMessage = require("child_process").execSync("git log -1 --pretty=%B").toString();
const pr = +(/\(\#(\d+)\)/g.exec(lastCommitMessage) || [])[1];
if (isNaN(pr)) throw `Could not deduce PR number from commit message ${JSON.stringify(lastCommitMessage)}`;
if (!version) {
version = getPublishedPackageVersion();
}
const ghClient = new GitHubCiClient(repo, githubToken);
await ghClient.createComment(pr, `${commentIndicatorPublish}
# 🤖 AutoRest automatic publish job 🤖
## success (version: ${version})
<!--IMPORTANT: this assumes that this script is only run after successful publish via VSTS! So no "Continue on error" on the publish task!-->`);
} catch(e) {
console.log("Posting 'published' comment to GitHub failed.");
console.log(e);
}
}
const comment = await collectCoverage();
await pushCoverage(repo, ref, azStorageAccount, azStorageAccessKey, comment, version);
}
module.exports = { show, push, immediatePush };