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

yarn install changes yarn.lock file #4379

Closed
artlogic opened this issue Sep 10, 2017 · 55 comments
Closed

yarn install changes yarn.lock file #4379

artlogic opened this issue Sep 10, 2017 · 55 comments
Labels

Comments

@artlogic
Copy link

artlogic commented Sep 10, 2017

Do you want to request a feature or report a bug?
Bug

What is the current behavior?
When installing certain packages the yarn.lock file is changed. It seems to be package specific. In this case cordova triggers the behavior.

If the current behavior is a bug, please provide the steps to reproduce.

In an empty directory, do the following:

yarn init
yarn add cordova
cp yarn.lock yarn.lock.initial
rm -r node_modules
yarn install
diff yarn.lock.initial yarn.lock

Notice that the yarn.lock file has changed.

What is the expected behavior?

Installing should not change the lock file if it already exists.

Please mention your node.js, yarn and operating system version.

node v6.11.3, yarn v1.0.1, Mac OS 10.11.6

@BYK
Copy link
Member

BYK commented Sep 10, 2017

I don't think this is a bug. I was able to reproduce the issue but the difference was

52,55d51
< ansi-regex@*:
<   version "3.0.0"
<   resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
<
1352c1348
< imurmurhash@*, imurmurhash@^0.1.4:
---
> imurmurhash@^0.1.4:

This change is just an optimization of the lockfile and doesn't change the semantics. We are planning to add a warning when the lockfile needs an update when running yarn install but if you want to ensure your lock file stays the same and is accurate, you should be using the --frozen-lockfile option.

I have to admit that this is a bit unintuitive and we are trying to come up with a good solution to this. You can follow or contribute to the discussion on #4147.

If you agree that this is not a bug and #4147 is a good place to continue the discussion, pleae close the issue :)

@artlogic
Copy link
Author

@BYK thanks for your thoughtful response. After reading #4147, I'm on the fence about closing this issue. I'm hoping a bit more discussion here can help.

#4147 seems to be exclusively about the case where the yarn.lock and package.json are not in sync - in fact the only time optimization is mentioned is in this comment: #4147 (comment) - and that comment touches on the issue that concerns me: yarn modifying the yarn.lock file when no changes have been made to package.json.

It seems to me that the yarn.lock file should only change if my dependencies are somehow changing. In fact, up to this point, I've been telling my devs that if they see a change in the yarn.lock file, it's time to run yarn install. With the recent upgrades several reported back that after they received my changes and they ran yarn install, their lock file changed (the optimization). This makes for a confusing situation - should they commit the change? Should I somehow pre-optimize the lock file (is that even possible)?

It looks like I may have to, in the short term, add --frozen-lockfile true to .yarnrc in all my repos - but I'm not a huge fan of this solution because it precludes the workflow mentioned in #4147 where you edit the package.json and then run yarn install.

Is the intention that any invocation of yarn might modify yarn.lock?

@artlogic
Copy link
Author

@BYK I'm sorry to bother you about this because I know you are very busy - but I'm hoping to get a definitive answer on this. My workflow for distributing dependency changes to my team has devolved into this:

yarn add [blah]
rm -r node_modules yarn.lock
yarn install
rm -r node_modules
yarn install

This seems to update the lock file properly (see #4476), and then optimize the lock file so that my team mates aren't checking in lock file changes.

Is my team using yarn incorrectly? Should we be expecting the lock file to change with every install command?

@k0pernikus
Copy link

k0pernikus commented Sep 25, 2017

@artlogic IMHO, your team mates should be allowed to check in lockfile changes even if they are just optimizations. I'd agree with the notion that yarn install optimizing the lockfile is counter-intuitive, yet still something that each developer of your team could safely commit. I don't understand why you want to prohibit that.

That being said, your workflow might lead to unexpected side-effects, as you are pretty much giving up the locked-in versions. Deleting the lockfile means that yarn has to resolve all the dependencies version again, and it will try to fetch the most current version as pointed out in your package.json leading to potential breakage, esp. if more than one dependency breaks at the same time in a future version.

If you still want to enforce that install does not touch lockfile, then you should use the frozen-lockfile flag:

 yarn add {blah}

Check in lockfile, and then another dev would use:

   yarn install --frozen-lockfile

DON'T ADD --frozen-lockfile to true in .yarnrc as it prevents you from ever updating, see: #4570

If you want to upgrade your dependencies, run:

 yarn upgrade

If you want to upgrade only one dependency:

  yarn upgrade {blah}

You can also just install a specific version of one dependency:

  yarn install {blah}@1.5

This allows for more fine-tuning and less headaches in the long run.

@artlogic
Copy link
Author

@k0pernikus - thanks for your detailed response. First, I should apologize for conflating two issues - #4476 is driving some of my workflow. The fact that yarn upgrade appears to be somewhat broken has nothing to do with this issue, of course.

As for workflow, I can't imagine mine is the only team where one developer is in charge of maintaining/testing new dependencies while the other developers work on the code base. The big issue I have with what has started happened is that I would install/test new dependencies, tell everyone to run yarn install and then get 4-5 questions about if the changed yarn.lock should be committed. It seems like I'd be in a worse place if I said "if the lockfile changes, commit it" because at that point I could end up for a commit lock that looks something like this:

  • yarn.lock changed (dev4)
  • yarn.lock changed (dev3)
  • yarn.lock changed (dev2)
  • yarn.lock changed (dev1)
  • Updated dependencies (me)

However, it could be this is just the way yarn is intended to work, so for my team's projects we'll change all our repos to use frozen lockfile so that only add and upgrade cause the lockfile to change.

One additional scenario... it seems like this could be a potential annoyance for projects with lots of contributors because potentially each time they clone and install, the lockfile might change. I certainly wouldn't want these optimizations in pull requests. Is the intention that most FOSS projects using yarn transition to a frozen lockfile as well?

@jboler
Copy link

jboler commented Sep 25, 2017

@artlogic Our team has --install.pure-lockfile true in the project's .yarnrc for exactly this reason.

@artlogic
Copy link
Author

@jboler - I hadn't seen that setting before. I'm going to have to take a look, but it looks like I'll be suggesting that we add that to the .yarnrc for all our repos, and all the repos of any FOSS projects I have.

If someone from the yarn team can confirm that the intention is that yarn install can and will change the lock file on every run (despite no changes to dependencies) then I'll close this issue.

@BYK
Copy link
Member

BYK commented Sep 26, 2017

@artlogic sorry for the late response.

The thing is, it is expected that yarn install to potentially change the lock file. I know this is not ideal and needs better communication though. I really want to have a better default but in the meantime, I think something like @jboler suggested with but maybe using --frozen-lockfile instead, would be the best solution until we figure out how yarn should behave under different scenarios like for workflows where people prefer simply editing package.json to update dependencies instead of using yarn add etc.

@vkrol
Copy link
Contributor

vkrol commented Sep 27, 2017

@BYK I agreed with @artlogic . This behavior is very confusing:

The big issue I have with what has started happened is that I would install/test new dependencies, tell everyone to run yarn install and then get 4-5 questions about if the changed yarn.lock should be committed.

Our team consists of ~50 people who run yarn install every day :(

@BYK
Copy link
Member

BYK commented Sep 27, 2017

@vkrol you should be able to check in a .yarnrc file that has --install.frozen-lockfile true or --install.pure-lockfile true to avoid issues until Yarn changes its behavior. Would that help?

@vkrol
Copy link
Contributor

vkrol commented Sep 27, 2017

@BYK pure-lockfile will help us, but not frozen-lockfile. If I understand correctly yarn install will fail with an error if frozen-lockfile is enabled. This behavior is absolutely unacceptable in our case.

@BYK
Copy link
Member

BYK commented Sep 27, 2017

@vkrol my preference is frozen-lockfile since it will fail only if your lock file needs changing and is not consistent. With pure-lockfile you may have a lockfile close to being useless or very inaccurate but you still wouldn't get a failure. Yarn would simply use the internal resolutions it calculated happily. If all your team members use the exact same version of Yarn, this should be fine. If not, it can be dangerous.

@vkrol
Copy link
Contributor

vkrol commented Sep 27, 2017

@BYK maybe I do not understand the behavior of frozen-lockfile correctly. Does it fail when the lockfile is consistent with the package.json content, but some internal optimization needed?

@BYK
Copy link
Member

BYK commented Sep 27, 2017

@vkrol it should not fail when the file can be optimized further but it is consistent with package.json and is consistent in itself. If not, this is a bug. There is even a test for this:

test.concurrent(
"doesn't write new lockfile if existing one satisfied but not fully optimized with --frozen-lockfile",
(): Promise<void> => {
return runInstall(
{frozenLockfile: true},
'install-should-not-write-lockfile-if-not-optimized-and-frozen',
async (config): Promise<void> => {
const lockfile = await fs.readFile(path.join(config.cwd, 'yarn.lock'));
expect(lockfile.indexOf('left-pad@1.1.3:')).toBeGreaterThanOrEqual(0);
},
);
},
);

@vkrol
Copy link
Contributor

vkrol commented Sep 27, 2017

@BYK I did not know about it. I will try this option, thanks! I think that this fact should be documented somewhere.

@vkrol
Copy link
Contributor

vkrol commented Sep 29, 2017

@BYK

it should not fail when the file can be optimized further but it is consistent with package.json and is consistent in itself.

I found some downside of the using of this flag. If yarn.lock can be optimized than the repeated invocations of this command yarn install --frozen-lockfile are not optimized via "integrity" check as without this flag. It this a bug? Do I need to create the separate issue?

@artlogic
Copy link
Author

artlogic commented Oct 7, 2017

@BYK Thanks for your response. For my team's projects, we're now using frozen-lockfile and things are working (relatively) fine. This issue remains rather concerning for me, however. Specifically the unnecessary optimizations yarn is making to the lock file when running yarn install.

Here's the clearest example I can give of where this behavior causes problems:

  1. I add a new dependency using yarn add [blah] and commit my updated package.json and yarn.lock.
  2. Contributors to my package pull down changes and notice that yarn.lock has been updated, and thus run a yarn install.
  3. In some cases these contributors end up with a modified yarn.lock after the install. What should they do in this case? Is it a race to see who can submit the pull request first?

To be clear, I have no problem with yarn install modifying yarn.lock if package.json has been modified. My problem is the optimization when package.json has not been changed. I see three possible solutions:

  1. Direct any project that manages dependencies centrally to add --install.frozen-lockfile true to a .yarnrc file. This would likely be a LOT of projects - most NPM packages I'd guess.
  2. Provide a switch to force yarn to optimize the lock file during the add phase, e.g. yarn add --optimize [blah]. Then direct package maintainers to always use that switch.
  3. Disallow yarn from optimizing yarn.lock during the install phase unless the package.json appears to have been updated.

I am advocating for option 3, but I could see option 2 being a reasonable choice as well.

Thanks for your time!

@fender
Copy link

fender commented Nov 8, 2017

I kind of like the idea that yarn install does not update the yarn.lock file but instead emits a warning saying that "Your yarn.lock file is out of date, run yarn blah to update it now`.

@spencer-brown
Copy link

spencer-brown commented Nov 11, 2017

@BYK why ~~~doesn't~~~ does yarn apply optimizations to yarn.lock on yarn install rather than when add/upgrade are run?

edit: fix typo

@artlogic
Copy link
Author

@spencer-brown: based on what I've seen, it actually does apply optimizations on install - that's what I find problematic

@mattblackdev
Copy link

Shouldn't the optimization to yarn.lock be run on yarn add? yarn.lock will be changing anyway. This is option number two in @artlogic's recent comment, right? Why doesn't the optimization occur then, so nobody else has to commit another yarn.lock change?

@spencer-brown
Copy link

@artlogic oops, typo :) - my comment should say "does"; edited.

@ryancastle
Copy link

We use composer a lot and composer install does not ever touch the lock file.

composer update or composer require (equivalent to yarn add) must be run for any changes or optimisations to be made to the lock file.

In many years, we have never had to worry about ambiguous behaviour of composer install.

I realise yarn fills a slightly different role, but composer has the equivalent issue of manual updates being made to composer.json and it getting out of sync with the lock file. Currently, composer install will completely ignore the composer.json file and issue a warning.

1 similar comment
@ryancastle
Copy link

We use composer a lot and composer install does not ever touch the lock file.

composer update or composer require (equivalent to yarn add) must be run for any changes or optimisations to be made to the lock file.

In many years, we have never had to worry about ambiguous behaviour of composer install.

I realise yarn fills a slightly different role, but composer has the equivalent issue of manual updates being made to composer.json and it getting out of sync with the lock file. Currently, composer install will completely ignore the composer.json file and issue a warning.

@mikeyc7m
Copy link

mikeyc7m commented Apr 6, 2018

hey kids, the lock file should never change on subsequent installs. it's just dumb. if you feel that the optimisation is worth touching it, just create a separate file instead that doesn't go into version control.

@jboler
Copy link

jboler commented Apr 6, 2018

As with Bundler's Gemfile.lock, the whole point of yarn.lock is that every time yarn install is run, you can guarantee deterministic results across all environments. If yarn install changes the lock file you lose that guarantee. Other commands such as yarn add or yarn update should obviously change yarn.lock but yarn install should not. Our team has run into issues where we have slightly different package versions installed in different environments which is exactly what we don't want.

@ryancastle
Copy link

I'm inclined to think that yarn install --pure-lockfile should be the default, and there could be an --fix-my-dev-process-inconsistencies-for-me-magically option to get the current behaviour.

@k0pernikus
Copy link

k0pernikus commented Apr 10, 2018

@ryancastle --pure-lockfile won't tell you that an update is for your lockfile. It only doesn't generate one. This might still lead to unexpected behavior. --frozen-lockfile will fail if an update is required.

@artlogic
Copy link
Author

I've been operating with --install.frozen-lockfile true in my .yarnrc for awhile now and it seems to work in a sane way. The trick is to create the initial yarn.lock for the repo without that flag in effect. Once it's created, installs can't change the yarn.lock, but updates can. Once I started using this workflow the number of accidental changes to yarn.lock dropped to zero.

@MartijnHols
Copy link

I've been telling people that PRs including changes to the lock file will not be merged as the lock file is only changed when adding new or updating dependencies. This is what the install documentation states:

yarn install

Install all the dependencies listed within package.json in the local node_modules folder.

The yarn.lock file is utilized as follows:

  • If yarn.lock is present and is enough to satisfy all the dependencies listed in package.json, the exact versions recorded in yarn.lock are installed, and yarn.lock will be unchanged. Yarn will not check for newer versions.
  • If yarn.lock is absent, or is not enough to satisfy all the dependencies listed in package.json (for example, if you manually add a dependency to package.json), Yarn looks for the newest versions available that satisfy the constraints in package.json. The results are written to yarn.lock.

If you want to ensure yarn.lock is not updated, use --frozen-lockfile.

Is the documentation wrong as there are these optimizations that can happen stated above or is this a bug to take into account for the time being?

ps. it still happens, and yarn --frozen-lockfile does not fail when it does.

@konekoya
Copy link

konekoya commented Feb 3, 2020

I'm current using --frozen-lockfile in my .yarnrc file, which effectively prevent yarn from modifying yarn.lock file when running yarn install on different machines. But this also prevent yarn add blahblah from modifying my yarn.lock. Is that the correct behavior or I'm missing something? I've read thru the entire thread and it seems to me that --frozen-lockfile is the recommended approach for now?

@k0pernikus
Copy link

k0pernikus commented Feb 3, 2020

@konekoya Yes, you are right that you currently MUST use

yarn install --frozen-lockfile

and cannot rely on the setting in the .yarnrc as it will prevent your yarn.lock from ever updating.

Depending on your content of your .npmrc and .yarnrc you may be able to use

yarn install --no-default-rc {dependency}

but I would not rely on that (since it would break as soon as you have other settings in your rc-files.)

See my comment and the relevant issue: #4570, esp. my conclusion.

@konekoya
Copy link

konekoya commented Feb 4, 2020

Thanks for clearing that up @k0pernikus. You just made my day :)

@qtiki
Copy link

qtiki commented Feb 6, 2020

@BYK why does yarn apply optimizations to yarn.lock on yarn install rather than when add/upgrade are run?

I think @spencer-brown 's comment here is key to "fixing" this problem. I just tested for myself and running yarn upgrade and then yarn I was told "Already up-to-date.". So I deleted my node_modules and ran yarn which then resulted in the "optimized" lockfile which the other devs in my project would have ended up if I had pushed the one I got from yarn upgrade.

Now if yarn upgrade (and yarn add) would run the same optimization as yarn install we wouldn't have this problem in the first place. There's been a lot of talk about not wanting to break any existing functionality and I don't see running the optimization after yarn upgrade and yarn add as breaking anything - just making it a little bit slower.

As a workaround I am thinking of instructing all of our devs to delete node_modules whenever they need to update the lockfile to force the "optimization" before pushing the lockfiles to others. Or maybe they can run yarn upgrade && yarn prune - maybe that would do the trick?

@qtiki
Copy link

qtiki commented Feb 6, 2020

As a workaround I am thinking of instructing all of our devs to delete node_modules whenever they need to update the lockfile to force the "optimization" before pushing the lockfiles to others. Or maybe they can run yarn upgrade && yarn prune - maybe that would do the trick

Update: You can't run prune manually, you just get this message: "The prune command isn't necessary. yarn install will prune extraneous packages". And since you can't run install either because you are "Already up-to-date" I guess we're going with deleting node_modules and then running yarn to do the pruning.

@peteorpeter
Copy link

For me, the single biggest selling point for yarn is predictable, reliable lock file behavior. Changing the lock file on yarn install gives me real anxiety.

@dtgriscom
Copy link

For me, the single biggest selling point for yarn is predictable, reliable lock file behavior. Changing the lock file on yarn install gives me real anxiety.

The lock file is presented as an exact specification of what will be installed, so that we don't have to worry about what will be installed. Use the same lock file, and you'll get the same install every time. But sometimes yarn will, on its own initiative, for its own reasons, and with no warning, change the lock file contents. Yes, you can argue that "the file changes don't change what will be installed", but why take such a clear guarantee and muddle it up? Why make me wonder if I should be re-committing the changed lock file? Why sully your main claim to fame?

@omarreiss
Copy link

This is really unbelievable. Others have already stated it well. A lock file should not change on install. This negatively impacts commit workflows. Every developer in our team knows under what circumstances the lockfile is allowed to change. When a lockfile changes without the dependencies being updated, that causes unnecessary confusion and extra checking. This is basic package manager UX that is just broken. Please fix.

@lobo-tuerto
Copy link

lobo-tuerto commented Apr 27, 2020

I just got surprised by this behaviour, when moving from Node.js 13 to 14 all my yarn.lock files changed when doing a yarn install and I was wondering why...

I think the appropriate behaviour would be to emit a warning if optimizing the yarn.lock file in any way.

@paul-soporan
Copy link
Member

Closing as fixed in v2.

https://yarnpkg.com/getting-started/migration

@paul-soporan paul-soporan added the fixed-in-modern This issue has been fixed / implemented in Yarn 2+. label Jan 3, 2021
@MrBrN197
Copy link

I'm a bit confused about yarn. I've started using it just now. if I download a project that has a yarn.lock with no node_modules folder. shouldn't running yarn install reproduce the exact setup in the yarn.lock file. but it seems running yarn install upgrades the version of the dependencies.

even running yarn install --pure-lockfile still install the latest versions, it keeps the yarn.lock file the same but updates the packages in node_modules. how would one install the current state of the packages as it is in the yarn.lock file

@rulatir
Copy link

rulatir commented May 13, 2021

I only detected this because image builds started failing due to yarn EACCESSing upon trying to write the lockfile. I never suspected that yarn would want to modify it, so I didn't care about write permissions.

@ryanklarhoelter
Copy link

ryanklarhoelter commented Mar 9, 2023

Sharing my experience here because it might help others who stumble across this issue: I was wondering why "yarn.lock" gets updated by "yarn install" when I changed the version requirement in "package.json" from "1.3.2" to "^1.3.2". "yarn.lock" seemed to already fulfill this requirement (so I expected no changes to happen in "yarn.lock"):

feiertagejs@1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/feiertagejs/-/feiertagejs-1.3.2.tgz#55e4c789fa7bf12154307d92b0b739f8785877f4"
integrity sha512-urZBA5C5ry4+z7YiZ+21ulEHAeQJBAyTQ6Fm3ueAL6roP4gRJUqmrDgIklwxghZn+unyRLev/xreCCeShq5FNw==

But when I ran "yarn install" it was changed to:

feiertagejs@^1.3.2:
version "1.3.6"
resolved "https://registry.yarnpkg.com/feiertagejs/-/feiertagejs-1.3.6.tgz#2a73c5b1a48830c83fdd2c5d5006008a8e511886"
integrity sha512-sbtLIbnHOW22KNszgRJhdvWZlohM2Ra/Fd1B1urMlz9KLn6Bc4KI/fIFfKfyxCh4KK83sFyrmWvbLPjN7z3Tow==

That didn't happen because there is an update available for the package but because the dependency name—the version of it—didn't match anymore. That is why "yarn install" touched "yarn.lock". The update of the package was just a side effect so to speak. The requirements have changed and Yarn just adapts the lockfile accordingly. I changed "yarn.lock" as followed:

feiertagejs@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/feiertagejs/-/feiertagejs-1.3.2.tgz#55e4c789fa7bf12154307d92b0b739f8785877f4"
integrity sha512-urZBA5C5ry4+z7YiZ+21ulEHAeQJBAyTQ6Fm3ueAL6roP4gRJUqmrDgIklwxghZn+unyRLev/xreCCeShq5FNw==

Now I get the version 1.3.2 when I run "yarn install"—and "yarn.lock" is not touched anymore.

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