export async function generateLintDiffReport()

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;
}