Yarn: Add flag to `yarn upgrade` to update package.json versions

Created on 30 Oct 2018  路  20Comments  路  Source: yarnpkg/yarn

yarn upgrade or even yarn upgrade --tilde does not update the package.json to the versions it selects to install. It does SOMETHING as it overwrites an exotic version specifier (dunno if that's correct behavior but at least it proves that it writes package.json) but it doesn't do anything for the many other packages that have either minor or patch upgrades available AND which it has installed.

For example, my package.json lists dependency "redux": "^4.0.0", but yarn installed version 4.0.1 which is the latest available at this moment and only a patch away. Running yarn upgrade or yarn upgrade --tilde makes no change to this line.

I can't figure out the specific relevance of https://github.com/yarnpkg/yarn/issues/5987 but I'll believe it if that and its related issues are also related here.

Windows 10
node v8.12.0
npm v6.4.1
yarn v1.10.1 and v1.12.1

cat-feature

Most helpful comment

This is very confusing. Can the behavior to write it please be added as a flag? Or is there another way to synchronize, after months of development on a project, the defacto requirement from the yarn.lock back into the package.json?

There are scenarios when yarn.lock must be rebuilt, such as when switching internal package repository infrastructure. Or merely that reading the package.json for correct version numbers is useful.

All 20 comments

That is the intended behavior. The docs don't explicitely state that package.json won't be changed, but do state

This command updates dependencies to their latest version based on the version range specified in the package.json file.

which is to say that the newly upgraded to version will still be valid for the range in package.json, so it shouldn't need to be updated. It's basically just updating the lock file to the latest version that matches the package.json range.


The --tilde flag is not a flag that upgrade uses unless you are using the --latest flag.

https://yarnpkg.com/en/docs/cli/upgrade#toc-yarn-upgrade-package-latest-l-caret-tilde-exact-pattern

which _will_ change your package.json to change the dependencies to a tilde. For example if your package.json has "redux": "~1.0.0" then yarn upgrade --latest --tilde will change it to "redux": "^4.0.1"

This is very confusing. Can the behavior to write it please be added as a flag? Or is there another way to synchronize, after months of development on a project, the defacto requirement from the yarn.lock back into the package.json?

There are scenarios when yarn.lock must be rebuilt, such as when switching internal package repository infrastructure. Or merely that reading the package.json for correct version numbers is useful.

Renamed this issue and flagged as a feature request.

A bit confused on this. I thought -T, --tilde install most recent release with the same minor version. Only used when --latest is specified. means it will upgrade the latest non-breaking minor change.

It's clearly making breaking changes:

    "chart.js": "2.4.0",
    "d3": "3.5.17",
    "d3-tip": "0.6.8",
    "datatables.net": "1.10.13",
    "dialog-polyfill": "0.4.7",
    "google-libphonenumber": "1.1.2",
    "handlebars": "4.0.6",
    "bowser": "~2.0.0-beta.3",
----
    "chart.js": "~2.7.3",
    "d3": "~5.7.0",
    "d3-tip": "~0.9.1",
    "datatables.net": "~1.10.19",
    "dialog-polyfill": "~0.4.10",
    "google-libphonenumber": "~3.2.1",
    "handlebars": "~4.0.12",

@artivilla

I think the --help output for yarn upgrade is incorrect and should be updated. Sorry about that. The docs from the website https://yarnpkg.com/en/docs/cli/upgrade are clearer.

The package.json file will be updated to reflect the latest version range. By default, the existing range specifier in package.json will be reused if it is one of: ^, ~, <=, >, or an exact version. Otherwise, it will be changed to a caret (^). One of the flags --caret, --tilde or --exact can be used to explicitly specify a range.

When --latest is specified, then package.json may be overwritten to update the version. --tilde will specify that you want the newly updated version to be ~ prefixed.

For example, if package.json contains

"chart.js": "2.4.0",

and latest is 2.7.3 then yarn upgrade --latest would change package.json to

"chart.js": "2.7.3",

preserving the "exact" version that was previously specified.

yarn upgrade --latest --tilde will tell it to tilde prefix the new version instead.

"chart.js": "~2.7.3",

As far as I know, there is no way to tell what the top level dependencies are for a project without consulting package.json.

That yarn upgrades packages in yarn.lock, but doesn't change the semver string in package.json makes it very tedious to figure out the versions of installed top level dependencies -- first you need to consult package.json to determine what the top level dependencies are, then you need to trawl through yarn.lock to see what is actually being installed.

If yarn would instead just update the semver string in package.json -- even if it's only a patch or minor version that is being incremented -- a developer can quickly scan that file and know exactly what the top level dependencies are, and what versions yarn will install.

@eddie-dunn

makes it very tedious to figure out the versions of installed top level dependencies

but that's how package.json dependencies have always worked since npm's first release. The range in package.json has never indicated the actually installed top level dependency. It represents the range of versions that this project is compatible with.

You can run yarn list or yarn why {package_name} if you want to see what packages and version(s) are actually installed.

@rally25rs

This is how npm works:

# 1. Simulate installing an older version from a lockfile
$ cat package.json
{
    "devDependencies": {
        "lodash": "4.1.0"
    }
}
$ npm install
# 2. Add actual range specifier by editing package.json, adding caret to version string
$ cat package.json
{
    "devDependencies": {
        "lodash": "^4.1.0"
    }
}
# 3. Instruct package manager to update package
$ npm update lodash
$ cat package.json
{
    "devDependencies": {
        "lodash": "^4.17.11"
    }
}

In other words, with npm you can actually use package.json to see if lodash as a top level dependency has been updated, and what version is the new minimum viable version for that package.

There is a difference between the implicit range "^4.17.11" and the range ">=4, <5" -- the former actually means ">=4.17.11, <5", which is why I think yarn also should update package.json after a user uses yarn to update a dependency.

To clarify my last paragraph: Semver minor increases only guarantee backward compatibility but are free to extend the existing API. In other words, there is no guarantee that code written for minor version 1.2.0 will work on version 1.1.0. There is an actual difference between ^1.1.0 and ^1.2.0 in that ^1.1.0 is limited to >=1.1.0,<2 and ^1.2.0 is limited to >=1.2.0,<2.

This means that when yarn upgrades the minor version it really should bump the version number listed in package.json in order to correctly display the minimum viable version of that particular top level dependency.

I can work on correcting this behavior, but if a pull request is rejected by some misguided maintainer I will have wasted my time, so I would appreciate if we could reach some kind of consensus regarding this matter.

@eddie-dunn sounds good to me. I've never objected to the package.json being changed; my stance has always been that what I think the feature does just differs from what everyone else things it does.

To me "yarn upgrade" doesn't mean "my code no longer supports anything older", it just means "please unlock the dependency and re-check what's latest based on the range I said my code works with".
To me changing the versions that your code supports means you manually edit the package.json and specify the new version. Clearly I'm in the minority with this thought, but that's fine. I've only ever expressed this as my stance, but never said I would reject a PR to change the behavior (hence tagging this issue as a feature request instead of closing it).

If you do submit a PR, we would appreciate the contribution! Feel free to tag me as a requested reviewer and I'd be happy to take a look at it. I think i'm probably the contributor that has spent the most time in that particular part of the code, so if you have any questions let me know (you can find me in the Discord channel too if needed) 馃憤

In the meantime, yarn-upgrade-all seems to be doing a great job at updating both node_modules and the package.json file. Do note that versions won't have a ^ prefix anymore.

@rally25rs
I was just trying what you recommended above and getting different results. Running yarn 1.16.0.

For example, if package.json contains

"chart.js": "2.4.0",

and latest is 2.7.3 then yarn upgrade --latest would change package.json to

"chart.js": "2.7.3",

preserving the "exact" version that was previously specified.

yarn upgrade --latest --tilde will tell it to tilde prefix the new version instead.

"chart.js": "~2.7.3",

I was focused on just updating one package, but when I ran

yarn upgrade some-package --latest --tilde

The result was

"some-package": "^2.7.3"

So that doesn't seem to be working as expected on my end.

Caveats: My previous version was a caret, but I don't think that should trump the explicit --tilde flag. Additionally, I had just upgraded to the most recent version, but wanted to run it again and re-write with a tilde, so maybe the fact that it wasn't actually needing to pull a new version had an impact? Still, I'd think the --tilde should still win out, but it didn't for me just now.

any progress on this issue?

It seems to be a very useful option for yarn upgrade to respect the current ^ and ~ semver in package, do the update and then write the new versions back to the package.json

(without having to use --latest and risk major version upgrades)

Does this have enough traction for the team to prioritize it?

here it explains why it doesn't update package.json to the latest version
you can do yarn upgrade package@^ as an alternative
also, I think the help documentation is wrong

That explanation is insufficient, and confuses ranges with actual semver dependencies.

It's actually quite simple:

  • Minor semver increases are allowed to add API extensions
  • This means that code developed for 3.1.4 is guaranteed to work with, e.g., 3.2.0
  • This means that code developed for 3.2.0 is not guaranteed to work with 3.1.4

Thus

  • if yarn upgrades a package from 3.1.4 to 3.2.0, developers may now use features in 3.2.0 which do not exist in 3.1.4
  • This means that the actual dependency range has changed to >=3.2.0 <4.0.0, or ^3.2.0
  • this should obviously should be reflected in package.json by changing the value to ^3.2.0

yarn upgrade package@^ is a nifty workaround however, thanks for that.

So, is there an equivalent of npm update --save? Which will also update the package.json to reflect the changes made?

I'm running yarn upgrade webdriverio in 1.19.1 and package.json is not being altered at all. I do get a success message:

success Saved lockfile.
success Saved 74 new dependencies.
info Direct dependencies
鈹斺攢 [email protected]
info All dependencies

but my package.json still has the old version:

        "webdriverio": "^5.11.13"

This is a violation of POLA: why would an upgrade command not actually change package.json?

I would expect yarn to respect the version settings in my .npmrc (etc) files: if I specify ~ then it should upgrade to the latest patch version. If I specify ^ then it should upgrade to the latest minor version. If there is a new major version around, I'd like to see a big warning about it.

Is this still an issue?

Docs say:

This will upgrade your package.json and your yarn.lock file.

https://yarnpkg.com/lang/en/docs/managing-dependencies/#toc-upgrading-a-dependency

Also says:

[package@version] : When a specified package contains a version then the specified version will be upgraded to. The package.json dependency reference will also be changed to match this specified version. You can use any SemVer version number or range.

https://yarnpkg.com/en/docs/cli/upgrade

Is this still an issue?

Just running yarn upgrade won't update package.json entries unless the upgraded version no longer matches the original semver range (e.g. if using --latest).

This is still an issue for me. I just want my package.json to be in sync with my yarn.lock when I upgrade a project without risking breaking changes using --latest.

Was this page helpful?
0 / 5 - 0 ratings