Type: New Feature
Affects Version/s: 3.6.0
Fix Version/s: None
Version ranges result in non-repeatable builds because, and only because, Maven chooses the greatest version within the range.
If we instead choose the lower inclusive bound of the range, then the build will always be the same.
Resolving to lower inclusive bound means taking 1.2.0 here. Always. Even after 1.3.0 is released.
Taking the lower inclusive bound means there are no holes that can later be filled in, resulting in non-repeatable builds. eg. If we took the lowest existing version in the range, then there would be a possibility of someone later adding a lower version. Taking the lower inclusive bound requires the lower inclusive bound to exist from day 1.
Version ranges are actually for defining compatibility ranges. Conceptually, there are 2 version numbers: the version you compile against and the version range your code is compatible with. Even if you declare a version range, javac only ever compiles against 1 specific version.
For repeatable builds, you want the version number you compile against to be the same. However, you also want to be able to declare a range of dependency versions with which your library is compatible. As Maven is now, you can't have both. By resolving version ranges to the lower inclusive bound, we can.
This should be obvious, but to be clear: If I am writing a library liba which depends on library libb with range [1.2.0,2.0.0.min) and someone writes an app including my library liba, then the app should get version 1.2.0 of libb. The app is free to declare a direct dependency on version 1.3.0 or 1.8.5 etc of libb, any version that falls into the range [1.2.0,2.0.0.min). If the app declares a direct dependency on version 2.2.0 of libb, Maven should report a dependency resolution error like it currently does.
But not all version ranges have a lower inclusive bound? Well, maybe they should. I honestly cant figure out a valid use for an exclusive lower bound - maybe for the lack of my imagination. Either way, I don't imagine that it would be possible to convince Maven devs to change existing behavior, so this should probably be implemented in a new version range spec scheme. ie. New version range type with new syntax that always has lower inclusive bound and always resolves to lower inclusive bound.
Without this, I am forced to accept either non-reproducible builds or to give up strict dependency convergence assistance from Maven.