Description
I recently learned about the libyear metric and this plugin, and ran an analysis on one of our projects.
Problem
One issue I noticed in the output was that some dependencies are reported as outdated, even when no stable version existed.
Example line from the report:
-> 1.7 years from jakarta.persistence:jakarta.persistence-api (3.1.0 => 3.2.0-M1)
However, currently the released versions look like this:
VERSION NUMBER | DATE PUBLISHED |
---|---|
3.2.0-M1 | 2023-11-23 |
3.2.0-B02 | 2023-11-06 |
3.2.0-B01 | 2023-08-28 |
3.1.0 | 2022-02-25 |
... | ... |
Given that using unstable/non-final dependency versions in production is considered to be bad practice, I think this plugin could either automatically exclude non-final versions, or at least allow the user to somehow configure which newer versions to consider.
Impact
For a project that had 79 outdated dependencies, 16 of them (i.e., ~20%) were compared against non-final versions:
-> 1.7 years from jakarta.persistence:jakarta.persistence-api (3.1.0 => 3.2.0-M1)
-> 1.5 years from jakarta.validation:jakarta.validation-api (3.0.2 => 3.1.0-M1)
-> 1.4 years from jakarta.annotation:jakarta.annotation-api (2.1.1 => 3.0.0-M1)
-> 1.2 years from net.sf.jopt-simple:jopt-simple (5.0.4 => 6.0-alpha-3)
-> 10 months from org.apache.logging.log4j:log4j-api (2.20.0 => 3.0.0-beta1)
-> 10 months from org.apache.logging.log4j:log4j-to-slf4j (2.20.0 => 3.0.0-beta1)
-> 6.2 months from org.jetbrains.kotlin:kotlin-stdlib-common (1.8.22 => 2.0.0-Beta2)
-> 6.2 months from org.jetbrains.kotlin:kotlin-reflect (1.8.22 => 2.0.0-Beta2)
-> 6.2 months from org.jetbrains.kotlin:kotlin-stdlib-jdk8 (1.8.22 => 2.0.0-Beta2)
-> 6.2 months from org.jetbrains.kotlin:kotlin-stdlib (1.8.22 => 2.0.0-Beta2)
-> 6.2 months from org.jetbrains.kotlin:kotlin-stdlib-jdk7 (1.8.22 => 2.0.0-Beta2)
-> 3.8 months from org.slf4j:jul-to-slf4j (2.0.9 => 2.1.0-alpha0)
-> 3.8 months from org.slf4j:slf4j-api (2.0.9 => 2.1.0-alpha0)
-> 28 days from org.apache.httpcomponents.client5:httpclient5 (5.2.3 => 5.4-alpha1)
-> 25.9 days from org.apache.httpcomponents.core5:httpcore5-h2 (5.2.4 => 5.3-alpha1)
-> 25.9 days from org.apache.httpcomponents.core5:httpcore5 (5.2.4 => 5.3-alpha1)
This results in either:
- Falsely reported dependencies - e.g., for
jakarta.persistence:jakarta.persistence-api
version3.1.0
that is used is actually the latest stable release - Incorrect libyear values - e.g. for
org.apache.httpcomponents.client5:httpclient5
libyear value of 28 days was reported (5.2.3 => 5.4-alpha1
), but if we compared against the latest stable version (5.2.3 => 5.3
), then libyear value would be just 5 days
Collectively this:
- Results in a higher libyear value than it actually is
- Makes the analysis results more difficult to interpret, as they require additional post-processing by a person
Potential solutions
General solution
Looking at semver, it seems that any pre-release version would contain a hyphen:
A pre-release version MAY be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. . . . Examples: 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92, 1.0.0-x-y-z.--.
And looking at the anecdotal evidence from this one project, it seems that:
- all pre-release versions did indeed contain a hyphen
- the only dependency, the version of which contained a hyphen, and which was a stable release was Guava (
com.google.guava:guava (32.1.3-jre => 33.0.0-jre)
)
Therefore, maybe the general rule could be "if current dependency version contains a hyphen, then consider all available dependency versions, while if it does not - only look at versions without hyphens)
User-configurable solution
Maybe there could be a configuration parameter that allows the user to specify what versions to include or exclude:
libyear {
configurations = ['compileClasspath']
ignoreNewerArtifactsWithVersionsMatching = "<regex that matches specific suffixes>"
^-- new parameter
failOnError = true
validator = allArtifactsCombinedMustNotBeOlderThan(days(5))
}
Example of such regex could be -(?!jre)
that would ignore anything with a hyphen, except if it was -jre