Skip to content

Commit 27ae6ac

Browse files
committed
Consolidate version numbering semantics (#27397)
Fixes to the build system, particularly around BWC testing, and to make future version bumps less painful.
1 parent d27828d commit 27ae6ac

File tree

12 files changed

+346
-166
lines changed

12 files changed

+346
-166
lines changed

build.gradle

Lines changed: 30 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@
1717
* under the License.
1818
*/
1919

20-
import java.nio.file.Path
21-
import java.util.regex.Matcher
22-
import org.eclipse.jgit.lib.Repository
23-
import org.eclipse.jgit.lib.RepositoryBuilder
24-
import org.gradle.plugins.ide.eclipse.model.SourceFolder
20+
2521
import org.apache.tools.ant.taskdefs.condition.Os
2622
import org.elasticsearch.gradle.BuildPlugin
27-
import org.elasticsearch.gradle.VersionProperties
2823
import org.elasticsearch.gradle.Version
24+
import org.elasticsearch.gradle.VersionCollection
25+
import org.elasticsearch.gradle.VersionProperties
26+
import org.gradle.plugins.ide.eclipse.model.SourceFolder
27+
28+
import java.nio.file.Path
2929

3030
// common maven publishing configuration
3131
subprojects {
@@ -67,61 +67,16 @@ configure(subprojects.findAll { it.projectDir.toPath().startsWith(rootPath) }) {
6767
}
6868
}
6969

70-
/* Introspect all versions of ES that may be tested agains for backwards
70+
/* Introspect all versions of ES that may be tested against for backwards
7171
* compatibility. It is *super* important that this logic is the same as the
72-
* logic in VersionUtils.java, modulo alphas, betas, and rcs which are ignored
73-
* in gradle because they don't have any backwards compatibility guarantees
74-
* but are not ignored in VersionUtils.java because the tests expect them not
75-
* to be. */
76-
Version currentVersion = Version.fromString(VersionProperties.elasticsearch.minus('-SNAPSHOT'))
77-
int prevMajor = currentVersion.major - 1
78-
File versionFile = file('core/src/main/java/org/elasticsearch/Version.java')
79-
List<String> versionLines = versionFile.readLines('UTF-8')
80-
List<Version> versions = []
81-
// keep track of the previous major version's last minor, so we know where wire compat begins
82-
int prevMinorIndex = -1 // index in the versions list of the last minor from the prev major
83-
int lastPrevMinor = -1 // the minor version number from the prev major we most recently seen
84-
int prevBugfixIndex = -1 // index in the versions list of the last bugfix release from the prev major
85-
for (String line : versionLines) {
86-
/* Note that this skips alphas and betas which is fine because they aren't
87-
* compatible with anything. */
88-
Matcher match = line =~ /\W+public static final Version V_(\d+)_(\d+)_(\d+) .*/
89-
if (match.matches()) {
90-
int major = Integer.parseInt(match.group(1))
91-
int minor = Integer.parseInt(match.group(2))
92-
int bugfix = Integer.parseInt(match.group(3))
93-
Version foundVersion = new Version(major, minor, bugfix, false)
94-
if (currentVersion != foundVersion) {
95-
versions.add(foundVersion)
96-
}
97-
if (major == prevMajor && minor > lastPrevMinor) {
98-
prevMinorIndex = versions.size() - 1
99-
lastPrevMinor = minor
100-
}
101-
if (major == prevMajor) {
102-
prevBugfixIndex = versions.size() - 1
103-
}
104-
}
105-
}
106-
if (versions.toSorted { it.id } != versions) {
107-
println "Versions: ${versions}"
108-
throw new GradleException("Versions.java contains out of order version constants")
109-
}
110-
if (prevBugfixIndex != -1) {
111-
versions[prevBugfixIndex] = new Version(
112-
versions[prevBugfixIndex].major, versions[prevBugfixIndex].minor, versions[prevBugfixIndex].bugfix, true)
113-
}
114-
if (currentVersion.bugfix == 0) {
115-
// If on a release branch, after the initial release of that branch, the bugfix version will
116-
// be bumped, and will be != 0. On master and N.x branches, we want to test against the
117-
// unreleased version of closest branch. So for those cases, the version includes -SNAPSHOT,
118-
// and the bwc distribution will checkout and build that version.
119-
Version last = versions[-1]
120-
versions[-1] = new Version(last.major, last.minor, last.bugfix, true)
121-
if (last.bugfix == 0) {
122-
versions[-2] = new Version(
123-
versions[-2].major, versions[-2].minor, versions[-2].bugfix, true)
124-
}
72+
* logic in VersionUtils.java, throwing out alphas because they don't have any
73+
* backwards compatibility guarantees and only keeping the latest beta or rc
74+
* in a branch if there are only betas and rcs in the branch so we have
75+
* *something* to test against. */
76+
VersionCollection versions = new VersionCollection(file('core/src/main/java/org/elasticsearch/Version.java').readLines('UTF-8'))
77+
if (versions.currentVersion.toString() != VersionProperties.elasticsearch) {
78+
throw new GradleException("The last version in Versions.java [${versions.currentVersion}] does not match " +
79+
"VersionProperties.elasticsearch [${VersionProperties.elasticsearch}]")
12580
}
12681

12782
// build metadata from previous build, contains eg hashes for bwc builds
@@ -140,9 +95,10 @@ allprojects {
14095
// for ide hacks...
14196
isEclipse = System.getProperty("eclipse.launcher") != null || gradle.startParameter.taskNames.contains('eclipse') || gradle.startParameter.taskNames.contains('cleanEclipse')
14297
isIdea = System.getProperty("idea.active") != null || gradle.startParameter.taskNames.contains('idea') || gradle.startParameter.taskNames.contains('cleanIdea')
143-
// for backcompat testing
144-
indexCompatVersions = versions
145-
wireCompatVersions = versions.subList(prevMinorIndex, versions.size())
98+
99+
// for BWC testing
100+
versionCollection = versions
101+
146102
buildMetadata = buildMetadataMap
147103
}
148104
}
@@ -160,13 +116,13 @@ task verifyVersions {
160116
Set<Version> knownVersions = new TreeSet<>(xml.versioning.versions.version.collect { it.text() }.findAll { it ==~ /\d\.\d\.\d/ }.collect { Version.fromString(it) })
161117

162118
// Limit the known versions to those that should be index compatible, and are not future versions
163-
knownVersions = knownVersions.findAll { it.major >= prevMajor && it.before(VersionProperties.elasticsearch) }
119+
knownVersions = knownVersions.findAll { it.major >= versions.currentVersion.major - 1 && it.before(VersionProperties.elasticsearch) }
164120

165121
/* Limit the listed versions to those that have been marked as released.
166122
* Versions not marked as released don't get the same testing and we want
167123
* to make sure that we flip all unreleased versions to released as soon
168124
* as possible after release. */
169-
Set<Version> actualVersions = new TreeSet<>(indexCompatVersions.findAll { false == it.snapshot })
125+
Set<Version> actualVersions = new TreeSet<>(versions.versionsIndexCompatibleWithCurrent.findAll { false == it.snapshot })
170126

171127
// Finally, compare!
172128
if (knownVersions.equals(actualVersions) == false) {
@@ -241,28 +197,17 @@ subprojects {
241197
"org.elasticsearch.plugin:aggs-matrix-stats-client:${version}": ':modules:aggs-matrix-stats',
242198
"org.elasticsearch.plugin:percolator-client:${version}": ':modules:percolator',
243199
]
244-
if (indexCompatVersions[-1].snapshot) {
245-
/* The last and second to last versions can be snapshots. Rather than use
246-
* snapshots built by CI we connect these versions to projects that build
247-
* those those versions from the HEAD of the appropriate branch. */
248-
if (indexCompatVersions[-1].bugfix == 0) {
249-
ext.projectSubstitutions["org.elasticsearch.distribution.deb:elasticsearch:${indexCompatVersions[-1]}"] = ':distribution:bwc-stable-snapshot'
250-
ext.projectSubstitutions["org.elasticsearch.distribution.rpm:elasticsearch:${indexCompatVersions[-1]}"] = ':distribution:bwc-stable-snapshot'
251-
ext.projectSubstitutions["org.elasticsearch.distribution.zip:elasticsearch:${indexCompatVersions[-1]}"] = ':distribution:bwc-stable-snapshot'
252-
ext.projectSubstitutions["org.elasticsearch.distribution.deb:elasticsearch:${indexCompatVersions[-2]}"] = ':distribution:bwc-release-snapshot'
253-
ext.projectSubstitutions["org.elasticsearch.distribution.rpm:elasticsearch:${indexCompatVersions[-2]}"] = ':distribution:bwc-release-snapshot'
254-
ext.projectSubstitutions["org.elasticsearch.distribution.zip:elasticsearch:${indexCompatVersions[-2]}"] = ':distribution:bwc-release-snapshot'
255-
} else {
256-
ext.projectSubstitutions["org.elasticsearch.distribution.deb:elasticsearch:${indexCompatVersions[-1]}"] = ':distribution:bwc-release-snapshot'
257-
ext.projectSubstitutions["org.elasticsearch.distribution.rpm:elasticsearch:${indexCompatVersions[-1]}"] = ':distribution:bwc-release-snapshot'
258-
ext.projectSubstitutions["org.elasticsearch.distribution.zip:elasticsearch:${indexCompatVersions[-1]}"] = ':distribution:bwc-release-snapshot'
200+
201+
for (final Version version : versionCollection.versionsIndexCompatibleWithCurrent) {
202+
if (version.branch != null) {
203+
final String snapshotProject = ":distribution:bwc-snapshot-${version.branch}"
204+
project(snapshotProject).ext.bwcVersion = version
205+
ext.projectSubstitutions["org.elasticsearch.distribution.deb:elasticsearch:${version}"] = snapshotProject
206+
ext.projectSubstitutions["org.elasticsearch.distribution.rpm:elasticsearch:${version}"] = snapshotProject
207+
ext.projectSubstitutions["org.elasticsearch.distribution.zip:elasticsearch:${version}"] = snapshotProject
259208
}
260-
} else if (indexCompatVersions[-2].snapshot) {
261-
/* This is a terrible hack for the bump to 6.0.1 which will be fixed by #27397 */
262-
ext.projectSubstitutions["org.elasticsearch.distribution.deb:elasticsearch:${indexCompatVersions[-2]}"] = ':distribution:bwc-release-snapshot'
263-
ext.projectSubstitutions["org.elasticsearch.distribution.rpm:elasticsearch:${indexCompatVersions[-2]}"] = ':distribution:bwc-release-snapshot'
264-
ext.projectSubstitutions["org.elasticsearch.distribution.zip:elasticsearch:${indexCompatVersions[-2]}"] = ':distribution:bwc-release-snapshot'
265209
}
210+
266211
project.afterEvaluate {
267212
configurations.all {
268213
resolutionStrategy.dependencySubstitution { DependencySubstitutions subs ->

buildSrc/src/main/groovy/org/elasticsearch/gradle/Version.groovy

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
package org.elasticsearch.gradle
2121

2222
import groovy.transform.Sortable
23+
import java.util.regex.Matcher
24+
import org.gradle.api.InvalidUserDataException
2325

2426
/**
2527
* Encapsulates comparison and printing logic for an x.y.z version.
@@ -29,35 +31,42 @@ public class Version {
2931

3032
final int major
3133
final int minor
32-
final int bugfix
34+
final int revision
3335
final int id
3436
final boolean snapshot
37+
final String branch
38+
/**
39+
* Suffix on the version name. Unlike Version.java the build does not
40+
* consider alphas and betas different versions, it just preserves the
41+
* suffix that the version was declared with in Version.java.
42+
*/
43+
final String suffix
3544

36-
public Version(int major, int minor, int bugfix, boolean snapshot) {
45+
public Version(int major, int minor, int revision,
46+
String suffix, boolean snapshot, String branch) {
3747
this.major = major
3848
this.minor = minor
39-
this.bugfix = bugfix
49+
this.revision = revision
4050
this.snapshot = snapshot
41-
this.id = major * 100000 + minor * 1000 + bugfix * 10 +
51+
this.suffix = suffix
52+
this.branch = branch
53+
this.id = major * 100000 + minor * 1000 + revision * 10 +
4254
(snapshot ? 1 : 0)
4355
}
4456

4557
public static Version fromString(String s) {
46-
String[] parts = s.split('\\.')
47-
String bugfix = parts[2]
48-
boolean snapshot = false
49-
if (bugfix.contains('-')) {
50-
snapshot = bugfix.endsWith('-SNAPSHOT')
51-
bugfix = bugfix.split('-')[0]
58+
Matcher m = s =~ /(\d+)\.(\d+)\.(\d+)(-alpha\d+|-beta\d+|-rc\d+)?(-SNAPSHOT)?/
59+
if (m.matches() == false) {
60+
throw new InvalidUserDataException("Invalid version [${s}]")
5261
}
53-
return new Version(parts[0] as int, parts[1] as int, bugfix as int,
54-
snapshot)
62+
return new Version(m.group(1) as int, m.group(2) as int,
63+
m.group(3) as int, m.group(4) ?: '', m.group(5) != null, null)
5564
}
5665

5766
@Override
5867
public String toString() {
5968
String snapshotStr = snapshot ? '-SNAPSHOT' : ''
60-
return "${major}.${minor}.${bugfix}${snapshotStr}"
69+
return "${major}.${minor}.${revision}${suffix}${snapshotStr}"
6170
}
6271

6372
public boolean before(String compareTo) {
@@ -75,4 +84,43 @@ public class Version {
7584
public boolean after(String compareTo) {
7685
return id > fromString(compareTo).id
7786
}
87+
88+
public boolean onOrBeforeIncludingSuffix(Version otherVersion) {
89+
if (id != otherVersion.id) {
90+
return id < otherVersion.id
91+
}
92+
93+
if (suffix == '') {
94+
return otherVersion.suffix == ''
95+
}
96+
97+
return otherVersion.suffix == '' || suffix < otherVersion.suffix
98+
}
99+
100+
boolean equals(o) {
101+
if (this.is(o)) return true
102+
if (getClass() != o.class) return false
103+
104+
Version version = (Version) o
105+
106+
if (id != version.id) return false
107+
if (major != version.major) return false
108+
if (minor != version.minor) return false
109+
if (revision != version.revision) return false
110+
if (snapshot != version.snapshot) return false
111+
if (suffix != version.suffix) return false
112+
113+
return true
114+
}
115+
116+
int hashCode() {
117+
int result
118+
result = major
119+
result = 31 * result + minor
120+
result = 31 * result + revision
121+
result = 31 * result + id
122+
result = 31 * result + (snapshot ? 1 : 0)
123+
result = 31 * result + (suffix != null ? suffix.hashCode() : 0)
124+
return result
125+
}
78126
}

0 commit comments

Comments
 (0)