Cli format option doesn't load modules
See original GitHub issueI’ve been busy with some formatters for Commitlint, so far I’ve created two; json and junit formats.
During initial testing, I encountered some unexpected behavior related to importing these formatters in the CLI package. On line 268, in cli.js, we use require.resolve
. I mistakenly assumed it would handle global/local modules and absolute/relative file paths. Unfortunately, this isn’t the case. I’ve tried to use flags.cwd
in the resolve method, but this only seems to fix locally installed modules and relative file paths.
TL;DR; Format module resolves must be improved, I suggest resolve-from and resolve-global. What do you think? I will create a PR with the solution listed below!
Expected Behavior
$ echo 'foo: bar' | npx commitlint -o commitlint-format-junit
<?xml version="1.0" encoding="utf-8"?>
<testsuites>
...
</testsuites>
Current Behavior
$ echo 'foo: bar' | npx commitlint -o commitlint-format-junit
/usr/local/lib/node_modules/commitlint/node_modules/@commitlint/cli/lib/cli.js:272
throw err;
Affected packages
- cli
- core
- prompt
- config-angular
Possible Solution
So, I took a look at @commitlint/load
how it’s loading the configuration. I noticed that cosmiconfig
is used, so I started digging there. It turns out; it’s pretty hard to resolve things like this. I would recommend using an external library to fix this. So far I found two libraries, both from Sindre Sorhus which should cover all of our needs; resolve-from and resolve-global (both MIT licensed).
With this we can do this:
function loadFormatter(config, flags) {
const moduleName = flags.format || config.formatter;
const moduleResolvers = [
name => resolveFrom.silent(flags.cwd, name),
name => resolveGlobal.silent(name),
];
const modulePath = moduleResolvers.find(resolve => resolve(moduleName));
if (modulePath) {
return require(modulePath);
}
throw new Error(`Cannot find format module ${moduleName}`);
}
I’ve briefly talked with demurgos, from node-tooling slack, about this. And I agree with him that local should be resolved before global, so the order is intentional.
Steps to Reproduce (for bugs)
npm install -g commitlint commitlint-format-junit
echo 'foo: bar' | npx commitlint -o commitlint-format-junit
Your Environment
I’m running this from a docker container, so I wouldn’t pollute my own global installations 😄If you want to use the same environment, spin it up with:
$ docker run -ti --rm -v $PWD:/code -w /code bycedric/ci-node sh
# apk add --no-cache git
Executable | Version |
---|---|
commitlint --version |
7.2.0 |
git --version |
2.18.0 |
node --version |
v10.11.0 |
Issue Analytics
- State:
- Created 5 years ago
- Comments:7 (7 by maintainers)
Top GitHub Comments
@byCedric I added a review to your PR. Apart from a minor thing I am fine with all your points - great work! 👍
Are you be interested in maintaining commitlint? I’ll be on vacation for two weeks starting on Friday 12th, so I’d introduce you to the project when I am back. What do you think?
Good catch! Going with
resolve-from
for starters should be enough. I think there is some complexity in this when thinking it throughprocess.cwd()
commitlint.config.js
should be resolved from the dirname of the config file they were specified in