Skip to content

Commit bafdcbd

Browse files
authored
Make improvements to the release notes generator (#83525)
Forward-port of the `build-tools-internal` parts of #83341.
1 parent 3ae08c8 commit bafdcbd

21 files changed

+412
-509
lines changed

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ValidateJsonAgainstSchemaTask.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
import java.util.stream.StreamSupport;
4343

4444
/**
45-
* Incremental task to validate a set of JSON files against against a schema.
45+
* Incremental task to validate a set of JSON files against a schema.
4646
*/
4747
public class ValidateJsonAgainstSchemaTask extends DefaultTask {
4848
private File jsonSchema;

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/ValidateYamlAgainstSchemaTask.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
1313

1414
/**
15-
* Incremental task to validate a set of YAML files against against a schema.
15+
* Incremental task to validate a set of YAML files against a schema.
1616
*/
1717
public class ValidateYamlAgainstSchemaTask extends ValidateJsonAgainstSchemaTask {
1818
@Override

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BreakingChangesGenerator.java

Lines changed: 27 additions & 103 deletions
Original file line numberDiff line numberDiff line change
@@ -11,148 +11,72 @@
1111
import com.google.common.annotations.VisibleForTesting;
1212

1313
import org.elasticsearch.gradle.VersionProperties;
14-
import org.gradle.api.GradleException;
1514

1615
import java.io.File;
1716
import java.io.FileWriter;
1817
import java.io.IOException;
1918
import java.nio.file.Files;
2019
import java.util.HashMap;
2120
import java.util.List;
22-
import java.util.Locale;
2321
import java.util.Map;
2422
import java.util.Objects;
25-
import java.util.Set;
2623
import java.util.TreeMap;
27-
import java.util.TreeSet;
28-
import java.util.stream.Collectors;
2924

3025
import static java.util.Comparator.comparing;
3126
import static java.util.stream.Collectors.groupingBy;
32-
import static java.util.stream.Collectors.toCollection;
27+
import static java.util.stream.Collectors.toList;
3328

3429
/**
35-
* Generates the page that contains an index into the breaking changes and lists deprecations for a minor version release,
36-
* and the individual pages for each breaking area.
30+
* Generates the page that contains breaking changes deprecations for a minor release series.
3731
*/
3832
public class BreakingChangesGenerator {
3933

40-
// Needs to match `changelog-schema.json`
41-
private static final List<String> BREAKING_AREAS = List.of(
42-
"Cluster and node setting",
43-
"Command line tool",
44-
"Index setting",
45-
"JVM option",
46-
"Java API",
47-
"Logging",
48-
"Mapping",
49-
"Packaging",
50-
"Painless",
51-
"REST API",
52-
"System requirement",
53-
"Transform"
54-
);
55-
56-
static void update(
57-
File indexTemplateFile,
58-
File indexOutputFile,
59-
File outputDirectory,
60-
File areaTemplateFile,
61-
List<ChangelogEntry> entries
62-
) throws IOException {
63-
if (outputDirectory.exists()) {
64-
if (outputDirectory.isDirectory() == false) {
65-
throw new GradleException("Path [" + outputDirectory + "] exists but isn't a directory!");
66-
}
67-
} else {
68-
Files.createDirectory(outputDirectory.toPath());
69-
}
70-
71-
try (FileWriter output = new FileWriter(indexOutputFile)) {
34+
static void update(File migrationTemplateFile, File migrationOutputFile, List<ChangelogEntry> entries) throws IOException {
35+
try (FileWriter output = new FileWriter(migrationOutputFile)) {
7236
output.write(
73-
generateIndexFile(
37+
generateMigrationFile(
7438
QualifiedVersion.of(VersionProperties.getElasticsearch()),
75-
Files.readString(indexTemplateFile.toPath()),
39+
Files.readString(migrationTemplateFile.toPath()),
7640
entries
7741
)
7842
);
7943
}
80-
81-
String areaTemplate = Files.readString(areaTemplateFile.toPath());
82-
83-
for (String breakingArea : BREAKING_AREAS) {
84-
final List<ChangelogEntry.Breaking> entriesForArea = entries.stream()
85-
.map(ChangelogEntry::getBreaking)
86-
.filter(entry -> entry != null && breakingArea.equals(entry.getArea()))
87-
.collect(Collectors.toList());
88-
89-
if (entriesForArea.isEmpty()) {
90-
continue;
91-
}
92-
93-
final String outputFilename = breakingArea.toLowerCase(Locale.ROOT).replaceFirst(" and", "").replaceAll(" ", "-")
94-
+ "-changes.asciidoc";
95-
96-
try (FileWriter output = new FileWriter(outputDirectory.toPath().resolve(outputFilename).toFile())) {
97-
output.write(
98-
generateBreakingAreaFile(
99-
QualifiedVersion.of(VersionProperties.getElasticsearch()),
100-
areaTemplate,
101-
breakingArea,
102-
entriesForArea
103-
)
104-
);
105-
}
106-
}
10744
}
10845

10946
@VisibleForTesting
110-
static String generateIndexFile(QualifiedVersion version, String template, List<ChangelogEntry> entries) throws IOException {
111-
final Map<String, List<ChangelogEntry.Deprecation>> deprecationsByArea = entries.stream()
47+
static String generateMigrationFile(QualifiedVersion version, String template, List<ChangelogEntry> entries) throws IOException {
48+
final Map<Boolean, Map<String, List<ChangelogEntry.Deprecation>>> deprecationsByNotabilityByArea = entries.stream()
11249
.map(ChangelogEntry::getDeprecation)
11350
.filter(Objects::nonNull)
11451
.sorted(comparing(ChangelogEntry.Deprecation::getTitle))
115-
.collect(groupingBy(ChangelogEntry.Deprecation::getArea, TreeMap::new, Collectors.toList()));
116-
117-
final List<String> breakingIncludeList = entries.stream()
118-
.filter(each -> each.getBreaking() != null)
119-
.map(each -> each.getBreaking().getArea().toLowerCase(Locale.ROOT).replaceFirst(" and", "").replaceAll(" ", "-"))
120-
.distinct()
121-
.sorted()
122-
.toList();
123-
124-
final Map<String, Object> bindings = new HashMap<>();
125-
bindings.put("breakingIncludeList", breakingIncludeList);
126-
bindings.put("deprecationsByArea", deprecationsByArea);
127-
bindings.put("isElasticsearchSnapshot", version.isSnapshot());
128-
bindings.put("majorDotMinor", version.major() + "." + version.minor());
129-
bindings.put("majorMinor", String.valueOf(version.major()) + version.minor());
130-
bindings.put("nextMajor", (version.major() + 1) + ".0");
131-
bindings.put("version", version);
132-
133-
return TemplateUtils.render(template, bindings);
134-
}
52+
.collect(
53+
groupingBy(
54+
ChangelogEntry.Deprecation::isNotable,
55+
TreeMap::new,
56+
groupingBy(ChangelogEntry.Deprecation::getArea, TreeMap::new, toList())
57+
)
58+
);
13559

136-
@VisibleForTesting
137-
static String generateBreakingAreaFile(
138-
QualifiedVersion version,
139-
String template,
140-
String breakingArea,
141-
List<ChangelogEntry.Breaking> entriesForArea
142-
) throws IOException {
143-
final Map<Boolean, Set<ChangelogEntry.Breaking>> breakingEntriesByNotability = entriesForArea.stream()
60+
final Map<Boolean, Map<String, List<ChangelogEntry.Breaking>>> breakingByNotabilityByArea = entries.stream()
61+
.map(ChangelogEntry::getBreaking)
62+
.filter(Objects::nonNull)
63+
.sorted(comparing(ChangelogEntry.Breaking::getTitle))
14464
.collect(
14565
groupingBy(
14666
ChangelogEntry.Breaking::isNotable,
147-
toCollection(() -> new TreeSet<>(comparing(ChangelogEntry.Breaking::getTitle)))
67+
TreeMap::new,
68+
groupingBy(ChangelogEntry.Breaking::getArea, TreeMap::new, toList())
14869
)
14970
);
15071

15172
final Map<String, Object> bindings = new HashMap<>();
152-
bindings.put("breakingArea", breakingArea);
153-
bindings.put("breakingEntriesByNotability", breakingEntriesByNotability);
154-
bindings.put("breakingAreaAnchor", breakingArea.toLowerCase(Locale.ROOT).replaceFirst(" and", "").replaceAll(" ", "_"));
73+
bindings.put("breakingByNotabilityByArea", breakingByNotabilityByArea);
74+
bindings.put("deprecationsByNotabilityByArea", deprecationsByNotabilityByArea);
75+
bindings.put("isElasticsearchSnapshot", version.isSnapshot());
76+
bindings.put("majorDotMinor", version.major() + "." + version.minor());
15577
bindings.put("majorMinor", String.valueOf(version.major()) + version.minor());
78+
bindings.put("nextMajor", (version.major() + 1) + ".0");
79+
bindings.put("version", version);
15680

15781
return TemplateUtils.render(template, bindings);
15882
}

build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ChangelogEntry.java

Lines changed: 21 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ public class ChangelogEntry {
4040

4141
private static final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
4242

43+
/**
44+
* Create a new instance by parsing the supplied file
45+
* @param file the YAML file to parse
46+
* @return a new instance
47+
*/
4348
public static ChangelogEntry parse(File file) {
4449
try {
4550
return yamlMapper.readValue(file, ChangelogEntry.class);
@@ -209,7 +214,11 @@ public String toString() {
209214
}
210215
}
211216

212-
public static class Breaking {
217+
public static class Breaking extends CompatibilityChange {}
218+
219+
public static class Deprecation extends CompatibilityChange {}
220+
221+
abstract static class CompatibilityChange {
213222
private String area;
214223
private String title;
215224
private String details;
@@ -277,13 +286,13 @@ public boolean equals(Object o) {
277286
if (o == null || getClass() != o.getClass()) {
278287
return false;
279288
}
280-
Breaking breaking = (Breaking) o;
281-
return notable == breaking.notable
282-
&& Objects.equals(area, breaking.area)
283-
&& Objects.equals(title, breaking.title)
284-
&& Objects.equals(details, breaking.details)
285-
&& Objects.equals(impact, breaking.impact)
286-
&& Objects.equals(essSettingChange, breaking.essSettingChange);
289+
CompatibilityChange breaking = (CompatibilityChange) o;
290+
return notable == breaking.isNotable()
291+
&& Objects.equals(area, breaking.getArea())
292+
&& Objects.equals(title, breaking.getTitle())
293+
&& Objects.equals(details, breaking.getDetails())
294+
&& Objects.equals(impact, breaking.getImpact())
295+
&& Objects.equals(essSettingChange, breaking.isEssSettingChange());
287296
}
288297

289298
@Override
@@ -294,7 +303,8 @@ public int hashCode() {
294303
@Override
295304
public String toString() {
296305
return String.format(
297-
"Breaking{area='%s', title='%s', details='%s', impact='%s', notable=%s, essSettingChange=%s}",
306+
"%s{area='%s', title='%s', details='%s', impact='%s', notable=%s, essSettingChange=%s}",
307+
this.getClass().getSimpleName(),
298308
area,
299309
title,
300310
details,
@@ -305,66 +315,11 @@ public String toString() {
305315
}
306316
}
307317

308-
public static class Deprecation {
309-
private String area;
310-
private String title;
311-
private String body;
312-
313-
public String getArea() {
314-
return area;
315-
}
316-
317-
public void setArea(String area) {
318-
this.area = area;
319-
}
320-
321-
public String getTitle() {
322-
return title;
323-
}
324-
325-
public void setTitle(String title) {
326-
this.title = title;
327-
}
328-
329-
public String getBody() {
330-
return body;
331-
}
332-
333-
public void setBody(String body) {
334-
this.body = body;
335-
}
336-
337-
public String getAnchor() {
338-
return generatedAnchor(this.title);
339-
}
340-
341-
@Override
342-
public boolean equals(Object o) {
343-
if (this == o) {
344-
return true;
345-
}
346-
if (o == null || getClass() != o.getClass()) {
347-
return false;
348-
}
349-
Deprecation that = (Deprecation) o;
350-
return Objects.equals(area, that.area) && Objects.equals(title, that.title) && Objects.equals(body, that.body);
351-
}
352-
353-
@Override
354-
public int hashCode() {
355-
return Objects.hash(area, title, body);
356-
}
357-
358-
@Override
359-
public String toString() {
360-
return String.format("Deprecation{area='%s', title='%s', body='%s'}", area, title, body);
361-
}
362-
}
363-
364318
private static String generatedAnchor(String input) {
365-
final List<String> excludes = List.of("the", "is", "a", "and");
319+
final List<String> excludes = List.of("the", "is", "a", "and", "now", "that");
366320

367321
final String[] words = input.toLowerCase(Locale.ROOT)
322+
.replaceAll("'", "")
368323
.replaceAll("[^\\w]+", "_")
369324
.replaceFirst("^_+", "")
370325
.replaceFirst("_+$", "")

0 commit comments

Comments
 (0)