Hi I’m using version catalog and convention plugin...
# gradle
h
Hi I’m using version catalog and convention plugin for a multi module project. This project is importing several dependencies. I would like to specify one or two dependencies to be the latest version automatically. And not the release version but the snapshot. How do I achieve that?
a
Gradle supports writing dynamic versions https://docs.gradle.org/current/userguide/single_versions.html so you can use
some-group-id:the-artifact:+
to always get the latest version Just be aware that’s such dynamic versions are pretty risky, and will lead to hard-to-track issues because the version can change basically at random. You can limit some of the damage by using a prefix, something like
1.0.+
, or a range
(1.0, 2.0)
You can use dependency locking to protect against ‘random’ changes too https://docs.gradle.org/current/userguide/dependency_locking.html Using a plugin that automatically updates the versions will be even more reliable https://github.com/ben-manes/gradle-versions-plugin
j
you have this too • A latest-status version: e.g. latest.integration, latest.release https://docs.gradle.org/current/userguide/single_versions.html
main problem is a release is higher than a snapshot so your use case can be a problem if you are publishing 1.0.0 and 1.0.0-snapshot
so you are forced to publish a snapshot with a higher value, for example 1.0.1-snapshot
• The strings rc, snapshot, final, ga, release and sp are considered higher than any other string part (sorted in this order): 1.0-zeta < 1.0-rc < 1.0-snapshot < 1.0-final < 1.0-ga < 1.0-release < 1.0-sp < 1.0.
h
We were using already the
group-I’d:artifact-id:+
but this is pulling only the latest release version. Not the snapshot from Nexus. And for some reason it’s getting the version 0.1298.0 from nexus but I can see version 0.1303.0 in nexus of that dependency. The former was created like 1 month ago, and the latter like few days ago. I have changed that project to use version catalog and upgraded to latest gradle after 0.1298.0 release. Maybe I’ve missed something in the publishing part that it’s not taking the latest version anymore? 1) What is gradle looking for when searching the remote repository for a dependency? 2) in the past it was only getting the latest release, so maybe I should try using the
latest.integration
as version? I’ll try tomorrow the 2nd step see if that does any difference.
Ive have tried that ben-manes plugin, together with the toml plugin, but that messes up my entire layout and screwup some lines for me in my toml file. (Is doing some ordering and removing dependencies it thinks that are not being used).
v
+
should be equivalent to
latest.integration
. It should give you the very latest version, whether snapshot or not. As your
+
is not even getting you your latest release version it seems there is something different broken or unexpected. Maybe you do have dependency locking in place?
h
We used to have lock files but that we also removed.
It was getting the latest release version but never the snapshot. And after the 0.1298.0 might be because upgraded the project to convention plugins and version catalog. And gradle 8.1.1. Maybe I’m missing some setting in the publish configuration? I will compare tomorrow the Pom.xml of the two versions tomorrow. I think that’s what being used right?
j
is the snapshot repository added?
h
Yes
v
Neither convention plugins nor version catalog per-se should cause that was long as they are doing the same things as before. For determining the available versions to pick from, it probably looks into
maven-metadata.xml
which lists versions. Check what it contains for you.
h
Thanks will take a look at that file in nexus right?
v
Yes
h
Looking in nexus and indeed newer versions don't exists after 0.1289.0, need to fix that one first.. the latest release version is being pulled from nexus with
latest.integration
The issue was that we did have a publishing with maven repositories for nexus defined but we didn't have publications. The project was made in java but now we upgraded to use kotlin with java source code. We don't specify the java plugin and I guess that is why we need to add the `mavenJava(MavenPublication)`:
Copy code
publishing {
    publications {
        mavenJava(MavenPublication) {
            from components.java

            artifact sourceJar {
                classifier "sources"
            }
        }
    }
}
v
You should always need to define the publication if you want to publish, whether you use the Java plugin or not. Regarding the source jar, better do not add the artifact manually. Better add the source jar to the Java component instead, or simply use
withSourcesJar()
which also adds it automatically.
h
Thanks for the info about the withSourceJar(), that it automatically will publish the sources. I did add it and removed that extra definition sourceJar.
I was reading this documentation (section 66.2.1) and there they say that this mavenJava in the publication is added by the Java Plugin. In the old gradle build file we were using, we were probably applying the java plugin and that's why we didn't define that extra publications part.
v
To start with, you should probably not use a copy of the documentation some page provides that documents Gradle 2.1 which was released in 2014! The current documentation is at https://docs.gradle.org/current/userguide/publishing_maven.html, or use the one matching the Gradle version you use, that hopefully is not 2.1. Besides that, even the docs you refer do not state what you say. It says that the
java
plugin adds the
java
component which you can then publish using the shown snippet which adds the
mavenJava
publication and configures it to publish the component which is added by the
java
plugin.
If you did not define a publication explicitly previously, it is more likely that you applied some plugin that defined the publication on your behalf.
h
We are using gradle 8.1.1 at this moment.
v
Good for you :-)
h
Yes and migrating from gralde groovy to kotlin DSL
I'm back to the old situation, have a snapshot version 0.1306.0-branchname-SNAPSHOT in nexus but it is only getting the latest release version from nexus 0.1298.0, as version I'm using the
latest.integration
in the version.ref that is pointing to my version of the jar. (i've checked and
+
is doing the same thing. The repositories are configured as follows:
Copy code
val releasesRepoUrl = "<https://our-internal-nexus:8443/repository/....releases/>"
val snapshotsRepoUrl = "<https://our-internal-nexus:8443/repository/....snapshots/>"

repositories {
    mavenLocal()
    maven("<https://our-internal-nexus:8443/repository/public/>")
    maven(releasesRepoUrl)
    maven(snapshotsRepoUrl)
}
I think it should be able to find the snapshot in the snapshot repository.
Only when I define the complete snapshot-name (
0.1306.0-branchname-SNAPSHOT
) it seems to use the one snapshot version.
But the snapshot name will be different each time, the
version
will increase and the
branch name
will change.
v
Works fine here. Published
0.1298.0
Copy code
...:+ -> 0.1298.0
Then published
0.1306.0-branchname-SNAPSHOT
Copy code
...:+ -> 0.1306.0-branchname-SNAPSHOT
Can you show an MCVE?
h
Can I do that MCVE without a nexus? Don't want to mess around this client company nexus, or share their code.
v
Whatever reproduces your problem.
h
publish to Maven Local will do?
v
Whatever reproduces your problem.
🙂
I did try with maven local and it worked fine for me.
Btw. one sidenote, your question is off-topic here. 😉 The whole slack and thus also this channel is about using Kotlin. This channel is for using Kotlin in Gradle build scripts, not for general Gradle topics as you can see in the channel topic. 😉
a
v
As he also tried with
+
vs.
latest.integration
I assumed that should not be the problem, but yeah, try running with
--refresh-dependencies
to be sure. 🙂
h
I have added this in my root build.gradle.kts file:
Copy code
configurations {
    all {
        resolutionStrategy {
            cacheChangingModulesFor(1, TimeUnit.MINUTES)
            cacheDynamicVersionsFor(1, TimeUnit.MINUTES)
            eachDependency {
                if (group == "our-group" && listOf("artifact-1", "artifact-2").contains(name)) {
                    useVersion("latest.snapshot")
                }
            }
        }
    }
}
yes also tried with
--refresh-dependencies
no luck
I know it should be 0 seconds but I think 1 minute should also do as the other jar file is uploaded like 10 minutes before the other projects requires it.
v
I don't think
latest.snapshot
is a thing unless you have custom stability values defined.
latest.integration
or
+
h
Oh will try with latest integration then.
v
Which you said you did further up 😉
h
Yes I did refresh dependencies, tried witl latest.integration and with +. Now also resloution strategy with and without that (for the caching dynamic verison) still getting the
0.1298.0
.
v
Well, we are probably back at please provide an MCVE 🙂
h
I'll try to make a MCVE tomorrow.
a
you could try using dependencyInsight to investigate more https://docs.gradle.org/current/userguide/viewing_debugging_dependencies.html#dependency_insights if you add
--debug
in there it will give a lot more information, so search through it and see if there’s anything relevant
h
I've tried a MCVE but that just seems to work with
group:artifact:+
seem to give me always the latest version (or snapshot). I've tried with publishing to maven local. I figured out something. Looks like that somehow only the release repository is being looked for, and not the snapshot see
maven-metadata.xml
below: In nexus my release repository looks like this (i've omitted the long list of versions):
Copy code
<metadata>
	<groupId>my-group</groupId>
	<artifactId>my-artifact</artifactId>
	<versioning>
		<latest>0.1298.0</latest>
		<release>0.1298.0</release>
		<versions>
			<version>0.1280.0</version>
			<version>0.1281.0</version>
			<version>0.1282.0</version>
			<version>0.1283.0</version>
			<version>0.1284.0</version>
			<version>0.1289.0</version>
			<version>0.1290.0</version>
			<version>0.1294.0</version>
			<version>0.1295.0</version>
			<version>0.1296.0</version>
			<version>0.1298.0</version>
		</versions>
		<lastUpdated>20230516101139</lastUpdated>
	</versioning>
</metadata>
and the snapshot:
Copy code
<metadata>
	<groupId>my-group</groupId>
	<artifactId>my-artifact</artifactId>
	<versioning>
		<latest>0.1306.0-PR-13-SNAPSHOT</latest>
		<versions>
			<version>0.1306.0-bugfix-publish-SNAPSHOT</version>
			<version>0.1306.0-PR-13-SNAPSHOT</version>
		</versions>
		<lastUpdated>20230606051712</lastUpdated>
	</versioning>
</metadata>
How do I configure gradle to look for both? I've now this in my configuration, maybe does the order matter? Should I put the snapshot first?
Copy code
repositories {
    mavenLocal()
    maven("<https://my-nexus:8443/repository/public/>")
    maven(releasesRepoUrl)
    maven(snapshotsRepoUrl)
}
a
do you have any
init.gradle
(or
init.gradle.kts
) scripts that might be adding / restricting repository contents?
h
Nope, i've just removed all old buid.gradle (groovy) and added build.gradle.kts instead.
a
what’s the output of this?
Copy code
./gradlew -q dependencyInsight --dependency my-group:my-artifact --configuration compileClassspath
(you might have to play around with the configuration)
h
You had a typo but after i get this error:
Copy code
configuration 'compileClasspath' not found in configuration container.
a
yeah it’s a pain that Gradle requires you know the exact configuration name - try a different name until you find one that works
h
Oh sorry yest this only have testImplementation.. I need to do testCompileClasspath
hmm same error.
a
do you have multiple subprojects? Try
Copy code
./gradlew -q :my-subproject:dependencyInsight
h
Yes it's a multi module project..
this is the complete list.
Copy code
FAILURE: Build failed with an exception.

* What went wrong:
configuration 'testCompileClasspath' not found in configuration container.
  Variant apiElements:
    | Attribute Name                     | Provided | Requested    |
    |------------------------------------|----------|--------------|
    | org.gradle.status                  | release  |              |
    | org.gradle.category                | library  | library      |
    | org.gradle.dependency.bundling     | external | external     |
    | org.gradle.jvm.version             | 11       | 11           |
    | org.gradle.libraryelements         | jar      | classes      |
    | org.gradle.usage                   | java-api | java-api     |
    | org.gradle.jvm.environment         |          | standard-jvm |
    | org.jetbrains.kotlin.platform.type |          | jvm          |

my-group:my-artifact:latest.integration -> 0.1298.0
\--- testCompileClasspath

A web-based, searchable dependency report is available by adding the --scan option.
Maybe I should add the info about releases and snapshot to the repositories?
Copy code
repositories {
    maven {
        url = uri("<https://repo.mycompany.com/releases>")
        mavenContent {
            releasesOnly()
        }
    }
    maven {
        url = uri("<https://repo.mycompany.com/snapshots>")
        mavenContent {
            snapshotsOnly()
        }
    }
}
a
that certainly wouldn’t hurt! You could even do
includeGroup()
too
h
That didn't help. Thanks for helping anyways.
a
can you take a look in your company’s Nexus repo and see if the Gradle Module Metadata files are present too? Not just the POMs
h
We do have • file-sources.jar (md5/sha1/sha256/sha512) • file.jar (md5/sha1/sha256/sha512) • file.module (md5/sha1/sha256/sha512) • file.pom (md5/sha1/sha256/sha512) As well for the snapshot repository as for the release repository.
a
that looks normal… so I’m out of ideas!
h
Me too. Thanks anyways.
a
my last suggestion is to run the
dependencyInsight
with the
--debug
flag and try digging through the logs to see if there’s any hints
v
https://docs.gradle.org/current/userguide/dependency_management_for_java_projects.html
A project can have multiple repositories. Gradle will look for a dependency in each repository in the order they are specified, stopping at the first repository that contains the requested module.
If you specify the snapshot version explicitly, it will not be found in the first repository and thus taken from the second. But if you use a dynamic version, it finds a version in the first respository and does not look in the second. If you swap the order, you will always get the snapshot version, even if there is a newer release version.
To get what you want, define a group repository in your Nexus that delegates to the release and the snapshot repository, then use that group repository in your build. Then you get the behavior you intend.
h
I'll contact someone who knows more about Nexus, think it's more of a nexus issue than gradle.
v
We also have a Nexus, you (or rather someone with Nexus configuration access) need to do exactly what I said. :-)
125 Views