mirror of
https://github.com/ant-design/ant-design.git
synced 2024-11-27 12:39:49 +08:00
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:
parent
daba39b88a
commit
b42ffe64f4
@ -181,6 +181,7 @@
|
|||||||
"@emotion/server": "^11.11.0",
|
"@emotion/server": "^11.11.0",
|
||||||
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
|
"@ianvs/prettier-plugin-sort-imports": "^4.2.1",
|
||||||
"@madccc/duplicate-package-checker-webpack-plugin": "^1.0.0",
|
"@madccc/duplicate-package-checker-webpack-plugin": "^1.0.0",
|
||||||
|
"@microflash/rehype-figure": "^2.1.0",
|
||||||
"@npmcli/run-script": "^7.0.4",
|
"@npmcli/run-script": "^7.0.4",
|
||||||
"@octokit/rest": "^20.1.0",
|
"@octokit/rest": "^20.1.0",
|
||||||
"@qixian.cs/github-contributors-list": "^2.0.1",
|
"@qixian.cs/github-contributors-list": "^2.0.1",
|
||||||
@ -314,13 +315,14 @@
|
|||||||
"react-router-dom": "^6.22.3",
|
"react-router-dom": "^6.22.3",
|
||||||
"react-sticky-box": "^2.0.5",
|
"react-sticky-box": "^2.0.5",
|
||||||
"regenerator-runtime": "^0.14.1",
|
"regenerator-runtime": "^0.14.1",
|
||||||
|
"rehype-stringify": "^10.0.0",
|
||||||
"remark": "^15.0.1",
|
"remark": "^15.0.1",
|
||||||
"remark-cli": "^12.0.0",
|
"remark-cli": "^12.0.0",
|
||||||
"remark-gfm": "^4.0.0",
|
"remark-gfm": "^4.0.0",
|
||||||
"remark-html": "^16.0.1",
|
|
||||||
"remark-lint": "^9.1.2",
|
"remark-lint": "^9.1.2",
|
||||||
"remark-lint-no-undefined-references": "^4.2.1",
|
"remark-lint-no-undefined-references": "^4.2.1",
|
||||||
"remark-preset-lint-recommended": "^6.1.3",
|
"remark-preset-lint-recommended": "^6.1.3",
|
||||||
|
"remark-rehype": "^11.1.0",
|
||||||
"runes2": "^1.1.4",
|
"runes2": "^1.1.4",
|
||||||
"semver": "^7.6.0",
|
"semver": "^7.6.0",
|
||||||
"sharp": "^0.33.3",
|
"sharp": "^0.33.3",
|
||||||
|
@ -6,17 +6,17 @@ import os from 'os';
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
import { finished } from 'stream/promises';
|
import { finished } from 'stream/promises';
|
||||||
|
import simpleGit from 'simple-git';
|
||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
import fse from 'fs-extra';
|
import fse from 'fs-extra';
|
||||||
import difference from 'lodash/difference';
|
import difference from 'lodash/difference';
|
||||||
import minimist from 'minimist';
|
import minimist from 'minimist';
|
||||||
import pixelmatch from 'pixelmatch';
|
import pixelmatch from 'pixelmatch';
|
||||||
import { PNG } from 'pngjs';
|
import { PNG } from 'pngjs';
|
||||||
import { remark } from 'remark';
|
|
||||||
import remarkGfm from 'remark-gfm';
|
|
||||||
import remarkHtml from 'remark-html';
|
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
|
|
||||||
|
import markdown2Html from './convert';
|
||||||
|
|
||||||
const ROOT_DIR = process.cwd();
|
const ROOT_DIR = process.cwd();
|
||||||
const ALI_OSS_BUCKET = 'antd-visual-diff';
|
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 {
|
interface IBadCase {
|
||||||
type: 'removed' | 'changed';
|
type: 'removed' | 'changed';
|
||||||
filename: string;
|
filename: string;
|
||||||
|
/**
|
||||||
|
* compare target file
|
||||||
|
*/
|
||||||
|
targetFilename?: string;
|
||||||
/**
|
/**
|
||||||
* 0 - 1
|
* 0 - 1
|
||||||
*/
|
*/
|
||||||
weight: number;
|
weight: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
function md2Html(md: string) {
|
const git = simpleGit();
|
||||||
return remark().use(remarkGfm).use(remarkHtml).processSync(md).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
function parseArgs() {
|
async function parseArgs() {
|
||||||
// parse args from -- --pr-id=123 --base_ref=feature
|
// parse args from -- --pr-id=123 --base_ref=feature
|
||||||
const argv = minimist(process.argv.slice(2));
|
const argv = minimist(process.argv.slice(2));
|
||||||
const prId = argv['pr-id'];
|
const prId = argv['pr-id'];
|
||||||
assert(prId, 'Missing --pr-id');
|
assert(prId, 'Missing --pr-id');
|
||||||
const baseRef = argv['base-ref'];
|
const baseRef = argv['base-ref'];
|
||||||
assert(baseRef, 'Missing --base-ref');
|
assert(baseRef, 'Missing --base-ref');
|
||||||
|
|
||||||
|
const { latest } = await git.log();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
prId,
|
prId,
|
||||||
baseRef,
|
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(
|
function generateReport(
|
||||||
badCases: IBadCase[],
|
badCases: IBadCase[],
|
||||||
targetBranch: string,
|
targetBranch: string,
|
||||||
targetRef: string,
|
targetRef: string,
|
||||||
|
currentRef: string,
|
||||||
prId: string,
|
prId: string,
|
||||||
): [string, string] {
|
): [string, string] {
|
||||||
const reportDirname = path.basename(REPORT_DIR);
|
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" />',
|
'<img src="https://github.com/ant-design/ant-design/assets/507615/2d1a77dc-dbc6-4b0f-9cbc-19a43d3c29cd" width="300" />',
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
return [mdStr, md2Html(mdStr)];
|
return [mdStr, markdown2Html(mdStr)];
|
||||||
}
|
}
|
||||||
|
|
||||||
let reportMdStr = `
|
let reportMdStr = `
|
||||||
${commonHeader}
|
${commonHeader}
|
||||||
${fullReport}
|
${fullReport}
|
||||||
|
|
||||||
| Image name | Expected | Actual | Diff |
|
| Expected (Branch ${targetBranch}) | Actual (Current PR) | Diff |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- |
|
||||||
`.trim();
|
`.trim();
|
||||||
|
|
||||||
reportMdStr += '\n';
|
reportMdStr += '\n';
|
||||||
@ -192,44 +256,33 @@ ${fullReport}
|
|||||||
let diffCount = 0;
|
let diffCount = 0;
|
||||||
|
|
||||||
for (const badCase of badCases) {
|
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;
|
diffCount += 1;
|
||||||
if (diffCount <= 10) {
|
if (diffCount <= 10) {
|
||||||
reportMdStr += lineReportMdStr;
|
// 将图片下方增加文件名
|
||||||
|
reportMdStr += generateLineReport(
|
||||||
|
badCase,
|
||||||
|
publicPath,
|
||||||
|
currentRef,
|
||||||
|
true,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fullVersionMd += lineReportMdStr;
|
fullVersionMd += generateLineReport(
|
||||||
|
badCase,
|
||||||
|
publicPath,
|
||||||
|
currentRef,
|
||||||
|
false,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
reportMdStr += addonFullReportDesc;
|
reportMdStr += addonFullReportDesc;
|
||||||
|
|
||||||
// convert fullVersionMd to html
|
// convert fullVersionMd to html
|
||||||
return [reportMdStr, md2Html(fullVersionMd)];
|
return [reportMdStr, markdown2Html(fullVersionMd)];
|
||||||
}
|
}
|
||||||
|
|
||||||
async function boot() {
|
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}`);
|
const baseImgSourceDir = path.resolve(ROOT_DIR, `./imageSnapshots-${targetBranch}`);
|
||||||
|
|
||||||
@ -324,6 +377,7 @@ async function boot() {
|
|||||||
badCases.push({
|
badCases.push({
|
||||||
type: 'changed',
|
type: 'changed',
|
||||||
filename: compareImgName,
|
filename: compareImgName,
|
||||||
|
targetFilename: baseImgName,
|
||||||
weight: mismatchedPxPercent,
|
weight: mismatchedPxPercent,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@ -340,6 +394,7 @@ async function boot() {
|
|||||||
badCases,
|
badCases,
|
||||||
targetBranch,
|
targetBranch,
|
||||||
targetCommitSha,
|
targetCommitSha,
|
||||||
|
currentRef,
|
||||||
prId,
|
prId,
|
||||||
);
|
);
|
||||||
await fse.writeFile(path.join(REPORT_DIR, './report.md'), reportMdStr);
|
await fse.writeFile(path.join(REPORT_DIR, './report.md'), reportMdStr);
|
||||||
|
17
scripts/visual-regression/convert.ts
Normal file
17
scripts/visual-regression/convert.ts
Normal 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();
|
||||||
|
}
|
@ -12,6 +12,16 @@
|
|||||||
padding-bottom: 16px;
|
padding-bottom: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* figcaption */
|
||||||
|
figcaption {
|
||||||
|
color: #a3a3a3;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
/* Table Styles */
|
/* Table Styles */
|
||||||
table {
|
table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
@ -33,12 +43,7 @@
|
|||||||
|
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
width: 10%;
|
width: 33%;
|
||||||
}
|
|
||||||
|
|
||||||
th+th,
|
|
||||||
td+td {
|
|
||||||
width: 30%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
@ -89,6 +94,22 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
{{reportContent}}
|
{{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>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
2
typings/custom-typings.d.ts
vendored
2
typings/custom-typings.d.ts
vendored
@ -25,3 +25,5 @@ declare module '@npmcli/run-script' {
|
|||||||
[key: string]: string | string[] | boolean | NodeJS.ProcessEnv;
|
[key: string]: string | string[] | boolean | NodeJS.ProcessEnv;
|
||||||
}): Promise<void>;
|
}): Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
declare module '@microflash/rehype-figure';
|
||||||
|
Loading…
Reference in New Issue
Block a user