From 097a085a2a980cf3890b68deb8fbdea9e26a962a Mon Sep 17 00:00:00 2001 From: Raz Luvaton <16746759+rluvaton@users.noreply.github.com> Date: Wed, 5 Jul 2023 21:56:44 +0300 Subject: [PATCH 1/3] feat: allow running on multiple packages --- .gitignore | 1 + README.md | 14 ++--- lib/bin/citgm.js | 127 ++++++++++++++++++++++++++++++----------- test/bin/test-citgm.js | 23 ++++++++ 4 files changed, 126 insertions(+), 39 deletions(-) diff --git a/.gitignore b/.gitignore index 0be52c37f..2f9914051 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ test/.* coverage/ .nyc_output/ .eslintcache +.idea diff --git a/README.md b/README.md index d2ac00b63..17ba12ff9 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ citgm --help ``` ``` -Usage: citgm [options] +Usage: citgm [options] Options: @@ -222,14 +222,14 @@ const coverageProcess = spawnSync('nyc', [ ]); const coverageSummary = require(path.join( - process.env.WORKSPACE, - packageName, - 'coverage-summary.json' + process.env.WORKSPACE, + packageName, + 'coverage-summary.json' )); console.log( - packageName, - 'total coverage result(%)', - coverageSummary.total.lines.pct + packageName, + 'total coverage result(%)', + coverageSummary.total.lines.pct ); ``` diff --git a/lib/bin/citgm.js b/lib/bin/citgm.js index 973ec0e29..7e5dacc90 100755 --- a/lib/bin/citgm.js +++ b/lib/bin/citgm.js @@ -7,18 +7,22 @@ import { windows, Tester } from '../citgm.js'; import { commonArgs } from '../common-args.js'; import { logger } from '../out.js'; import * as reporter from '../reporter/index.js'; +import async from 'async'; -let mod; +let mods; -const yargs = commonArgs().usage('citgm [options] ').option('sha', { - alias: 'c', - type: 'string', - description: 'Install module from commit-sha, branch or tag' -}); +const yargs = commonArgs() + .usage('citgm [options] ') + .option('sha', { + alias: 'c', + type: 'string', + description: 'Install module from commit-sha, branch or tag' + }); const app = yargs.argv; -mod = app._[0]; +mods = app._; +let modules = []; const log = logger({ level: app.verbose, @@ -32,7 +36,7 @@ if (!app.su) { log.warn('root', 'Running as root! Use caution!'); } -if (!mod) { +if (!mods.length) { yargs.showHelp(); process.exit(0); } @@ -56,18 +60,23 @@ if (!windows) { uidnumber(uid, gid, (err, uid, gid) => { options.uid = uid; options.gid = gid; - launch(mod, options); + launch(); }); } else { - launch(mod, options); + launch(); } -const start = new Date(); -function launch(mod, options) { +function runCitgm(mod, next) { + const start = new Date(); const runner = new Tester(mod, options); + let bailed = false; function cleanup() { + bailed = true; runner.cleanup(); + process.removeListener('SIGINT', cleanup); + process.removeListener('SIGHUP', cleanup); + process.removeListener('SIGBREAK', cleanup); } process.on('SIGINT', cleanup); @@ -84,28 +93,82 @@ function launch(mod, options) { .on('data', (type, key, message) => { log[type](key, message); }) - .on('end', (module) => { - module.duration = new Date() - start; - reporter.logger(log, module); - - log.info('duration', `test duration: ${module.duration}ms`); - if (app.markdown) { - reporter.markdown(log.bypass, module); + .on('end', (result) => { + result.duration = new Date() - start; + log.info('duration', `test duration: ${result.duration}ms`); + if (result.error) { + log.error( + `${result.name} done`, + `done - the test suite for ${result.name} version ${result.version} failed` + ); + } else { + log.info( + `${result.name} done`, + `done - the test suite for ${result.name} version ${result.version} passed.` + ); } - if (app.tap) { - const tap = typeof app.tap === 'string' ? app.tap : log.bypass; - reporter.tap(tap, module, app.append); + modules.push(result); + if (!bailed) { + process.removeListener('SIGINT', cleanup); + process.removeListener('SIGHUP', cleanup); + process.removeListener('SIGBREAK', cleanup); } - - if (app.junit) { - const junit = typeof app.junit === 'string' ? app.junit : log.bypass; - reporter.junit(junit, module, app.append); - } - - process.removeListener('SIGINT', cleanup); - process.removeListener('SIGHUP', cleanup); - process.removeListener('SIGBREAK', cleanup); - process.exit(module.error ? 1 : 0); + return next(bailed); }) .run(); } + +function runTask(mod, next) { + runCitgm(mod, next); +} +// +// function mapCallback(name) { +// return { name: name, mod: lookup[name] }; +// } + +function launch() { + const collection = mods; + + const q = async.queue(runTask, app.parallel || 1); + q.push(collection); + function done(exitCode = 0) { + q.kill(); + reporter.logger(log, modules); + + if (app.markdown) { + reporter.markdown(log.bypass, modules); + } + + if (app.tap) { + // If tap is a string it should be a path to write output to + // If not use `log.bypass` which is currently process.stdout.write + // TODO check that we can write to that path, perhaps require a flag to + // Overwrite + const tap = typeof app.tap === 'string' ? app.tap : log.bypass; + reporter.tap(tap, modules, app.append); + } + + if (app.junit) { + const junit = typeof app.junit === 'string' ? app.junit : log.bypass; + reporter.junit(junit, modules, app.append); + } + + const hasFailures = reporter.util.hasFailures(modules) ? 1 : 0; + process.exit(hasFailures || exitCode); + } + + function abort() { + q.pause(); + q.kill(); + process.removeListener('SIGINT', abort); + process.removeListener('SIGHUP', abort); + process.removeListener('SIGBREAK', abort); + done(1); + } + + q.drain(done); + + process.on('SIGINT', abort); + process.on('SIGHUP', abort); + process.on('SIGBREAK', abort); +} diff --git a/test/bin/test-citgm.js b/test/bin/test-citgm.js index bff8fa29d..f3e62803a 100644 --- a/test/bin/test-citgm.js +++ b/test/bin/test-citgm.js @@ -61,6 +61,29 @@ test('bin: omg-i-pass /w local module', (t) => { }); }); +test('bin: multiple packages', (t) => { + t.plan(3); + const proc = spawn(citgmPath, ['omg-i-pass', 'omg-i-fail']); + let stdout = ''; + + proc.on('close', (code) => { + t.ok(code !== 0, 'omg-i-fail should fail with a non-zero exit code'); + t.match( + stdout, + /info:\s*starting\s*\|\s*omg-i-pass\s*/, + 'stdout should contain omg-i-pass' + ); + t.match( + stdout, + /info:\s*starting\s*\|\s*omg-i-fail\s*/, + 'stdout should contain omg-i-fail' + ); + }); + proc.stdout.on('data', (data) => { + stdout += data; + }); +}); + test('bin: no module /w root check', (t) => { t.plan(1); const proc = spawn(citgmPath, ['-s']); From ca3aa05234853cf2501b585dfdbcf1750a82e254 Mon Sep 17 00:00:00 2001 From: Raz Luvaton <16746759+rluvaton@users.noreply.github.com> Date: Wed, 5 Jul 2023 21:57:10 +0300 Subject: [PATCH 2/3] remove commented code --- lib/bin/citgm.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/bin/citgm.js b/lib/bin/citgm.js index 7e5dacc90..5abab80a6 100755 --- a/lib/bin/citgm.js +++ b/lib/bin/citgm.js @@ -121,10 +121,6 @@ function runCitgm(mod, next) { function runTask(mod, next) { runCitgm(mod, next); } -// -// function mapCallback(name) { -// return { name: name, mod: lookup[name] }; -// } function launch() { const collection = mods; From a3c1b1662c5369ee7427985873f642f20938c646 Mon Sep 17 00:00:00 2001 From: Raz Luvaton <16746759+rluvaton@users.noreply.github.com> Date: Wed, 5 Jul 2023 21:59:00 +0300 Subject: [PATCH 3/3] revert format --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 17ba12ff9..2c9ef1b51 100644 --- a/README.md +++ b/README.md @@ -222,14 +222,14 @@ const coverageProcess = spawnSync('nyc', [ ]); const coverageSummary = require(path.join( - process.env.WORKSPACE, - packageName, - 'coverage-summary.json' + process.env.WORKSPACE, + packageName, + 'coverage-summary.json' )); console.log( - packageName, - 'total coverage result(%)', - coverageSummary.total.lines.pct + packageName, + 'total coverage result(%)', + coverageSummary.total.lines.pct ); ```