chore: 整理 third-party Dark Reader 目录并移除本地说明文件跟踪
This commit is contained in:
Vendored
+208
@@ -0,0 +1,208 @@
|
||||
/**
|
||||
* This file executes build.js in a child process, this is needed for two things:
|
||||
* 1. Enable interrupts like Ctrl+C for regular builds
|
||||
* 2. Support building older versions of Dark Reader and then inserting signatures into archives
|
||||
*/
|
||||
|
||||
// @ts-check
|
||||
import assert from 'node:assert/strict';
|
||||
import {fork} from 'node:child_process';
|
||||
import {rm, stat} from 'node:fs/promises';
|
||||
import {join} from 'node:path';
|
||||
import process from 'node:process';
|
||||
import {fileURLToPath} from 'node:url';
|
||||
|
||||
import signature from './bundle-signature.js';
|
||||
import {PLATFORM} from './platform.js';
|
||||
import {runTasks} from './task.js';
|
||||
import {execute, log} from './utils.js';
|
||||
import zip from './zip.js';
|
||||
|
||||
|
||||
const __filename = join(fileURLToPath(import.meta.url), '../build.js');
|
||||
|
||||
function getSignatureDir(version) {
|
||||
return join(fileURLToPath(import.meta.url), `../../integrity/firefox/`, version);
|
||||
}
|
||||
|
||||
async function executeChildProcess(args) {
|
||||
const child = fork(__filename, args);
|
||||
// Send SIGINTs as SIGKILLs, which are not ignored
|
||||
process.on('SIGINT', () => {
|
||||
child.kill('SIGKILL');
|
||||
process.exit(130);
|
||||
});
|
||||
return new Promise((resolve, reject) => child.on('error', reject).on('close', resolve));
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
console.log([
|
||||
'Dark Reader build utility',
|
||||
'',
|
||||
'Usage: build [build parameters]',
|
||||
'',
|
||||
'To narrow down the list of build targets (for efficiency):',
|
||||
' --api Library build (published to NPM)',
|
||||
' --chrome MV2 for Chromium-based browsers (published to Chrome Web Store)',
|
||||
' --chrome-mv3 MV3 for Chromium-based browsers (will replace MV2 version eventually)',
|
||||
' --firefox MV2 for Firefox (published to Mozilla Add-on store)',
|
||||
' --thunderbird Thunderbird',
|
||||
'',
|
||||
'To specify type of build:',
|
||||
' --release Release bundle for signing prior to publication',
|
||||
' --version=* Released bundle complete with digital signature (Firefox only)',
|
||||
' --debug Build for development',
|
||||
' --watch Incremental build for development',
|
||||
'',
|
||||
'To log errors to disk (for debugging and bug reports):',
|
||||
' --log-info Log lots of data',
|
||||
' --log-warn Log only warnings',
|
||||
'',
|
||||
'Build for testing (not to be used by humans):',
|
||||
' --test',
|
||||
].join('\n'));
|
||||
}
|
||||
|
||||
function getVersion(args) {
|
||||
const prefix = '--version=';
|
||||
const arg = args.find((arg) => arg.startsWith(prefix));
|
||||
if (!arg) {
|
||||
return null;
|
||||
}
|
||||
const version = arg.substring(prefix.length);
|
||||
if (/^\d+(.\d+){0,3}$/.test(version)) {
|
||||
return version;
|
||||
}
|
||||
throw new Error(`Invalid version argument ${version}`);
|
||||
}
|
||||
|
||||
async function ensureGitClean() {
|
||||
const diff = await execute('git diff');
|
||||
if (diff) {
|
||||
throw new Error('git source tree is not clean. Pease commit your work and try again');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks out a particular revision of source code and dependencies,
|
||||
* audits dependencies and applies fixes to vulnerabilities.
|
||||
* Fixes for vulnerabilities should not affect build output since most
|
||||
* vulnerabilities reside in code which never gets reached during build.
|
||||
* However, fixing the vulnerabilities and obtaining a build with all "clean"
|
||||
* dependencies which is identical to already published version serves as a proof
|
||||
* that the published version was always free of (now known) vulnerabilities.
|
||||
*
|
||||
* @param {string} version The desired git version, e.g., 'v4.9.63' or 'v4.9.37.1'
|
||||
* @param {boolean} fixVulnerabilities Whether of not to attempt to fix known vulnerabilities
|
||||
*/
|
||||
async function checkoutVersion(version, fixVulnerabilities) {
|
||||
log.ok(`Checking out version ${version}`);
|
||||
// Use -- to disambiguate the tag (release version) and file paths
|
||||
await rm('src', {force: true, recursive: true});
|
||||
await execute(`git restore --source v${version} -- package.json package-lock.json src/ tasks/`);
|
||||
log.ok(`Installing dependencies`);
|
||||
await execute('npm install --ignore-scripts');
|
||||
if (!fixVulnerabilities) {
|
||||
log.ok(`Skipping dependency audit`);
|
||||
return;
|
||||
}
|
||||
log.ok(`Dependency audit`);
|
||||
const deps = JSON.parse(await execute('npm audit fix --force --ignore-scripts --json'));
|
||||
if (deps.audit.auditReportVersion !== 2) {
|
||||
throw new Error('Could not audit dependencies');
|
||||
}
|
||||
if (deps.audit.metadata.vulnerabilities.total !== 0) {
|
||||
throw new Error('Dependency vulnerability without a fix found, please audit manually');
|
||||
}
|
||||
}
|
||||
|
||||
async function checkoutHead() {
|
||||
// Restore current files
|
||||
await execute('git restore --source HEAD -- package.json package-lock.json src/ tasks/');
|
||||
// Clean up files which existed earlier but were deleted
|
||||
await execute('git clean -f -- package.json package-lock.json src/ tasks/');
|
||||
await execute('npm install --ignore-scripts');
|
||||
}
|
||||
|
||||
function validateArguments(args) {
|
||||
const validationErrors = [];
|
||||
|
||||
const validFlags = ['--api', '--chrome', '--chrome-mv2', '--chrome-mv3', '--firefox', '--firefox-mv2', '--thunderbird', '--release', '--debug', '--watch', '--plus', '--log-info', '--log-warn', '--test'];
|
||||
const invalidFlags = args.filter((flag) => !validFlags.includes(flag) && !flag.startsWith('--version='));
|
||||
invalidFlags.forEach((flag) => validationErrors.push(`Invalid flag ${flag}`));
|
||||
|
||||
if (args.some((arg) => arg.startsWith('--version='))) {
|
||||
if (!args.includes('--firefox') || !args.includes('--release') || args.length !== 3) {
|
||||
validationErrors.push('Only Firefox build currently supports signed builds');
|
||||
}
|
||||
}
|
||||
return validationErrors;
|
||||
}
|
||||
|
||||
function parseArguments(args) {
|
||||
return args.filter((arg) => !arg.startsWith('--version='));
|
||||
}
|
||||
|
||||
async function run() {
|
||||
const args = process.argv.slice(3);
|
||||
|
||||
const shouldPrintHelp = args.length === 0 || process.argv[2] !== 'build' || args.includes('-h') || args.includes('--help');
|
||||
if (shouldPrintHelp) {
|
||||
printHelp();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const validationErrors = validateArguments(args);
|
||||
if (validationErrors.length > 0) {
|
||||
validationErrors.forEach(log.error);
|
||||
printHelp();
|
||||
process.exit(130);
|
||||
}
|
||||
|
||||
const version = getVersion(args);
|
||||
|
||||
// If building signed build, check that required signature files exist
|
||||
if (version) {
|
||||
try {
|
||||
const signatureDir = getSignatureDir(version);
|
||||
const stats = await stat(signatureDir);
|
||||
assert(stats.isDirectory());
|
||||
} catch (e) {
|
||||
console.log(`Could not find signature files for version ${version}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// We need to install new deps prior to forking for them to be loaded properly
|
||||
if (version) {
|
||||
try {
|
||||
await ensureGitClean();
|
||||
await checkoutVersion(version, args.includes('--fix-deps'));
|
||||
} catch (e) {
|
||||
log.error(`Could not check out tag ${version}. ${e}`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const childArgs = parseArguments(args);
|
||||
|
||||
await executeChildProcess(childArgs);
|
||||
|
||||
if (version) {
|
||||
log.ok('PACKING SIGNATURES');
|
||||
await checkoutHead();
|
||||
|
||||
await runTasks([signature, zip], {
|
||||
version,
|
||||
platforms: {
|
||||
[PLATFORM.FIREFOX_MV2]: true,
|
||||
},
|
||||
debug: false,
|
||||
watch: false,
|
||||
log: false,
|
||||
test: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
Reference in New Issue
Block a user