Does go modules support upgrading transitive dependencies? - go

Say I have a go module with each dependency pointing to different versions of the same transitive dependency.
example.com/foo v1.1 --> example3.com/baz v0.1
example2.com/bar v2.1 --> example3.com/baz v0.2
Say I find a bug in v0.2, which is the version resolved by the go modules minimum version algorithm, and would like to upgrade all dependencies that point to a specified version of a transitive dependency. Let's call it example3.com/v0.4.
Is there a command that I can run that upgrades example.com/foo and example2.com/bar so that the transitive dependencies are satisfied by example3.com/v0.4 if they exist?
Ideally I would call go get <some flag> example3.com/bar v0.4 and the result would look something like:
example.com/foo v1.x --> example3.com/baz v0.4
example2.com/bar v2.x --> example3.com/baz v0.4

Go's dependencies only specific minimum versions — they don't pin exact or maximum versions, and do assume that dependencies generally remain compatible as they evolve. So go get example3.com/bar#v0.4 will upgrade example3.com/bar to v0.4, and will downgrade anything that depends on a version higher than v0.4, but it will assume that anything written against v0.1 or v0.2 is more-or-less compatible — and you could perhaps verify that using go test all.
So there isn't a built-in command that directly does what you're trying to do.
That said, you could use go mod graph and grep to figure out which external modules depend on any example3.com/bar. Then you could use sed to chop those lines down to just the module path, and upgrade those modules using go get:
MODS=$(go mod graph | grep '#.* example3.com/bar#.*' | sed 's/#.*//')
go get -d $MODS
You could do that even more precisely using go list -json all, which would give you structured information about the packages imported by the main module. The Deps, ImportPath, and Module fields are probably sufficient to identify which packages need to be updated. (There may be an elegant way to filter and transform that using jq, but I don't have the bandwidth to figure that out today.)

Related

How to update a go dependency with different module name than src path?

The location: github.com/elastic/beats
The mod file: github.com/elastic/beats/go.mod
The module name: github.com/elastic/beats/v7
The tag: v7.10.2
What LoTR incantation of go get to I have to run to get a little dependency update action?
This will update to latest minor.patch version of v7:
go get github.com/elastic/beats/v7
or if you want a specific version to update/downgrade to:
go get github.com/elastic/beats/v7#v7.10.2
Adding the -u flag will additionally update the dependencies of github.com/elastic/beats/v7:
go get -u github.com/elastic/beats/v7
The argument list passed to go get should generally be a list of package paths or patterns, not just a module path.
For example, you might invoke:
go get -d github.com/elastic/beats/v7/libbeat/beat#latest
in order to obtain the latest version of package …/libbeat/beat and also download any transitive dependencies needed for that package.
(You can pass just a module path, and that should also update the version of the dependency module overall, but it will not download source code or module checksums for transitive dependencies that may be needed in order to build the updated package. go get does not in general know which transitive dependencies will be relevant to the commands that you plan to invoke after it, and it does not do extra work to speculatively identify relevant dependencies.)

How to use current version in configurations in gradle

Situation: In my build.gradle file I have 2 separate configurations for pulling in specific dependencies.
One is called configJars where I pull down jars to unpack and get specific json files from.
My question is, is there a way to call out the versions that are already being resolved in the compile/transitive dependencies.
com.example:common:2.0.0-SNAPSHOT -> 2.0.1-SNAPSHOT
I attempted to use "+" but this only pulls the latest version that is available in the repo which is not what I require.
configJars(group: "com.example", name: "common", version: "+")
+--- com.example:common:+ -> 3.2.18-SNAPSHOT
I need to use the version that is being used by a specific dependency that gets updated by a different team.
I ended up adding the library that was doing the update to my other libraries and removed the other libraries from the build file. SO they get pulled in transitively and explicitly exclude the libraries I don't need from the transitive pull.
I had to change the configuration to transitive = true and change all the dependency declarations to { transitive = false}.
A bit messy but it worked out.

Why go module pseudo version have a specific version?

I have a go.mod looks like
require(
...
github.com/google/wire v0.3.1-0.20190716160000-66f78fc84606
...
)
Based on my understanding, if a package looks like that (yyyymmddMMSS-commit_id), which version should be v0.0.0 but not v0.3.1 as this example.
Could someone guide me how should I explain this? Does go mod ignore the v0.3.1- prefix?
It's the result of go get'ing a specific commit that exists in the tree after a semantic version tag:
go get github.com/google/wire#66f78fc84606
Pseudo versions are used not only when there is no version tag.
As the official documentation about pseudo versions shows:
Pseudo-versions may refer to revisions for which no semantic version tags are available. They may be used to test commits before creating version tags, for example, on a development branch.
...
vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefabcdef is used when the base version is a release version like vX.Y.Z.
In this case, the repository does have semantic version tags. The base version here is v0.3.0, and by getting a specific commit (66f78fc84606) that exists after v0.3.0 and before the next one v0.4.0, you end up with:
github.com/google/wire v0.3.1-0.20190716160000-66f78fc84606
In fact there are 3 acceptable forms of pseudo-version:
vX.0.0-yyyymmddhhmmss-abcdefxyz.
when no earlier versioned commit with an appropriate major version before target commit
vX.Y.Z-pre.0.yyyymmddhhmmss-abcdefxyz
when most recent versioned commit before the target commit is vX.Y.Z-pre
vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdefxyz
when most recent versioned commit before the target commit is vX.Y.Z
Some more details about Managing Go Module Pseudo-Versions:
https://hackernoon.com/managing-go-module-pseudo-versions-in-go-113-412h30lw

Use Groovy app and test code in combination with jlink solution for bundling JavaFX

This follows on from this excellent solution to the question of how to get Gradle to bundle up JavaFX with your distributions.
NB specs: Linux Mint 18.3, Java 11, JavaFX 13.
That stuff, involving jlink and a module-info.java, is beyond my pay grade (although I'm trying to read up on these things).
I want to move to using Groovy in my app and test code (i.e. Spock) rather than Java. The trouble is, the minute I include the "normal" dependency in my build.gradle i.e.
implementation 'org.codehaus.groovy:groovy-all:2.5.9'
and try to build, I get multiple errors:
mike#M17A ~/IdeaProjects/TestProj $ ./gradlew build
> Configure project :
Found module name 'javafx.jlink.example.main'
> Task :compileTestJava FAILED
error: the unnamed module reads package org.codehaus.groovy.tools.shell.util from both org.codehaus.groovy.groovysh and org.codehaus.groovy
[...]
error: the unnamed module reads package groovy.xml from both org.codehaus.groovy and org.codehaus.groovy.xml
[...]
error: module org.codehaus.groovy.ant reads package groovy.lang from both org.codehaus.groovy and org.codehaus.groovy.test
error: module org.codehaus.groovy.ant reads package groovy.util from both org.codehaus.groovy.xml and org.codehaus.groovy.ant
100 errors
FAILURE: Build failed with an exception.
* What went wrong:
Execution failed for task ':compileTestJava'.
Yes, 100 errors... probably more! By commenting out various things I think I've come to the conclusion that some Groovy dependency is being injected by the jlink stuff. Fine, I can live with that (although it'd be nice to know what version of Groovy it is).
The trouble is, even if I omit the Groovy dependency line, the same errors occur when I try to introduce the Spock dependency:
testImplementation 'org.spockframework:spock-core:1.2-groovy-2.5'
Has anyone got any idea what's going on here and what to do about it?
I searched for an answer. I didn't find a good solution.
According to this, it seems that Groovy is currently not really compatible with Java modules. It is due to the fact that some packages are contained by multiple jars of the library (not compatible with modules). You will have to wait for Groovy 4 for a compatible version.
I discovered that the JavaFX plugin use this plugin internally. This plugin seems to consider that all dependencies are modules (it is not the default Gradle behaviour).
To make your application works, it seems that you have to:
force Gradle to put Groovy in the classpath instead of the modulepath (it will not be considerered as a module, but seems impossible if you use the javafx plugin)
use the "patch-module" system: it allows Gradle to make a fusion of the library jars into a single module, to prevent the problem of packages that are in different jars
I searched the Groovy jars with IDEA (Project structure/Libraries), and I tried to use the syntax offered by the plugin to use "patch-module":
patchModules.config = [
"org.codehaus.groovy=groovy-ant-3.0.1.jar",
"org.codehaus.groovy=groovy-cli-picocli-3.0.1.jar",
"org.codehaus.groovy=groovy-console-3.0.1.jar",
"org.codehaus.groovy=groovy-datetime-3.0.1.jar",
"org.codehaus.groovy=groovy-docgenerator-3.0.1.jar",
"org.codehaus.groovy=groovy-groovydoc-3.0.1.jar",
"org.codehaus.groovy=groovy-groovysh-3.0.1.jar",
"org.codehaus.groovy=groovy-jmx-3.0.1.jar",
"org.codehaus.groovy=groovy-json-3.0.1.jar",
"org.codehaus.groovy=groovy-jsr-3.0.1.jar",
"org.codehaus.groovy=groovy-macro-3.0.1.jar",
"org.codehaus.groovy=groovy-nio-3.0.1.jar",
"org.codehaus.groovy=groovy-servlet-3.0.1.jar",
"org.codehaus.groovy=groovy-sql-3.0.1.jar",
"org.codehaus.groovy=groovy-swing-3.0.1.jar",
"org.codehaus.groovy=groovy-templates-3.0.1.jar",
"org.codehaus.groovy=groovy-test-junit-3.0.1.jar",
"org.codehaus.groovy=groovy-test-3.0.1.jar",
"org.codehaus.groovy=groovy-testng-3.0.1.jar",
"org.codehaus.groovy=groovy-xml-3.0.1.jar"
]
It only works with a single line "org.codehaus.groovy=X.jar", but a bug prevents it to work with all of the library jars (Look at this issue on Github).
So you have multiple choices:
Use Java instead of Groovy
Wait for a new Groovy release, or new releases of plugins (modules-plugin, and a version of javafx-plugin that use this one internally)
Use old javafx configuration: dependencies are not module by default, and you have to specify manually in build.gradle that JavaFX dependencies should be considered as a module (check my "obsolete" answer to this question)

Is there a way to show the dependency graph of a Go package?

For example, given a package A that depends on package B and package C, where package C also depends on package D - is there a way to output this information? (Using a vendoring tool or otherwise)
The vendor.yaml output by govend doesn't include transitive dependency information - neither does the Gopkg.toml file
output by dep, from what I can see. The go.mod file produced by Golang 1.11's mod and does annotate some dependencies as // indirect - but it does not annotate dependencies with any information about which dependency they were pulled in via.
Did you try https://github.com/KyleBanks/depth?
It does provide a decent dependency tree at first look I tried.

Resources