Skip to content

Commit

Permalink
feat: update command-line options
Browse files Browse the repository at this point in the history
This commit updates the CLI processing function
within the valiator, along with associated tests.
Specifically, the "debug" and "print-validators",
and "report-statistics" options were removed,
and a new "summary-only" option was introduced.

Additionally, the 'statistics' section of the output
has been renamed as 'summary'.

BREAKING CHANGE: The 'summary-only', 'debug', 'print-validators' options have been removed.

Signed-off-by: Phil Adams <[email protected]>
  • Loading branch information
padamstx authored and dpopp07 committed Mar 31, 2023
1 parent f5aa2fc commit 53f4fbb
Show file tree
Hide file tree
Showing 22 changed files with 5,696 additions and 2,978 deletions.
2 changes: 1 addition & 1 deletion .secrets.baseline
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"files": "package-lock.json|^.secrets.baseline$",
"lines": null
},
"generated_at": "2023-01-27T15:53:56Z",
"generated_at": "2023-01-30T22:48:27Z",
"plugins_used": [
{
"name": "AWSKeyDetector"
Expand Down
15 changes: 6 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,16 +96,13 @@ Once pulled, the container can be run directly, but mount a volume containing th
`lint-openapi [options] [<files>]`

##### [options]
- -d (--default_mode) : This option turns off [configuration](#configuration) and runs the validator in [default mode](#default-mode).
- -e (--errors_only) : Only print the errors, ignore the warnings.
- -j (--json) : Output results as a JSON object
- -l (--loglevel) `<loggername>=<loglevel> ...` : Set loglevel of logger named `<loggername>` to `<loglevel>` (e.g. `-l root=info -l ibm-schema-description=debug`)
- -n (--no_colors) : The output is colored by default. If this bothers you, this flag will turn off the coloring.
- -p (--print_validator_modules) : Print the name of the validator source file the error/warning was caught it. This can be helpful for developing validations.
- -v (--verbose) : Increase verbosity of reported results. Use this option to display the rule for each reported result.
- -e (--errors-only) : Only print the errors, ignore the warnings.
- -j (--json) : Output results as a JSON object.
- -l (--log-level) `<loggername>=<loglevel> ...` : Set log level of logger named `<loggername>` to `<loglevel>` (e.g. `-l root=info -l ibm-schema-description=debug`). If you omit the logger name, then `root` is assumed (e.g. `-l info`).
- -n (--no-colors) : Disables colorization of the output messages, which is enabled by default.
- -v (--verbose) : Display verbose output.
- -r (--ruleset) `<path/to/your/ruleset>` : Path to Spectral ruleset file, used instead of .spectral.yaml if provided.
- -s (--report_statistics) : Print a simple report at the end of the output showing the frequency, in percentage, of each error/warning.
- --debug : Enable debugging output.
- -s (--summary-only) : Display only the summary section, and avoid displaying individual errors and warnings. This applies to both JSON and non-JSON output.
- --version : Print the current semantic version of the validator
- -h (--help) : This option prints the usage menu.

Expand Down
7,283 changes: 5,075 additions & 2,208 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions packages/ruleset/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
},
"dependencies": {
"@ibm-cloud/openapi-ruleset-utilities": "0.0.1",
"@stoplight/spectral-formats": "^1.1.0",
"@stoplight/spectral-functions": "^1.6.1",
"@stoplight/spectral-rulesets": "^1.6.0",
"@stoplight/spectral-formats": "^1.4.0",
"@stoplight/spectral-functions": "^1.7.2",
"@stoplight/spectral-rulesets": "^1.14.1",
"lodash": "^4.17.21",
"validator": "^13.7.0",
"loglevel": "^1.8.1",
Expand Down
14 changes: 5 additions & 9 deletions packages/validator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,13 @@ The `-g` flag installs the tool globally so that the validator can be run from a
`lint-openapi [options] [command] [<files>]`

##### [options]
- -c (--config) <path/to/your/config> : Path to a validator configuration file. If provided, this is used instead of .validaterc.
- -d (--default_mode) : This option turns off [configuration](#configuration) and runs the validator in [default mode](#default-mode).
- -e (--errors_only) : Only print the errors, ignore the warnings.
- -e (--errors-only) : Print only the errors and skip the warnings.
- -j (--json) : Output results as a JSON object
- -n (--no_colors) : The output is colored by default. If this bothers you, this flag will turn off the coloring.
- -p (--print_validator_modules) : Print the name of the validator source file the error/warning was caught it. This can be helpful for developing validations.
- -v (--verbose) : Increase verbosity of reported results. Use this option to display the rule for each reported result.
- -n (--no-colors) : The output is colorized by default. Using this flag will turn off the colorizing.
- -v (--verbose) : Display more verbose output.
- -r (--ruleset) <path/to/your/ruleset> : Path to Spectral ruleset file, used instead of .spectral.yaml if provided.
- -s (--report_statistics) : Print a simple report at the end of the output showing the frequency, in percentage, of each error/warning.
- --debug : Enable debugging output.
- --version : Print the current semantic version of the validator
- -s (--summary-only) : Display only the summary section and skip individual errors and warnings.
- --version : Print the current semantic version of the validator.
- -h (--help) : This option prints the usage menu.


Expand Down
3 changes: 2 additions & 1 deletion packages/validator/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@
"nimma/fallbacks": "<rootDir>/../../node_modules/nimma/dist/cjs/fallbacks/",
"@stoplight/spectral-ruleset-bundler/presets/node": "<rootDir>/../../node_modules/@stoplight/spectral-ruleset-bundler/dist/presets/node",
"@stoplight/spectral-ruleset-bundler/plugins/stdin": "<rootDir>/../../node_modules/@stoplight/spectral-ruleset-bundler/dist/plugins/stdin",
"@stoplight/spectral-ruleset-bundler/plugins/builtins": "<rootDir>/../../node_modules/@stoplight/spectral-ruleset-bundler/dist/plugins/builtins"
"@stoplight/spectral-ruleset-bundler/plugins/builtins": "<rootDir>/../../node_modules/@stoplight/spectral-ruleset-bundler/dist/plugins/builtins",
"@stoplight/spectral-ruleset-bundler/plugins/commonjs": "<rootDir>/../../node_modules/@stoplight/spectral-ruleset-bundler/dist/plugins/commonjs"
}
}
}
71 changes: 2 additions & 69 deletions packages/validator/src/cli-validator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,75 +5,8 @@
// the passed in argument (currently 10.0.0)
require('./utils/check-version')('10.0.0');

const program = require('./utils/modified-commander');
const getVersionString = require('./utils/get-version-string');
const cliValidator = require('./run-validator');

// set up the command line options
/* prettier-ignore */
program
.name('lint-openapi')
.description('Run the validator on a specified file')
.arguments('[<file>]')
.option(
'-c, --config <file>',
'path to config file, used instead of .validaterc if provided'
)
.option(
'-d, --default_mode',
'ignore config file and run in default mode'
)
.option(
'-e, --errors_only',
'only print the errors, ignore the warnings'
)
.option(
'-j, --json',
'output as json'
)
.option(
'-n, --no_colors',
'turn off output coloring'
)
.option(
'-p, --print_validator_modules',
'print the validators that catch each error/warning (helpful for development)'
)
.option(
'-r, --ruleset <file>',
'path to Spectral ruleset file, used instead of .spectral.yaml if provided'
)
.option(
'-s, --report_statistics',
'report the frequency of each occurring error/warning'
)
.option('-v, --verbose',
'increase the verbosity of reported results',
increaseVerbosity,
0
)
.option(
'--debug',
'enable debugging output'
)
.option(
'-l, --log-level <loglevel...>',
'Set the log level for one or more loggers (e.g. -l root=info -l schema-description=debug ...)'
)
.version(getVersionString(), '--version');
program.addHelpText(
'beforeAll',
`IBM OpenAPI Validator: ${getVersionString()}\n`
);

function increaseVerbosity(dummyValue, previous) {
return previous + 1;
}

program.parse(process.argv);

// run the program
cliValidator(program)
const runValidator = require('./run-validator');
runValidator(process.argv)
.then(exitCode => {
process.exitCode = exitCode;
return exitCode;
Expand Down
119 changes: 59 additions & 60 deletions packages/validator/src/cli-validator/run-validator.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,29 @@ const print = require('./utils/print-results');
const { printJson } = require('./utils/json-results');
const spectralValidator = require('../spectral/spectral-validator');
const validator = require('./utils/validator');
const getVersionString = require('./utils/get-version-string');
const getCopyrightString = require('./utils/get-copyright-string');
const { LoggerFactory } = require('@ibm-cloud/openapi-ruleset/src/utils');
const createCLIOptions = require('./utils/cli-options');

let logger;

// this function processes the input, does the error handling,
// this function processes the command-line arguments, does the error handling,
// and acts as the main function for the program
const processInput = async function(program) {
/**
* This function is the main entry point to the validator.
* It processes the passed-in cli arguments and performs error handling as needed.
* @param {*} cliArgs the array of command-line arguments (normally this should be process.argv)
* @param {*} parseOptions an optional object containing parse options
*/
async function cliValidator(cliArgs, parseOptions = {}) {
const program = createCLIOptions();
program.parse(cliArgs, parseOptions);

let args = program.args;

// require that arguments are passed in
// If no arguments are passed in, then display help text and exit.
if (args.length === 0) {
program.help();
console.log(`${getCopyrightString()}\n${program.helpInformation()}`);
return Promise.reject(2);
}

Expand All @@ -42,43 +52,25 @@ const processInput = async function(program) {
loggerFactory.addLoggerSetting('root', 'info');
logger = loggerFactory.getLogger('root');

let opts = program;
if (typeof program.opts === 'function') {
opts = program.opts();
}

// Leaving this here for debugging.
// console.log(`Program opts:\n`, opts);
const opts = program.opts();

// interpret the options
const printValidators = !!opts.print_validator_modules;
const reportingStats = !!opts.report_statistics;

const turnOffColoring = !!opts.no_colors;
const defaultMode = !!opts.default_mode;
// Retrieve the options.
const summaryOnly = !!opts.summaryOnly;
const colorizeOutput = !!opts.colors;
const jsonOutput = !!opts.json;
const errorsOnly = !!opts.errors_only;
const debug = !!opts.debug;

const configFileOverride = opts.config;
const errorsOnly = !!opts.errorsOnly;
const rulesetFileOverride = opts.ruleset;

const verbose = !!opts.verbose;
const logLevels = opts.logLevel || [];
const limitsFileOverride = opts.limits;

const verbose = opts.verbose > 0;

// Process each loglevel entry supplied on the command line.
// Add each option to our LoggerFactory so they can be used to affect the
// log level of both existing loggers and loggers created later by individual rules.
// Examples:
// -l info (equivalent to -l root=info)
// --log-level schema-*=debug (enable debug for all rules like "schema-*")
// -l property-description=debug (enable debug for the "property-description" rule)
let logLevels = opts.logLevel;
if (!logLevels) {
logLevels = [];
}

// --log-level ibm-schema-*=debug (enable debug for all rules like "ibm-schema-*")
// -l ibm-property-description=debug (enable debug for the "ibm-property-description" rule)
for (const entry of logLevels) {
let [loggerName, logLevel] = entry.split('=');

Expand All @@ -97,16 +89,12 @@ const processInput = async function(program) {
loggerFactory.applySettingsToAllLoggers();

// turn off coloring if explicitly requested
if (turnOffColoring) {
if (!colorizeOutput) {
chalk.level = 0;
}

if (verbose && !jsonOutput) {
logger.info(
chalk.green(
`IBM OpenAPI Validator (${getVersionString()}), @Copyright IBM Corporation 2017, 2023.\n`
)
);
logger.info(chalk.green(getCopyrightString()));
}

// run the validator on the passed in files
Expand All @@ -121,6 +109,8 @@ const processInput = async function(program) {
// determine which files were removed from args because they were 'ignored'
// then, print these for the user. this way, the user is alerted to why files
// aren't validated
// "filteredArgs" is the list of files to process after removing ignored files
// "filteredFiles" is the list of files to be ignored
const filteredFiles = args.filter(file => !filteredArgs.includes(file));
filteredFiles.forEach(filename => {
logger.warn(
Expand Down Expand Up @@ -183,7 +173,12 @@ const processInput = async function(program) {
// process the config file for the validations
let configObject;
try {
configObject = await config.get(defaultMode, chalk, configFileOverride);
// "defaultMode" changed to true in the following line since we no longer
// want to read in a user's .validaterc.
// We need to re-visit this when we address the legacy code inside validate()
// that is invoked below.
// Passing null for "configFileOverride" since we no longer support the -c option.
configObject = await config.get(true, chalk, null);
} catch (err) {
return Promise.reject(err);
}
Expand Down Expand Up @@ -258,9 +253,7 @@ const processInput = async function(program) {
'There is a problem with the API definition.',
getError(err)
);
if (debug) {
logger.error(err.stack);
}
logger.debug(err.stack);
exitCode = 1;
continue;
} finally {
Expand All @@ -276,7 +269,6 @@ const processInput = async function(program) {
const spectral = await spectralValidator.setup(
logger,
rulesetFileOverride,
debug,
chalk
);

Expand All @@ -288,13 +280,20 @@ const processInput = async function(program) {

const doc = new Document(originalFile, parser, validFile);
spectralResults = await spectral.run(doc);
// console.log(`spectralResults: `, spectralResults);
} catch (err) {
logError(chalk, 'There was a problem with spectral.', getError(err));
if (debug || err.message === 'Error running Nimma') {
logError(chalk, 'Additional error details:', err);
if (err.message === 'Error running Nimma') {
logger.debug(chalk.red('Additional error details:'));
logger.debug(chalk.red(err));
}

if (
// this check can be removed once we support spectral overrides
if (err.message.startsWith('Document must have some source assigned.')) {
console.log(
'This error likely occurred because Spectral `exceptions` are deprecated and `overrides` are not yet supported.\n' +
'Remove these fields from your Spectral config file to proceed.'
);
} else if (
err.message ==
"Cannot use 'in' operator to search for '**' in undefined"
) {
Expand All @@ -310,16 +309,10 @@ const processInput = async function(program) {
// run validator, print the results, and determine if validator passed
let results;
try {
results = validator(
logger,
swagger,
configObject,
spectralResults,
debug
);
results = validator(logger, swagger, configObject, spectralResults);
} catch (err) {
logError(chalk, 'There was a problem with a validator.', getError(err));
if (debug) {
if (verbose) {
logger.error(err.stack);
}
exitCode = 1;
Expand Down Expand Up @@ -363,16 +356,22 @@ const processInput = async function(program) {
}

if (jsonOutput) {
printJson(logger, results, originalFile, verbose, errorsOnly);
printJson(
logger,
results,
originalFile,
verbose,
errorsOnly,
summaryOnly
);
} else {
if (results.error || results.warning || results.info || results.hint) {
print(
logger,
results,
chalk,
printValidators,
verbose,
reportingStats,
summaryOnly,
originalFile,
errorsOnly
);
Expand All @@ -383,7 +382,7 @@ const processInput = async function(program) {
}

return exitCode;
};
}

// if the error has a message property (it should),
// this is the cleanest way to present it. If not,
Expand All @@ -400,4 +399,4 @@ function logError(chalk, description, message = '') {
}

// this exports the entire program so it can be used or tested
module.exports = processInput;
module.exports = cliValidator;
Loading

0 comments on commit 53f4fbb

Please sign in to comment.