Hacker News new | ask | show | jobs
by munificent 3035 days ago
> In the tour it states, "We've seen that when a new module must be added to a build to resolve a new import, vgo takes the latest one." which means that the newest Rails would be used and set in your `go.mod` file.

That works for adding a new dependency. But, as I understand it, if I decide to upgrade my dependency on foo by changing its already-present version in my app's module file, this does not upgrade any of the transitive dependencies that foo has. Instead, it selects the lowest versions of all of those transitive dependencies even though my goal with foo itself is to increase its version.

So now I have to reason about sometimes it picks the latest version and sometimes it doesn't, depending on the kind of change I'm making.

2 comments

The new release of the dependency can also bump the minimum required versions of its dependencies, as part of their release cycle. If they don't, you can upgrade them as any other dependency; after all transitive dependencies are just dependencies.

That said, you can just upgrade all the dependencies with vgo get -u and get the "always latest" behaviour. This is a desirable result, but it shouldn't happen at each and every fresh build.

You can have automation that periodically tries to bump all the versions and if all tests passes send you a PR with the proposed update.

With the proposed rules you get 1. Repeatable builds as with lock files 2. Simple to reason about constraint resolution on case of multiple modules depending on the same module.

Let's say I create a program that is using foo and end up with the following dependencies:

main:

    requires "foo" v1.0.0
foo (v1.0.0):

    requires "bar" v1.0.0
Right now if I check my dependencies, I'll have something like this:

    MODULE    VERSION
    main      -
    bar       v1.0.0
    foo       v1.0.0
Now lets say some time passes, and both foo and bar release new versions:

foo:

    v1.0.0
    v1.1.0
bar:

    v1.0.0
    v1.0.1
    v1.1.0
    v1.1.1
    v1.1.2

And the deps for foo v1.1.0 are:

foo (v1.1.0):

    require "bar" v1.0.1
Realizing that foo has an update, I decide I want to upgrade. I'd do vgo get foo. My updated dependencies (shown with "vgo list -m") are:

    MODULE    VERSION
    main      -
    bar       v1.0.1
    foo       v1.1.0
bar gets its version increased as well, using the version specified by the foo package's module. This makes sense to me - the foo package maintainer has stated that he only needs v1.0.1 to be stable, so we default to what he specified.

Now imagine I want to add another package, say it is the wham package and it has the following dependencies:

wham (v1.0.0):

    require "bar" v1.1.1
If I add this to my code my versions will now be:

    MODULE    VERSION
    main      -
    wham      v1.0.0
    bar       v1.1.1
    foo       v1.1.0
bar now uses v1.1.1 because it is the minimal version that satisfies all of my modules. vgo DOES upgrade bar for us, but not beyond the lower version number required to satisfy all of our modules. That said, we can still upgrade it manually with "vgo get bar", after which it will be using v1.1.2 because our main dependencies would become:

main:

    requires "foo" v1.1.0
    requires "wham" v1.0.0
    requires "bar" v1.1.2
In short, upgrading foo WILL upgrade all of foo's dependencies in order to meet it's minimum version requirements, but no further. That said, you can still manually upgrade any of those dependencies.

To me this makes sense. The creator of foo may have avoided upgrading the dependency on bar for some performance reasons, so this upgrade only happens in your code if it is required by another package, you initiate it manually, or if the foo package releases a new version with updated dependencies in its go.mod file.

PS - I've tested this all using the prototype of vgo. You can see yourself by grabbing this code: github.com/joncalhoun/vgo_foo_main and then use vgo to list dependency versions and try upgrading foo which has a dep on demo.