This is an automated email from the ASF dual-hosted git repository. dsmiley pushed a commit to branch branch_9x in repository https://gitbox.apache.org/repos/asf/solr.git
commit e90263546d4fcdba1362af09c117417fe0ea6323 Author: David Smiley <[email protected]> AuthorDate: Thu Oct 29 15:22:39 2026 -0400 SOLR-18432: SolrVersion tolerates prerelease qualifier (#5254) SolrVersion now tolerates a prerelease qualifier such as -SNAPSHOT. Package version constraints are matched ignoring the qualifier, the cluster version-compatibility warning no longer treats a prerelease as older than its release, and /api/node/system reports the correct Solr implementation version. Co-authored-by: Claude Sonnet 5.5 <[email protected]> Co-authored-by: Nick Shanin <[email protected]> (cherry picked from commit 852b427c1154ce9eec988b9adaeb212294442126) (cherry picked from commit 11ebc82c4a70c6393135348ed78feb9b2f8fc32c) Omits the SystemInfoProvider change and its test; that class (SOLR-16458) is not on branch_9x. --- .../SOLR-18432-solrversion-prerelease.yml | 7 +++ .../apache/solr/client/api/util/SolrVersion.java | 12 ++++- .../test/org/apache/solr/util/TestSolrVersion.java | 60 ++++++++++++++++++++++ .../java/org/apache/solr/cloud/ZkController.java | 2 +- 4 files changed, 78 insertions(+), 3 deletions(-) diff --git a/changelog/unreleased/SOLR-18432-solrversion-prerelease.yml b/changelog/unreleased/SOLR-18432-solrversion-prerelease.yml new file mode 100644 index 00000000000..ee6404c23cd --- /dev/null +++ b/changelog/unreleased/SOLR-18432-solrversion-prerelease.yml @@ -0,0 +1,7 @@ +title: SolrVersion now tolerates a prerelease qualifier such as -SNAPSHOT. Package version constraints are matched ignoring the qualifier, the cluster version-compatibility warning no longer treats a prerelease as older than its release, and /api/node/system reports the correct Solr implementation version. +type: fixed +authors: + - name: David Smiley +links: + - name: SOLR-18432 + url: https://issues.apache.org/jira/browse/SOLR-18432 diff --git a/solr/api/src/java/org/apache/solr/client/api/util/SolrVersion.java b/solr/api/src/java/org/apache/solr/client/api/util/SolrVersion.java index 44ae184d3ba..e58284d09b9 100644 --- a/solr/api/src/java/org/apache/solr/client/api/util/SolrVersion.java +++ b/solr/api/src/java/org/apache/solr/client/api/util/SolrVersion.java @@ -76,12 +76,20 @@ public final class SolrVersion implements Comparable<SolrVersion> { /** * Returns true if this version satisfies the provided <a href="https://devhints.io/semver">SemVer - * Expression</a> + * Expression</a>. Any prerelease qualifier (e.g. "-SNAPSHOT") is ignored, unlike plain SemVer + * range semantics where a prerelease satisfies no range that doesn't name one. * * @param semVerExpression the expression to test */ public boolean satisfies(String semVerExpression) { - return version.satisfies(semVerExpression); + return version.withClearedPreRelease().satisfies(semVerExpression); + } + + /** + * Returns this version with any prerelease qualifier removed, e.g. "10.1.0-SNAPSHOT" to "10.1.0" + */ + public SolrVersion withoutPrerelease() { + return new SolrVersion(version.withClearedPreRelease()); } public int getMajorVersion() { diff --git a/solr/api/src/test/org/apache/solr/util/TestSolrVersion.java b/solr/api/src/test/org/apache/solr/util/TestSolrVersion.java index ff55514e4ab..cb2394468fe 100644 --- a/solr/api/src/test/org/apache/solr/util/TestSolrVersion.java +++ b/solr/api/src/test/org/apache/solr/util/TestSolrVersion.java @@ -59,4 +59,64 @@ public class TestSolrVersion extends SolrTestCase { assertFalse(SOLR_9_0_1.satisfies("8.x")); assertTrue(SOLR_9_0_1.satisfies("8 - 9")); } + + public void testPrereleaseIgnoredBySatisfies() { + SolrVersion snapshot = SolrVersion.valueOf("10.1.0-SNAPSHOT"); + assertTrue(snapshot.satisfies(">=9.0.0")); + assertTrue(snapshot.satisfies("10.x")); + assertTrue(snapshot.satisfies("~10.1")); + assertFalse(snapshot.satisfies("<10.1")); + } + + public void testPrereleaseRangeBoundaries() { + SolrVersion release = SolrVersion.valueOf("10.1.0"); + for (String versionString : new String[] {"10.1.0-SNAPSHOT", "10.1.0-rc.1+b123"}) { + SolrVersion version = SolrVersion.valueOf(versionString); + assertTrue(versionString, version.satisfies(">=10.1.0")); + assertTrue(versionString, version.satisfies("<=10.1.0")); + assertTrue(versionString, version.satisfies("10.1.0")); + assertFalse(versionString, version.satisfies("<10.1.0")); + assertFalse(versionString, version.satisfies(">10.1.0")); + assertTrue(versionString, version.compareTo(release) < 0); + assertNotEquals(release, version); + } + } + + public void testWithoutPrerelease() { + SolrVersion snapshot = SolrVersion.valueOf("10.1.0-SNAPSHOT"); + assertTrue(snapshot.lessThan(SolrVersion.valueOf("10.1.0"))); + assertEquals(SolrVersion.valueOf("10.1.0"), snapshot.withoutPrerelease()); + } + + public void testWithoutPrereleasePreservesBuildMetadata() { + SolrVersion prerelease = SolrVersion.valueOf("10.1.0-rc.1+build.123"); + SolrVersion normalized = prerelease.withoutPrerelease(); + assertEquals("10.1.0+build.123", normalized.toString()); + assertEquals("10.1.0-rc.1+build.123", prerelease.toString()); + assertTrue(prerelease.lessThan(normalized)); + } + + public void testWithoutPrereleaseOnRelease() { + for (String versionString : new String[] {"10.1.2", "10.1.2+build.123"}) { + SolrVersion release = SolrVersion.valueOf(versionString); + SolrVersion normalized = release.withoutPrerelease(); + assertEquals(versionString, normalized.toString()); + assertEquals(versionString, normalized.withoutPrerelease().toString()); + } + } + + public void testWithoutPrereleaseOrdering() { + SolrVersion normalized = SolrVersion.valueOf("10.1.0-SNAPSHOT").withoutPrerelease(); + for (String versionString : new String[] {"10.1.0", "10.1.0-alpha.1", "10.1.0-rc.1+b123"}) { + SolrVersion sameRelease = SolrVersion.valueOf(versionString).withoutPrerelease(); + assertFalse(versionString, normalized.lessThan(sameRelease)); + assertFalse(versionString, sameRelease.lessThan(normalized)); + } + for (String versionString : + new String[] {"10.1.1-SNAPSHOT", "10.2.0-SNAPSHOT", "11.0.0-SNAPSHOT"}) { + SolrVersion higherRelease = SolrVersion.valueOf(versionString).withoutPrerelease(); + assertTrue(versionString, normalized.lessThan(higherRelease)); + assertFalse(versionString, higherRelease.lessThan(normalized)); + } + } } diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkController.java b/solr/core/src/java/org/apache/solr/cloud/ZkController.java index 05157a55f4c..22849c9bd8e 100644 --- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java +++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java @@ -618,7 +618,7 @@ public class ZkController implements Closeable { SolrVersion ourVersion = SolrVersion.LATEST; SolrVersion clusterVersion = lowestVersion.get(); - if (ourVersion.lessThan(clusterVersion)) { + if (ourVersion.withoutPrerelease().lessThan(clusterVersion.withoutPrerelease())) { log.warn( "Our Solr version {} is older than cluster version {}", ourVersion, clusterVersion);
