Skip to content

Commit a290692

Browse files
authored
Add initial transport version generation task (#134333) (#134408)
This commit adds a new generateInitialTransportVersion task to gradle. This task will be called by release automation to ensure each new release version of Elasticsearch has a unique transport version id.
1 parent 96736d4 commit a290692

File tree

7 files changed

+209
-8
lines changed

7 files changed

+209
-8
lines changed

build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/transport/AbstractTransportVersionFuncTest.groovy

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,29 @@ class AbstractTransportVersionFuncTest extends AbstractGradleFuncTest {
9393
assert file("myserver/src/main/resources/transport/definitions/referable/${name}.csv").exists() == false
9494
}
9595

96+
void assertUnreferableDefinition(String name, String content) {
97+
File definitionFile = file("myserver/src/main/resources/transport/definitions/unreferable/${name}.csv")
98+
assert definitionFile.exists()
99+
assert definitionFile.text.strip() == content
100+
}
101+
96102
void assertUpperBound(String name, String content) {
97103
assert file("myserver/src/main/resources/transport/upper_bounds/${name}.csv").text.strip() == content
98104
}
99105

106+
void assertNoChanges() {
107+
String output = execute("git diff")
108+
assert output.strip().isEmpty() : "Expected no local git changes, but found:${System.lineSeparator()}${output}"
109+
}
110+
100111
def setup() {
101112
configurationCacheCompatible = false
102113
internalBuild()
103114
settingsFile << """
104115
include ':myserver'
105116
include ':myplugin'
106117
"""
118+
versionPropertiesFile.text = versionPropertiesFile.text.replace("9.1.0", "9.2.0")
107119

108120
file("myserver/build.gradle") << """
109121
apply plugin: 'java-library'
@@ -116,10 +128,12 @@ class AbstractTransportVersionFuncTest extends AbstractGradleFuncTest {
116128
"""
117129
referableTransportVersion("existing_91", "8012000")
118130
referableTransportVersion("existing_92", "8123000,8012001")
119-
unreferableTransportVersion("initial_9_0_0", "8000000")
131+
unreferableTransportVersion("initial_9.0.0", "8000000")
132+
unreferableTransportVersion("initial_8.19.7", "7123001")
120133
transportVersionUpperBound("9.2", "existing_92", "8123000")
121134
transportVersionUpperBound("9.1", "existing_92", "8012001")
122-
transportVersionUpperBound("9.0", "initial_9_0_0", "8000000")
135+
transportVersionUpperBound("9.0", "initial_9.0.0", "8000000")
136+
transportVersionUpperBound("8.19", "initial_8.19.7", "7123001")
123137
// a mock version of TransportVersion, just here so we can compile Dummy.java et al
124138
javaSource("myserver", "org.elasticsearch", "TransportVersion", "", """
125139
public static TransportVersion fromName(String name) {
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.gradle.internal.transport
11+
12+
import org.gradle.testkit.runner.BuildResult
13+
import org.gradle.testkit.runner.TaskOutcome
14+
15+
class GenerateInitialTransportVersionFuncTest extends AbstractTransportVersionFuncTest {
16+
def runGenerateAndValidateTask(String... additionalArgs) {
17+
List<String> args = new ArrayList<>()
18+
args.add(":myserver:validateTransportVersionResources")
19+
args.add(":myserver:generateInitialTransportVersion")
20+
args.addAll(additionalArgs);
21+
return gradleRunner(args.toArray())
22+
}
23+
24+
def runGenerateTask(String... additionalArgs) {
25+
List<String> args = new ArrayList<>()
26+
args.add(":myserver:generateInitialTransportVersion")
27+
args.addAll(additionalArgs);
28+
return gradleRunner(args.toArray())
29+
}
30+
31+
void assertGenerateSuccess(BuildResult result) {
32+
assert result.task(":myserver:generateInitialTransportVersion").outcome == TaskOutcome.SUCCESS
33+
}
34+
35+
void assertGenerateFailure(BuildResult result, String expectedOutput) {
36+
assert result.task(":myserver:generateInitialTransportVersion").outcome == TaskOutcome.FAILED
37+
assertOutputContains(result.output, expectedOutput)
38+
}
39+
40+
void assertValidateSuccess(BuildResult result) {
41+
assert result.task(":myserver:validateTransportVersionResources").outcome == TaskOutcome.SUCCESS
42+
}
43+
44+
void assertGenerateAndValidateSuccess(BuildResult result) {
45+
assertGenerateSuccess(result)
46+
assertValidateSuccess(result)
47+
}
48+
49+
def "setup is valid"() {
50+
when:
51+
def result = runGenerateAndValidateTask("--release-version", "9.0.0").build()
52+
53+
then:
54+
assertGenerateAndValidateSuccess(result)
55+
// should have been idempotent, nothing actually changed
56+
assertNoChanges();
57+
}
58+
59+
def "new minor also creates next upper bound"() {
60+
given:
61+
// version properties will be updated by release automation before running initial version generation
62+
versionPropertiesFile.text = versionPropertiesFile.text.replace("9.2.0", "9.3.0")
63+
64+
when:
65+
System.out.println("Running generation initial task")
66+
def result = runGenerateAndValidateTask("--release-version", "9.2.0").build()
67+
System.out.println("Done running generation task")
68+
69+
then:
70+
assertGenerateAndValidateSuccess(result)
71+
assertUnreferableDefinition("initial_9.2.0", "8124000")
72+
assertUpperBound("9.2", "initial_9.2.0,8124000")
73+
assertUpperBound("9.3", "initial_9.2.0,8124000")
74+
}
75+
76+
def "patch updates existing upper bound"() {
77+
when:
78+
def result = runGenerateAndValidateTask("--release-version", "9.1.2").build()
79+
80+
then:
81+
assertGenerateAndValidateSuccess(result)
82+
assertUnreferableDefinition("initial_9.1.2", "8012002")
83+
assertUpperBound("9.1", "initial_9.1.2,8012002")
84+
}
85+
86+
def "cannot create upper bound file for patch"() {
87+
when:
88+
def result = runGenerateTask("--release-version", "9.3.7").buildAndFail()
89+
90+
then:
91+
assertGenerateFailure(result, "Missing upper bound 9.3 for release version 9.3.7")
92+
}
93+
}

build-tools-internal/src/integTest/groovy/org/elasticsearch/gradle/internal/transport/TransportVersionGenerationFuncTest.groovy

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -412,7 +412,7 @@ class TransportVersionGenerationFuncTest extends AbstractTransportVersionFuncTes
412412
def result = runGenerateTask("--backport-branches=9.1,8.13,7.17,6.0").buildAndFail()
413413

414414
then:
415-
assertGenerateFailure(result, "Missing upper bounds files for branches [6.0, 7.17, 8.13], known branches are [9.0, 9.1, 9.2]")
415+
assertGenerateFailure(result, "Missing upper bounds files for branches [6.0, 7.17, 8.13], known branches are [8.19, 9.0, 9.1, 9.2]")
416416
}
417417

418418
def "name can be found from committed definition"() {
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.gradle.internal.transport;
11+
12+
import org.elasticsearch.gradle.Version;
13+
import org.gradle.api.DefaultTask;
14+
import org.gradle.api.provider.Property;
15+
import org.gradle.api.services.ServiceReference;
16+
import org.gradle.api.tasks.Input;
17+
import org.gradle.api.tasks.TaskAction;
18+
import org.gradle.api.tasks.options.Option;
19+
20+
import java.io.IOException;
21+
import java.util.List;
22+
23+
public abstract class GenerateInitialTransportVersionTask extends DefaultTask {
24+
25+
@ServiceReference("transportVersionResources")
26+
abstract Property<TransportVersionResourcesService> getResourceService();
27+
28+
@Input
29+
@Option(option = "release-version", description = "The Elasticsearch release version this transport version will be associated with")
30+
public abstract Property<String> getReleaseVersion();
31+
32+
@Input
33+
abstract Property<Version> getCurrentVersion();
34+
35+
@TaskAction
36+
public void run() throws IOException {
37+
Version releaseVersion = Version.fromString(getReleaseVersion().get());
38+
String upperBoundName = getUpperBoundName(releaseVersion);
39+
TransportVersionResourcesService resources = getResourceService().get();
40+
TransportVersionUpperBound upstreamUpperBound = resources.getUpperBoundFromUpstream(upperBoundName);
41+
String initialDefinitionName = "initial_" + releaseVersion;
42+
TransportVersionDefinition existingDefinition = resources.getUnreferableDefinitionFromUpstream(initialDefinitionName);
43+
44+
if (existingDefinition != null) {
45+
// this initial version has already been created upstream
46+
return;
47+
}
48+
49+
if (upstreamUpperBound == null) {
50+
throw new RuntimeException("Missing upper bound " + upperBoundName + " for release version " + releaseVersion);
51+
}
52+
// minors increment by 1000 to create a unique base, patches increment by 1 as other patches do
53+
int increment = releaseVersion.getRevision() == 0 ? 1000 : 1;
54+
var id = TransportVersionId.fromInt(upstreamUpperBound.definitionId().complete() + increment);
55+
var definition = new TransportVersionDefinition(initialDefinitionName, List.of(id));
56+
resources.writeUnreferableDefinition(definition);
57+
var newUpperBound = new TransportVersionUpperBound(upperBoundName, initialDefinitionName, id);
58+
resources.writeUpperBound(newUpperBound);
59+
60+
if (releaseVersion.getRevision() == 0) {
61+
Version currentVersion = getCurrentVersion().get();
62+
String currentUpperBoundName = getUpperBoundName(currentVersion);
63+
var currentUpperBound = new TransportVersionUpperBound(currentUpperBoundName, initialDefinitionName, id);
64+
resources.writeUpperBound(currentUpperBound);
65+
}
66+
}
67+
68+
private String getUpperBoundName(Version version) {
69+
return version.getMajor() + "." + version.getMinor();
70+
}
71+
}

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/transport/TransportVersionResourcesPlugin.java

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
package org.elasticsearch.gradle.internal.transport;
1111

1212
import org.elasticsearch.gradle.Version;
13-
import org.elasticsearch.gradle.VersionProperties;
1413
import org.elasticsearch.gradle.internal.ProjectSubscribeServicePlugin;
14+
import org.elasticsearch.gradle.internal.conventions.VersionPropertiesPlugin;
1515
import org.gradle.api.Plugin;
1616
import org.gradle.api.Project;
1717
import org.gradle.api.file.Directory;
@@ -20,6 +20,7 @@
2020
import org.gradle.language.base.plugins.LifecycleBasePlugin;
2121

2222
import java.util.Map;
23+
import java.util.Properties;
2324

2425
public class TransportVersionResourcesPlugin implements Plugin<Project> {
2526

@@ -28,7 +29,12 @@ public class TransportVersionResourcesPlugin implements Plugin<Project> {
2829
@Override
2930
public void apply(Project project) {
3031
project.getPluginManager().apply(LifecycleBasePlugin.class);
32+
project.getPluginManager().apply(VersionPropertiesPlugin.class);
3133
var psService = project.getPlugins().apply(ProjectSubscribeServicePlugin.class).getService();
34+
35+
Properties versions = (Properties) project.getExtensions().getByName(VersionPropertiesPlugin.VERSIONS_EXT);
36+
Version currentVersion = Version.fromString(versions.getProperty("elasticsearch"));
37+
3238
var resourceRoot = getResourceRoot(project);
3339

3440
String taskGroup = "Transport Versions";
@@ -79,11 +85,17 @@ public void apply(Project project) {
7985
t.setDescription("(Re)generates a transport version definition file");
8086
t.getReferencesFiles().setFrom(tvReferencesConfig);
8187
t.getIncrement().convention(1000);
82-
Version esVersion = VersionProperties.getElasticsearchVersion();
83-
t.getCurrentUpperBoundName().convention(esVersion.getMajor() + "." + esVersion.getMinor());
88+
t.getCurrentUpperBoundName().convention(currentVersion.getMajor() + "." + currentVersion.getMinor());
8489
});
85-
8690
validateTask.configure(t -> t.mustRunAfter(generateDefinitionsTask));
91+
92+
var generateInitialTask = project.getTasks()
93+
.register("generateInitialTransportVersion", GenerateInitialTransportVersionTask.class, t -> {
94+
t.setGroup(taskGroup);
95+
t.setDescription("(Re)generates an initial transport version for an Elasticsearch release version");
96+
t.getCurrentVersion().set(currentVersion);
97+
});
98+
validateTask.configure(t -> t.mustRunAfter(generateInitialTask));
8799
}
88100

89101
private static String getResourceRoot(Project project) {

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/transport/TransportVersionResourcesService.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,16 @@ Path getUnreferableDefinitionRepositoryPath(TransportVersionDefinition definitio
174174
return rootDir.relativize(transportResourcesDir.resolve(getUnreferableDefinitionRelativePath(definition.name())));
175175
}
176176

177+
void writeUnreferableDefinition(TransportVersionDefinition definition) throws IOException {
178+
Path path = transportResourcesDir.resolve(getUnreferableDefinitionRelativePath(definition.name()));
179+
logger.debug("Writing unreferable definition [" + definition + "] to [" + path + "]");
180+
Files.writeString(
181+
path,
182+
definition.ids().stream().map(Object::toString).collect(Collectors.joining(",")) + "\n",
183+
StandardCharsets.UTF_8
184+
);
185+
}
186+
177187
/** Read all upper bound files and return them mapped by their release name */
178188
Map<String, TransportVersionUpperBound> getUpperBounds() throws IOException {
179189
Map<String, TransportVersionUpperBound> upperBounds = new HashMap<>();

build-tools/src/testFixtures/groovy/org/elasticsearch/gradle/fixtures/AbstractGradleFuncTest.groovy

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ abstract class AbstractGradleFuncTest extends Specification {
211211
"""
212212
}
213213

214-
void execute(String command, File workingDir = testProjectDir.root) {
214+
String execute(String command, File workingDir = testProjectDir.root) {
215215
def proc = command.execute(Collections.emptyList(), workingDir)
216216
proc.waitFor()
217217
if (proc.exitValue()) {
@@ -221,6 +221,7 @@ abstract class AbstractGradleFuncTest extends Specification {
221221
"""
222222
throw new RuntimeException(msg)
223223
}
224+
return proc.inputStream.text
224225
}
225226

226227
File dir(String path) {

0 commit comments

Comments
 (0)