Skip to content

Ability to filter out pre-release dependency versions #11

Open
@grimsa

Description

@grimsa

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 version 3.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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions