ant-design/scripts/visual-regression/upload.js
renovate[bot] 863f61d908
chore(deps): update dependency eslint to v9 ()
Co-authored-by: afc163 <afc163@gmail.com>
2024-09-19 03:30:19 +08:00

170 lines
4.3 KiB
JavaScript

// Attention: use all node builtin modules except `ali-oss`
// Must keep our ak/sk safe
const OSS = require('ali-oss');
const path = require('path');
const fs = require('fs');
const assert = require('assert');
// node scripts/visual-regression/upload.js ./visualRegressionReport.tar.gz --ref=pr-id
// node scripts/visual-regression/upload.js ./imageSnapshots.tar.gz --ref=master-commitId
const args = process.argv.slice(2);
if (args.length < 2) {
console.error('Usage: node scripts/visual-regression/upload.js <tarFilePath> --ref=<refValue>');
process.exit(1);
}
const ALI_OSS_BUCKET = 'antd-visual-diff';
function retry(promise, retries, delay = 3000) {
return new Promise((resolve, reject) => {
const attempt = () => {
promise.then(resolve).catch((error) => {
if (retries > 0) {
setTimeout(() => {
attempt();
}, delay);
retries--;
} else {
reject(error);
}
});
};
attempt();
});
}
/**
* Extract the tar file path and ref value from the cli arguments
* @param {string[]} cliArgs
*/
function parseArgs(cliArgs) {
const filepath = cliArgs[0];
let refValue = '';
for (let i = 1; i < cliArgs.length; i++) {
if (cliArgs[i].startsWith('--ref=')) {
refValue = cliArgs[i].substring(6);
break;
}
}
assert(filepath, 'filepath is required');
assert(refValue, 'refValue is required');
return [filepath, refValue];
}
async function walkDir(dirPath) {
const fileList = [];
const files = await fs.promises.readdir(dirPath);
for (const file of files) {
const filePath = path.join(dirPath, file);
const fileStat = fs.statSync(filePath);
if (fileStat.isDirectory()) {
// Recursively call this func for subdirs
fileList.push(...(await walkDir(filePath)));
} else {
fileList.push(filePath);
}
}
return fileList;
}
/**
*
* @param {import('ali-oss')} client
* @param {*} filePath
* @param {*} refValue
*/
async function uploadFile(client, filePath, refValue) {
const headers = {
// https://help.aliyun.com/zh/oss/user-guide/object-acl
'x-oss-object-acl': 'public-read',
// https://help.aliyun.com/zh/oss/developer-reference/prevent-objects-from-being-overwritten-by-objects-that-have-the-same-names-3
'x-oss-forbid-overwrite': 'false',
'Content-Disposition': 'inline',
};
// Set content-type to allow individual preview of images
if (path.extname(filePath) === '.png') {
headers['Content-Type'] = 'image/png';
}
console.log('Uploading file: %s', filePath);
try {
const targetFilePath = path.relative(process.cwd(), filePath);
const r1 = await client.put(`${refValue}/${targetFilePath}`, filePath, {
headers,
timeout: 60000 * 2,
});
console.log('Uploading file successfully: %s', r1.name);
} catch (err) {
console.error('Uploading file failed: %s', err);
throw err;
}
}
async function boot() {
const [fileOrFolderName, refValue] = parseArgs(args);
// check if exists
const workspacePath = path.resolve(process.cwd(), fileOrFolderName);
if (!fs.existsSync(workspacePath)) {
console.error('File not exists: %s', workspacePath);
process.exit(1);
}
const client = new OSS({
endpoint: 'oss-cn-shanghai.aliyuncs.com',
accessKeyId: process.env.ALI_OSS_AK_ID,
accessKeySecret: process.env.ALI_OSS_AK_SECRET,
bucket: ALI_OSS_BUCKET,
});
// if is a file then upload it directly
const stat = fs.statSync(workspacePath);
if (stat.isFile()) {
const doUpload = uploadFile(client, workspacePath, refValue);
try {
await retry(doUpload, 3);
} catch (err) {
console.error(
'Uploading file `%s` failed after retry %s, error: %s',
fileOrFolderName,
3,
err,
);
process.exit(1);
}
return;
}
if (stat.isDirectory()) {
const fileList = await walkDir(workspacePath);
for (const file of fileList) {
const doUpload = uploadFile(client, file, refValue);
try {
await retry(doUpload, 3);
} catch (err) {
console.warn(
'Skip uploading file `%s` in folder `%s` failed after retry %s, error: %s',
path.relative(workspacePath, file),
fileOrFolderName,
3,
err,
);
}
}
}
}
boot();