bashlint-stagedyarnpkg-v3

lint-staged is linting more than just staged files


THE PROBLEM

I have two JavaScript files in packageA that I know have lint errors. I fixed and staged one. When I try to commit the staged file, it fails because of the unfixed/unstaged file.

SETUP

I have a monorepo with a structure like this:

.lintstagedrc.mjs
    |...packages
        |...packageA
            .lintstagedrc.mjs
            |...components
                compA
                compB
        |...packageB
            .lintstagedrc.mjs
        |...packageC
            .lintstagedrc.mjs

The root .lintstagedrc.mjs is

export default {
  '*.js': 'eslint --fix'
};

Each package's .lintstagedrc.mjs is

export default {
  '*.js': 'yarn lint:js',
  '*.hbs': 'yarn lint:hbs'
};

Each package's package.json has:

"scripts": {
    "lint:js": "eslint . --cache",
    "lint:hbs": "handlebars-lint ."

I use Husky to run lint-staged. It's configured via .husky/pre-commit which has:

npx lint-staged

DEBUGGING

If I run lint-staged in debug mode, I see:

  lint-staged:generateTasks Generating linter tasks +0ms
  lint-staged:generateTasks Generated task: 
  lint-staged:generateTasks {
  lint-staged:generateTasks   pattern: '*.js',
  lint-staged:generateTasks   commands: 'yarn lint:js',
  lint-staged:generateTasks   fileList: [
  lint-staged:generateTasks     '/myapp/packages/packageA/components/compA.js'
  lint-staged:generateTasks   ]
  lint-staged:generateTasks } +1ms
  lint-staged:generateTasks Generated task: 
  lint-staged:generateTasks { pattern: '*.hbs', commands: 'yarn lint:hbs', fileList: [] } +0ms

This looks like what I'd expect. One JS file, and ho HBS files.

It then backs up the original state, and runs the task for staged files.

[STARTED] Running tasks for staged files...
[STARTED] packages/packageA/.lintstagedrc.mjs — 1 file
[STARTED] *.js — 1 file
[STARTED] *.hbs — 0 files
[SKIPPED] *.hbs — no files
[STARTED] yarn lint:js
[FAILED] yarn lint:js [FAILED]

I believe the problem is that the list of staged files, which is appended to yarn lint:js is being ignored because that script is eslint . --cache.

I'd like it if I can update the yarn script to handle passed in files, or defaulting to .. I tried to use bash with the command eslint ${@:-.} --cache, but that didn't work.

I'm assuming I can update my .lintstagedrc.mjs to directly call eslint, but I'd really like to call it via yarn. That way if we ever change how we're linting in the future, only one place (package.json) needs to be changed.


Solution

  • I used the following Yarn script, and that seems to provide the desired result:

    "lint:js": "sh -c 'eslint --cache ${@:-.}' --"
    

    This allows me to run lint:js from lint-staged and it only lints the staged files, and I can also manually run yarn lint:js and it lints all JS files.