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

Publish does not update package-lock #1415

Closed
Robinfr opened this issue May 8, 2018 · 26 comments
Closed

Publish does not update package-lock #1415

Robinfr opened this issue May 8, 2018 · 26 comments
Labels

Comments

@Robinfr
Copy link

Robinfr commented May 8, 2018

Expected Behavior

When doing a publish, the version number should not only be bumped in the package.json but also in the package-lock.json when available.

Current Behavior

The package-lock version does not get updated. This causes the version to be updated the next time an install is run creating an extra (useless) commit.

Possible Solution

package-lock.json version number should be made equal to the package.json version number when publishing.

Context

I'm doing a Lerna publish automatically. This pulls the latest version and publishes all of the packages to NPM. However, now I constantly have to create extra commits for the package-lock.

Your Environment

Executable Version
lerna --version 2.2.0
npm --version 5.8.0
node --version 8.11.1
@evocateur
Copy link
Member

The root package-lock.json, or the leaf package-locks (packages/*/package-lock.json)?

@Robinfr
Copy link
Author

Robinfr commented May 8, 2018 via email

@evocateur
Copy link
Member

We're not calling npm version, just modifying the package.json directly and then calling npm publish. I try to avoid leaf package lockfiles, much like lerna itself does (requires lerna 3.x).

@Robinfr
Copy link
Author

Robinfr commented May 8, 2018 via email

@evocateur
Copy link
Member

Is there any reason not to?

For lerna 2.x, it's because I don't want to deal with that old codebase anymore.

For lerna 3.x (current master), it's a bandwidth issue. I'm only one person, and I have a day-job.

@Robinfr
Copy link
Author

Robinfr commented May 8, 2018 via email

@evocateur
Copy link
Member

Sure, a PR would be great.

@tizmagik
Copy link

I'd be happy to assist with this as well if you could point me in the right direction 😄

@Robinfr
Copy link
Author

Robinfr commented May 11, 2018

I was reading through the code but I think I also need some directions, I understand how the system works but it's entirely centered around the package.json file so adding the code for package-lock.json anywhere feels hacky to me..

@evocateur how did you disable the package-lock.json in the Lerna packages anyway? I can't find any .npmrc file or .gitignore in the project that would do this.

@doug-wade
Copy link
Contributor

@Robinfr we use npm's file: specifiers to manage our monorepo, which means that when you run bootstrap, npm i is only run in the root directory. Thus, the extraneous package-lock.jsons are never generated.

@Robinfr
Copy link
Author

Robinfr commented May 16, 2018

@doug-wade but then the additional dependencies in the sub-packages are not installed?

@garthk
Copy link
Contributor

garthk commented Jun 7, 2018

@Robinfr when Lerna writes its temporary package.json it pulls out everything it thinks it doesn't need — including version and name, both of which get materialised into package-lock.json in the way you need. I think the fix is to write both version and name to the temporary package.json. If you're doing version, could you also do name for #1454? Thanks.

@Robinfr
Copy link
Author

Robinfr commented Jun 7, 2018

@garthk this issue has nothing to do with the package.json, but rather with the package-lock.json.

@garthk
Copy link
Contributor

garthk commented Jun 13, 2018

@Robinfr npm derives package-lock.json from package.json, so by changing how Lerna produces package.json during bootstrap you can get the desired result observed in package-lock.json without having to write code to read, alter, and re-write the latter.

@evocateur
Copy link
Member

publish and bootstrap are completely separate operations, and bootstrap should not elicit unstaged changes. thus it needs to be updated during lerna publish. but it is not, at present, because i personally never use nested lockfiles.

@tivac
Copy link

tivac commented Jun 26, 2018

I'm currently working around this by running

> npx lerna exec -- npm i

after each lerna publish. It's not ideal but it at least gets things stabilized again.

@evocateur what's your argument against nested lockfiles? I've got all my devDependencies hoisted to the root, but I still want to have consistent installs of the regular dependencies for everything in my packages dir.

I'm currently using npm ci for installs and I definitely don't want to let it just randomly decide to upgrade a nested package.

@evocateur
Copy link
Member

evocateur commented Jun 26, 2018 via email

@tivac
Copy link

tivac commented Jun 26, 2018

I'm using relative file specifiers in modular-css, but I've still got dependencies in all my packages because I can't hoist those to the root. Lerna looks to be doing the same thing?

"npmlog": "^4.1.2"

So I still don't get how you get around having leaf node package-lock.json files. I've got one in the root for all my devDependencies just like lerna, but that doesn't help w/ anything in packages/ does it?

Would definitely love to know how I could improve my setup or workflow for using lerna@3 in modular-css so I appreciate any wisdom you can share!

@lizardruss
Copy link

Relative file: specifiers, just like the lerna source. It’s a unified package-lock for the entire tree, no bootstrap required. (I really need to document this pattern, I feel like I’ve repeated myself about eleventy-billion times over the past six months)

This approach won't work when a leaf package is going to be built into a Docker image. The docker build process won't follow symlinks, and the file:/// specifiers won't resolve unless the local dependencies are copied into the build context.

I'm not requesting a fix, only giving this example if anyone runs into the same issue I'm having. I realize it's not within the scope of this project to support docker builds.

@stale
Copy link

stale bot commented Dec 27, 2018

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Dec 27, 2018
@stale stale bot closed this as completed Jan 3, 2019
@trippingtarballs
Copy link

trippingtarballs commented Jan 19, 2019

Edit 20/01/19

Fix

Add the following to the root package.json of your project:

{
  "scripts": {
    "version": "lerna clean --yes && lerna exec \"npm install --ignore-scripts --package-lock-only --no-audit\" && git add packages/*/package-lock.json",
  }
}

Explanation

  • lerna exec \"npm install --ignore-scripts --package-lock-only --no-audit\"
    • The use of lerna exec "npm install" over lerna bootstrap is because the bootstrap does not do what I expected.. In my particular use-case I have a package in my project where the package.json contains peerDependencis, but no dependencies or devDependencies. And, as it so turns out, if there are no dependencies or devDependencies in a package's package.json then the lerna bootstrap does not trigger an npm install and the package-lock.json of that package does not have its version pumped (but its package.json) does.
    • In order to generate the rather empty looking package-lock.json for a package with an empty dependencies and devDependencies I had to manually perform an npm install in the package's root folder.
    • I wanted to add a package-lock.json for my package with an empty dependencies and devDependencies for consistency, and because I may well have dependencies / devDependencies in this package in future.

My work around ...

Fix

Add the following to the root package.json of your project:

{
  "scripts": {
    "version": "lerna clean --yes && lerna bootstrap --ignore-scripts -- --package-lock-only --no-audit && git add packages/*/package-lock.json"
  }
}

Explanation

When the lerna publish command is executed the version run-script is invoked by lerna "AFTER bumping the package version, but BEFORE commit". So, breaking down the above run-script:

  • lerna clean --yes
    • This is necessary because if a node_modules folder is present during the installation of a package's dependencies then the version that package's package-lock.json will not be updated by npm. I claim as much based on trial and error.
    • Given my workflow (where I perform a lerna publish) I do not expect there to be a node_modules present for any of my project's packages. However, it does no harm to be explicit.
  • lerna bootstrap --ignore-scripts -- --package-lock-only --no-audit
  • git add packages/*/package-lock.json
    • Specific to my use-case. I have all my project's packages as subfolders of packages/.
    • The use of the * in packages/*/package-lock.json means the git add will only match on the package-lock.json file that is in a folder one-level down. Again, something that makes sense for my project.

Possible PR?

The need for a git add at all is due to the following lines (from lerna source code, commands/version/index.js):

    // exec version lifecycle in root (after all updates)
    chain = chain.then(() => this.runRootLifecycle("version"));

    if (this.commitAndTag) {
      chain = chain.then(() => gitAdd(Array.from(changedFiles), this.execOpts));
    }

The logic of the version command for lerna will; 1. compile a list of files that are to be included with the tag commit, 2. execute whatever version run-script you might have in your project's root package.json, and 3. execute the git add part of the tag commit.

In other words, it's not enough that lerna bootstrap --ignore-scripts -- --package-lock-only --no-audit would have updated the package-lock.json because lerna would have already decided on what files to stage for the tag commit. Hence why I include git add packages/*/package-lock.json – to ensure the package-lock.json is added to the tag commit.

Conclusions

Apologies for the monologue. This issue has been raised more than once (#925). Hopefully my input is helpful to some.

I did think about a PR to have the git add part of the tag commit be moved to after the version run-script has been invoked. But I don't know enough about lerna's source code to know if such a change would have unwanted side-effects.

@evocateur
Copy link
Member

@trippingtarballs The git add in your custom lifecycle script is perfectly appropriate. Just because you're using Lerna doesn't mean Lerna must do all the work.

brophdawg11 added a commit to brophdawg11/vue-dummy-mono-repo that referenced this issue Apr 20, 2019
basti1302 added a commit to instana/nodejs that referenced this issue Apr 25, 2019
Plus, add a hook so that this is taken care of automatically in future,
see lerna/lerna#1415 (comment)
@binomialstew
Copy link

@trippingtarballs, in your example, when/how does the commit happen for the lock files? If I understand correctly, this is supposed to happen in the same commit where versions are tagged, but if I have these changed lock files added during the version script, I see the fatal lerna ERR! EUNCOMMIT Working tree has uncommitted changes.

qiu8310 added a commit to qiu8310/serpent that referenced this issue Jul 4, 2019
teshoudong pushed a commit to svrxjs/svrx that referenced this issue Jul 7, 2019
* chore: first commit

* build: add depency

* v0.0.2

* build(npm): add test framewokr like mocha expect.js nyc etc

* feat(svrx): add middleware basic logic

- add testcase for utility
- add testcase for middleware basic (proxy , serveStatic )
- fix eslint error

* feat(plugin): basic plugin feature privode

- npm install
- system load (contains load inplace)
- system setup
- basic svrx integration usecase

* feat(injector): server side logic provide

- stream replace
- gzip support
- testcase in svrx.injector
- injector client webpack config

* feat(core): implement full logic of plugin system

- support markdown/proxy/serve/livereload/console plugin
- add io logic combine with
- add basic services
- fix proxy with gzip & chunked

* feat(core): add engine-based loader logic

- add semver depend for version compute
- add two-way check: Plugin version and Svrx version

* feat(core): imodel support watcher

all mutations like set,splice,produce will trigger watcher digesting

* feat(logger): add color modifier

* chore: add eslint prettier plugin

* feat(core): basic https support

- add node-easy-cert for simple cert gen
- add https options

* feat(markdown): beautify markdown style

* refactor(util): add svrx-util

* feat(cli): add svrx core installation

* refactor(cli): return svrx instance fix

* feat(cli): print option list help info

* feat(cli): parse options and pass to core

* refactor(cli): modify options passed to core

* feat(core): reformat options from cli and rc file

* refactor(core): fix if plugins not exists in rc file

* feat(core): handle rc file change

* feat(core): add sorted event system to svrx

- Support chainable event transmit
- Refactoring emit to async way
- Fix Some Bugs
- Coverage of events are almost 100% now

* refactor(svrx-plugin-markdown): remove redundancy plugin from main repo

- svrx-plugin-eruda
- svrx-plugin-markdown

* feat(livereload): livereload event support preventDefault

- Refactor event to support ordered emitting
- Fix some style issues
- Refactor io to support easy communication with client
- isolate events with io

* feat(core): fetch plugin props and handle plugin options

* refactor(core): add plugin config getter

* refactor(core): refact config

* fix(core): fix alias handle

* test(core): fix test errors

* feat(svrx-toolkit): add scaffold for toolkit

* perf(cli): set default command serve

* perf(core): enable inline options set

* feat(core): support Plugin get builtin pathes

* refactor(core): watch config and trigger onOptionChange

* feat(svrx-plugin-webpack): basic support webpack

* fix(core): use local pluginConfig

* fix(svrx-plugin-webpack): use $.root to get global rootOC

* refactor(core): watchEvent support builtin and plugin option query

* feat(core): validate options

* refactor(core): change plugin.configs to plugin.configSchema

* refactor(core): enable function option

* feat(serve): add headers and define all configs

* feat(livereload): define all configs

* feat(proxy): use http-proxy-middleware

* feat(cors): replace @koa/cors with koa2-cors

* feat(logger): add logger level and pluginLogger

- add getPluginLogger when inject logger to Plugin
- add setLevel to control logger level global

* test(serve): fix config name change

* refactor(proxy): add boolean type

* refactor(proxy): remove http-proxy-middleware

* feat(proxy): add changeOrigin

* fix(config): add urls.external and urls.local definition

* feat(core): add external link message

- add getExternalIp
- add notify logger level

* feat(logger): optimize logger

- add plugin installed spin
- add plugin list log
- add date formating

* fix(injector): fix style splitter

* feat(serve): support historyApiFallback

* feat(logger): prevent default npm  logger

- add ora for progress message
- add global locked to suppress all message
- fix system logger to suppress npm log
- add testcase 90%

* refactor(serve): historyApiFallback enable only when 404

* feat(serve): add serveIndex config

* refactor(proxy): set request.jar to true

* fix(proxy): set reqeust.followredirect to false

to fix cookie lose after redirect

* refactor(logger): move core logger to svrx-util

* feat(svrx-util): add c2k util for convert connect middle to koa

- monking patching connect2-koa and response for bubble ctx

* feat(webpack): fix webpack serve error

- use svrx-util for convert middleware

* feat(core): remove koa2-connect , add util.c2k

- use util.c2k for convert connect middleware to koa

* fix(core): resolve conflict with proxyw

* ci: modify test script

* feat(proxy): add proxy log

* feat(injector): add function support to injector content

- log error.track for global capture

* feat(svrx-plugin-webpack): fix hot-reloader issue in c2k

- create dummyRes every time
- load webpack local first

* feat(core): support opener

* perf(cli): change default svrx to the latest version installed locally

* fix(core): disable open in testcase

* fix(core): open local typofix

* feat(core): add plugin client wraping

- Refactoring injector.content logic for wraping
- add basic $.config service for client.config

* refactor(util): remove test log

* feat(svrx): add updateNotifier

* feat(cli): add new commands: ls,ls-remote,install

* perf(cli): add more detail to help log

* refactor(svrx): remove duplicated dependency

* refactor: add eslint-config-airbnb, remove prettier

* refactor: eslint auto fix

* refactor(svre): fix lint error in testcase

* fix(open): open.default changeto local

* refactor(cli): fix lint errors

* refactor(util): fix lint errors

* refactor(core): fix some lint errors

* docs(cors): add doc to plugin cors

* refactor(cli): move logger progress to npm install

* refactor(util): set default object value to undefined

* feat: add webpack setting, auto inject webpackConfig

* refactor(core): change serve priority to lowest

* refactor(core): add some progress log

* docs(core): add some description to config list

* feat(proxy): get raw body of post request

* fix(serve): adjust priority of middlewares

* fix(webpack): fix some bug when hot== false

* docs(plugin): add option docs to builtin plugins

* docs(core): add readme docs to builtin configs

* feat(logger): add middleware track in debug mode

* feat(proxy): add secure to enable/disable ssl validate

* refactor(serve): rename serve.serveIndex to serve.directory

* docs(cors): remove detail of cors options

* fix(webpack): webpack-hot-middleware/client resolve error

* fix(logger): remove unnecessary notify

* feat(webpack): add local webpack version validate

* docs(cli): add readme

* refactor: fix some lint errors

* feat(cli): change plugin options insert rule

* refactor(core): move cli helpPrinter to core

* docs: refine readme

* refactor(serve): move historyApiFallback out of serve config

* feat(serve): add index file name config

* feat(proxy): add proxy api and support mock

* feat(core): add scoped plugin package support

* feat(cli): ignore beta versions

* refactor(core): use util/npm.install instead of original one

* refactor(test): remove console

* fix(io): io/client  proxy to eventsObj to support all events feature

* refactor: fix some lint errors

* fix: eslint error

* fix: eslint issue

* build: add some build scripts

* refactor(core): fix configure lint errors

* build: add publish script

* refactor(cli): ignore eslint no-console

* build: set toolkit and ui package private to true

* build: add some lerna config

* chore(release): publish

 - svrx-cli@0.0.3-beta.0
 - svrx-plugin-webpack@0.0.3-beta.0
 - svrx-toolkit@0.0.2-beta.0
 - svrx-ui@0.0.3-beta.0
 - svrx-util@0.0.3-beta.0
 - svrx@0.0.3-beta.0

* fix(test): eslint lint error in __tests__

* fix(test): fix plugin testcase conflict

* fix(core): add requireEnsure to fix module cache

* fix(config): client lint error

* fix(ci): npm ci error, update package-lock.json

* fix(cli): install not-beta version first

* fix(webpack): set svrx version to engines

* fix(cli): move installed dependencies into local directory

* chore(release): publish

 - svrx-cli@0.0.3-beta.1
 - svrx-plugin-webpack@0.0.3-beta.1
 - svrx-toolkit@0.0.2-beta.1
 - svrx-ui@0.0.3-beta.1
 - svrx-util@0.0.3-beta.1
 - svrx@0.0.3-beta.1

* perf(cli): load svrx before print info

* build: add version hook to update package.lock

see lerna/lerna#1415 (comment)

* build: modify build scripts

* refactor(cli): use mkdirp instead of fs.mkdir

* build(webpack): update core version

* chore(release): publish

 - svrx-cli@0.0.3-beta.2
 - svrx-plugin-webpack@0.0.3-beta.2
 - svrx-toolkit@0.0.2-beta.2
 - svrx-ui@0.0.3-beta.2
 - svrx-util@0.0.3-beta.2
 - svrx@0.0.3-beta.2

* feat: add example for mobile debug

* feat(util): npm support registry

* feat(core): use util npm and set registry

* test(util): move npm testcases

* refactor(util): move logger out of util npm

* feat: change svrx-toolkit template

* feat: mv example

* docs(examples): add serve-static-page

* Feature/router (#1)

* feat(router): first support router

* feat(router): support router feature

* feat(config): update config for routing dsl

* feat(injector): support injector.replace

* fix(example): eslint warning disable

* chore(release): publish

 - svrx-cli@0.0.3-beta.3
 - svrx-plugin-webpack@0.0.3-beta.3
 - svrx-toolkit@0.0.2-beta.3
 - svrx-util@0.0.3-beta.3
 - svrx@0.0.3-beta.3

* docs(examples): add proxy example

* feat(cli): add stop events listener

* fix: remove example img

* chore(core,cli): remove useless dependencies
evocateur added a commit that referenced this issue Oct 21, 2019
automateddecision pushed a commit to automateddecision/joblink-loopback-explorer that referenced this issue Apr 9, 2020
peterbraden pushed a commit to hoprnet/hoprnet that referenced this issue Oct 16, 2020
@huboneo
Copy link

huboneo commented Oct 29, 2020

This full on breaks NPM functionality for lerna packages. Since dependency changes are not reflected in lock files basic npm commands such as npm audit fail to execute. If lerna uses NPM (or yarn), I feel it only appropriate it ensures they work as expected?

@matthias-ccri
Copy link

matthias-ccri commented Feb 20, 2021

If you're using hoist, the lerna exec "npm i" workaround is not a good solution, because it generates a bad lockfile. Normally when bootstrapping with hoisting, lerna populates the lockfile with only the non-hoisted packages. npm i populates it with all.

Then, when you run lerna bootstrap, the lockfile takes precedence. Npm installs from the lockfile and not from the package.json, which effectively means packages aren't hoisted properly. I may be wrong about that, but it's what I've seen.

charkour added a commit to charkour/harmoniously that referenced this issue May 6, 2021
@remjx
Copy link

remjx commented May 30, 2021

This workaround ensures that leaf packages are included as dependencies in the package-locks of other leaf packages: #1462 (comment)

tuner added a commit to genome-spy/genome-spy that referenced this issue Nov 23, 2021
I hope this works. After lerna has updated versions in `package.json` files,
`npm install` should update them in the `package-lock.json`.

Source:
lerna/lerna#1415 (comment)
speedytwenty pushed a commit to speedytwenty/http-caching-proxy that referenced this issue Feb 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests