Search code examples
elixirgithookslint-staged

lint-staged for elixir/phoenix projects


How would one lint files staged to commit, not all files in the project, using mix credo, mix format, etc?

In the JavaScript ecosystem this is accomplished with lint-staged and husky. Elixir has its version of the husky package called git_hooks, but I haven't found anything resembling lint-staged.

Is there an elixir package that exists to accomplish my goal of only running lint commands when I commit elixir files?

Example config I run with git_hook in config/dev.ex.

config :git_hooks,
  auto_install: true,
  verbose: true,
  mix_path: "docker exec --tty $(docker-compose ps -q web) mix",
  hooks: [
    pre_commit: [
      tasks: [
        {:mix_task, :format, ["--check-formatted"]},
        {:mix_task, :credo, ["--strict"]}
      ]
    ]
  ]

Solution

  • I got this working with git_hooks package and with the following:

    config/dev.ex

    config :git_hooks,
      auto_install: true,
      verbose: true,
      mix_path: "docker exec --tty $(docker-compose ps -q web) mix",
      hooks: [
        pre_commit: [
          tasks: [{:file, "./priv/githooks/pre_commit.sh"}]
       ]
     ]
    
    

    priv/githooks/pre_commit.sh

    #!/bin/ash
    
    # notice the hash bang is for alpine linux's ash
    
    # run mix format
    git diff --name-only --cached | grep -E ".*\.(ex|exs)$" | xargs mix format --check-formatted
    
    # run mix credo
    git diff --name-only --cached | xargs mix credo --strict
    

    Using the file task type, I used the git diff command and piped the staged files to the different mix commands for linting.