From a4e0d9b9ddece166a1d7b9f489ea78f08fb563ef Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Thu, 2 Jun 2022 16:05:18 +0200 Subject: [PATCH] Added migration/index.asciidoc generation support (#87318) Including extracting static content from migration/index, so the template would be as light as possible. The reason for this work is because the gradle task `generateReleaseNotes` was not correctly adding new links and imports to the migrations/index and that caused documentation to fail building for 8.3.0. --- .../release/GenerateReleaseNotesTask.java | 37 ++++++++++++++ .../release/MigrationIndexGenerator.java | 50 +++++++++++++++++++ .../gradle/internal/release/MinorVersion.java | 47 +++++++++++++++++ .../internal/release/ReleaseToolsPlugin.java | 2 + .../templates/migration-index.asciidoc | 4 ++ .../release/GenerateReleaseNotesTaskTest.java | 23 +++++++++ docs/reference/migration/index.asciidoc | 33 +----------- .../migration/migration_intro.asciidoc | 31 ++++++++++++ 8 files changed, 196 insertions(+), 31 deletions(-) create mode 100644 build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/MigrationIndexGenerator.java create mode 100644 build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/MinorVersion.java create mode 100644 build-tools-internal/src/main/resources/templates/migration-index.asciidoc create mode 100644 docs/reference/migration/migration_intro.asciidoc 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 c02c19e107864..25034eb36b1a7 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 @@ -56,11 +56,13 @@ public class GenerateReleaseNotesTask extends DefaultTask { private final RegularFileProperty releaseNotesTemplate; private final RegularFileProperty releaseHighlightsTemplate; private final RegularFileProperty breakingChangesTemplate; + private final RegularFileProperty migrationIndexTemplate; private final RegularFileProperty releaseNotesIndexFile; private final RegularFileProperty releaseNotesFile; private final RegularFileProperty releaseHighlightsFile; private final RegularFileProperty breakingChangesMigrationFile; + private final RegularFileProperty migrationIndexFile; private final GitWrapper gitWrapper; @@ -72,11 +74,13 @@ public GenerateReleaseNotesTask(ObjectFactory objectFactory, ExecOperations exec releaseNotesTemplate = objectFactory.fileProperty(); releaseHighlightsTemplate = objectFactory.fileProperty(); breakingChangesTemplate = objectFactory.fileProperty(); + migrationIndexTemplate = objectFactory.fileProperty(); releaseNotesIndexFile = objectFactory.fileProperty(); releaseNotesFile = objectFactory.fileProperty(); releaseHighlightsFile = objectFactory.fileProperty(); breakingChangesMigrationFile = objectFactory.fileProperty(); + migrationIndexFile = objectFactory.fileProperty(); gitWrapper = new GitWrapper(execOperations); } @@ -137,6 +141,13 @@ public void executeTask() throws IOException { this.breakingChangesMigrationFile.get().getAsFile(), entries ); + + LOGGER.info("Updating migration/index..."); + MigrationIndexGenerator.update( + getMinorVersions(versions), + this.migrationIndexTemplate.get().getAsFile(), + this.migrationIndexFile.get().getAsFile() + ); } /** @@ -154,6 +165,14 @@ static Set getVersions(GitWrapper gitWrapper, String currentVe .collect(toSet()); } + /** + * Convert set of QualifiedVersion to MinorVersion by deleting all but the major and minor components. + */ + @VisibleForTesting + static Set getMinorVersions(Set versions) { + return versions.stream().map(MinorVersion::of).collect(toSet()); + } + /** * Group a set of files by the version in which they first appeared, up until the supplied version. Any files not * present in an earlier version are assumed to have been introduced in the specified version. @@ -320,6 +339,15 @@ public void setBreakingChangesTemplate(RegularFile file) { this.breakingChangesTemplate.set(file); } + @InputFile + public RegularFileProperty getMigrationIndexTemplate() { + return migrationIndexTemplate; + } + + public void setMigrationIndexTemplate(RegularFile file) { + this.migrationIndexTemplate.set(file); + } + @OutputFile public RegularFileProperty getReleaseNotesIndexFile() { return releaseNotesIndexFile; @@ -355,4 +383,13 @@ public RegularFileProperty getBreakingChangesMigrationFile() { public void setBreakingChangesMigrationFile(RegularFile file) { this.breakingChangesMigrationFile.set(file); } + + @OutputFile + public RegularFileProperty getMigrationIndexFile() { + return migrationIndexFile; + } + + public void setMigrationIndexFile(RegularFile file) { + this.migrationIndexFile.set(file); + } } diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/MigrationIndexGenerator.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/MigrationIndexGenerator.java new file mode 100644 index 0000000000000..ca420294fede0 --- /dev/null +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/MigrationIndexGenerator.java @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.gradle.internal.release; + +import com.google.common.annotations.VisibleForTesting; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeSet; +import java.util.stream.Collectors; + +import static java.util.Comparator.reverseOrder; + +/** + * This class ensures that the migrate/index page has the appropriate anchors and include directives + * for the current repository version. + */ +public class MigrationIndexGenerator { + + static void update(Set versions, File indexTemplate, File indexFile) throws IOException { + try (FileWriter indexFileWriter = new FileWriter(indexFile)) { + indexFileWriter.write(generateFile(versions, Files.readString(indexTemplate.toPath()))); + } + } + + @VisibleForTesting + static String generateFile(Set versionsSet, String template) throws IOException { + final Set versions = new TreeSet<>(reverseOrder()); + versions.addAll(versionsSet); + final List includeVersions = versions.stream().map(MinorVersion::underscore).collect(Collectors.toList()); + + final Map bindings = new HashMap<>(); + bindings.put("versions", versions); + bindings.put("includeVersions", includeVersions); + + return TemplateUtils.render(template, bindings); + } +} diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/MinorVersion.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/MinorVersion.java new file mode 100644 index 0000000000000..8c78c6b38b79d --- /dev/null +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/release/MinorVersion.java @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +package org.elasticsearch.gradle.internal.release; + +import java.util.Comparator; +import java.util.Objects; + +/** + * Encapsulates comparison and printing logic for an x.y. + */ +public record MinorVersion(int major, int minor) implements Comparable { + /** + * Converts a QualifiedVersion into a MinorVersion by deleting all but the major and minor components. + */ + public static MinorVersion of(final QualifiedVersion v) { + Objects.requireNonNull(v); + return new MinorVersion(v.major(), v.minor()); + } + + @Override + public String toString() { + return major + "." + minor; + } + + /** Generate version string with underscore instead of dot */ + public String underscore() { + return major + "_" + minor; + } + + private static final Comparator COMPARATOR = Comparator.comparing((MinorVersion v) -> v.major) + .thenComparing(v -> v.minor); + + @Override + public int compareTo(MinorVersion other) { + return COMPARATOR.compare(this, other); + } + + public boolean isBefore(MinorVersion other) { + return this.compareTo(other) < 0; + } +} 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 7d9d4dceba265..fb6ddc5e1be16 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 @@ -96,6 +96,8 @@ public void apply(Project project) { String.format("docs/reference/migration/migrate_%d_%d.asciidoc", version.getMajor(), version.getMinor()) ) ); + task.setMigrationIndexTemplate(projectDirectory.file(RESOURCES + "templates/migration-index.asciidoc")); + task.setMigrationIndexFile(projectDirectory.file("docs/reference/migration/index.asciidoc")); task.dependsOn(validateChangelogsTask); }); diff --git a/build-tools-internal/src/main/resources/templates/migration-index.asciidoc b/build-tools-internal/src/main/resources/templates/migration-index.asciidoc new file mode 100644 index 0000000000000..a83792900e527 --- /dev/null +++ b/build-tools-internal/src/main/resources/templates/migration-index.asciidoc @@ -0,0 +1,4 @@ +include::migration_intro.asciidoc[] + +<% versions.each { print "* <>\n" } %> +<% includeVersions.each { print "include::migrate_${ it }.asciidoc[]\n" } %> 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 35e3eabcc872f..b020b1ee93126 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 @@ -180,6 +180,29 @@ public void getVersions_includesCurrentVersion() { ); } + /** + * Check that when deriving a list of major.minor versions from git tags, the current unreleased version is included, + * but any higher version numbers are not. + */ + @Test + public void getMinorVersions_includesCurrentButNotFutureVersions() { + // given: + when(gitWrapper.listVersions(anyString())).thenReturn( + Stream.of("8.0.0-alpha1", "8.0.0-alpha2", "8.0.0", "8.0.1", "8.1.0", "8.2.0", "8.2.1", "8.3.0", "8.3.1", "8.4.0") + .map(QualifiedVersion::of) + ); + + // when: + Set versions = GenerateReleaseNotesTask.getVersions(gitWrapper, "8.3.0-SNAPSHOT"); + Set minorVersions = GenerateReleaseNotesTask.getMinorVersions(versions); + + // then: + assertThat( + minorVersions, + containsInAnyOrder(new MinorVersion(8, 0), new MinorVersion(8, 1), new MinorVersion(8, 2), new MinorVersion(8, 3)) + ); + } + /** * Check that the task partitions the list of files correctly by version for a prerelease. */ diff --git a/docs/reference/migration/index.asciidoc b/docs/reference/migration/index.asciidoc index cb6b21f434b9b..0d72d22bc1f62 100644 --- a/docs/reference/migration/index.asciidoc +++ b/docs/reference/migration/index.asciidoc @@ -1,34 +1,4 @@ -[[breaking-changes]] -= Migration guide - -This section discusses the changes that you need to be aware of to migrate -your application to {version}. For more information about what's new in this -release, see the <> and <>. - -As {es} introduces new features and improves existing ones, the changes -sometimes make older settings, APIs, and parameters obsolete. We typically -deprecate obsolete functionality as part of a release. If possible, we support -the deprecated functionality for several subsequent releases before removing it. -This enables applications to continue working unchanged while you prepare to -migrate away from the deprecated functionality. - -To get the most out of {es} and facilitate future upgrades, we strongly -encourage migrating away from using deprecated functionality as soon as -possible. - -To give you insight into what deprecated features you're using, {es}: - -- Returns a `Warn` HTTP header whenever you -submit a request that uses deprecated functionality. -- <> when -deprecated functionality is used. -- <> -that scans a cluster's configuration -and mappings for deprecated functionality. - -For more information about {minor-version}, -see the <> and <>. -For information about how to upgrade your cluster, see <>. +include::migration_intro.asciidoc[] * <> * <> @@ -37,3 +7,4 @@ For information about how to upgrade your cluster, see <>. include::migrate_8_2.asciidoc[] include::migrate_8_1.asciidoc[] include::migrate_8_0.asciidoc[] + diff --git a/docs/reference/migration/migration_intro.asciidoc b/docs/reference/migration/migration_intro.asciidoc new file mode 100644 index 0000000000000..293cef85d57c8 --- /dev/null +++ b/docs/reference/migration/migration_intro.asciidoc @@ -0,0 +1,31 @@ +[[breaking-changes]] += Migration guide + +This section discusses the changes that you need to be aware of to migrate +your application to {version}. For more information about what's new in this +release, see the <> and <>. + +As {es} introduces new features and improves existing ones, the changes +sometimes make older settings, APIs, and parameters obsolete. We typically +deprecate obsolete functionality as part of a release. If possible, we support +the deprecated functionality for several subsequent releases before removing it. +This enables applications to continue working unchanged while you prepare to +migrate away from the deprecated functionality. + +To get the most out of {es} and facilitate future upgrades, we strongly +encourage migrating away from using deprecated functionality as soon as +possible. + +To give you insight into what deprecated features you're using, {es}: + +- Returns a `Warn` HTTP header whenever you +submit a request that uses deprecated functionality. +- <> when +deprecated functionality is used. +- <> +that scans a cluster's configuration +and mappings for deprecated functionality. + +For more information about {minor-version}, +see the <> and <>. +For information about how to upgrade your cluster, see <>.