Skip to content

Cli format option doesn't load modules #463

@byCedric

Description

@byCedric

I'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)

  1. npm install -g commitlint commitlint-format-junit
  2. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions