diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BreakingChangesGenerator.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BreakingChangesGenerator.java index fc33c288cf944..286f23d83e5bb 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BreakingChangesGenerator.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/BreakingChangesGenerator.java @@ -11,6 +11,7 @@ import com.google.common.annotations.VisibleForTesting; import org.elasticsearch.gradle.VersionProperties; +import org.gradle.api.GradleException; import java.io.File; import java.io.FileWriter; @@ -18,49 +19,110 @@ import java.nio.file.Files; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Objects; +import java.util.Set; import java.util.TreeMap; +import java.util.TreeSet; import java.util.stream.Collectors; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.toCollection; /** - * Generates the page that lists the breaking changes and deprecations for a minor version release. + * Generates the page that contains an index into the breaking changes and lists deprecations for a minor version release, + * and the individual pages for each breaking area. */ public class BreakingChangesGenerator { - static void update(File templateFile, File outputFile, List entries) throws IOException { - try (FileWriter output = new FileWriter(outputFile)) { + // Needs to match `changelog-schema.json` + private static final List BREAKING_AREAS = List.of( + "Cluster and node setting", + "Command line tool", + "Index setting", + "JVM option", + "Java API", + "Logging", + "Mapping", + "Packaging", + "Painless", + "REST API", + "System requirement", + "Transform" + ); + + static void update( + File indexTemplateFile, + File indexOutputFile, + File outputDirectory, + File areaTemplateFile, + List entries + ) throws IOException { + if (outputDirectory.exists()) { + if (outputDirectory.isDirectory() == false) { + throw new GradleException("Path [" + outputDirectory + "] exists but isn't a directory!"); + } + } else { + Files.createDirectory(outputDirectory.toPath()); + } + + try (FileWriter output = new FileWriter(indexOutputFile)) { output.write( - generateFile(QualifiedVersion.of(VersionProperties.getElasticsearch()), Files.readString(templateFile.toPath()), entries) + generateIndexFile( + QualifiedVersion.of(VersionProperties.getElasticsearch()), + Files.readString(indexTemplateFile.toPath()), + entries + ) ); } - } - @VisibleForTesting - static String generateFile(QualifiedVersion version, String template, List entries) throws IOException { + String areaTemplate = Files.readString(areaTemplateFile.toPath()); - final Map>> breakingChangesByNotabilityByArea = entries.stream() - .map(ChangelogEntry::getBreaking) - .filter(Objects::nonNull) - .sorted(comparing(ChangelogEntry.Breaking::getTitle)) - .collect( - groupingBy( - ChangelogEntry.Breaking::isNotable, - groupingBy(ChangelogEntry.Breaking::getArea, TreeMap::new, Collectors.toList()) - ) - ); + for (String breakingArea : BREAKING_AREAS) { + final List entriesForArea = entries.stream() + .map(ChangelogEntry::getBreaking) + .filter(entry -> entry != null && breakingArea.equals(entry.getArea())) + .collect(Collectors.toList()); + + if (entriesForArea.isEmpty()) { + continue; + } + + final String outputFilename = breakingArea.toLowerCase(Locale.ROOT).replaceFirst(" and", "").replaceAll(" ", "-") + + "-changes.asciidoc"; + + try (FileWriter output = new FileWriter(outputDirectory.toPath().resolve(outputFilename).toFile())) { + output.write( + generateBreakingAreaFile( + QualifiedVersion.of(VersionProperties.getElasticsearch()), + areaTemplate, + breakingArea, + entriesForArea + ) + ); + } + } + } + @VisibleForTesting + static String generateIndexFile(QualifiedVersion version, String template, List entries) throws IOException { final Map> deprecationsByArea = entries.stream() .map(ChangelogEntry::getDeprecation) .filter(Objects::nonNull) .sorted(comparing(ChangelogEntry.Deprecation::getTitle)) .collect(groupingBy(ChangelogEntry.Deprecation::getArea, TreeMap::new, Collectors.toList())); + final List breakingIncludeList = entries.stream() + .filter(each -> each.getBreaking() != null) + .map(each -> each.getBreaking().getArea().toLowerCase(Locale.ROOT).replaceFirst(" and", "").replaceAll(" ", "-")) + .distinct() + .sorted() + .toList(); + final Map bindings = new HashMap<>(); - bindings.put("breakingChangesByNotabilityByArea", breakingChangesByNotabilityByArea); + bindings.put("breakingIncludeList", breakingIncludeList); bindings.put("deprecationsByArea", deprecationsByArea); bindings.put("isElasticsearchSnapshot", version.isSnapshot()); bindings.put("majorDotMinor", version.getMajor() + "." + version.getMinor()); @@ -70,4 +132,28 @@ static String generateFile(QualifiedVersion version, String template, List entriesForArea + ) throws IOException { + final Map> breakingEntriesByNotability = entriesForArea.stream() + .collect( + groupingBy( + ChangelogEntry.Breaking::isNotable, + toCollection(() -> new TreeSet<>(comparing(ChangelogEntry.Breaking::getTitle))) + ) + ); + + final Map bindings = new HashMap<>(); + bindings.put("breakingArea", breakingArea); + bindings.put("breakingEntriesByNotability", breakingEntriesByNotability); + bindings.put("breakingAreaAnchor", breakingArea.toLowerCase(Locale.ROOT).replaceFirst(" and", "").replaceAll(" ", "_")); + bindings.put("majorMinor", String.valueOf(version.getMajor()) + version.getMinor()); + + return TemplateUtils.render(template, bindings); + } } diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ChangelogEntry.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ChangelogEntry.java index 19b9ed2f274a4..94c77768b14b0 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ChangelogEntry.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ChangelogEntry.java @@ -215,6 +215,7 @@ public static class Breaking { private String details; private String impact; private boolean notable; + private boolean essSettingChange; public String getArea() { return area; @@ -260,6 +261,14 @@ public String getAnchor() { return generatedAnchor(this.title); } + public boolean isEssSettingChange() { + return essSettingChange; + } + + public void setEssSettingChange(boolean essSettingChange) { + this.essSettingChange = essSettingChange; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -273,23 +282,25 @@ public boolean equals(Object o) { && Objects.equals(area, breaking.area) && Objects.equals(title, breaking.title) && Objects.equals(details, breaking.details) - && Objects.equals(impact, breaking.impact); + && Objects.equals(impact, breaking.impact) + && Objects.equals(essSettingChange, breaking.essSettingChange); } @Override public int hashCode() { - return Objects.hash(area, title, details, impact, notable); + return Objects.hash(area, title, details, impact, notable, essSettingChange); } @Override public String toString() { return String.format( - "Breaking{area='%s', title='%s', details='%s', impact='%s', isNotable=%s}", + "Breaking{area='%s', title='%s', details='%s', impact='%s', notable=%s, essSettingChange=%s}", area, title, details, impact, - notable + notable, + essSettingChange ); } } @@ -351,7 +362,7 @@ public String toString() { } private static String generatedAnchor(String input) { - final List excludes = List.of("the", "is", "a"); + final List excludes = List.of("the", "is", "a", "and"); final String[] words = input.toLowerCase(Locale.ROOT) .replaceAll("[^\\w]+", "_") diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTask.java index 70fafc303bcd3..7f09dbb87d3f0 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTask.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTask.java @@ -14,6 +14,8 @@ import org.gradle.api.DefaultTask; import org.gradle.api.GradleException; import org.gradle.api.file.ConfigurableFileCollection; +import org.gradle.api.file.Directory; +import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.FileCollection; import org.gradle.api.file.RegularFile; import org.gradle.api.file.RegularFileProperty; @@ -22,6 +24,7 @@ import org.gradle.api.model.ObjectFactory; import org.gradle.api.tasks.InputFile; import org.gradle.api.tasks.InputFiles; +import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.TaskAction; import org.gradle.process.ExecOperations; @@ -55,11 +58,13 @@ public class GenerateReleaseNotesTask extends DefaultTask { private final RegularFileProperty releaseNotesTemplate; private final RegularFileProperty releaseHighlightsTemplate; private final RegularFileProperty breakingChangesTemplate; + private final RegularFileProperty breakingChangesAreaTemplate; private final RegularFileProperty releaseNotesIndexFile; private final RegularFileProperty releaseNotesFile; private final RegularFileProperty releaseHighlightsFile; - private final RegularFileProperty breakingChangesFile; + private final RegularFileProperty breakingChangesIndexFile; + private final DirectoryProperty breakingChangesDirectory; private final GitWrapper gitWrapper; @@ -71,11 +76,13 @@ public GenerateReleaseNotesTask(ObjectFactory objectFactory, ExecOperations exec releaseNotesTemplate = objectFactory.fileProperty(); releaseHighlightsTemplate = objectFactory.fileProperty(); breakingChangesTemplate = objectFactory.fileProperty(); + breakingChangesAreaTemplate = objectFactory.fileProperty(); releaseNotesIndexFile = objectFactory.fileProperty(); releaseNotesFile = objectFactory.fileProperty(); releaseHighlightsFile = objectFactory.fileProperty(); - breakingChangesFile = objectFactory.fileProperty(); + breakingChangesIndexFile = objectFactory.fileProperty(); + breakingChangesDirectory = objectFactory.directoryProperty(); gitWrapper = new GitWrapper(execOperations); } @@ -129,7 +136,9 @@ public void executeTask() throws IOException { LOGGER.info("Generating breaking changes / deprecations notes..."); BreakingChangesGenerator.update( this.breakingChangesTemplate.get().getAsFile(), - this.breakingChangesFile.get().getAsFile(), + this.breakingChangesIndexFile.get().getAsFile(), + this.breakingChangesDirectory.get().getAsFile(), + this.breakingChangesAreaTemplate.get().getAsFile(), entries ); } @@ -339,11 +348,29 @@ public void setReleaseHighlightsFile(RegularFile file) { } @OutputFile - public RegularFileProperty getBreakingChangesFile() { - return breakingChangesFile; + public RegularFileProperty getBreakingChangesIndexFile() { + return breakingChangesIndexFile; } - public void setBreakingChangesFile(RegularFile file) { - this.breakingChangesFile.set(file); + public void setBreakingChangesIndexFile(RegularFile file) { + this.breakingChangesIndexFile.set(file); + } + + public void setBreakingChangesDirectory(Directory breakingChangesDirectory) { + this.breakingChangesDirectory.set(breakingChangesDirectory); + } + + @OutputDirectory + public DirectoryProperty getBreakingChangesDirectory() { + return breakingChangesDirectory; + } + + @InputFile + public RegularFileProperty getBreakingChangesAreaTemplate() { + return breakingChangesAreaTemplate; + } + + public void setBreakingChangesAreaTemplate(RegularFile file) { + this.breakingChangesAreaTemplate.set(file); } } diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ReleaseToolsPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ReleaseToolsPlugin.java index 8f08da371ec4b..97b0b46365bda 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ReleaseToolsPlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/ReleaseToolsPlugin.java @@ -84,11 +84,15 @@ public void apply(Project project) { task.setReleaseHighlightsFile(projectDirectory.file("docs/reference/release-notes/highlights.asciidoc")); task.setBreakingChangesTemplate(projectDirectory.file(RESOURCES + "templates/breaking-changes.asciidoc")); - task.setBreakingChangesFile( + task.setBreakingChangesIndexFile( projectDirectory.file( String.format("docs/reference/migration/migrate_%d_%d.asciidoc", version.getMajor(), version.getMinor()) ) ); + task.setBreakingChangesAreaTemplate(projectDirectory.file(RESOURCES + "templates/breaking-changes-area.asciidoc")); + task.setBreakingChangesDirectory( + projectDirectory.dir(String.format("docs/reference/migration/migrate_%d_%d", version.getMajor(), version.getMinor())) + ); task.dependsOn(validateChangelogsTask); }); diff --git a/build-tools-internal/src/main/resources/changelog-schema.json b/build-tools-internal/src/main/resources/changelog-schema.json index 433c841ebbc8a..9492bcb84261a 100644 --- a/build-tools-internal/src/main/resources/changelog-schema.json +++ b/build-tools-internal/src/main/resources/changelog-schema.json @@ -157,6 +157,9 @@ }, "notable": { "type": "boolean" + }, + "ess_setting_change": { + "type": "boolean" } }, "required": [ @@ -179,6 +182,9 @@ "body": { "type": "string", "minLength": 1 + }, + "ess_setting_change": { + "type": "boolean" } }, "required": [ diff --git a/build-tools-internal/src/main/resources/templates/breaking-changes-area.asciidoc b/build-tools-internal/src/main/resources/templates/breaking-changes-area.asciidoc new file mode 100644 index 0000000000000..43d6d376bbbbe --- /dev/null +++ b/build-tools-internal/src/main/resources/templates/breaking-changes-area.asciidoc @@ -0,0 +1,39 @@ +[discrete] +[[breaking_${majorMinor}_${breakingAreaAnchor}]] +==== ${breakingArea} + +//NOTE: The notable-breaking-changes tagged regions are re-used in the +//Installation and Upgrade Guide + +TIP: {ess-setting-change} + +<% +[true, false].each { isNotable -> + def breakingChanges = breakingEntriesByNotability.getOrDefault(isNotable, []) + + if (breakingChanges.isEmpty() == false) { + if (isNotable) { + /* No newline here, one will be added below */ + print "// tag::notable-breaking-changes[]" + } + + for (breaking in breakingChanges) { %> +[[${ breaking.anchor }]] +. ${breaking.title}${ breaking.essSettingChange ? ' {ess-icon}' : '' } +[%collapsible] +==== +*Details* + +${breaking.details.trim()} + +*Impact* + +${breaking.impact.trim()} +==== +<% + } + + if (isNotable) { + print "// end::notable-breaking-changes[]\n" + } + } +} +%> diff --git a/build-tools-internal/src/main/resources/templates/breaking-changes.asciidoc b/build-tools-internal/src/main/resources/templates/breaking-changes.asciidoc index 38573747863e9..dc240761a5714 100644 --- a/build-tools-internal/src/main/resources/templates/breaking-changes.asciidoc +++ b/build-tools-internal/src/main/resources/templates/breaking-changes.asciidoc @@ -9,11 +9,11 @@ your application to {es} ${majorDotMinor}. See also <> and <>. <% if (isElasticsearchSnapshot) { %> -coming[${version}] +coming::[${version}] <% } %> //NOTE: The notable-breaking-changes tagged regions are re-used in the //Installation and Upgrade Guide -<% if (breakingChangesByNotabilityByArea.isEmpty() == false) { %> +<% if (breakingIncludeList.isEmpty() == false) { %> [discrete] [[breaking-changes-${majorDotMinor}]] === Breaking changes @@ -29,41 +29,14 @@ Significant changes in behavior are deprecated in a minor release and the old behavior is supported until the next major release. To find out if you are using any deprecated functionality, enable <>. -<% -[true, false].each { isNotable -> - def breakingChangesByArea = breakingChangesByNotabilityByArea.getOrDefault(isNotable, []) - - breakingChangesByArea.eachWithIndex { area, breakingChanges, i -> - print "\n" - - if (isNotable) { - print "// tag::notable-breaking-changes[]\n" - } - print "[discrete]\n" - print "[[breaking_${majorMinor}_${ area.toLowerCase().replaceAll("[^a-z0-9]+", "_") }]]\n" - print "==== ${area}\n" - - for (breaking in breakingChanges) { %> -[[${ breaking.anchor }]] -.${breaking.title} -[%collapsible] -==== -*Details* + -${breaking.details.trim()} - -*Impact* + -${breaking.impact.trim()} -==== <% - } + for (include in breakingIncludeList) { + print "include::migrate_${version.major}_${version.minor}/${include}.asciidoc[]\n"; + } - if (isNotable) { - print "// end::notable-breaking-changes[]\n" - } - } -} } + if (deprecationsByArea.empty == false) { %> [discrete] diff --git a/build-tools-internal/src/test/java/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.java b/build-tools-internal/src/test/java/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.java index 601d3b8ed4870..7d05fbb82a328 100644 --- a/build-tools-internal/src/test/java/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.java +++ b/build-tools-internal/src/test/java/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.java @@ -16,8 +16,8 @@ import java.util.List; import java.util.Objects; +import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.equalTo; -import static org.junit.Assert.assertThat; public class BreakingChangesGeneratorTest { @@ -25,17 +25,46 @@ public class BreakingChangesGeneratorTest { * Check that the breaking changes can be correctly generated. */ @Test - public void generateFile_rendersCorrectMarkup() throws Exception { + public void generateIndexFile_rendersCorrectMarkup() throws Exception { // given: final String template = getResource("/templates/breaking-changes.asciidoc"); final String expectedOutput = getResource( - "/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateFile.asciidoc" + "/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateIndexFile.asciidoc" ); final List entries = getEntries(); // when: - final String actualOutput = BreakingChangesGenerator.generateFile(QualifiedVersion.of("8.4.0-SNAPSHOT"), template, entries); + final String actualOutput = BreakingChangesGenerator.generateIndexFile(QualifiedVersion.of("8.4.0-SNAPSHOT"), template, entries); + + // then: + assertThat(actualOutput, equalTo(expectedOutput)); + } + + /** + * Check that the breaking changes for a specific area can be correctly generated. + */ + @Test + public void generateAreaFile_rendersCorrectMarkup() throws Exception { + // given: + final String template = getResource("/templates/breaking-changes-area.asciidoc"); + final String expectedOutput = getResource( + "/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateAreaFile.asciidoc" + ); + final String breakingArea = "Cluster and node setting"; + + final List entries = getEntries().stream() + .map(ChangelogEntry::getBreaking) + .filter(each -> each.getArea().equals(breakingArea)) + .toList(); + + // when: + final String actualOutput = BreakingChangesGenerator.generateBreakingAreaFile( + QualifiedVersion.of("8.4.0-SNAPSHOT"), + template, + breakingArea, + entries + ); // then: assertThat(actualOutput, equalTo(expectedOutput)); @@ -58,7 +87,7 @@ private List getEntries() { breaking2.setNotable(true); breaking2.setTitle("Breaking change number 2"); - breaking2.setArea("Cluster"); + breaking2.setArea("Cluster and node setting"); breaking2.setDetails("Breaking change details 2"); breaking2.setImpact("Breaking change impact description 2"); @@ -72,7 +101,18 @@ private List getEntries() { breaking3.setDetails("Breaking change details 3"); breaking3.setImpact("Breaking change impact description 3"); - return List.of(entry1, entry2, entry3); + ChangelogEntry entry4 = new ChangelogEntry(); + ChangelogEntry.Breaking breaking4 = new ChangelogEntry.Breaking(); + entry4.setBreaking(breaking4); + + breaking4.setNotable(true); + breaking4.setTitle("Breaking change number 4"); + breaking4.setArea("Cluster and node setting"); + breaking4.setDetails("Breaking change details 4"); + breaking4.setImpact("Breaking change impact description 4"); + breaking4.setEssSettingChange(true); + + return List.of(entry1, entry2, entry3, entry4); } private String getResource(String name) throws Exception { diff --git a/build-tools-internal/src/test/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTaskTest.java b/build-tools-internal/src/test/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTaskTest.java index 8f35997c1e7d5..d2deffdbf332f 100644 --- a/build-tools-internal/src/test/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTaskTest.java +++ b/build-tools-internal/src/test/java/org/elasticsearch/gradle/internal/release/GenerateReleaseNotesTaskTest.java @@ -10,7 +10,6 @@ import org.elasticsearch.gradle.internal.test.GradleUnitTestCase; import org.junit.Before; -import org.junit.Ignore; import org.junit.Test; import java.io.File; @@ -34,7 +33,6 @@ import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; -@Ignore("https://github.com/elastic/elasticsearch/issues/77190") public class GenerateReleaseNotesTaskTest extends GradleUnitTestCase { private GitWrapper gitWrapper; diff --git a/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateAreaFile.asciidoc b/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateAreaFile.asciidoc new file mode 100644 index 0000000000000..dcd4d646d5a6a --- /dev/null +++ b/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateAreaFile.asciidoc @@ -0,0 +1,33 @@ +[discrete] +[[breaking_84_cluster_node_setting]] +==== Cluster and node setting + +//NOTE: The notable-breaking-changes tagged regions are re-used in the +//Installation and Upgrade Guide + +TIP: {ess-setting-change} + +// tag::notable-breaking-changes[] +[[breaking_change_number_2]] +. Breaking change number 2 +[%collapsible] +==== +*Details* + +Breaking change details 2 + +*Impact* + +Breaking change impact description 2 +==== + +[[breaking_change_number_4]] +. Breaking change number 4 {ess-icon} +[%collapsible] +==== +*Details* + +Breaking change details 4 + +*Impact* + +Breaking change impact description 4 +==== +// end::notable-breaking-changes[] + diff --git a/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateFile.asciidoc b/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateIndexFile.asciidoc similarity index 54% rename from build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateFile.asciidoc rename to build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateIndexFile.asciidoc index 4a61c2de4016f..277833e0171be 100644 --- a/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateFile.asciidoc +++ b/build-tools-internal/src/test/resources/org/elasticsearch/gradle/internal/release/BreakingChangesGeneratorTest.generateIndexFile.asciidoc @@ -9,7 +9,7 @@ your application to {es} 8.4. See also <> and <>. -coming[8.4.0-SNAPSHOT] +coming::[8.4.0-SNAPSHOT] //NOTE: The notable-breaking-changes tagged regions are re-used in the //Installation and Upgrade Guide @@ -30,52 +30,7 @@ the old behavior is supported until the next major release. To find out if you are using any deprecated functionality, enable <>. -// tag::notable-breaking-changes[] -[discrete] -[[breaking_84_api]] -==== API - -[[breaking_change_number_1]] -.Breaking change number 1 -[%collapsible] -==== -*Details* + -Breaking change details 1 - -*Impact* + -Breaking change impact description 1 -==== -// end::notable-breaking-changes[] - -// tag::notable-breaking-changes[] -[discrete] -[[breaking_84_cluster]] -==== Cluster - -[[breaking_change_number_2]] -.Breaking change number 2 -[%collapsible] -==== -*Details* + -Breaking change details 2 - -*Impact* + -Breaking change impact description 2 -==== -// end::notable-breaking-changes[] - -[discrete] -[[breaking_84_transform]] -==== Transform - -[[breaking_change_number_3]] -.Breaking change number 3 -[%collapsible] -==== -*Details* + -Breaking change details 3 - -*Impact* + -Breaking change impact description 3 -==== +include::migrate_8_4/api.asciidoc[] +include::migrate_8_4/cluster-node-setting.asciidoc[] +include::migrate_8_4/transform.asciidoc[]