feat: improve CLI
- Replace `commander.js` with `yargs` - Add CLI unit tests - Add a `--version` option - Improve `--help` output - Remove `commander.js` related workaround - Allow to set list option with arg repetition or space separated list - Maintain the list options defined as comma separated list
This commit is contained in:
committed by
Gregor Martynus
parent
f92677b092
commit
97cb354fea
@@ -1,64 +1,64 @@
|
||||
const program = require('commander');
|
||||
const {pickBy, isUndefined} = require('lodash');
|
||||
|
||||
function list(values) {
|
||||
return values
|
||||
.split(',')
|
||||
.map(value => value.trim())
|
||||
.filter(value => value && value !== 'false');
|
||||
}
|
||||
const stringList = {
|
||||
type: 'string',
|
||||
array: true,
|
||||
coerce: values =>
|
||||
values.length === 1 && values[0].trim() === 'false'
|
||||
? []
|
||||
: values.reduce((values, value) => values.concat(value.split(',').map(value => value.trim())), []),
|
||||
};
|
||||
|
||||
module.exports = async () => {
|
||||
program
|
||||
.name('semantic-release')
|
||||
.description('Run automated package publishing')
|
||||
.option('-b, --branch <branch>', 'Branch to release from')
|
||||
.option('-r, --repository-url <repositoryUrl>', 'Git repository URL')
|
||||
.option('-t, --tag-format <tagFormat>', `Git tag format`)
|
||||
.option('-e, --extends <paths>', 'Comma separated list of shareable config paths or packages name', list)
|
||||
.option(
|
||||
'--verify-conditions <paths>',
|
||||
'Comma separated list of paths or packages name for the verifyConditions plugin(s)',
|
||||
list
|
||||
)
|
||||
.option('--analyze-commits <path>', 'Path or package name for the analyzeCommits plugin')
|
||||
.option(
|
||||
'--verify-release <paths>',
|
||||
'Comma separated list of paths or packages name for the verifyRelease plugin(s)',
|
||||
list
|
||||
)
|
||||
.option('--generate-notes <path>', 'Path or package name for the generateNotes plugin')
|
||||
.option('--publish <paths>', 'Comma separated list of paths or packages name for the publish plugin(s)', list)
|
||||
.option('--success <paths>', 'Comma separated list of paths or packages name for the success plugin(s)', list)
|
||||
.option('--fail <paths>', 'Comma separated list of paths or packages name for the fail plugin(s)', list)
|
||||
.option(
|
||||
'--no-ci',
|
||||
'Skip Continuous Integration environment verifications, allowing to make releases from a local machine'
|
||||
)
|
||||
.option('--debug', 'Output debugging information')
|
||||
.option(
|
||||
'-d, --dry-run',
|
||||
'Dry-run mode, skipping verifyConditions, publishing and release, printing next version and release notes'
|
||||
)
|
||||
.parse(process.argv);
|
||||
|
||||
if (program.debug) {
|
||||
// Debug must be enabled before other requires in order to work
|
||||
require('debug').enable('semantic-release:*');
|
||||
}
|
||||
const cli = require('yargs')
|
||||
.command('$0', 'Run automated package publishing', yargs => {
|
||||
yargs.demandCommand(0, 0).usage(`Run automated package publishing
|
||||
Usage:
|
||||
semantic-release [options] [plugins]`);
|
||||
})
|
||||
.option('b', {alias: 'branch', describe: 'Git branch to release from', type: 'string', group: 'Options'})
|
||||
.option('r', {alias: 'repository-url', describe: 'Git repository URL', type: 'string', group: 'Options'})
|
||||
.option('t', {alias: 'tag-format', describe: 'Git tag format', type: 'string', group: 'Options'})
|
||||
.option('e', {alias: 'extends', describe: 'Shareable configurations', ...stringList, group: 'Options'})
|
||||
.option('ci', {describe: 'Toggle CI verifications', default: true, type: 'boolean', group: 'Options'})
|
||||
.option('verify-conditions', {...stringList, group: 'Plugins'})
|
||||
.option('analyze-commits', {type: 'string', group: 'Plugins'})
|
||||
.option('verify-release', {...stringList, group: 'Plugins'})
|
||||
.option('generate-notes', {type: 'string', group: 'Plugins'})
|
||||
.option('publish', {...stringList, group: 'Plugins'})
|
||||
.option('success', {...stringList, group: 'Plugins'})
|
||||
.option('fail', {...stringList, group: 'Plugins'})
|
||||
.option('debug', {describe: 'Output debugging information', default: false, type: 'boolean', group: 'Options'})
|
||||
.option('d', {alias: 'dry-run', describe: 'Skip publishing', default: false, type: 'boolean', group: 'Options'})
|
||||
.option('h', {alias: 'help', group: 'Options'})
|
||||
.option('v', {alias: 'version', group: 'Options'})
|
||||
.strict(false)
|
||||
.exitProcess(false);
|
||||
|
||||
try {
|
||||
if (program.args.length > 0) {
|
||||
program.outputHelp();
|
||||
process.exitCode = 1;
|
||||
} else {
|
||||
const opts = program.opts();
|
||||
// Set the `noCi` options as commander.js sets the `ci` options instead (because args starts with `--no`)
|
||||
opts.noCi = opts.ci === false ? true : undefined;
|
||||
// Remove option with undefined values, as commander.js sets non defined options as `undefined`
|
||||
await require('.')(pickBy(opts, value => !isUndefined(value)));
|
||||
const {help, version, ...opts} = cli.argv;
|
||||
if (Boolean(help) || Boolean(version)) {
|
||||
process.exitCode = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the `noCi` options as yargs sets the `ci` options instead (because arg starts with `--no`)
|
||||
if (opts.ci === false) {
|
||||
opts.noCi = true;
|
||||
}
|
||||
|
||||
if (opts.debug) {
|
||||
// Debug must be enabled before other requires in order to work
|
||||
require('debug').enable('semantic-release:*');
|
||||
}
|
||||
|
||||
// Remove option with undefined values, as yargs sets non defined options as `undefined`
|
||||
await require('.')(pickBy(opts, value => !isUndefined(value)));
|
||||
process.exitCode = 0;
|
||||
} catch (err) {
|
||||
if (err.name !== 'YError') {
|
||||
console.error(err);
|
||||
}
|
||||
process.exitCode = 1;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user