giteslintpylintpre-commit.comgit-husky

Pylint with pre-commit and EsLlint with husky


I have a project with a frontend in JS and backend in Python. Frontend had been configured with husky pre-commit hook. Today I've configured Pylint with pre-commit library but husky hooks had been overwritten by that move. Is it possible to combine pre-commit and husky libraries? If not... what's the best way to solve the problem?


Solution

  • pre-commit has a "migration mode" for running other existing hook frameworks. It seems that husky is slightly too clever in their hook implementation for detecting what hook you're running -- they base it on the filename that's being executed

    the way pre-commit's migration mode works is it takes any existing hook script (in this case, the hook script written by husky to .git/hooks/pre-commit) and adds the extension .legacy. then during execution it runs that script.

    but to husky, it looks like the pre-commit.legacy hook is running (!)

    a little hack is to define pre-commit.legacy in package.json which seems to work:

    package.json

    {
      "husky": {
        "hooks": {
          "pre-commit.legacy": "echo hello world"
        }
      },
      "dependencies": {
        "husky": "^4.3.0"
      }
    }
    

    .pre-commit-config.yaml

    # See https://pre-commit.com for more information
    # See https://pre-commit.com/hooks.html for more hooks
    repos:
    -   repo: https://github.com/pre-commit/pre-commit-hooks
        rev: v3.2.0
        hooks:
        -   id: trailing-whitespace
        -   id: end-of-file-fixer
        -   id: check-yaml
        -   id: check-added-large-files
    $ git commit -m "both"
    husky > pre-commit.legacy (node v12.18.3)
    hello world
    Trim Trailing Whitespace.................................................Passed
    Fix End of Files.........................................................Passed
    Check Yaml...........................................(no files to check)Skipped
    Check for added large files..............................................Passed
    [master 7bd8807] both
     1 file changed, 1 insertion(+), 1 deletion(-)
    

    that said, this seems fragile. pre-commit is designed to support many different programming languages (even though it is written in python, it has native support for 10+ programming languages (including javascript))


    A first place replacement might be to just call husky from a local pre-commit hook:

    package.json

    {
      "husky": {
        "hooks": {
          "pre-commit": "echo hello world"
        }
      },
      "dependencies": {
        "husky": "^4.3.0"
      }
    }
    

    .pre-commit-config.yaml

    # See https://pre-commit.com for more information
    # See https://pre-commit.com/hooks.html for more hooks
    repos:
    -   repo: https://github.com/pre-commit/pre-commit-hooks
        rev: v3.2.0
        hooks:
        -   id: trailing-whitespace
        -   id: end-of-file-fixer
        -   id: check-yaml
        -   id: check-added-large-files
    -   repo: local
        hooks:
        -   id: husky-run-pre-commit
            name: husky
            language: system
            entry: node_modules/.bin/husky-run pre-commit
            pass_filenames: false
            always_run: true
    

    execution

    $ pre-commit run --all-files --verbose
    Trim Trailing Whitespace.................................................Passed
    - hook id: trailing-whitespace
    - duration: 0.03s
    Fix End of Files.........................................................Passed
    - hook id: end-of-file-fixer
    - duration: 0.03s
    Check Yaml...............................................................Passed
    - hook id: check-yaml
    - duration: 0.05s
    Check for added large files..............................................Passed
    - hook id: check-added-large-files
    - duration: 0.05s
    husky....................................................................Passed
    - hook id: husky-run-pre-commit
    - duration: 0.07s
    
    husky > pre-commit (node v12.18.3)
    hello world
    
    

    this solution however doesn't take advantage of pre-commit's js support, it just invokes the already-existing husky hooks


    a more native solution would be to install js hooks directly with pre-commit, for example if you're using eslint:

    repos:
    -   repo: https://github.com/pre-commit/mirrors-eslint
        rev: 'v7.9.0'  # Use the sha / tag you want to point at
        hooks:
        -   id: eslint
    
    $ pre-commit  run --all-files
    [INFO] Initializing environment for https://github.com/pre-commit/mirrors-eslint.
    [INFO] Initializing environment for https://github.com/pre-commit/mirrors-eslint:eslint@7.9.0.
    [INFO] Installing environment for https://github.com/pre-commit/mirrors-eslint.
    [INFO] Once installed this environment will be reused.
    [INFO] This may take a few minutes...
    eslint...................................................................Passed
    

    disclaimer: I am the author of pre-commit