Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] npm ci doesn't run postinstall script #1905

Closed
davidmurdoch opened this issue Oct 6, 2020 · 23 comments · Fixed by #2316
Closed

[BUG] npm ci doesn't run postinstall script #1905

davidmurdoch opened this issue Oct 6, 2020 · 23 comments · Fixed by #2316
Labels
Bug thing that needs fixing Release 7.x work is associated with a specific npm 7 release

Comments

@davidmurdoch
Copy link

Current Behavior:

npm ci doesn't run the postinstall script

Expected Behavior:

npm ci should run the postinstall script

Steps To Reproduce:

  1. create a new folder and put the following minimal package.json in it:
{
  "scripts": {
    "postinstall": "echo \"it should echo this\""
  }
}

  1. run npm install
  2. run npm ci
  3. notice how npm ci DOES NOT run the postinstall script

Environment:

ex.

  • OS: Kubuntu 20.04
  • Node: 14.13.0
  • npm: 7.0.0-rc.0
@davidmurdoch davidmurdoch added Bug thing that needs fixing Needs Triage needs review for next steps Release 7.x work is associated with a specific npm 7 release labels Oct 6, 2020
@darcyclarke darcyclarke removed the Needs Triage needs review for next steps label Oct 8, 2020
@darcyclarke
Copy link
Contributor

I think this is functioning as intended or at least the same as npm v6 & doesn't look like a bug but probably is very confusing.

The preinstall, install & postinstall scripts are actually lifecycle events that are triggered when a package itself is being installed into another project or as a dependency. That said, you can trigger these scripts manually using npm run.

If you want to execute some code every time you run install at the project level, I think you'll want to use hook scripts (ie. define an executable with the same name as the event in ./node_modules/.hooks/).

Definitely let me know if I'm wrong though & that this is/was working on a previous version of the CLI. Other option here is just to chain (ie. npm install x && npm run y, or we've got handy commands like install-test & install-ci-test which do an npm install then npm run test which is/was a common workflow for folks)

@davidmurdoch
Copy link
Author

This is not how npm 6 works.

npm 6:

image

npm 7:

image

@darcyclarke darcyclarke added this to the OSS - Sprint 17 milestone Oct 9, 2020
@darcyclarke
Copy link
Contributor

Hmm, looking into this a bit more, I know that we did want to quiet down installs & we did implement an RFC for that (ref. https://github.com/npm/rfcs/blob/latest/implemented/0022-quieter-install-scripts.md); But we should still be running those. I'll file this & see if we can get someone to dig in a bit more.

@darcyclarke darcyclarke removed this from the OSS - Sprint 17 milestone Oct 19, 2020
@jameschensmith
Copy link
Contributor

I can second this. I have projects using Husky. When doing a fresh install, Husky does not run, nor does it install the git hooks. This was changed from NPM v6 to NPM v7. One thing that's slightly different than OP's issue, is that (I believe) the postinstall scripts run are in Husky's module, and not in the root project's scripts.

Example npm ci snippet for Husky:

$ npm ci
npm WARN prepare removing existing node_modules/ before installation

> husky@4.3.0 install ./atlas-server/node_modules/husky
> node husky install

husky > Setting up git hooks
husky > Done

> husky@4.3.0 postinstall ./atlas-server/node_modules/husky
> opencollective-postinstall || exit 0

Thank you for using husky!
If you rely on this package, please consider supporting our open collective:
> https://opencollective.com/husky/donate

...

@georgeOsdDev
Copy link

I'm using lerna and using postinstall on my project like below.

  "scripts": {
    "postinstall": "lerna bootstrap",

https://github.com/mobilusoss/textlint-browser-runner/blob/master/package.json#L18

postinstall was called after npm ci on TravisCI with npm v 6.14.8
https://travis-ci.com/github/mobilusoss/textlint-browser-runner/builds/191070080

But npm v7.0.3 does not call postinstall
https://travis-ci.com/github/mobilusoss/textlint-browser-runner/jobs/403527216

My solution is calling lerna bootstrap manually after npm ci

@katsanva
Copy link

katsanva commented Nov 5, 2020

Confirm. Breaking change since npm 7.0.0

Probably caused by

Commands that just run a single script (npm test, npm start, npm stop, and npm restart) will now run their script even if --ignore-scripts is set. Prior to the GA v7.0.0 release, they will not run the pre/post scripts, however. (So, it'll be possible to run npm test --ignore-scripts to run your test but not your linter, for example.)

@simllll
Copy link

simllll commented Nov 10, 2020

Will this be considered as a bug or as a breaking change for npm 7?

@billyjanitsch
Copy link

@darcyclarke @isaacs apologies for the direct tags, but I see that this issue was removed from one of the sprint milestones, so I want to make sure that it wasn't overlooked as it's a fairly major regression.

Here's a minimal repro, in case it's not clear from the original issue:

{
  "scripts": {
    "prepare": "echo foo"
  }
}

With npm@6, both npm install and npm ci print "foo". With npm@7, npm install prints "foo" but npm ci does not.

The problem is that the install command has the following block to explicitly run the appropriate install scripts, but the ci command has no such block:

cli/lib/install.js

Lines 44 to 62 in a28aff7

const scripts = [
'preinstall',
'install',
'postinstall',
'prepublish', // XXX should we remove this finally??
'preprepare',
'prepare',
'postprepare',
]
for (const event of scripts) {
await runScript({
path: where,
args: [],
scriptShell,
stdio: 'inherit',
stdioString: true,
event,
})
}

peterjuras added a commit to peterjuras/time-sync that referenced this issue Nov 21, 2020
Runs the prepare script manually, since npm@7 has a bug and no longer runs the prepare script when running `npm ci`.

See: npm/cli#1905
@cheapsteak
Copy link

cheapsteak commented Dec 3, 2020

fwiw, this breaks builds that use patch-package

@XhmikosR
Copy link
Contributor

XhmikosR commented Dec 9, 2020

This should be considered as a bug and should be higher priority IMHO. So many packages out there use postinstall scripts, and those are broken right now on npm 7.x.

@isaacs isaacs self-assigned this Dec 9, 2020
@isaacs
Copy link
Contributor

isaacs commented Dec 9, 2020

Yes, this is a bug. We misunderstood the initial report to be about deps being installed, not the install/etc scripts of the root project, sorry about that.

Will be fixed on the next release.

isaacs added a commit that referenced this issue Dec 9, 2020
`npm ci` should run all the same preinstall/install/postinstall/prepare
scripts for the root project just like `npm install`.

Fixes: #1905
@isaacs isaacs mentioned this issue Dec 11, 2020
mroderick added a commit to sinonjs/sinon that referenced this issue Jan 4, 2021
Despite npm/cli#1905
being fixed for `npm@7.1.2`, there are still
issues with installing `puppeteer` using `npm@7`.

See puppeteer/puppeteer#6586 (comment)

Therefore, we're reverting the accidental schema
upgrade from 0d1e40b to
the previous version, and removing
`markdownlint-cli` once more.
r3dDoX added a commit to webplatformz/tetris-challenge that referenced this issue Mar 26, 2021
@CalculonPrime
Copy link

CalculonPrime commented Apr 11, 2021

Running with node v14 or v15 and npm v7, I'm finding that the "install" script of the modules being installed don't run if "npm install" is run in the directory of the dependent module. Is that related to this problem or should I file a new bug? Very simple to reproduce:

  • create a new directory and run "npm init" in it
  • in that same directory then do "npm install foo" where foo is a module with the following package.json in its "npm pack":
{
  "name": "foo",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "install": "echo 'FOOBAR!!!'",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "MOBY"
}

The message "FOOBAR!!!" never appears with npm v7, whereas it does with npm v6 and node v14. This is a huge problem.

@CalculonPrime
Copy link

quiet

What's the workaround for modules that were doing interactive install? With output and input from the user? This "quieting" has broken things badly for me! Apparently, if the module calls readline() it just never executes at all.

@webstech
Copy link

For anyone else getting here after searching on postinstall not running in dependent packages, see npm/cli #2606. "hasInstallScript": true was not set during conversion to version 2. Deleting package-lock.json and node-modules to do a fresh install will correct things.

Someone could probably write a script to update package-lock.json for any dependant package.json files with a postinstall entry.

@darkobits
Copy link

Curious why the determination as to whether or not a package has a postinstall script is based on this boolean and not by whether the package in question has a script named postinstall.

@webstech
Copy link

Curious why the determination as to whether or not a package has a postinstall script is based on this boolean and not by whether the package in question has a script named postinstall.

Performance I assume. package-lock.json should have enough information to avoid reading the dependent package.json files.

@isaacs
Copy link
Contributor

isaacs commented Jun 21, 2021

quiet

What's the workaround for modules that were doing interactive install? With output and input from the user? This "quieting" has broken things badly for me! Apparently, if the module calls readline() it just never executes at all.

@CalculonPrime https://docs.npmjs.com/cli/v7/using-npm/config#foreground-scripts

@webstech
Copy link

Someone could probably write a script to update package-lock.json for any dependant package.json files with a postinstall entry.

Published a package on npm to do this. This will minimize change for anyone in tightly managed environments. Run this is the same directory as package-lock.json. It will report the packages that have install scripts.

npx fix-has-install-script --dry-run

--dry-run prevents the lockfile from being updated. Running without the parameter will update the lockfile as needed.

@ginkosen
Copy link

ginkosen commented Jul 6, 2021

still in npm@7.18.1

example vue-demi

image

npm install not running dependencies's postinstall

@webstech
Copy link

webstech commented Jul 7, 2021

still in npm@7.18.1

npm install not running dependencies's postinstall

npm@7.19.1 does work IF it is converting the version of the package-lock.json. Run the fix-has-install-script mentioned in my previous post to see if your lockfile needs to be updated/rebuilt.

@ginkosen
Copy link

ginkosen commented Jul 9, 2021

still in npm@7.18.1
npm install not running dependencies's postinstall

npm@7.19.1 does work IF it is converting the version of the package-lock.json. Run the fix-has-install-script mentioned in my previous post to see if your lockfile needs to be updated/rebuilt.

Ok .thanks. I will try it later.

@CalculonPrime
Copy link

CalculonPrime commented Sep 30, 2021

foreground-scripts

While this does cause the prompt for my npm module to show up, my module not only has a prompt. It also shows an interactive download status during installation using cursor movement commands. Both the query string and periodic download progress output are now injected with spam from some other dependency (bluebird npm module?) like:

[##################] \ reify:bluebird: timing reifyNode:node_modules/binary Completed in 331ms

which gets injected after every printed string and overwritten on top of my refreshing status line. I tried to suppress foreground-scripts for my own module's dependencies with an .npmrc file declaration, but even after forcing that file to be added to npm pack, it has no effect, I suspect because my dependencies are added as siblings of my module by npm, rather than in my module's own node_modules directory.

So, unfortnately, your suggestion isn't a working replacement for npm v6 behavior (which didn't inject spam output like that).

[Update: this problem has nothing to do with bluebird npm package or its parent unzipper, which is how my module has a dependency on it. If I remove unzipper, then I see similar spam from a different dependency. So something in npm v7 is echoing some log message (the last one?) from a dependency and spamming the install/postinstall process with it so that any module actually outputting via "--foreground-scripts" generates garbled output.

If I apply "--quiet" there is no impact. If I apply "--silent" then the problem is solved, but only because that seems to switch off "--foreground-scripts".]

domharrington added a commit to readmeio/metrics-sdks that referenced this issue Apr 21, 2022
I think we were reliant on buggy behaviour in npm@7 where `npm ci`
wasn't running some of the lifecycle hooks:
npm/cli#1905 (comment)

This got fixed in npm@8 but now our CI process breaks:
npm/cli@d825e90

Decided to follow the recommendations from husky's docs to do this so it
doesnt run the `prepare` step:

```sh
npm ci --ignore-scripts
```

https://github.com/typicode/husky/blob/0bcdac6b4dad6eedecc49cf3837ecc05b321db2e/docs/README.md#disable-husky-in-cidockerprod=
domharrington added a commit to readmeio/metrics-sdks that referenced this issue Apr 21, 2022
* feat: adding support for node 18, dropping node 12

* chore: bump the root lockfile

* ci: installing the latest npm 8 in most environmnets

* ci: install npm8 everywhere in ci

* ci: debugging

* fix: add --ignore-scripts to `npm ci` in github action

I think we were reliant on buggy behaviour in npm@7 where `npm ci`
wasn't running some of the lifecycle hooks:
npm/cli#1905 (comment)

This got fixed in npm@8 but now our CI process breaks:
npm/cli@d825e90

Decided to follow the recommendations from husky's docs to do this so it
doesnt run the `prepare` step:

```sh
npm ci --ignore-scripts
```

https://github.com/typicode/husky/blob/0bcdac6b4dad6eedecc49cf3837ecc05b321db2e/docs/README.md#disable-husky-in-cidockerprod=

Co-authored-by: Dom Harrington <domharrington@protonmail.com>
domharrington added a commit to readmeio/metrics-sdks-node that referenced this issue Apr 22, 2022
* feat: adding support for node 18, dropping node 12

* chore: bump the root lockfile

* ci: installing the latest npm 8 in most environmnets

* ci: install npm8 everywhere in ci

* ci: debugging

* fix: add --ignore-scripts to `npm ci` in github action

I think we were reliant on buggy behaviour in npm@7 where `npm ci`
wasn't running some of the lifecycle hooks:
npm/cli#1905 (comment)

This got fixed in npm@8 but now our CI process breaks:
npm/cli@d825e90

Decided to follow the recommendations from husky's docs to do this so it
doesnt run the `prepare` step:

```sh
npm ci --ignore-scripts
```

https://github.com/typicode/husky/blob/0bcdac6b4dad6eedecc49cf3837ecc05b321db2e/docs/README.md#disable-husky-in-cidockerprod=

Co-authored-by: Dom Harrington <domharrington@protonmail.com>
@zWingz
Copy link

zWingz commented Jul 24, 2023

still not work at npm@8.19.x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug thing that needs fixing Release 7.x work is associated with a specific npm 7 release
Projects
None yet
Development

Successfully merging a pull request may close this issue.