npmpre-commitpre-commit.comsolhint

Understanding different ways to run SolHint 4.5.4 in pre-commit without errors


Context

I have tried 3 different approaches to running SolHint 4.5.4 using pre-commit.

Approach I - run script.

The relevant pre-commit section contains:

# Performs static code analysis to check for programming errors.
 - repo: local
   hooks:
     - id: pylint
       name: pylint
       entry: pylint
       language: system
       types: [python]
       args:
         [
           "-rn", # Only display messages
           "-sn", # Don't display the score
         ]
     - id: run-solhint
       name: run-solhint
       language: script
       entry: .pre-commit/run_solhint.sh
       types: [ file, solidity ]
       require_serial: true

And the .pre-commit/run_script.sh contains:


#!/usr/bin/env bash

# Solhint's repo doesn't support pre-commit out-of-the-box, so this script is the workaround.

VERSION="4.5.4"

if ! which solhint 1>/dev/null || [[ $(solhint --version) != "$VERSION" ]]; then
  echo "Installing solhint@$VERSION"
  npm install -g solhint@$VERSION
fi
solhint $@
echo "$(solhint $@)" >

Note, if I just have solhint $@ without the echo, it does not show the Solhint warnings nor errors:

run-solhint..............................................................Passed If I just have echo "$(solhint $@)" > "hi.txt" its the same. If I remove the hi.txt, and do: `` it says:

somedir/.pre-commit/run_solhint.sh: line 12: syntax error near unexpected token newline' somedir/.pre-commit/run_solhint.sh: line 12: echo "$(solhint $@)" >' And if I combine the two with:

solhint $@
echo "$(solhint $@)" > "hi.txt"

it works, without errors. So I first tried echo-ing it into a temporary file with:

TMPFILE=$(mktemp)
solhint $@
echo "$(solhint $@)" > "$TMPFILE"
rm "$TMPFILE"

but then it does not show the warnings and errors anymore:

run-solhint..............................................................Passed And if I do:

solhint $@
echo "$(solhint $@)" > "hi.txt"
rm "hi.txt"

It does work again, without errors.

Approach 2 - run npm.

The relevant pre-commit section contains:

- id: run-solhint
       name: run-solhint
       language: script
       entry: .pre-commit/run_solhint.sh
       types: [ file, solidity ]
       require_serial: true

This does not work, because running npm run solhint returns:

npm run solhint
npm ERR! Missing script: "solhint"
npm ERR! 
npm ERR! To see a list of scripts, run:
npm ERR!   npm run

npm ERR! A complete log of this run can be found in: /home/a/.npm/_logs/2024-04-21T10_46_27_279Z-debug-0.log

Even though the output of npm install -g solhint is:

 npm install -g solhint

changed 109 packages in 5s

24 packages are looking for funding
  run `npm fund` for details

Approach 3 - CLI solhint.

The relevant pre-commit section contains:

- id: solhint
       name: Solidity style guide compliance.
       entry: solhint
       language: node
       verbose: true
       files: ^(contracts/|interfaces/|libraries/|src/|script/|test/)
       args:
         [
           "--fix", # Automatically fix those issues that can be auto-fixed.
           "--noPrompt", # Do not ask for backup before fix.
         ]

This works.

Question

How could one make the SolHint 4.5.4 runscript work such that shows errors and warnings in Pre-commit, with colours, without creating an artifact file? Why does the npm run solhintcommand not work?


Solution

  • I would recommend instead using the supported setup / bootstrap process through additional_dependencies -- in this setup pre-commit will manage the tool for you and won't need your contributors to set something up externally (and it won't muck with their global node installation like your npm install -g script does!) -- I'm not personally familiar with solhint but something like this should get you started:

    -   repo: local
        hooks:
         - id: solhint
           name: Solidity style guide compliance.
           entry: solhint
           language: node
           additional_dependencies: [solhint@4.5.4]
           files: \.sol$
           args:
             [
               "--fix", # Automatically fix those issues that can be auto-fixed.
               "--noPrompt", # Do not ask for backup before fix.
             ]
    

    disclaimer: I wrote pre-commit