scripts(visual-regression): show target filename (#48444)

* scripts(visual-regression): show target filename

* feat: update

* feat: show filename

* feat: update
This commit is contained in:
vagusX 2024-04-15 14:40:10 +08:00 committed by GitHub
parent daba39b88a
commit b42ffe64f4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 141 additions and 44 deletions

View File

@ -181,6 +181,7 @@
"@emotion/server": "^11.11.0",
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
"@madccc/duplicate-package-checker-webpack-plugin": "^1.0.0",
"@microflash/rehype-figure": "^2.1.0",
"@npmcli/run-script": "^7.0.4",
"@octokit/rest": "^20.1.0",
"@qixian.cs/github-contributors-list": "^2.0.1",
@ -314,13 +315,14 @@
"react-router-dom": "^6.22.3",
"react-sticky-box": "^2.0.5",
"regenerator-runtime": "^0.14.1",
"rehype-stringify": "^10.0.0",
"remark": "^15.0.1",
"remark-cli": "^12.0.0",
"remark-gfm": "^4.0.0",
"remark-html": "^16.0.1",
"remark-lint": "^9.1.2",
"remark-lint-no-undefined-references": "^4.2.1",
"remark-preset-lint-recommended": "^6.1.3",
"remark-rehype": "^11.1.0",
"runes2": "^1.1.4",
"semver": "^7.6.0",
"sharp": "^0.33.3",

View File

@ -6,17 +6,17 @@ import os from 'os';
import path from 'path';
import { Readable } from 'stream';
import { finished } from 'stream/promises';
import simpleGit from 'simple-git';
import chalk from 'chalk';
import fse from 'fs-extra';
import difference from 'lodash/difference';
import minimist from 'minimist';
import pixelmatch from 'pixelmatch';
import { PNG } from 'pngjs';
import { remark } from 'remark';
import remarkGfm from 'remark-gfm';
import remarkHtml from 'remark-html';
import sharp from 'sharp';
import markdown2Html from './convert';
const ROOT_DIR = process.cwd();
const ALI_OSS_BUCKET = 'antd-visual-diff';
@ -119,36 +119,100 @@ async function downloadBaseSnapshots(ref: string, targetDir: string) {
});
}
interface IImageDesc {
src: string;
alt: string;
}
function getMdImageTag(desc: IImageDesc, extraCaption?: boolean) {
const { src, alt } = desc;
if (!extraCaption || !alt) {
// in md2html report, we use `@microflash/rehype-figure` to generate a figure
return `![${alt}](${src})`;
}
// show caption with image in github markdown comment
return `![${alt}](${src}) ${alt}`;
}
interface IBadCase {
type: 'removed' | 'changed';
filename: string;
/**
* compare target file
*/
targetFilename?: string;
/**
* 0 - 1
*/
weight: number;
}
function md2Html(md: string) {
return remark().use(remarkGfm).use(remarkHtml).processSync(md).toString();
}
const git = simpleGit();
function parseArgs() {
async function parseArgs() {
// parse args from -- --pr-id=123 --base_ref=feature
const argv = minimist(process.argv.slice(2));
const prId = argv['pr-id'];
assert(prId, 'Missing --pr-id');
const baseRef = argv['base-ref'];
assert(baseRef, 'Missing --base-ref');
const { latest } = await git.log();
return {
prId,
baseRef,
currentRef: latest?.hash.slice(0, 8) || '',
};
}
function generateLineReport(
badCase: IBadCase,
publicPath: string,
currentRef: string,
extraCaption?: boolean,
) {
const { filename, type, targetFilename } = badCase;
let lineHTMLReport = '';
if (type === 'changed') {
lineHTMLReport += '| ';
lineHTMLReport += [
// add ref as query to avoid github cache image object
getMdImageTag({
src: `${publicPath}/images/base/${filename}?ref=${currentRef}`,
alt: targetFilename || '',
}, extraCaption),
getMdImageTag({
src: `${publicPath}/images/current/${filename}?ref=${currentRef}`,
alt: filename,
}, extraCaption),
getMdImageTag({
src: `${publicPath}/images/diff/${filename}?ref=${currentRef}`,
alt: '',
}, extraCaption),
].join(' | ');
lineHTMLReport += ' |\n';
} else if (type === 'removed') {
lineHTMLReport += '| ';
lineHTMLReport += [
getMdImageTag({
src: `${publicPath}/images/base/${filename}?ref=${currentRef}`,
alt: targetFilename || '',
}, extraCaption),
`⛔️⛔️⛔️ Missing ⛔️⛔️⛔️`,
`🚨🚨🚨 Removed 🚨🚨🚨`,
].join(' | ');
lineHTMLReport += ' |\n';
}
return lineHTMLReport;
}
function generateReport(
badCases: IBadCase[],
targetBranch: string,
targetRef: string,
currentRef: string,
prId: string,
): [string, string] {
const reportDirname = path.basename(REPORT_DIR);
@ -174,15 +238,15 @@ function generateReport(
'<img src="https://github.com/ant-design/ant-design/assets/507615/2d1a77dc-dbc6-4b0f-9cbc-19a43d3c29cd" width="300" />',
].join('\n');
return [mdStr, md2Html(mdStr)];
return [mdStr, markdown2Html(mdStr)];
}
let reportMdStr = `
${commonHeader}
${fullReport}
| Image name | Expected | Actual | Diff |
| --- | --- | --- | --- |
| Expected (Branch ${targetBranch}) | Actual (Current PR) | Diff |
| --- | --- | --- |
`.trim();
reportMdStr += '\n';
@ -192,44 +256,33 @@ ${fullReport}
let diffCount = 0;
for (const badCase of badCases) {
const { filename, type } = badCase;
let lineReportMdStr = '';
if (type === 'changed') {
lineReportMdStr += '| ';
lineReportMdStr += [
`\`${badCase.filename}\``,
`![${targetBranch}: ${targetRef}](${publicPath}/images/base/${filename})`,
`![current: pr-${prId}](${publicPath}/images/current/${filename})`,
`![diff](${publicPath}/images/diff/${filename})`,
].join(' | ');
lineReportMdStr += ' |\n';
} else if (type === 'removed') {
lineReportMdStr += '| ';
lineReportMdStr += [
`\`${badCase.filename}\``,
`![${targetBranch}: ${targetRef}](${publicPath}/images/base/${filename})`,
`⛔️⛔️⛔️ Missing ⛔️⛔️⛔️`,
`🚨🚨🚨 Removed 🚨🚨🚨`,
].join(' | ');
lineReportMdStr += ' |\n';
}
diffCount += 1;
if (diffCount <= 10) {
reportMdStr += lineReportMdStr;
// 将图片下方增加文件名
reportMdStr += generateLineReport(
badCase,
publicPath,
currentRef,
true,
);
}
fullVersionMd += lineReportMdStr;
fullVersionMd += generateLineReport(
badCase,
publicPath,
currentRef,
false,
);
}
reportMdStr += addonFullReportDesc;
// convert fullVersionMd to html
return [reportMdStr, md2Html(fullVersionMd)];
return [reportMdStr, markdown2Html(fullVersionMd)];
}
async function boot() {
const { prId, baseRef: targetBranch = 'master' } = parseArgs();
const { prId, baseRef: targetBranch = 'master', currentRef } = await parseArgs();
const baseImgSourceDir = path.resolve(ROOT_DIR, `./imageSnapshots-${targetBranch}`);
@ -324,6 +377,7 @@ async function boot() {
badCases.push({
type: 'changed',
filename: compareImgName,
targetFilename: baseImgName,
weight: mismatchedPxPercent,
});
} else {
@ -340,6 +394,7 @@ async function boot() {
badCases,
targetBranch,
targetCommitSha,
currentRef,
prId,
);
await fse.writeFile(path.join(REPORT_DIR, './report.md'), reportMdStr);

View File

@ -0,0 +1,17 @@
/* eslint-disable compat/compat */
/* eslint-disable no-console, no-await-in-loop, import/no-extraneous-dependencies, no-restricted-syntax */
import { remark } from 'remark';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypeFigure from '@microflash/rehype-figure';
export default function markdown2Html(content: string) {
return remark()
.use(remarkGfm)
.use(remarkRehype)
.use(rehypeFigure)
.use(rehypeStringify)
.processSync(content)
.toString();
}

View File

@ -12,6 +12,16 @@
padding-bottom: 16px;
}
/* figcaption */
figcaption {
color: #a3a3a3;
text-align: center;
}
figure {
cursor: pointer;
}
/* Table Styles */
table {
width: 100%;
@ -33,12 +43,7 @@
th,
td {
width: 10%;
}
th+th,
td+td {
width: 30%;
width: 33%;
}
th {
@ -89,6 +94,22 @@
<body>
{{reportContent}}
<script>
window.addEventListener('click', function (e) {
if (e.target.tagName === 'FIGCAPTION') {
// get previous sibling
const img = e.target.previousElementSibling;
if (img.tagName === 'IMG' && img.src) {
window.open(img.src, '_blank');
}
}
if (e.target.tagName === 'IMG' && e.target.src) {
window.open(e.target.src, '_blank');
}
});
</script>
</body>
</html>
</html>

View File

@ -25,3 +25,5 @@ declare module '@npmcli/run-script' {
[key: string]: string | string[] | boolean | NodeJS.ProcessEnv;
}): Promise<void>;
}
declare module '@microflash/rehype-figure';