From e54a2297e840a3b376818cd570d40fc8be87e527 Mon Sep 17 00:00:00 2001 From: toasted-nutbread Date: Fri, 18 Dec 2020 20:51:22 -0500 Subject: [PATCH] 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 --- dev/build.js | 114 ++++++++++++++++++++++++++++++++++----------------- dev/util.js | 4 +- package.json | 5 ++- 3 files changed, 82 insertions(+), 41 deletions(-) diff --git a/dev/build.js b/dev/build.js index df38e2a4..63975519 100644 --- a/dev/build.js +++ b/dev/build.js @@ -17,42 +17,50 @@ const fs = require('fs'); const path = require('path'); +const assert = require('assert'); const readline = require('readline'); const childProcess = require('child_process'); const util = require('./util'); -const {getAllFiles, getDefaultManifestAndVariants, createManifestString, getArgs} = util; +const {getAllFiles, getDefaultManifestAndVariants, createManifestString, getArgs, testMain} = util; function clone(value) { return JSON.parse(JSON.stringify(value)); } -async function createZip(directory, excludeFiles, outputFileName, sevenZipExes=[], onUpdate=null) { - fs.unlinkSync(outputFileName); - for (const exe of sevenZipExes) { - try { - const excludeArguments = excludeFiles.map((excludeFilePath) => `-x!${excludeFilePath}`); - childProcess.execFileSync( - exe, - [ - 'a', - outputFileName, - '.', - ...excludeArguments - ], - { - cwd: directory - } - ); - return; - } catch (e) { - // NOP +async function createZip(directory, excludeFiles, outputFileName, sevenZipExes, onUpdate, dryRun) { + try { + fs.unlinkSync(outputFileName); + } catch (e) { + // NOP + } + + if (!dryRun) { + for (const exe of sevenZipExes) { + try { + const excludeArguments = excludeFiles.map((excludeFilePath) => `-x!${excludeFilePath}`); + childProcess.execFileSync( + exe, + [ + 'a', + outputFileName, + '.', + ...excludeArguments + ], + { + 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 files = getAllFiles(directory, directory); removeItemsFromArray(files, excludeFiles); @@ -76,7 +84,9 @@ async function createJSZip(directory, excludeFiles, outputFileName, onUpdate) { }, onUpdate); 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) { @@ -272,15 +282,18 @@ function createVariantManifest(manifest, variant, variantMap) { 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']; // Create build directory - if (!fs.existsSync(buildDir)) { + if (!fs.existsSync(buildDir) && !dryRun) { fs.mkdirSync(buildDir, {recursive: true}); } + const dontLogOnUpdate = !process.stdout.isTTY; const onUpdate = (metadata) => { + if (dontLogOnUpdate) { return; } + let message = `Progress: ${metadata.percent.toFixed(2)}%`; if (metadata.currentFile) { message += ` (${metadata.currentFile})`; @@ -305,13 +318,21 @@ async function build(manifest, buildDir, extDir, manifestPath, variantMap, varia const fileNameSafe = path.basename(fileName); const fullFileName = path.join(buildDir, fileNameSafe); - fs.writeFileSync(manifestPath, createManifestString(modifiedManifest)); - await createZip(extDir, excludeFiles, fullFileName, sevenZipExes, onUpdate); + ensureFilesExist(extDir, excludeFiles); + if (!dryRun) { + fs.writeFileSync(manifestPath, createManifestString(modifiedManifest)); + } - if (Array.isArray(fileCopies)) { - for (const fileName2 of fileCopies) { - const fileName2Safe = path.basename(fileName2); - fs.copyFileSync(fullFileName, path.join(buildDir, fileName2Safe)); + if (!dryRun || dryRunBuildZip) { + await createZip(extDir, excludeFiles, fullFileName, sevenZipExes, onUpdate, dryRun); + } + + 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([ ['all', false], ['default', false], ['manifest', null], + ['dry-run', false], + ['dry-run-build-zip', false], [null, []] ])); + const dryRun = args.get('dry-run'); + const dryRunBuildZip = args.get('dry-run-build-zip'); + const {manifest, variants} = getDefaultManifestAndVariants(); const rootDir = path.join(__dirname, '..'); @@ -343,7 +374,7 @@ async function main() { try { 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 { // Restore manifest let restoreManifest = manifest; @@ -354,9 +385,18 @@ async function main() { } } 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 +}; diff --git a/dev/util.js b/dev/util.js index c17cd29a..a5d1ead9 100644 --- a/dev/util.js +++ b/dev/util.js @@ -137,9 +137,9 @@ function createDictionaryArchive(dictionaryDirectory, dictionaryName) { } -async function testMain(func) { +async function testMain(func, ...args) { try { - await func(); + await func(...args); } catch (e) { console.log(e); process.exit(-1); diff --git a/package.json b/package.json index 0add0cc6..02320d0c 100644 --- a/package.json +++ b/package.json @@ -7,11 +7,12 @@ }, "scripts": { "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-web-ext": "npx web-ext lint", "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": { "type": "git",