in eng/tools/lint-diff/src/generateReport.ts [16:114]
export async function generateLintDiffReport(
runCorrelations: Map<string, BeforeAfter>,
affectedSwaggers: Set<string>,
outFile: string,
baseBranch: string,
compareSha: string,
): Promise<boolean> {
console.log("Generating LintDiff report...");
let pass = true;
let outputMarkdown = "";
// See unifiedPipelineHelper.ts:386
// Compared specs (link to npm package: @microsoft.azure/openapi-validator/v/<version>)
const dependencyVersion = await getDependencyVersion(
await getPathToDependency("@microsoft.azure/openapi-validator"),
);
outputMarkdown += `| Compared specs ([v${dependencyVersion}](https://www.npmjs.com/package/@microsoft.azure/openapi-validator/v/${dependencyVersion})) | new version | base version |\n`;
outputMarkdown += `| --- | --- | --- |\n`;
// Compared Specs | New Version | Base Version
// <tag name> | link: readme.md#tag-<tag-name> | link: readme.md#tag-<tag-name>
// ... | ... | ...
for (const [, { before, after }] of runCorrelations.entries()) {
const afterName = getName(after);
const beforeName = before ? getName(before) : "default";
const afterPath = getPath(after);
const beforePath = before ? getPath(before) : "";
outputMarkdown += `| ${afterName} | [${afterName}](${getFileLink(compareSha, afterPath)}) | [${beforeName}](${getFileLink(baseBranch, beforePath)}) |\n`;
}
outputMarkdown += `\n\n`;
const [newViolations, existingViolations] = getViolations(runCorrelations, affectedSwaggers);
for (const newItem of newViolations) {
// TODO: Potential performance issue, make parallel
newItem.armRpcs = await getRelatedArmRpcFromDoc(newItem.code);
}
newViolations.sort(compareLintDiffViolations);
existingViolations.sort(compareLintDiffViolations);
console.log(`New violations: ${newViolations.length}`);
if (newViolations.length > 0) {
outputMarkdown += "**[must fix]The following errors/warnings are intorduced by current PR:**\n";
if (newViolations.length > 50) {
outputMarkdown += `${LIMIT_50_MESSAGE}\n`;
}
outputMarkdown += "\n";
outputMarkdown += "| Rule | Message | Related RPC [For API reviewers] |\n";
outputMarkdown += "| ---- | ------- | ------------------------------- |\n";
for (const violation of newViolations.slice(0, 50)) {
outputMarkdown += getNewViolationReportRow(violation, compareSha);
}
if (newViolations.some((v) => isFailure(v.level))) {
console.log("\t❌ At least one violation has error or fatal level. LintDiff will fail.");
// New violations with level error or fatal fail the build. If all new
// violations are warnings, the build passes.
pass = false;
} else {
console.log("\t✅ No new violations with error or fatal level. LintDiff will pass.");
}
LogViolations("New violations list", newViolations);
outputMarkdown += "\n";
}
console.log(`Existing violations: ${existingViolations.length}`);
if (existingViolations.length > 0) {
outputMarkdown += "**The following errors/warnings exist before current PR submission:**\n";
if (existingViolations.length > 50) {
outputMarkdown += `${LIMIT_50_MESSAGE}\n`;
}
outputMarkdown += "\n";
outputMarkdown += "| Rule | Message |\n";
outputMarkdown += "| ---- | ------- |\n";
for (const violation of existingViolations.slice(0, 50)) {
const { level, code, message } = violation;
outputMarkdown += `| ${iconFor(level)} [${code}](${getDocUrl(code)}) | ${message}<br />Location: [${getPathSegment(relativizePath(getFile(violation)))}#L${getLine(violation)}](${getFileLink(compareSha, relativizePath(getFile(violation)), getLine(violation))}) |\n`;
}
LogViolations("Existing violations list", existingViolations);
outputMarkdown += `\n`;
}
console.log(`Writing output to ${outFile}`);
await writeFile(outFile, outputMarkdown);
return pass;
}