diff --git a/CHANGELOG.adoc b/CHANGELOG.adoc index e8b464cc8205adf8b0b5bc2db69a36bcd460f142..547d955328e0ef1d8c38e5e37b63ffcac9356915 100644 --- a/CHANGELOG.adoc +++ b/CHANGELOG.adoc @@ -16,6 +16,7 @@ For a detailed view of what's changed, refer to the {url-repo}/commits[commit hi * move repository URL inside paranthetical context in error message * report missing command in error message using ps.spawnargs[0] instead of cmdv[0] for consistency * rename project to Antora Collector and project repository to antora-collector (name of npm package remains the same) (#45) +* suppress stderr from command if runtime.silent key on playbook is true (#46) === Fixed diff --git a/docs/collector-extension/modules/ROOT/pages/configure-run.adoc b/docs/collector-extension/modules/ROOT/pages/configure-run.adoc index 32344c9d28fbc82bda4fe114f2b2a6cbc2363a0a..823087fe34d069b64a1c91ae1081e853d24d97d3 100644 --- a/docs/collector-extension/modules/ROOT/pages/configure-run.adoc +++ b/docs/collector-extension/modules/ROOT/pages/configure-run.adoc @@ -147,7 +147,8 @@ This alternation is not often needed if the command has arguments. By default, both the stdout (output stream) and stderr (error stream) of the command are directed to the current terminal. The extension also logs the command it's about to run at the info level. If you want to suppress the stdout and the info log message, you can set the `runtime.quiet` key in the playbook to true. -It's not currently possible to suppress the stderr. +If you also want to suppress the stderr, you can set the `runtime.silent` key in the playbook to true. +If the command fails, the stderr lines will still be appended to the error message. === Use the current Node.js diff --git a/packages/collector-extension/lib/index.js b/packages/collector-extension/lib/index.js index 37ac3422be2dba78c0ecb6c1eb4d61fca23b6882..20bbdcca3ab927739c444fe9cb4b682173075d4a 100644 --- a/packages/collector-extension/lib/index.js +++ b/packages/collector-extension/lib/index.js @@ -23,7 +23,8 @@ module.exports.register = function ({ config: { createWorktrees = 'auto', keepWo this.once('contentAggregated', async ({ playbook, contentAggregate }) => { let logger const playbookEnv = playbook.env - const quiet = playbook.runtime?.quiet + const silent = playbook.runtime?.silent + const quiet = silent || playbook.runtime?.quiet const cacheDir = ospath.join(getBaseCacheDir(playbook), 'collector') await fsp.mkdir(cacheDir, { recursive: true }) const git = this.require('@antora/content-aggregator/git') @@ -140,7 +141,7 @@ module.exports.register = function ({ config: { createWorktrees = 'auto', keepWo commandContext = createCommandContext(url, remote, startPath, worktree, reftype, refname) logger.info(`run.command: ${command}${commandContext}`) } - await runCommand(command, { cwd, local, shell: !!shell, env, quiet, cache: runCache }) + await runCommand(command, { cwd, local, shell: !!shell, env, quiet, silent, cache: runCache }) } catch (err) { commandContext ??= createCommandContext(url, remote, startPath, worktree, reftype, refname) err.message = err.message.replace(/$/m, commandContext) diff --git a/packages/collector-extension/lib/util/run-command.js b/packages/collector-extension/lib/util/run-command.js index 31ed0af9557adea1866e6501dac3a42f1439c190..7a9d55f797a96a7c7274a46f35569f2896cdf4f4 100644 --- a/packages/collector-extension/lib/util/run-command.js +++ b/packages/collector-extension/lib/util/run-command.js @@ -18,7 +18,7 @@ async function runCommand (cmd = '', opts = {}) { let cmdv = parseCommand(String(cmd), { preserveQuotes: shell }) if (!cmdv.length) throw new TypeError('Command not specified') let cmd0 = cmdv[0] - const { quiet, local, cache: { where = {} } = {}, ...spawnOpts } = opts + const { silent, quiet = silent, local, cache: { where = {} } = {}, ...spawnOpts } = opts if (IS_WIN) { if (~cmd0.indexOf('/')) cmdv[0] = cmd0 = cmd0.replace(/[/]/g, ospath.sep) if (shell) { @@ -64,10 +64,10 @@ async function runCommand (cmd = '', opts = {}) { } else if (local && !~cmd0.indexOf('/')) { cmdv[0] = './' + cmd0 } - return spawnCommand(cmdv, spawnOpts, quiet) + return spawnCommand(cmdv, spawnOpts, { stdout: !quiet, stderr: !silent }) } -async function spawnCommand (cmdv, opts, quiet) { +async function spawnCommand (cmdv, opts, output) { return new Promise((resolve, reject) => { try { const [cmd, ...args] = cmdv @@ -75,7 +75,7 @@ async function spawnCommand (cmdv, opts, quiet) { const ps = spawn(cmd, args, opts) ps.on('close', (exitCode, signalCode) => { if (exitCode === 0) { - if (stderr.length) process.stderr.write(stderr.join('')) + if (stderr.length && output.stderr) process.stderr.write(stderr.join('')) resolve() } else { const result = signalCode ? `terminated with signal ${signalCode}` : `failed with exit code ${exitCode ?? -1}` @@ -85,7 +85,7 @@ async function spawnCommand (cmdv, opts, quiet) { } }) ps.on('error', (err) => reject(err.code === 'ENOENT' ? new Error(`Command not found: ${ps.spawnargs[0]}`) : err)) - ps.stdout.on('data', (data) => quiet || process.stdout.write(data)) + ps.stdout.on('data', (data) => output.stdout && process.stdout.write(data)) ps.stderr.on('data', (data) => stderr.push(data)) ps.stdin.end() } catch (err) { diff --git a/packages/collector-extension/test/collector-extension-test.js b/packages/collector-extension/test/collector-extension-test.js index c0dbbf7316281af09b4555ca31bc2594c0397b68..663d7b666ad84d43fe85adc48dcd8e432f9cfbf8 100644 --- a/packages/collector-extension/test/collector-extension-test.js +++ b/packages/collector-extension/test/collector-extension-test.js @@ -153,7 +153,7 @@ describe('collector extension', () => { } const runScenario = async (opts) => { - const { repoName, branches, tags, startPath, local, collectorConfig, quiet, before, after } = opts + const { repoName, branches, tags, startPath, local, collectorConfig, quiet, silent, before, after } = opts const repo = await createRepository({ repoName, branches, tags, startPath, collectorConfig }) const playbook = { content: { @@ -167,7 +167,7 @@ describe('collector extension', () => { ], }, env: process.env, - runtime: { cacheDir: CACHE_DIR, quiet: quiet == null ? true : quiet }, + runtime: { cacheDir: CACHE_DIR, quiet: quiet == null ? true : quiet, silent }, } const contentAggregate = await aggregateContent(playbook) if (before) isAsync(before) ? await before(contentAggregate, playbook) : before(contentAggregate, playbook) @@ -2055,13 +2055,18 @@ describe('collector extension', () => { assert.equal(stdout, 'start\nall done!\n') }) - // TODO: perhaps direct these messages to the log? it('should direct stderr from command to parent stderr even when quiet is true', async () => { const collectorConfig = { run: { command: '$NODE .gen-error-output.js' } } const stderr = await captureStderr(() => runScenario({ repoName: 'at-root', collectorConfig })) assert.equal(stderr, 'there were some issues\n') }) + it('should suppress stderr from command when silent is true', async () => { + const collectorConfig = { run: { command: '$NODE .gen-error-output.js' } } + const stderr = await captureStderr(() => runScenario({ repoName: 'at-root', collectorConfig, silent: true })) + assert.equal(stderr.length, 0) + }) + it('should suppress stdout from command when quiet is true', async () => { const collectorConfig = { run: { command: '$NODE .gen-output.js' } } const stdout = await captureStdout(() => runScenario({ repoName: 'at-root', collectorConfig }))