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
Use exact maven versions #8337
Comments
You talk about reproducability/deterministic but then talk about network access. The two are a bit different here. The The network access is because the square brackets and parentheses define compatible version ranges so Maven goes and looks up the available versions. With our specific usage though, the results are deterministic. The network access is quite unfortunate, but there's not many alternatives. |
Yeah, I did make a bit of a leap without connecting the dots in my explanation. When a non-bracketed dependency version used in pom.xml matches the dependency stored in the local maven repository, it doesn't hit the network looking for an update, it simply uses what exists in the local maven repository. When a bracketed version is used, such as So:
I'm not sure I got your example about choosing versions due to broken APIs. Sounds like what you are saying is that you do prefer to use a list of versions in case something is broken and you want to automatically fix things. That's kind of my point, developers should be forced into version upgrades unless they've chosen to. Feel free to close the ticket if it's not going to be fixed. |
As I said, the two aren't really equivalent. Does
We don't want to use actual ranges. We do want the version used to be reproducable. The only reason we allowed ourselves to use
It's more that we have internal classes that are reused across modules, but they have no API stability. We encourage keeping the versions of the various grpc components in sync (all the same version), but some things that we know are using those internal APIs we pin the versions to reduce chances a user gets bitten by version skew. |
Thanks for clarifying! If a single version is desired, then a bracket isn't necessary. Your builds will work exactly the same irrespective of API stability issues if you remove the brackets. When you set a non-bracketed version, it's still pinned to that version. For example, here is the pom.xml and no dependency except gRPC uses brackets. I'm not suggesting to fully remove the version, just the brackets.. If you remove the version completely, then yeah, that would be a problem and it would be 'unpinned'. If I missed your point about API stability, my apologies. Don't want to keep replying and seem like I'm pressing. |
Nope. They are treated differently by Maven. I made the change on purpose. 90db93b A bare version suggests a version, but upgrading and downgrading are allowed. It is essentially unrestricted. A To demonstrate, take a look at this pom: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.grpc</groupId>
<artifactId>examples</artifactId>
<packaging>jar</packaging>
<version>1.38.1</version>
<name>examples</name>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty</artifactId>
<version>1.39.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.38.1</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project> If you try to build, you'll get an error because of the version ranges. Without the version ranges this would have compiled (but may have behaved strange at runtime):
Or consider this pom (grpc-core instead of grpc-netty as before): <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.grpc</groupId>
<artifactId>examples</artifactId>
<packaging>jar</packaging>
<version>1.38.1</version>
<name>examples</name>
<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-core</artifactId>
<version>1.39.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.38.1</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project> The normal version resolution order would have chosen grpc-core 1.39.0, since that is the first in the breadth-first search. But maven is selecting 1.38.1 because it has to select a version in the "range":
All that said, I did that before BOMs were really a thing. The behavior is different with BOMs. |
Thanks for your patience, I followed your link into the past work you did 5 years ago and thankfully you were thorough in documenting your rationale. It was helpful to read it and understand your context. This link explained the exact situation. The solution you applied solves your issue, and I've never seen versions used that way. I'm more accustomed to seeing parent poms that leverage I can also understand that it's even more complicated since the gradle file is creating a pom file on the fly, so it's perhaps not as convenient to use To provide a contrast, the brackets help address an internal versioning of gRPC components, but as a consumer of gRPC I'm still going to struggle with versioning no matter what. For example, gRPC is using the guava library version 30.1, while a different library I'm using prefers 28.0.. The best practice I have employed on my side is that I still use the |
Earlier I tried searching for official documentation on the matter to share with you but failed. I just stumbled on it: https://maven.apache.org/pom.html#Dependency_Version_Requirement_Specification .
We are strongly against
Gradle doesn't need it at all, and specifying dependencyManagement in our pom files does nothing for our users from what I've seen. I've not looked into it deeply though. Gradle does have a function to do the equivalent of dependencyConvergence and we were using it until recently (#8238) due to lack of alternative to avoid Maven's broken dependency resolution.
Libraries must not use |
Thanks for finding and sharing that dependency version link. I understand more clearly your point about soft/hard dependencies and the dependency tree. I also appreciate You've convinced me that the brackets do serve a functional and required purpose. I'll work around the network issue using a workaround on my end. I still don't want it to output the network access during builds. |
I can imagine one day they may cause more pain than gain. For example, BOMs have reduced the likelihood of issues and Gradle users don't seemed to have suffered very often, given the rate of user reports. But yes, it is providing some value.
Do keep in touch if you continue to suffer and if Closing as it seems we've come to an understanding, but if something changes comment and we can reopen. |
What version of gRPC-Java are you using?
1.38.0
What is your environment?
Maven
What did you expect to see?
Developers and DevOps people that build CI/CD pipelines expect builds to be reproducible and deterministic. If we build a project today or next year (assuming the same exact commit id), we expect the same binary to be built. That is not the case with the grpc maven artifacts.
For example, snapshots are discouraged from being used in production builds because they can be overwritten with newer code or completely deleted; either changing application behavior or breaking the build.
What did you see instead?
When building the project using maven it will reach out across the network to check for a newer version of grpc to build with. This opens the project to builds that are not deterministic.
Steps to reproduce the bug
I have a maven project that uses
grpc-okhttp
, and I executemvn clean install
. Observe the output containsExpected Resolution
Please consider updating this line of code so that it stops wrapping the version with
[ ]
and use only specific version numbers:https://github.com/grpc/grpc-java/blob/master/build.gradle#L411
Instead of
[1.38.0]
(which causes the network activity), the unwrapped value1.38.0
is the expected output.The text was updated successfully, but these errors were encountered: