Skip to content

Need to run npm install as a local hook before a hook that needs to import dependencies #2128

@jklaiho

Description

@jklaiho

Honestly, this would be better at home as a Discussions post, but this repo doesn't have that enabled, so here we go instead.

prek.toml:

[[repos]]
repo = "https://github.com/thibaudcolas/pre-commit-stylelint"
rev = "v17.4.0"
hooks = [
  {
    id = "stylelint",
    types = ["css"],
  },
]

stylelint.config.js:

export default {
  "extends": "stylelint-config-standard",
  "plugins": ["stylelint-gamut"],
  "rules": {/* ... */},
};

Running prek run --all-files fails with this error:

ConfigurationError: Could not find "stylelint-config-standard". Do you need to install the package or use the "configBasedir" option?

That's expected; I'm not installing stylelint-config-standard anywhere, and the same goes for stylelint-gamut. So I add these lines into the hook config:

additional_dependencies = [
  "stylelint-config-standard",
  "stylelint-gamut",
]

Retrying the hook run, this error:

error: Failed to run hook `stylelint`
  caused by: Run command `node hook` failed
  caused by: No such file or directory (os error 2)

OK, I don't quite understand this, but I recall that with pre-commit, using additional_dependencies requires the package itself in there, so I add "stylelint" to additional_dependencies and retry:

ConfigurationError: Could not find "stylelint-config-standard". Do you need to install the package or use the "configBasedir" option?

So we're back to the initial error. I then comment out both the extends and plugins lines from stylelint.config.js, re-run the hook, and it works! additional_dependencies is no longer needed for the hook to work, but of course, I actually need both stylelint-config-standard and stylelint-gamut. So when I uncomment those config lines, how do I get stylelint to work?

What I need to do is to add a package.json file with this included:

  "devDependencies": {
    "stylelint": "17.4.0",
    "stylelint-config-standard": "40.0.0",
    "stylelint-gamut": "2.0.0"
  }

And then add this local hook before the stylelint hook in prek.toml:

[[repos]]
repo = "local"
hooks = [
  {
    id = "npm-install",
    name = "npm install",
    language = "system",
    # npm install updates the mtime of package-lock.json even when content is
    # unchanged. prek checks for modifications with `git diff-files --quiet`
    # (stat-only), so a stale mtime falsely trips it. The refresh re-hashes
    # the file and updates the git index stat cache, so prek's check succeeds.
    entry = """bash -c 'npm install --prefer-offline --no-audit --progress=false \
      && { git update-index --refresh -q -- package-lock.json || true; }'
    """,
    always_run = true,
    pass_filenames = false
  }
]

Finally, with all these elements in place, I can configure stylelint to extend from stylelint-config-standard and include stylelint-gamut as a plugin. additional_dependencies is not needed on the hook at all.

If the configuration file of a hook refers to things it needs to import, like stylelint here, then whatever additional_dependencies is doing to install packages, those installed packages are not importable during the hook run. I need that package.json and that npm install hook. To be clear, I have to do the same if I use pre-commit, so this is not a Prek regression.

That local hook is pretty convoluted, and the comment in there is based on some Claude-assisted troubleshooting. Prek would choke on the hook changing package-lock.json's mtime, even when its contents hadn't changed. If there's a "bug" included in this issue, it's probably this. This didn't use to happen, and may be something that later npm versions are causing, but it feels like Prek should only care about the contents changing with a hook run and not the mtime?

Is this really the only way to go about this use case of JS config files of hooks causing dependency imports, or am I missing something significant?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions