Build dry run test (#1129)

* Update testMain to support function args

* Add support for dry run and basic validation

* Don't log progress if not a TTY

* Ignore errors from fs.unlinkSync

* Add --dry-run-build-zip option to build zip in memory

* Add test-build
This commit is contained in:
toasted-nutbread 2020-12-18 20:51:22 -05:00 committed by GitHub
parent 2fa9b91515
commit e54a2297e8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 82 additions and 41 deletions

View File

@ -17,42 +17,50 @@
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const assert = require('assert');
const readline = require('readline'); const readline = require('readline');
const childProcess = require('child_process'); const childProcess = require('child_process');
const util = require('./util'); const util = require('./util');
const {getAllFiles, getDefaultManifestAndVariants, createManifestString, getArgs} = util; const {getAllFiles, getDefaultManifestAndVariants, createManifestString, getArgs, testMain} = util;
function clone(value) { function clone(value) {
return JSON.parse(JSON.stringify(value)); return JSON.parse(JSON.stringify(value));
} }
async function createZip(directory, excludeFiles, outputFileName, sevenZipExes=[], onUpdate=null) { async function createZip(directory, excludeFiles, outputFileName, sevenZipExes, onUpdate, dryRun) {
fs.unlinkSync(outputFileName); try {
for (const exe of sevenZipExes) { fs.unlinkSync(outputFileName);
try { } catch (e) {
const excludeArguments = excludeFiles.map((excludeFilePath) => `-x!${excludeFilePath}`); // NOP
childProcess.execFileSync( }
exe,
[ if (!dryRun) {
'a', for (const exe of sevenZipExes) {
outputFileName, try {
'.', const excludeArguments = excludeFiles.map((excludeFilePath) => `-x!${excludeFilePath}`);
...excludeArguments childProcess.execFileSync(
], exe,
{ [
cwd: directory 'a',
} outputFileName,
); '.',
return; ...excludeArguments
} catch (e) { ],
// NOP {
cwd: directory
}
);
return;
} catch (e) {
// NOP
}
} }
} }
return await createJSZip(directory, excludeFiles, outputFileName, onUpdate); return await createJSZip(directory, excludeFiles, outputFileName, onUpdate, dryRun);
} }
async function createJSZip(directory, excludeFiles, outputFileName, onUpdate) { async function createJSZip(directory, excludeFiles, outputFileName, onUpdate, dryRun) {
const JSZip = util.JSZip; const JSZip = util.JSZip;
const files = getAllFiles(directory, directory); const files = getAllFiles(directory, directory);
removeItemsFromArray(files, excludeFiles); removeItemsFromArray(files, excludeFiles);
@ -76,7 +84,9 @@ async function createJSZip(directory, excludeFiles, outputFileName, onUpdate) {
}, onUpdate); }, onUpdate);
process.stdout.write('\n'); process.stdout.write('\n');
fs.writeFileSync(outputFileName, data, {encoding: null, flag: 'w'}); if (!dryRun) {
fs.writeFileSync(outputFileName, data, {encoding: null, flag: 'w'});
}
} }
function removeItemsFromArray(array, removeItems) { function removeItemsFromArray(array, removeItems) {
@ -272,15 +282,18 @@ function createVariantManifest(manifest, variant, variantMap) {
return modifiedManifest; return modifiedManifest;
} }
async function build(manifest, buildDir, extDir, manifestPath, variantMap, variantNames) { async function build(manifest, buildDir, extDir, manifestPath, variantMap, variantNames, dryRun, dryRunBuildZip) {
const sevenZipExes = ['7za', '7z']; const sevenZipExes = ['7za', '7z'];
// Create build directory // Create build directory
if (!fs.existsSync(buildDir)) { if (!fs.existsSync(buildDir) && !dryRun) {
fs.mkdirSync(buildDir, {recursive: true}); fs.mkdirSync(buildDir, {recursive: true});
} }
const dontLogOnUpdate = !process.stdout.isTTY;
const onUpdate = (metadata) => { const onUpdate = (metadata) => {
if (dontLogOnUpdate) { return; }
let message = `Progress: ${metadata.percent.toFixed(2)}%`; let message = `Progress: ${metadata.percent.toFixed(2)}%`;
if (metadata.currentFile) { if (metadata.currentFile) {
message += ` (${metadata.currentFile})`; message += ` (${metadata.currentFile})`;
@ -305,13 +318,21 @@ async function build(manifest, buildDir, extDir, manifestPath, variantMap, varia
const fileNameSafe = path.basename(fileName); const fileNameSafe = path.basename(fileName);
const fullFileName = path.join(buildDir, fileNameSafe); const fullFileName = path.join(buildDir, fileNameSafe);
fs.writeFileSync(manifestPath, createManifestString(modifiedManifest)); ensureFilesExist(extDir, excludeFiles);
await createZip(extDir, excludeFiles, fullFileName, sevenZipExes, onUpdate); if (!dryRun) {
fs.writeFileSync(manifestPath, createManifestString(modifiedManifest));
}
if (Array.isArray(fileCopies)) { if (!dryRun || dryRunBuildZip) {
for (const fileName2 of fileCopies) { await createZip(extDir, excludeFiles, fullFileName, sevenZipExes, onUpdate, dryRun);
const fileName2Safe = path.basename(fileName2); }
fs.copyFileSync(fullFileName, path.join(buildDir, fileName2Safe));
if (!dryRun) {
if (Array.isArray(fileCopies)) {
for (const fileName2 of fileCopies) {
const fileName2Safe = path.basename(fileName2);
fs.copyFileSync(fullFileName, path.join(buildDir, fileName2Safe));
}
} }
} }
@ -319,16 +340,26 @@ async function build(manifest, buildDir, extDir, manifestPath, variantMap, varia
} }
} }
function ensureFilesExist(directory, files) {
for (const file of files) {
assert.ok(fs.existsSync(path.join(directory, file)));
}
}
async function main() {
const argv = process.argv.slice(2); async function main(argv) {
const args = getArgs(argv, new Map([ const args = getArgs(argv, new Map([
['all', false], ['all', false],
['default', false], ['default', false],
['manifest', null], ['manifest', null],
['dry-run', false],
['dry-run-build-zip', false],
[null, []] [null, []]
])); ]));
const dryRun = args.get('dry-run');
const dryRunBuildZip = args.get('dry-run-build-zip');
const {manifest, variants} = getDefaultManifestAndVariants(); const {manifest, variants} = getDefaultManifestAndVariants();
const rootDir = path.join(__dirname, '..'); const rootDir = path.join(__dirname, '..');
@ -343,7 +374,7 @@ async function main() {
try { try {
const variantNames = (argv.length === 0 || args.get('all') ? variants.map(({name}) => name) : args.get(null)); const variantNames = (argv.length === 0 || args.get('all') ? variants.map(({name}) => name) : args.get(null));
await build(manifest, buildDir, extDir, manifestPath, variantMap, variantNames); await build(manifest, buildDir, extDir, manifestPath, variantMap, variantNames, dryRun, dryRunBuildZip);
} finally { } finally {
// Restore manifest // Restore manifest
let restoreManifest = manifest; let restoreManifest = manifest;
@ -354,9 +385,18 @@ async function main() {
} }
} }
process.stdout.write('Restoring manifest...\n'); process.stdout.write('Restoring manifest...\n');
fs.writeFileSync(manifestPath, createManifestString(restoreManifest)); if (!dryRun) {
fs.writeFileSync(manifestPath, createManifestString(restoreManifest));
}
} }
} }
if (require.main === module) { main(); } if (require.main === module) {
testMain(main, process.argv.slice(2));
}
module.exports = {
main
};

View File

@ -137,9 +137,9 @@ function createDictionaryArchive(dictionaryDirectory, dictionaryName) {
} }
async function testMain(func) { async function testMain(func, ...args) {
try { try {
await func(); await func(...args);
} catch (e) { } catch (e) {
console.log(e); console.log(e);
process.exit(-1); process.exit(-1);

View File

@ -7,11 +7,12 @@
}, },
"scripts": { "scripts": {
"build": "node ./dev/build.js", "build": "node ./dev/build.js",
"test": "npm run test-lint && npm run test-code && npm run test-manifest", "test": "npm run test-lint && npm run test-code && npm run test-manifest && npm run test-build",
"test-lint": "eslint . && node ./dev/lint/global-declarations.js && node ./dev/lint/html-scripts.js", "test-lint": "eslint . && node ./dev/lint/global-declarations.js && node ./dev/lint/html-scripts.js",
"test-lint-web-ext": "npx web-ext lint", "test-lint-web-ext": "npx web-ext lint",
"test-code": "node ./test/test-all.js ./test --skip ./test/test-manifest.js", "test-code": "node ./test/test-all.js ./test --skip ./test/test-manifest.js",
"test-manifest": "node ./test/test-manifest.js" "test-manifest": "node ./test/test-manifest.js",
"test-build": "node ./dev/build.js --dry-run --all"
}, },
"repository": { "repository": {
"type": "git", "type": "git",