husky: `husky install` fails when using `--prod`
I have a package.json
similar to:
{
"scripts": {
"prepare": "husky install"
},
"devDependencies": {
"husky": "^5.2.0"
}
}
Running npm install --prod
(or NODE_ENV=production
) will only install production dependencies and thus node_modules/.bin/husky
will not be present. In my case this happens when trying to build a docker container where I want to install only the production dependencies.
$ npm install --prod
> foobar@1.0.0 prepare
> husky install
sh: line 1: husky: command not found
npm ERR! code 127
npm ERR! path /home/ext/foobar
npm ERR! command failed
npm ERR! command sh -c husky install
npm ERR! A complete log of this run can be found in:
npm ERR! /home/ext/.npm/_logs/2021-03-28T15_18_18_181Z-debug.log
What is the suggested way to handle this scenario?
With husky 4 it worked properly as husky install
wasn’t needed.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 33
- Comments: 38 (4 by maintainers)
Commits related to this issue
- Replaced npm prepare step to fix fail to install If `husky` is not present, `npm` fails to install `fetch-retry` as a dependency for `production` or `ci` environments. ``` npm ERR! code 127 npm ERR!... — committed to bamse16/fetch-retry by bamse16 2 years ago
- husky not found in prepare workaround https://github.com/typicode/husky/issues/914 — committed to zanami/slr-storefront by zanami a year ago
- chore: fix install from git with production flag reference: https://github.com/typicode/husky/issues/914#issuecomment-1046274220 https://github.com/typicode/husky/issues/920#issuecomment-1202503697 ... — committed to DIYgod/RSSHub by TonyRL a year ago
- chore: fix install from git with production flag reference: https://github.com/typicode/husky/issues/914#issuecomment-1046274220 https://github.com/typicode/husky/issues/920#issuecomment-1202503697 ... — committed to bywhite0/RSSHub by TonyRL a year ago
- chore: fix install from git with production flag reference: https://github.com/typicode/husky/issues/914#issuecomment-1046274220 https://github.com/typicode/husky/issues/920#issuecomment-1202503697 ... — committed to nullqwertyuiop/RSSHub by TonyRL a year ago
adding --ignore-scripts worked for me
RUN npm ci --only=production --ignore-scripts
I still consider this to be an issue.
I had a similar issue and the problem with using a blanket
--ignore-scripts
is it affects all packages being installed. So for example, I had a project that needed scripts to run for installing a binary (like imagemin-jpegtran) because a package using it appeared independencies
.I don’t know what the solution is, but it’ll be difficult to consider
husky
as an option if using--production
will only work if no other dependencies do need scripts to run on install, which is often out of my hands.Hey,
I don’t think there’s a one-size-fits-all solution to this problem. It’s a chicken/egg issue.
Ideally, if there was a
devPostInstall
hook supported by package managers that would solve the issue completely. Since that’s not case, we can only come up with solutions that aren’t perfect.Also reverting to husky 4 way of doing would bring back another array of issues. Package managers don’t treat
postinstall
hook the same way as before.Accounting for every cases, environments, type of deployment isn’t possible, instead the recommended way is to pick the approach that works best for the particular use case. That could be
npm set-script prepare
,node prepare.js
, some env variable checking, etc… it depends on the user and which options are available to them.I’ll add the following also to the list of possible solutions:
If husky is not found/installed, which is the case with
--prod
,prepare
script will fail silently.Sorry to not be able to come with a definitive answer.
There are a large variety of approaches, and not one is satisfying
I personally prefer
IMO, it’s evidence that many projects are getting deployed with dev dependencies, which is sad to realize
For now i am using this solution
RUN npm set-script prepare "" && npm ci --only=production
in my Docker fileMy 2 cents to this issue that make our CI pipelines fail too. Using the prepare npm script is IMHO not a good idea at all. the prepare script is called not only on install but also on publish and perhaps i’m missing something but I don’t want it to be executed on publish at all. Also it will make stuffs more complicated if you intend to use that prepare script for yourself as you will have to deal with including “husky install” somewhere in your prepare script.
Finally I think best options so far are:
npm set-scripts prepare ""
before running install or publish during you CI jobs."prepare": "if [[ -x \"$(command -v husky)\" ]]; then husky install; fi"
I can’t recommend the --ignore-scripts as it will avoid all other legitimate script to be run, it can’t be a good solution.
The “custom script” option listed in the husky docs worked best for me while deploying a small hobby project to Heroku, which is not supported by the
is-ci
tool. The fact that it’s a node script adds the flexibility to check for production environment:Valid issue IMO and the workarounds above are just workarounds.
Most of the linked approaches wont help,
--ignore-scripts
is the best (only?) option so far.HUSKY=0
wont help asprepare
/postinstall
will still try to executehusky install
(causing command not found).[ -n "$CI" ]
(or similar) in the scripts assumehusky
is a production dependency, if it is a devDependency it still causes command isn’t found.is-ci
would only work ifis-ci
is a production dependency or it will also fail becauseis-ci
isn’t found instead.Additionally building docker images locally will not trigger
CI
oris-ci
as it is not running in a CI environment.I guess another hack that might work would be:
But that would be really wasteful and inefficient.
I just hit this problem found this issue, and discovered that there is an official recommended approach, using the
is-ci
module: https://typicode.github.io/husky/#/?id=disable-husky-in-cidockerIf you use command like
npm ci --omit=dev
you can access those property via$npm_config_omit
. According to value of$npm_config_omit
you can decide to run husky install command or not.The way the package works after v4 is problematic as evident by this and other related issues reported in this repo. I wonder why author doesn’t want to acknowledge that the new way of handling hooks is just too problematic (even if intentions were good) and probably should be reverted.
Updated version of the popular workaround for this given above from @pinalbhatt - since later npm versions give warnings that
set-script
and--prod
are both deprecated:npm pkg delete scripts.prepare && npm install --omit=dev
(
Note the single space rather than empty string- have raised a SO question in case some further light can be thrown on this: https://stackoverflow.com/questions/73896448. UPDATE - got a good answer to this and have now updated this one accordingly.)I have to disagree with you there.
ci-info
being pulled as well.I still value your suggestion thought. Maybe it will help someone else?
We’re seeing this with Google App Engine (node flex environment), where it’s Google doing the
npm install
that’s somehow kicking this off. Can’t reproduce it locally 🤷is-ci
contributes 84 KiB tonode_modules
, so this is not too bad.works for me with one caveat:
is-ci
doesn’t seem to detectnpm ci --production
as being “CI”…At least
CI=1 npm ci --production
can complete successfully now.My take:
Don’t know how cross-env it is, but works just fine for me on linux.
I solved my occurance of this with @pinalbhatt 's suggestion of
npm set-script prepare "" && npm ci --only=production
.In version 8.x and above use –omit=dev flag to install only regular dependencies:
RUN npm ci --omit=dev --ignore-scripts
This will install only dependencies, and not devDependencies, regardless of the value of the NODE_ENV environment variable. If you use 6.x or an earlier version, you need to use the --only=prod flag instead.@malko Thanks for the tip, this actually did the job for me. 🙏
UPD: Had to adjust it a bit to make it also work in my local env:
I wanted to say just use
npm pkg delete scripts.prepare
, but you already got it 😃Just a nit pick, the npm command actually is
set-script
in singular.I’m running into this out of the blue on
onetwo of my apps w/ husky 7.0.4.I’ve deleted
node_modules
,package-lock.json
and rannpm install
to rebuild them w/ no success.I’ve edited my deploy job to
npm ci --only=production --ignore-scripts
w/ no success.Big sad.
Yes, good suggestion. PR welcome.