For me the major annoyance in the current resolution mechanism is that [1.1.0, 1.2.0) appears to include 1.2.0-SNAPSHOT, but exclude 1.1.0-SNAPSHOT, which looks completely counter-intuitive to me. In order to make sure that 1.2.0-SNAPSHOT is never resolved to, one needs to change all range specifications to an equivalent of [1.1.0, 1.1.999] in the above case. This does not solve the problem of not resolving to the initial snapshot in the range (1.1.0-SNAPSHOT in our case). When one starts development of a 1.1.x line, they are forced to change range specifications in dependencies to a fixed 1.1.0-SNAPSHOT version until the time 1.1.0 is released.
Another major annoyance is that whenever there is a snapshot in the local repo and that snapshot is resolved from a version range, the release build of a dependent project is doomed to fail. There is no way to force Maven release execution to disregard snapshots and resolve to released versions only. In fact this is almost a blocker, unless one uses a workaround as described below.
We have a very fluid project consisting of lots of applications and lots of internally developed libraries, and we have to use version ranges for internal dependencies, because otherwise keeping tens of projects in sync with their upstream dependencies becomes a living hell. However, because of this very MNG-3092, we had to make special arrangements in our CI environment in order to make our builds stable and predictable.
In our CI environment, we have two completely Maven settings.xml configurations:
a) configuration for snapshot builds, which resolves from both release and snapshot remote repositories and has its own separate local repository;
b) configuration for release builds, which does only resolve from remote release repositories, and has its own separate local repository.
We use configuration (a) for CI jobs that either run "snapshot vs. snapshot" builds, or nightly code analysis builds. We use configuration (b) for CI jobs that run "snapshot vs. release" builds and for releasing new versions of artifacts (effectively "release vs. release"). Only by separating local repositories and by making sure that snapshots never make their way into local release repository we can make sure that our release builds are stable.
Considering the current issue from a wider perspective, I am curious if there's generally a strong use case for fine-grained control on snapshot resolution (on a dependency declaration level), or whether the snapshot resolution strategy must apply to the entire build execution.
Personally I am leaning towards an execution-level control via e.g. a command line option. This way,
a) one could easily switch between "snapshot vs. snapshot" and "snapshot vs. release" configurations in the same build, without having to set up separate environments. This could especially be useful for IDE integration.
b) maven-release-plugin could automatically suppress resolution of version ranges to snapshots in forked maven executions.
c) no additional changes are required for POM model.
To summarise, here's what I believe the desired behaviour would be, with the option turned on or off respectively:
1. mvn --use-snapshots-in-ranges=false
This includes forked Maven executions from maven-release-plugin.
[1.1.0, 1.2.0] resolves to 1.1.0, 1.1.1, ..., 1.2.0
[1.1.0, 1.2.0) resolves to 1.1.0, 1.1.1, ..., 1.1.99999999999
(1.1.0, 1.2.0) resolves to 1.1.1, 1.1.2, ..., 1.1.99999999999
(1.1.0, 1.2.0] resolves to 1.1.1, 1.1.2, ..., 1.2.0
2. mvn --use-snapshots-in-ranges=true
[1.1.0, 1.2.0] resolves to 1.1.0-SNAPSHOT, 1.1.0, 1.1.1-SNAPSHOT, 1.1.1, ..., 1.2.0-SNAPSHOT, 1.2.0
[1.1.0, 1.2.0) resolves to 1.1.0-SNAPSHOT, 1.1.0, 1.1.1-SNAPSHOT, 1.1.1, ..., 1.1.99999999999-SNAPSHOT, 1.1.99999999999
(1.1.0, 1.2.0) resolves to 1.1.1-SNAPSHOT, 1.1.1, 1.1.2-SNAPSHOT, 1.1.2, ..., 1.1.99999999999-SNAPSHOT, 1.1.99999999999
(1.1.0, 1.2.0] resolves to 1.1.1-SNAPSHOT, 1.1.1, 1.1.2-SNAPSHOT, 1.1.2, ..., 1.2.0-SNAPSHOT, 1.2.0
How does that feel?