mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Prepare buildSrc for migration to Antora
Replace `AsciidoctorConventions` with `AntoraConventions` in preparation for the migration to Antora. See gh-33766
This commit is contained in:
parent
d18f60e9af
commit
8d64e99714
|
@ -17,7 +17,7 @@ def versions = [:]
|
|||
new File(projectDir.parentFile, "gradle.properties").withInputStream {
|
||||
def properties = new Properties()
|
||||
properties.load(it)
|
||||
["assertj", "commonsCodec", "hamcrest", "junitJupiter", "kotlin", "maven"].each {
|
||||
["assertj", "commonsCodec", "hamcrest", "junitJupiter", "kotlin", "maven", "snakeYaml"].each {
|
||||
versions[it] = properties[it + "Version"]
|
||||
}
|
||||
}
|
||||
|
@ -42,20 +42,23 @@ dependencies {
|
|||
implementation(platform("org.springframework:spring-framework-bom:${versions.springFramework}"))
|
||||
implementation("com.diffplug.gradle:goomph:3.37.2")
|
||||
implementation("com.fasterxml.jackson.core:jackson-databind:${versions.jackson}")
|
||||
implementation("com.github.node-gradle:gradle-node-plugin:3.5.1")
|
||||
implementation("com.gradle:gradle-enterprise-gradle-plugin:3.12.1")
|
||||
implementation("com.tngtech.archunit:archunit:1.0.0")
|
||||
implementation("commons-codec:commons-codec:${versions.commonsCodec}")
|
||||
implementation("de.undercouch.download:de.undercouch.download.gradle.plugin:5.5.0")
|
||||
implementation("io.spring.gradle.antora:spring-antora-plugin:0.0.1")
|
||||
implementation("io.spring.javaformat:spring-javaformat-gradle-plugin:${javaFormatVersion}")
|
||||
implementation("io.spring.nohttp:nohttp-gradle:0.0.11")
|
||||
implementation("org.apache.httpcomponents.client5:httpclient5:5.3.1")
|
||||
implementation("org.apache.maven:maven-embedder:${versions.maven}")
|
||||
implementation("org.asciidoctor:asciidoctor-gradle-jvm:3.3.2")
|
||||
implementation("org.antora:gradle-antora-plugin:1.0.0")
|
||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-compiler-embeddable:${versions.kotlin}")
|
||||
implementation("org.springframework:spring-context")
|
||||
implementation("org.springframework:spring-core")
|
||||
implementation("org.springframework:spring-web")
|
||||
implementation("io.spring.nohttp:nohttp-gradle:0.0.11")
|
||||
implementation("org.yaml:snakeyaml:${versions.snakeYaml}")
|
||||
|
||||
testImplementation("org.assertj:assertj-core:${versions.assertj}")
|
||||
testImplementation("org.hamcrest:hamcrest:${versions.hamcrest}")
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Copyright 2023-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.github.gradle.node.NodeExtension;
|
||||
import io.spring.gradle.antora.GenerateAntoraYmlPlugin;
|
||||
import io.spring.gradle.antora.GenerateAntoraYmlTask;
|
||||
import org.antora.gradle.AntoraExtension;
|
||||
import org.antora.gradle.AntoraPlugin;
|
||||
import org.antora.gradle.AntoraTask;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.file.RegularFile;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.logging.LogLevel;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.tasks.TaskContainer;
|
||||
|
||||
import org.springframework.boot.build.antora.AntoraAsciidocAttributes;
|
||||
import org.springframework.boot.build.antora.Extensions;
|
||||
import org.springframework.boot.build.antora.GenerateAntoraPlaybook;
|
||||
import org.springframework.boot.build.bom.BomExtension;
|
||||
import org.springframework.boot.build.constraints.ExtractVersionConstraints;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Conventions that are applied in the presence of the {@link AntoraPlugin} and
|
||||
* {@link GenerateAntoraYmlPlugin}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class AntoraConventions {
|
||||
|
||||
private static final String DEPENDENCIES_PATH = ":spring-boot-project:spring-boot-dependencies";
|
||||
|
||||
private static final String ANTORA_VERSION = "3.2.0-alpha.4";
|
||||
|
||||
private static final String ANTORA_SOURCE_DIR = "src/docs/antora";
|
||||
|
||||
private static final List<String> NAV_FILES = List.of("nav.adoc", "local-nav.adoc");
|
||||
|
||||
void apply(Project project) {
|
||||
project.getPlugins().withType(AntoraPlugin.class, (antoraPlugin) -> apply(project, antoraPlugin));
|
||||
}
|
||||
|
||||
private void apply(Project project, AntoraPlugin antoraPlugin) {
|
||||
ExtractVersionConstraints dependencyVersionsTask = addDependencyVersionsTask(project);
|
||||
project.getPlugins().apply(GenerateAntoraYmlPlugin.class);
|
||||
TaskContainer tasks = project.getTasks();
|
||||
GenerateAntoraPlaybook generateAntoraPlaybookTask = tasks.create("generateAntoraPlaybook",
|
||||
GenerateAntoraPlaybook.class);
|
||||
tasks.withType(GenerateAntoraYmlTask.class, (generateAntoraYmlTask) -> configureGenerateAntoraYmlTask(project,
|
||||
generateAntoraYmlTask, dependencyVersionsTask));
|
||||
tasks.withType(AntoraTask.class,
|
||||
(antoraTask) -> configureAntoraTask(project, antoraTask, generateAntoraPlaybookTask));
|
||||
project.getExtensions().configure(AntoraExtension.class, (antoraExtension) -> {
|
||||
RegularFileProperty outputFile = generateAntoraPlaybookTask.getOutputFile();
|
||||
configureAntoraExtension(project, antoraExtension, outputFile);
|
||||
});
|
||||
project.getExtensions()
|
||||
.configure(NodeExtension.class, (nodeExtension) -> configureNodeExtension(project, nodeExtension));
|
||||
}
|
||||
|
||||
private ExtractVersionConstraints addDependencyVersionsTask(Project project) {
|
||||
return project.getTasks()
|
||||
.create("dependencyVersions", ExtractVersionConstraints.class,
|
||||
(task) -> task.enforcedPlatform(DEPENDENCIES_PATH));
|
||||
}
|
||||
|
||||
private void configureGenerateAntoraYmlTask(Project project, GenerateAntoraYmlTask generateAntoraYmlTask,
|
||||
ExtractVersionConstraints dependencyVersionsTask) {
|
||||
generateAntoraYmlTask.getOutputs().doNotCacheIf("getAsciidocAttributes() changes output", (task) -> true);
|
||||
generateAntoraYmlTask.dependsOn(dependencyVersionsTask);
|
||||
generateAntoraYmlTask.setProperty("componentName", "spring-boot");
|
||||
generateAntoraYmlTask.setProperty("outputFile",
|
||||
new File(project.getBuildDir(), "generated/docs/antora-yml/antora.yml"));
|
||||
generateAntoraYmlTask.setProperty("yml", getDefaultYml(project));
|
||||
generateAntoraYmlTask.doFirst((task) -> generateAntoraYmlTask.getAsciidocAttributes()
|
||||
.putAll(project.provider(() -> getAsciidocAttributes(project, dependencyVersionsTask))));
|
||||
}
|
||||
|
||||
private Map<String, ?> getDefaultYml(Project project) {
|
||||
String navFile = null;
|
||||
for (String candidate : NAV_FILES) {
|
||||
if (project.file(ANTORA_SOURCE_DIR + "/" + candidate).exists()) {
|
||||
Assert.state(navFile == null, "Multiple nav files found");
|
||||
navFile = candidate;
|
||||
}
|
||||
}
|
||||
Map<String, Object> defaultYml = new LinkedHashMap<>();
|
||||
defaultYml.put("title", "Spring Boot");
|
||||
if (navFile != null) {
|
||||
defaultYml.put("nav", List.of(navFile));
|
||||
}
|
||||
return defaultYml;
|
||||
}
|
||||
|
||||
private Map<String, String> getAsciidocAttributes(Project project,
|
||||
ExtractVersionConstraints dependencyVersionsTask) {
|
||||
BomExtension bom = (BomExtension) project.project(DEPENDENCIES_PATH).getExtensions().getByName("bom");
|
||||
Map<String, String> dependencyVersions = dependencyVersionsTask.getVersionConstraints();
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes(project, bom, dependencyVersions);
|
||||
return attributes.get();
|
||||
}
|
||||
|
||||
private void configureAntoraTask(Project project, AntoraTask antoraTask,
|
||||
GenerateAntoraPlaybook generateAntoraPlaybookTask) {
|
||||
antoraTask.setGroup("Documentation");
|
||||
antoraTask.getDependsOn().add(generateAntoraPlaybookTask);
|
||||
project.getPlugins()
|
||||
.withType(JavaBasePlugin.class,
|
||||
(javaBasePlugin) -> project.getTasks()
|
||||
.getByName(JavaBasePlugin.CHECK_TASK_NAME)
|
||||
.dependsOn(antoraTask));
|
||||
}
|
||||
|
||||
private void configureAntoraExtension(Project project, AntoraExtension antoraExtension,
|
||||
Provider<RegularFile> playbook) {
|
||||
antoraExtension.getVersion().convention(ANTORA_VERSION);
|
||||
antoraExtension.getPackages().convention(Extensions.packages());
|
||||
antoraExtension.getPlaybook().convention(playbook.map(RegularFile::getAsFile));
|
||||
if (project.getGradle().getStartParameter().getLogLevel() != LogLevel.DEBUG) {
|
||||
antoraExtension.getOptions().add("--quiet");
|
||||
}
|
||||
else {
|
||||
antoraExtension.getOptions().addAll("--log-level", "all");
|
||||
}
|
||||
}
|
||||
|
||||
private void configureNodeExtension(Project project, NodeExtension nodeExtension) {
|
||||
File buildDir = project.getBuildDir();
|
||||
nodeExtension.getWorkDir().set(buildDir.toPath().resolve(".gradle/nodejs").toFile());
|
||||
nodeExtension.getNpmWorkDir().set(buildDir.toPath().resolve(".gradle/npm").toFile());
|
||||
}
|
||||
|
||||
}
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask;
|
||||
import org.asciidoctor.gradle.jvm.AsciidoctorJExtension;
|
||||
import org.asciidoctor.gradle.jvm.AsciidoctorJPlugin;
|
||||
import org.asciidoctor.gradle.jvm.AsciidoctorTask;
|
||||
import org.gradle.api.JavaVersion;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.tasks.PathSensitivity;
|
||||
import org.gradle.api.tasks.Sync;
|
||||
|
||||
import org.springframework.boot.build.artifacts.ArtifactRelease;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Conventions that are applied in the presence of the {@link AsciidoctorJPlugin}. When
|
||||
* the plugin is applied:
|
||||
*
|
||||
* <ul>
|
||||
* <li>All warnings are made fatal.
|
||||
* <li>The version of AsciidoctorJ is upgraded to 2.4.3.
|
||||
* <li>An {@code asciidoctorExtensions} configuration is created.
|
||||
* <li>For each {@link AsciidoctorTask} (HTML only):
|
||||
* <ul>
|
||||
* <li>A task is created to sync the documentation resources to its output directory.
|
||||
* <li>{@code doctype} {@link AsciidoctorTask#options(Map) option} is configured.
|
||||
* <li>The {@code backend} is configured.
|
||||
* </ul>
|
||||
* <li>For each {@link AbstractAsciidoctorTask} (HTML and PDF):
|
||||
* <ul>
|
||||
* <li>{@link AsciidoctorTask#attributes(Map) Attributes} are configured to enable
|
||||
* warnings for references to missing attributes, the GitHub tag, the Artifactory repo for
|
||||
* the current version, etc.
|
||||
* <li>{@link AbstractAsciidoctorTask#baseDirFollowsSourceDir() baseDirFollowsSourceDir()}
|
||||
* is enabled.
|
||||
* <li>{@code asciidoctorExtensions} is added to the task's configurations.
|
||||
* </ul>
|
||||
* </ul>
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
class AsciidoctorConventions {
|
||||
|
||||
private static final String ASCIIDOCTORJ_VERSION = "2.4.3";
|
||||
|
||||
private static final String EXTENSIONS_CONFIGURATION_NAME = "asciidoctorExtensions";
|
||||
|
||||
void apply(Project project) {
|
||||
project.getPlugins().withType(AsciidoctorJPlugin.class, (asciidoctorPlugin) -> {
|
||||
makeAllWarningsFatal(project);
|
||||
upgradeAsciidoctorJVersion(project);
|
||||
createAsciidoctorExtensionsConfiguration(project);
|
||||
project.getTasks()
|
||||
.withType(AbstractAsciidoctorTask.class,
|
||||
(asciidoctorTask) -> configureAsciidoctorTask(project, asciidoctorTask));
|
||||
});
|
||||
}
|
||||
|
||||
private void makeAllWarningsFatal(Project project) {
|
||||
project.getExtensions().getByType(AsciidoctorJExtension.class).fatalWarnings(".*");
|
||||
}
|
||||
|
||||
private void upgradeAsciidoctorJVersion(Project project) {
|
||||
project.getExtensions().getByType(AsciidoctorJExtension.class).setVersion(ASCIIDOCTORJ_VERSION);
|
||||
}
|
||||
|
||||
private void createAsciidoctorExtensionsConfiguration(Project project) {
|
||||
project.getConfigurations().create(EXTENSIONS_CONFIGURATION_NAME, (configuration) -> {
|
||||
project.getConfigurations()
|
||||
.matching((candidate) -> "dependencyManagement".equals(candidate.getName()))
|
||||
.all(configuration::extendsFrom);
|
||||
configuration.getDependencies()
|
||||
.add(project.getDependencies()
|
||||
.create("io.spring.asciidoctor.backends:spring-asciidoctor-backends:0.0.5"));
|
||||
configuration.getDependencies()
|
||||
.add(project.getDependencies().create("org.asciidoctor:asciidoctorj-pdf:1.5.3"));
|
||||
});
|
||||
}
|
||||
|
||||
private void configureAsciidoctorTask(Project project, AbstractAsciidoctorTask asciidoctorTask) {
|
||||
asciidoctorTask.configurations(EXTENSIONS_CONFIGURATION_NAME);
|
||||
configureCommonAttributes(project, asciidoctorTask);
|
||||
configureOptions(asciidoctorTask);
|
||||
configureForkOptions(asciidoctorTask);
|
||||
asciidoctorTask.baseDirFollowsSourceDir();
|
||||
createSyncDocumentationSourceTask(project, asciidoctorTask);
|
||||
if (asciidoctorTask instanceof AsciidoctorTask task) {
|
||||
boolean pdf = task.getName().toLowerCase().contains("pdf");
|
||||
String backend = (!pdf) ? "spring-html" : "spring-pdf";
|
||||
task.outputOptions((outputOptions) -> outputOptions.backends(backend));
|
||||
}
|
||||
}
|
||||
|
||||
private void configureCommonAttributes(Project project, AbstractAsciidoctorTask asciidoctorTask) {
|
||||
ArtifactRelease artifacts = ArtifactRelease.forProject(project);
|
||||
Map<String, Object> attributes = new HashMap<>();
|
||||
attributes.put("attribute-missing", "warn");
|
||||
attributes.put("github-tag", determineGitHubTag(project));
|
||||
attributes.put("artifact-release-type", artifacts.getType());
|
||||
attributes.put("artifact-download-repo", artifacts.getDownloadRepo());
|
||||
attributes.put("revnumber", null);
|
||||
asciidoctorTask.attributes(attributes);
|
||||
}
|
||||
|
||||
// See https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/597
|
||||
private void configureForkOptions(AbstractAsciidoctorTask asciidoctorTask) {
|
||||
if (JavaVersion.current().isCompatibleWith(JavaVersion.VERSION_16)) {
|
||||
asciidoctorTask.forkOptions((options) -> options.jvmArgs("--add-opens", "java.base/sun.nio.ch=ALL-UNNAMED",
|
||||
"--add-opens", "java.base/java.io=ALL-UNNAMED"));
|
||||
}
|
||||
}
|
||||
|
||||
private String determineGitHubTag(Project project) {
|
||||
String version = "v" + project.getVersion();
|
||||
return (version.endsWith("-SNAPSHOT")) ? "main" : version;
|
||||
}
|
||||
|
||||
private void configureOptions(AbstractAsciidoctorTask asciidoctorTask) {
|
||||
asciidoctorTask.options(Collections.singletonMap("doctype", "book"));
|
||||
}
|
||||
|
||||
private Sync createSyncDocumentationSourceTask(Project project, AbstractAsciidoctorTask asciidoctorTask) {
|
||||
Sync syncDocumentationSource = project.getTasks()
|
||||
.create("syncDocumentationSourceFor" + StringUtils.capitalize(asciidoctorTask.getName()), Sync.class);
|
||||
File syncedSource = new File(project.getBuildDir(), "docs/src/" + asciidoctorTask.getName());
|
||||
syncDocumentationSource.setDestinationDir(syncedSource);
|
||||
syncDocumentationSource.from("src/docs/");
|
||||
asciidoctorTask.dependsOn(syncDocumentationSource);
|
||||
asciidoctorTask.getInputs()
|
||||
.dir(syncedSource)
|
||||
.withPathSensitivity(PathSensitivity.RELATIVE)
|
||||
.withPropertyName("synced source");
|
||||
asciidoctorTask.setSourceDir(project.relativePath(new File(syncedSource, "asciidoc/")));
|
||||
return syncDocumentationSource;
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package org.springframework.boot.build;
|
||||
|
||||
import org.asciidoctor.gradle.jvm.AsciidoctorJPlugin;
|
||||
import org.antora.gradle.AntoraPlugin;
|
||||
import org.gradle.api.Plugin;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
|
@ -32,8 +32,8 @@ import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
|
|||
* When the {@link MavenPublishPlugin} is applied, the conventions in
|
||||
* {@link MavenPublishingConventions} are applied.
|
||||
*
|
||||
* When the {@link AsciidoctorJPlugin} is applied, the conventions in
|
||||
* {@link AsciidoctorConventions} are applied.
|
||||
* When the {@link AntoraPlugin} is applied, the conventions in {@link AntoraConventions}
|
||||
* are applied.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Christoph Dreis
|
||||
|
@ -46,7 +46,7 @@ public class ConventionsPlugin implements Plugin<Project> {
|
|||
new NoHttpConventions().apply(project);
|
||||
new JavaConventions().apply(project);
|
||||
new MavenPublishingConventions().apply(project);
|
||||
new AsciidoctorConventions().apply(project);
|
||||
new AntoraConventions().apply(project);
|
||||
new KotlinConventions().apply(project);
|
||||
new WarConventions().apply(project);
|
||||
new EclipseConventions().apply(project);
|
||||
|
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build.antora;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
|
||||
import org.springframework.boot.build.artifacts.ArtifactRelease;
|
||||
import org.springframework.boot.build.bom.BomExtension;
|
||||
import org.springframework.boot.build.bom.Library;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Generates Asciidoctor attributes for use with Antora.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class AntoraAsciidocAttributes {
|
||||
|
||||
private static final String DASH_SNAPSHOT = "-SNAPSHOT";
|
||||
|
||||
private final String version;
|
||||
|
||||
private final boolean latestVersion;
|
||||
|
||||
private final ArtifactRelease artifactRelease;
|
||||
|
||||
private final List<Library> libraries;
|
||||
|
||||
private final Map<String, String> dependencyVersions;
|
||||
|
||||
private final Map<String, ?> projectProperties;
|
||||
|
||||
public AntoraAsciidocAttributes(Project project, BomExtension dependencyBom,
|
||||
Map<String, String> dependencyVersions) {
|
||||
this.version = String.valueOf(project.getVersion());
|
||||
this.latestVersion = Boolean.valueOf(String.valueOf(project.findProperty("latestVersion")));
|
||||
this.artifactRelease = ArtifactRelease.forProject(project);
|
||||
this.libraries = dependencyBom.getLibraries();
|
||||
this.dependencyVersions = dependencyVersions;
|
||||
this.projectProperties = project.getProperties();
|
||||
}
|
||||
|
||||
AntoraAsciidocAttributes(String version, boolean latestVersion, List<Library> libraries,
|
||||
Map<String, String> dependencyVersions, Map<String, ?> projectProperties) {
|
||||
this.version = version;
|
||||
this.latestVersion = latestVersion;
|
||||
this.artifactRelease = ArtifactRelease.forVersion(version);
|
||||
this.libraries = (libraries != null) ? libraries : Collections.emptyList();
|
||||
this.dependencyVersions = (dependencyVersions != null) ? dependencyVersions : Collections.emptyMap();
|
||||
this.projectProperties = (projectProperties != null) ? projectProperties : Collections.emptyMap();
|
||||
}
|
||||
|
||||
public Map<String, String> get() {
|
||||
Map<String, String> attributes = new LinkedHashMap<>();
|
||||
addGitHubAttributes(attributes);
|
||||
addVersionAttributes(attributes);
|
||||
addUrlArtifactRepository(attributes);
|
||||
addUrlLibraryLinkAttributes(attributes);
|
||||
addPropertyAttributes(attributes);
|
||||
return attributes;
|
||||
}
|
||||
|
||||
private void addGitHubAttributes(Map<String, String> attributes) {
|
||||
attributes.put("github-repo", "spring-projects/spring-boot");
|
||||
attributes.put("github-ref", determineGitHubRef());
|
||||
}
|
||||
|
||||
private String determineGitHubRef() {
|
||||
int snapshotIndex = this.version.lastIndexOf(DASH_SNAPSHOT);
|
||||
if (snapshotIndex == -1) {
|
||||
return "v" + this.version;
|
||||
}
|
||||
if (this.latestVersion) {
|
||||
return "main";
|
||||
}
|
||||
String versionRoot = this.version.substring(0, snapshotIndex);
|
||||
int lastDot = versionRoot.lastIndexOf('.');
|
||||
return versionRoot.substring(0, lastDot) + ".x";
|
||||
}
|
||||
|
||||
private void addVersionAttributes(Map<String, String> attributes) {
|
||||
this.libraries.forEach((library) -> {
|
||||
String name = "version-" + library.getLinkRootName();
|
||||
String value = library.getVersion().toString();
|
||||
attributes.put(name, value);
|
||||
});
|
||||
attributes.put("version-native-build-tools", (String) this.projectProperties.get("nativeBuildToolsVersion"));
|
||||
attributes.put("version-graal", (String) this.projectProperties.get("graalVersion"));
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-commons");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-couchbase");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-elasticsearch");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-jdbc");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-jpa");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-mongodb");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-neo4j");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-r2dbc");
|
||||
addSpringDataDependencyVersion(attributes, "spring-data-rest", "spring-data-rest-core");
|
||||
}
|
||||
|
||||
private void addSpringDataDependencyVersion(Map<String, String> attributes, String artifactId) {
|
||||
addSpringDataDependencyVersion(attributes, artifactId, artifactId);
|
||||
}
|
||||
|
||||
private void addSpringDataDependencyVersion(Map<String, String> attributes, String name, String artifactId) {
|
||||
String version = this.dependencyVersions.get("org.springframework.data:" + artifactId);
|
||||
Assert.notNull(version, () -> "No version found for Spring Data artificat " + artifactId);
|
||||
attributes.put("version-" + name, version);
|
||||
}
|
||||
|
||||
private void addUrlArtifactRepository(Map<String, String> attributes) {
|
||||
attributes.put("url-artifact-repository", this.artifactRelease.getDownloadRepo());
|
||||
}
|
||||
|
||||
private void addUrlLibraryLinkAttributes(Map<String, String> attributes) {
|
||||
this.libraries.forEach((library) -> {
|
||||
String prefix = "url-" + library.getLinkRootName() + "-";
|
||||
library.getLinks().forEach((name, link) -> attributes.put(prefix + name, link));
|
||||
});
|
||||
}
|
||||
|
||||
private void addPropertyAttributes(Map<String, String> attributes) {
|
||||
Properties properties = new Properties() {
|
||||
|
||||
@Override
|
||||
public synchronized Object put(Object key, Object value) {
|
||||
// Put directly because order is important for us
|
||||
return attributes.put(key.toString(), value.toString());
|
||||
}
|
||||
|
||||
};
|
||||
try (InputStream in = getClass().getResourceAsStream("antora-asciidoc-attributes.properties")) {
|
||||
properties.load(in);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build.antora;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* Antora and Asciidoc extensions used by Spring Boot.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public final class Extensions {
|
||||
|
||||
private static final String ROOT_COMPONENT_EXTENSION = "@springio/antora-extensions/root-component-extension";
|
||||
|
||||
private static final List<Extension> antora;
|
||||
static {
|
||||
List<Extension> extensions = new ArrayList<>();
|
||||
extensions.add(new Extension("@springio/antora-extensions", "1.8.2", ROOT_COMPONENT_EXTENSION,
|
||||
"@springio/antora-extensions/static-page-extension"));
|
||||
extensions.add(new Extension("@springio/antora-xref-extension", "1.0.0-alpha.3"));
|
||||
extensions.add(new Extension("@springio/antora-zip-contents-collector-extension", "1.0.0-alpha.2"));
|
||||
antora = List.copyOf(extensions);
|
||||
}
|
||||
|
||||
private static final List<Extension> asciidoc;
|
||||
static {
|
||||
List<Extension> extensions = new ArrayList<>();
|
||||
extensions.add(new Extension("@asciidoctor/tabs", "1.0.0-beta.6"));
|
||||
extensions
|
||||
.add(new Extension("@springio/asciidoctor-extensions", "1.0.0-alpha.10", "@springio/asciidoctor-extensions",
|
||||
"@springio/asciidoctor-extensions/configuration-properties-extension",
|
||||
"@springio/asciidoctor-extensions/section-ids-extension"));
|
||||
asciidoc = List.copyOf(extensions);
|
||||
}
|
||||
|
||||
private static final Map<String, String> localOverrides = Collections.emptyMap();
|
||||
|
||||
private Extensions() {
|
||||
}
|
||||
|
||||
public static Map<String, String> packages() {
|
||||
Map<String, String> packages = new TreeMap<>();
|
||||
antora.stream().forEach((extension) -> packages.put(extension.name(), extension.version()));
|
||||
asciidoc.stream().forEach((extension) -> packages.put(extension.name(), extension.version()));
|
||||
return Collections.unmodifiableMap(packages);
|
||||
}
|
||||
|
||||
static List<Map<String, Object>> antora(Consumer<AntoraExtensionsConfiguration> extensions) {
|
||||
AntoraExtensionsConfiguration result = new AntoraExtensionsConfiguration(
|
||||
antora.stream().flatMap(Extension::names).sorted().toList());
|
||||
extensions.accept(result);
|
||||
return result.config();
|
||||
}
|
||||
|
||||
static List<String> asciidoc() {
|
||||
return asciidoc.stream().flatMap(Extension::names).sorted().toList();
|
||||
}
|
||||
|
||||
private record Extension(String name, String version, String... includeNames) {
|
||||
|
||||
Stream<String> names() {
|
||||
return (this.includeNames.length != 0) ? Arrays.stream(this.includeNames) : Stream.of(this.name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static final class AntoraExtensionsConfiguration {
|
||||
|
||||
private Map<String, Map<String, Object>> extensions = new TreeMap<>();
|
||||
|
||||
private AntoraExtensionsConfiguration(List<String> names) {
|
||||
names.forEach((name) -> this.extensions.put(name, null));
|
||||
}
|
||||
|
||||
void xref(Consumer<Xref> xref) {
|
||||
xref.accept(new Xref());
|
||||
}
|
||||
|
||||
void zipContentsCollector(Consumer<ZipContentsCollector> zipContentsCollector) {
|
||||
zipContentsCollector.accept(new ZipContentsCollector());
|
||||
}
|
||||
|
||||
void rootComponent(Consumer<RootComponent> rootComponent) {
|
||||
rootComponent.accept(new RootComponent());
|
||||
}
|
||||
|
||||
List<Map<String, Object>> config() {
|
||||
List<Map<String, Object>> config = new ArrayList<>();
|
||||
Map<String, Map<String, Object>> orderedExtensions = new LinkedHashMap<>(this.extensions);
|
||||
// The root component extension must be last
|
||||
Map<String, Object> rootComponentConfig = orderedExtensions.remove(ROOT_COMPONENT_EXTENSION);
|
||||
orderedExtensions.put(ROOT_COMPONENT_EXTENSION, rootComponentConfig);
|
||||
orderedExtensions.forEach((name, customizations) -> {
|
||||
Map<String, Object> extensionConfig = new LinkedHashMap<>();
|
||||
extensionConfig.put("require", localOverrides.getOrDefault(name, name));
|
||||
if (customizations != null) {
|
||||
extensionConfig.putAll(customizations);
|
||||
}
|
||||
config.add(extensionConfig);
|
||||
});
|
||||
return List.copyOf(config);
|
||||
}
|
||||
|
||||
abstract class Customizer {
|
||||
|
||||
private final String name;
|
||||
|
||||
Customizer(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
protected void customize(String key, Object value) {
|
||||
AntoraExtensionsConfiguration.this.extensions.computeIfAbsent(this.name, (name) -> new TreeMap<>())
|
||||
.put(key, value);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Xref extends Customizer {
|
||||
|
||||
Xref() {
|
||||
super("@springio/antora-xref-extension");
|
||||
}
|
||||
|
||||
void stub(List<String> stub) {
|
||||
if (stub != null && !stub.isEmpty()) {
|
||||
customize("stub", stub);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ZipContentsCollector extends Customizer {
|
||||
|
||||
ZipContentsCollector() {
|
||||
super("@springio/antora-zip-contents-collector-extension");
|
||||
}
|
||||
|
||||
void versionFile(String versionFile) {
|
||||
customize("version_file", versionFile);
|
||||
}
|
||||
|
||||
void locations(Path... locations) {
|
||||
locations(Arrays.stream(locations).map(Path::toString).toList());
|
||||
}
|
||||
|
||||
private void locations(List<String> locations) {
|
||||
customize("locations", locations);
|
||||
}
|
||||
|
||||
void alwaysInclude(Map<String, String> alwaysInclude) {
|
||||
if (alwaysInclude != null && !alwaysInclude.isEmpty()) {
|
||||
customize("always_include", List.of(new TreeMap<>(alwaysInclude)));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class RootComponent extends Customizer {
|
||||
|
||||
RootComponent() {
|
||||
super(ROOT_COMPONENT_EXTENSION);
|
||||
}
|
||||
|
||||
void name(String name) {
|
||||
customize("root_component_name", name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,209 @@
|
|||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build.antora;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.ProjectDependency;
|
||||
import org.gradle.api.file.RegularFileProperty;
|
||||
import org.gradle.api.provider.ListProperty;
|
||||
import org.gradle.api.provider.MapProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.Optional;
|
||||
import org.gradle.api.tasks.OutputFile;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.yaml.snakeyaml.DumperOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
|
||||
/**
|
||||
* Task to generate a local Antora playbook.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public abstract class GenerateAntoraPlaybook extends DefaultTask {
|
||||
|
||||
private static final String ANTORA_SOURCE_DIR = "src/docs/antora";
|
||||
|
||||
private static final String GENERATED_DOCS = "build/generated/docs/";
|
||||
|
||||
@OutputFile
|
||||
public abstract RegularFileProperty getOutputFile();
|
||||
|
||||
@Input
|
||||
public abstract Property<String> getContentSourceConfiguration();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public abstract ListProperty<String> getXrefStubs();
|
||||
|
||||
@Input
|
||||
@Optional
|
||||
public abstract MapProperty<String, String> getAlwaysInclude();
|
||||
|
||||
public GenerateAntoraPlaybook() {
|
||||
setGroup("Documentation");
|
||||
setDescription("Generates an Antora playbook.yml file for local use");
|
||||
getOutputFile().convention(getProject().getLayout()
|
||||
.getBuildDirectory()
|
||||
.file("generated/docs/antora-playbook/antora-playbook.yml"));
|
||||
getContentSourceConfiguration().convention("antoraContent");
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
public void writePlaybookYml() throws IOException {
|
||||
File file = getOutputFile().get().getAsFile();
|
||||
file.getParentFile().mkdirs();
|
||||
try (FileWriter out = new FileWriter(file)) {
|
||||
createYaml().dump(getData(), out);
|
||||
}
|
||||
}
|
||||
|
||||
@Input
|
||||
final Map<String, Object> getData() throws IOException {
|
||||
Map<String, Object> data = loadPlaybookTemplate();
|
||||
addExtensions(data);
|
||||
addSources(data);
|
||||
addDir(data);
|
||||
return data;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Map<String, Object> loadPlaybookTemplate() throws IOException {
|
||||
try (InputStream resource = getClass().getResourceAsStream("antora-playbook-template.yml")) {
|
||||
return createYaml().loadAs(resource, LinkedHashMap.class);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void addExtensions(Map<String, Object> data) {
|
||||
Map<String, Object> antora = (Map<String, Object>) data.get("antora");
|
||||
antora.put("extensions", Extensions.antora((extensions) -> {
|
||||
extensions.xref((xref) -> xref.stub(getXrefStubs().getOrElse(Collections.emptyList())));
|
||||
extensions.zipContentsCollector((zipContentsCollector) -> {
|
||||
zipContentsCollector.versionFile("gradle.properties");
|
||||
String locationName = getProject().getName() + "-${version}-${name}-${classifier}.zip";
|
||||
Path antoraContent = getRelativeProjectPath()
|
||||
.resolve(GENERATED_DOCS + "antora-content/" + locationName);
|
||||
Path antoraDepenencies = getRelativeProjectPath()
|
||||
.resolve(GENERATED_DOCS + "antora-dependencies-content/" + locationName);
|
||||
zipContentsCollector.locations(antoraContent, antoraDepenencies);
|
||||
zipContentsCollector.alwaysInclude(getAlwaysInclude().getOrNull());
|
||||
});
|
||||
extensions.rootComponent((rootComponent) -> rootComponent.name("spring-boot"));
|
||||
}));
|
||||
Map<String, Object> asciidoc = (Map<String, Object>) data.get("asciidoc");
|
||||
asciidoc.put("extensions", Extensions.asciidoc());
|
||||
}
|
||||
|
||||
private void addSources(Map<String, Object> data) {
|
||||
List<Map<String, Object>> contentSources = getList(data, "content.sources");
|
||||
contentSources.add(createContentSource());
|
||||
}
|
||||
|
||||
private Map<String, Object> createContentSource() {
|
||||
Map<String, Object> source = new LinkedHashMap<>();
|
||||
Path playbookPath = getOutputFile().get().getAsFile().toPath().getParent();
|
||||
Path antoraSrc = getProjectPath(getProject()).resolve(ANTORA_SOURCE_DIR);
|
||||
StringBuilder url = new StringBuilder(".");
|
||||
relativizeFromRootProject(playbookPath).normalize().forEach((path) -> url.append("/.."));
|
||||
source.put("url", url.toString());
|
||||
source.put("branches", "HEAD");
|
||||
source.put("version", getProject().getVersion().toString());
|
||||
Set<String> startPaths = new LinkedHashSet<>();
|
||||
addAntoraContentStartPaths(startPaths);
|
||||
startPaths.add(relativizeFromRootProject(antoraSrc).toString());
|
||||
source.put("start_paths", startPaths.stream().toList());
|
||||
return source;
|
||||
}
|
||||
|
||||
private void addAntoraContentStartPaths(Set<String> startPaths) {
|
||||
Configuration configuration = getProject().getConfigurations().findByName("antoraContent");
|
||||
if (configuration != null) {
|
||||
for (ProjectDependency dependency : configuration.getAllDependencies().withType(ProjectDependency.class)) {
|
||||
Path path = dependency.getDependencyProject().getProjectDir().toPath();
|
||||
startPaths.add(relativizeFromRootProject(path).resolve(ANTORA_SOURCE_DIR).toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addDir(Map<String, Object> data) {
|
||||
Path playbookDir = toRealPath(getOutputFile().get().getAsFile().toPath()).getParent();
|
||||
Path outputDir = toRealPath(getProject().getBuildDir().toPath().resolve("site"));
|
||||
data.put("output", Map.of("dir", "./" + playbookDir.relativize(outputDir).toString()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> List<T> getList(Map<String, Object> data, String location) {
|
||||
return (List<T>) get(data, location);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Object get(Map<String, Object> data, String location) {
|
||||
Object result = data;
|
||||
String[] keys = location.split("\\.");
|
||||
for (String key : keys) {
|
||||
result = ((Map<String, Object>) result).get(key);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Yaml createYaml() {
|
||||
DumperOptions options = new DumperOptions();
|
||||
options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
|
||||
options.setPrettyFlow(true);
|
||||
return new Yaml(options);
|
||||
}
|
||||
|
||||
private Path getRelativeProjectPath() {
|
||||
return relativizeFromRootProject(getProjectPath(getProject()));
|
||||
}
|
||||
|
||||
private Path relativizeFromRootProject(Path subPath) {
|
||||
Path rootProjectPath = getProjectPath(getProject().getRootProject());
|
||||
return rootProjectPath.relativize(subPath).normalize();
|
||||
}
|
||||
|
||||
private Path getProjectPath(Project project) {
|
||||
return toRealPath(project.getProjectDir().toPath());
|
||||
}
|
||||
|
||||
private Path toRealPath(Path path) {
|
||||
try {
|
||||
return Files.exists(path) ? path.toRealPath() : path;
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new UncheckedIOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -26,24 +26,18 @@ import org.gradle.api.Project;
|
|||
*/
|
||||
public final class ArtifactRelease {
|
||||
|
||||
private static final String SNAPSHOT = "snapshot";
|
||||
|
||||
private static final String MILESTONE = "milestone";
|
||||
|
||||
private static final String RELEASE = "release";
|
||||
|
||||
private static final String SPRING_REPO = "https://repo.spring.io/%s";
|
||||
|
||||
private static final String MAVEN_REPO = "https://repo.maven.apache.org/maven2";
|
||||
|
||||
private final String type;
|
||||
private final Type type;
|
||||
|
||||
private ArtifactRelease(String type) {
|
||||
private ArtifactRelease(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return this.type;
|
||||
return this.type.toString().toLowerCase();
|
||||
}
|
||||
|
||||
public String getDownloadRepo() {
|
||||
|
@ -51,24 +45,34 @@ public final class ArtifactRelease {
|
|||
}
|
||||
|
||||
public boolean isRelease() {
|
||||
return RELEASE.equals(this.type);
|
||||
return this.type == Type.RELEASE;
|
||||
}
|
||||
|
||||
public static ArtifactRelease forProject(Project project) {
|
||||
return new ArtifactRelease(determineReleaseType(project));
|
||||
return forVersion(project.getVersion().toString());
|
||||
}
|
||||
|
||||
private static String determineReleaseType(Project project) {
|
||||
String version = project.getVersion().toString();
|
||||
int modifierIndex = version.lastIndexOf('-');
|
||||
if (modifierIndex == -1) {
|
||||
return RELEASE;
|
||||
public static ArtifactRelease forVersion(String version) {
|
||||
return new ArtifactRelease(Type.forVersion(version));
|
||||
}
|
||||
|
||||
enum Type {
|
||||
|
||||
SNAPSHOT, MILESTONE, RELEASE;
|
||||
|
||||
static Type forVersion(String version) {
|
||||
int modifierIndex = version.lastIndexOf('-');
|
||||
if (modifierIndex == -1) {
|
||||
return RELEASE;
|
||||
}
|
||||
String type = version.substring(modifierIndex + 1);
|
||||
if (type.startsWith("M") || type.startsWith("RC")) {
|
||||
return MILESTONE;
|
||||
}
|
||||
return SNAPSHOT;
|
||||
|
||||
}
|
||||
String type = version.substring(modifierIndex + 1);
|
||||
if (type.startsWith("M") || type.startsWith("RC")) {
|
||||
return MILESTONE;
|
||||
}
|
||||
return SNAPSHOT;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -89,9 +89,9 @@ public class DocumentAutoConfigurationClasses extends DefaultTask {
|
|||
|
||||
for (AutoConfigurationClass autoConfigurationClass : autoConfigurationClasses.classes) {
|
||||
writer.println();
|
||||
writer.printf("| {spring-boot-code}/spring-boot-project/%s/src/main/java/%s.java[`%s`]%n",
|
||||
writer.printf("| {code-spring-boot}/spring-boot-project/%s/src/main/java/%s.java[`%s`]%n",
|
||||
autoConfigurationClasses.module, autoConfigurationClass.path, autoConfigurationClass.name);
|
||||
writer.printf("| {spring-boot-api}/%s.html[javadoc]%n", autoConfigurationClass.path);
|
||||
writer.printf("| xref:api:java/%s.html[javadoc]%n", autoConfigurationClass.path);
|
||||
}
|
||||
|
||||
writer.println("|===");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -29,6 +29,7 @@ import org.gradle.api.DefaultTask;
|
|||
import org.gradle.api.Task;
|
||||
import org.gradle.api.artifacts.ComponentMetadataDetails;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.artifacts.DependencyConstraint;
|
||||
import org.gradle.api.artifacts.DependencyConstraintMetadata;
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler;
|
||||
|
@ -64,10 +65,9 @@ public class ExtractVersionConstraints extends DefaultTask {
|
|||
}
|
||||
|
||||
public void enforcedPlatform(String projectPath) {
|
||||
this.configuration.getDependencies()
|
||||
.add(getProject().getDependencies()
|
||||
.enforcedPlatform(
|
||||
getProject().getDependencies().project(Collections.singletonMap("path", projectPath))));
|
||||
Dependency project = getProject().getDependencies().project(Map.of("path", projectPath));
|
||||
Dependency dependency = getProject().getDependencies().enforcedPlatform(project);
|
||||
this.configuration.getDependencies().add(dependency);
|
||||
this.projectPaths.add(projectPath);
|
||||
}
|
||||
|
||||
|
@ -104,9 +104,8 @@ public class ExtractVersionConstraints extends DefaultTask {
|
|||
}
|
||||
|
||||
private void extractVersionProperties(String projectPath) {
|
||||
Object bom = getProject().project(projectPath).getExtensions().getByName("bom");
|
||||
BomExtension bomExtension = (BomExtension) bom;
|
||||
for (Library lib : bomExtension.getLibraries()) {
|
||||
BomExtension bom = (BomExtension) getProject().project(projectPath).getExtensions().getByName("bom");
|
||||
for (Library lib : bom.getLibraries()) {
|
||||
String versionProperty = lib.getVersionProperty();
|
||||
if (versionProperty != null) {
|
||||
this.versionProperties.add(new VersionProperty(lib.getName(), versionProperty));
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -102,11 +102,7 @@ class Snippets {
|
|||
|
||||
private void writeAsciidoc(Path outputDirectory, Snippet snippet, Asciidoc asciidoc) throws IOException {
|
||||
String[] parts = (snippet.getAnchor()).split("\\.");
|
||||
Path path = outputDirectory;
|
||||
for (int i = 0; i < parts.length; i++) {
|
||||
String name = (i < parts.length - 1) ? parts[i] : parts[i] + ".adoc";
|
||||
path = path.resolve(name);
|
||||
}
|
||||
Path path = outputDirectory.resolve(parts[parts.length - 1] + ".adoc");
|
||||
createDirectory(path.getParent());
|
||||
Files.deleteIfExists(path);
|
||||
try (OutputStream outputStream = Files.newOutputStream(path)) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -50,7 +50,7 @@ public class DocumentDevtoolsPropertyDefaults extends DefaultTask {
|
|||
this.outputFile = getProject().getObjects().fileProperty();
|
||||
this.outputFile.convention(getProject().getLayout()
|
||||
.getBuildDirectory()
|
||||
.file("docs/generated/using/devtools-property-defaults.adoc"));
|
||||
.file("generated/docs/using/devtools-property-defaults.adoc"));
|
||||
Map<String, String> dependency = new HashMap<>();
|
||||
dependency.put("path", ":spring-boot-project:spring-boot-devtools");
|
||||
dependency.put("configuration", "propertyDefaults");
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -92,7 +92,7 @@ public class DocumentPluginGoals extends DefaultTask {
|
|||
writer.println("| Goal | Description");
|
||||
writer.println();
|
||||
for (Mojo mojo : plugin.getMojos()) {
|
||||
writer.printf("| <<%s,%s:%s>>%n", goalSectionId(mojo), plugin.getGoalPrefix(), mojo.getGoal());
|
||||
writer.printf("| xref:%s[%s:%s]%n", goalSectionId(mojo, false), plugin.getGoalPrefix(), mojo.getGoal());
|
||||
writer.printf("| %s%n", mojo.getDescription());
|
||||
writer.println();
|
||||
}
|
||||
|
@ -102,11 +102,9 @@ public class DocumentPluginGoals extends DefaultTask {
|
|||
|
||||
private void documentMojo(Plugin plugin, Mojo mojo) throws IOException {
|
||||
try (PrintWriter writer = new PrintWriter(new FileWriter(new File(this.outputDir, mojo.getGoal() + ".adoc")))) {
|
||||
String sectionId = goalSectionId(mojo);
|
||||
writer.println();
|
||||
writer.println();
|
||||
String sectionId = goalSectionId(mojo, true);
|
||||
writer.printf("[[%s]]%n", sectionId);
|
||||
writer.printf("= `%s:%s`%n", plugin.getGoalPrefix(), mojo.getGoal());
|
||||
writer.printf("= `%s:%s`%n%n", plugin.getGoalPrefix(), mojo.getGoal());
|
||||
writer.printf("`%s:%s:%s`%n", plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion());
|
||||
writer.println();
|
||||
writer.println(mojo.getDescription());
|
||||
|
@ -114,37 +112,43 @@ public class DocumentPluginGoals extends DefaultTask {
|
|||
List<Parameter> requiredParameters = parameters.stream().filter(Parameter::isRequired).toList();
|
||||
String detailsSectionId = sectionId + ".parameter-details";
|
||||
if (!requiredParameters.isEmpty()) {
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.printf("[[%s.required-parameters]]%n", sectionId);
|
||||
writer.println("== Required parameters");
|
||||
writer.println();
|
||||
writeParametersTable(writer, detailsSectionId, requiredParameters);
|
||||
}
|
||||
List<Parameter> optionalParameters = parameters.stream()
|
||||
.filter((parameter) -> !parameter.isRequired())
|
||||
.toList();
|
||||
if (!optionalParameters.isEmpty()) {
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.printf("[[%s.optional-parameters]]%n", sectionId);
|
||||
writer.println("== Optional parameters");
|
||||
writer.println();
|
||||
writeParametersTable(writer, detailsSectionId, optionalParameters);
|
||||
}
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.println();
|
||||
writer.printf("[[%s]]%n", detailsSectionId);
|
||||
writer.println("== Parameter details");
|
||||
writer.println();
|
||||
writeParameterDetails(writer, parameters, detailsSectionId);
|
||||
}
|
||||
}
|
||||
|
||||
private String goalSectionId(Mojo mojo) {
|
||||
private String goalSectionId(Mojo mojo, boolean innerReference) {
|
||||
String goalSection = this.goalSections.get(mojo.getGoal());
|
||||
if (goalSection == null) {
|
||||
throw new IllegalStateException("Goal '" + mojo.getGoal() + "' has not be assigned to a section");
|
||||
}
|
||||
String sectionId = goalSection + "." + mojo.getGoal() + "-goal";
|
||||
return sectionId;
|
||||
return (!innerReference) ? goalSection + "#" + sectionId : sectionId;
|
||||
}
|
||||
|
||||
private void writeParametersTable(PrintWriter writer, String detailsSectionId, List<Parameter> parameters) {
|
||||
|
@ -236,10 +240,10 @@ public class DocumentPluginGoals extends DefaultTask {
|
|||
|
||||
private String typeNameToJavadocLink(String shortName, String name) {
|
||||
if (name.startsWith("org.springframework.boot.maven")) {
|
||||
return "{spring-boot-docs}/maven-plugin/api/" + typeNameToJavadocPath(name) + ".html[" + shortName + "]";
|
||||
return "xref:maven-plugin:api/java/" + typeNameToJavadocPath(name) + ".html[" + shortName + "]";
|
||||
}
|
||||
if (name.startsWith("org.springframework.boot")) {
|
||||
return "{spring-boot-docs}/api/" + typeNameToJavadocPath(name) + ".html[" + shortName + "]";
|
||||
return "xref:api:java/" + typeNameToJavadocPath(name) + ".html[" + shortName + "]";
|
||||
}
|
||||
return shortName;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
@ -158,7 +158,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
|
|||
DocumentPluginGoals task = project.getTasks().create("documentPluginGoals", DocumentPluginGoals.class);
|
||||
File pluginXml = new File(generatePluginDescriptorTask.getOutputs().getFiles().getSingleFile(), "plugin.xml");
|
||||
task.setPluginXml(pluginXml);
|
||||
task.setOutputDir(new File(project.getBuildDir(), "docs/generated/goals/"));
|
||||
task.setOutputDir(new File(project.getBuildDir(), "generated/docs/maven-plugin-goals/"));
|
||||
task.dependsOn(generatePluginDescriptorTask);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
# === INCLUDE-CODE LOCATIONS ===
|
||||
|
||||
include-java=ROOT:example$java/org/springframework/boot/docs
|
||||
include-kotlin= ROOT:example$kotlin/org/springframework/boot/docs
|
||||
|
||||
# === URLs ===
|
||||
|
||||
url-ant-docs=https://ant.apache.org/manual
|
||||
url-buildpacks-docs=https://buildpacks.io/docs
|
||||
url-dynatrace-docs=https://docs.dynatrace.com/docs
|
||||
url-dynatrace-docs-shortlink={url-dynatrace-docs}/shortlink
|
||||
url-github-raw=https://raw.githubusercontent.com/{github-repo}/{github-ref}
|
||||
url-github-issues=https://github.com/{github-repo}/issues
|
||||
url-github-wiki=https://github.com/{github-repo}/wiki
|
||||
url-github=https://github.com/{github-repo}
|
||||
url-graal-docs=https://www.graalvm.org/{version-graal}/reference-manual
|
||||
url-graal-docs-native-image={url-graal-docs}/native-image
|
||||
url-gradle-docs=https://docs.gradle.org/current/userguide
|
||||
url-gradle-docs-application-plugin={url-gradle-docs}/application_plugin.html
|
||||
url-gradle-docs-groovy-plugin={url-gradle-docs}/groovy_plugin.html
|
||||
url-gradle-docs-java-plugin={url-gradle-docs}/java_plugin.html
|
||||
url-gradle-docs-war-plugin={url-gradle-docs}/war_plugin.html
|
||||
url-gradle-dsl=https://docs.gradle.org/current/dsl
|
||||
url-gradle-javadoc=https://docs.gradle.org/current/javadoc
|
||||
url-kotlin-docs-kotlin-plugin={url-kotlin-docs}/using-gradle.html
|
||||
url-micrometer-docs-concepts={url-micrometer-docs}/concepts
|
||||
url-micrometer-docs-implementations={url-micrometer-docs}/implementations
|
||||
url-download-liberica-nik=https://bell-sw.com/pages/downloads/native-image-kit/#/nik-22-17
|
||||
url-native-build-tools-docs=https://graalvm.github.io/native-build-tools/{version-native-build-tools}
|
||||
url-native-build-tools-docs-gradle-plugin={url-native-build-tools-docs}/gradle-plugin.html
|
||||
url-native-build-tools-docs-maven-plugin={url-native-build-tools-docs}/maven-plugin.html
|
||||
url-paketo-docs=https://paketo.io/docs
|
||||
url-paketo-docs-java-buildpack={url-paketo-docs}/buildpacks/language-family-buildpacks/java
|
||||
url-spring-boot-for-apache-geode-docs=https://docs.spring.io/spring-boot-data-geode-build/2.0.x/reference/html5
|
||||
url-spring-boot-for-apache-geode-site=https://github.com/spring-projects/spring-boot-data-geode
|
||||
url-spring-data-cassandra-site=https://spring.io/projects/spring-data-cassandra
|
||||
url-spring-data-commons-javadoc=https://docs.spring.io/spring-data/commons/docs/{version-spring-data-commons}/api
|
||||
url-spring-data-couchbase-docs=https://docs.spring.io/spring-data/couchbase/reference/{version-spring-data-couchbase}
|
||||
url-spring-data-couchbase-site=https://spring.io/projects/spring-data-couchbase
|
||||
url-spring-data-elasticsearch-docs=https://docs.spring.io/spring-data/elasticsearch/reference/{version-spring-data-elasticsearch}
|
||||
url-spring-data-elasticsearch-site=https://spring.io/projects/spring-data-elasticsearch
|
||||
url-spring-data-envers-site=https://spring.io/projects/spring-data-envers
|
||||
url-spring-data-gemfire-site=https://spring.io/projects/spring-data-gemfire
|
||||
url-spring-data-geode-site=https://spring.io/projects/spring-data-geode
|
||||
url-spring-data-jdbc-docs=https://docs.spring.io/spring-data/relational/reference/{version-spring-data-jdbc}
|
||||
url-spring-data-jpa-javadoc=https://docs.spring.io/spring-data/jpa/docs/{version-spring-data-jpa}/api
|
||||
url-spring-data-jpa-site=https://spring.io/projects/spring-jpa
|
||||
url-spring-data-jpa-docs=https://docs.spring.io/spring-data/jpa/reference/{version-spring-data-jpa}
|
||||
url-spring-data-ldap-site=https://spring.io/projects/spring-data-ldap
|
||||
url-spring-data-mongodb-javadoc=https://docs.spring.io/spring-data/mongodb/docs/{version-spring-data-mongodb}/api
|
||||
url-spring-data-mongodb-site=https://spring.io/projects/spring-data-mongodb
|
||||
url-spring-data-mongodb-docs=https://docs.spring.io/spring-data/mongodb/reference/{version-spring-data-mongodb}
|
||||
url-spring-data-neo4j-docs=https://docs.spring.io/spring-data/neo4j/reference/{version-spring-data-neo4j}
|
||||
url-spring-data-neo4j-site=https://spring.io/projects/spring-data-neo4j
|
||||
url-spring-data-r2dbc-javadoc=https://docs.spring.io/spring-data/r2dbc/docs/{version-spring-data-r2dbc}/api
|
||||
url-spring-data-r2dbc-docs=https://docs.spring.io/spring-data/relational/reference/{version-spring-data-r2dbc}
|
||||
url-spring-data-redis-site=https://spring.io/projects/spring-data-redis
|
||||
url-spring-data-rest-javadoc=https://docs.spring.io/spring-data/rest/docs/{version-spring-data-rest}/api
|
||||
url-spring-data-site=https://spring.io/projects/spring-data
|
||||
|
||||
# === API References ===
|
||||
|
||||
apiref-gradle-plugin-boot-build-image=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/bundling/BootBuildImage.html
|
||||
apiref-gradle-plugin-boot-jar=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/bundling/BootJar.html
|
||||
apiref-gradle-plugin-boot-run=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/run/BootRun.html
|
||||
apiref-gradle-plugin-boot-war=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/bundling/BootWar.html
|
||||
apiref-gradle-plugin-boot-build-info=xref:gradle-plugin:api/java/org/springframework/boot/gradle/tasks/buildinfo/BuildInfo.html
|
||||
apiref-openjdk=https://docs.oracle.com/en/java/javase/17/docs/api
|
||||
|
||||
# === Code Links ===
|
||||
|
||||
code-spring-boot=https://github.com/{github-repo}/tree/{github-ref}
|
||||
code-spring-boot-src={code-spring-boot}/spring-boot-project/spring-boot/src/main/java/org/springframework/boot
|
||||
code-spring-boot-actuator-autoconfigure-src={code-spring-boot}/spring-boot-project/spring-boot-actuator-autoconfigure/src/main/java/org/springframework/boot/actuate/autoconfigure
|
||||
code-spring-boot-actuator-src={code-spring-boot}/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate
|
||||
code-spring-boot-autoconfigure-src={code-spring-boot}/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure
|
||||
code-spring-boot-devtools-src={code-spring-boot}/spring-boot-project/spring-boot-devtools/src/main/java/org/springframework/boot/devtools
|
||||
code-spring-boot-test-autoconfigure-src={code-spring-boot}/spring-boot-project/spring-boot-test-autoconfigure/src/main/java/org/springframework/boot/test/autoconfigure
|
||||
code-spring-boot-latest=https://github.com/{github-repo}/tree/main
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
antora:
|
||||
extensions:
|
||||
site:
|
||||
title: Spring Boot
|
||||
content:
|
||||
sources: []
|
||||
asciidoc:
|
||||
sourcemap: true
|
||||
attributes:
|
||||
chomp: all
|
||||
hide-uri-scheme: '@'
|
||||
page-pagination: ''
|
||||
page-stackoverflow-url: https://stackoverflow.com/tags/spring-boot
|
||||
tabs-sync-option: '@'
|
||||
extensions:
|
||||
- '@asciidoctor/tabs'
|
||||
- '@springio/asciidoctor-extensions'
|
||||
- '@springio/asciidoctor-extensions/configuration-properties-extension'
|
||||
- '@springio/asciidoctor-extensions/section-ids-extension'
|
||||
urls:
|
||||
latest_version_segment: ''
|
||||
runtime:
|
||||
log:
|
||||
failure_level: warn
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.11/ui-bundle.zip
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build.antora;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.build.bom.Library;
|
||||
import org.springframework.boot.build.bom.Library.Group;
|
||||
import org.springframework.boot.build.bom.Library.LibraryVersion;
|
||||
import org.springframework.boot.build.bom.Library.ProhibitedVersion;
|
||||
import org.springframework.boot.build.bom.Library.VersionAlignment;
|
||||
import org.springframework.boot.build.bom.bomr.version.DependencyVersion;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link AntoraAsciidocAttributes}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class AntoraAsciidocAttributesTests {
|
||||
|
||||
@Test
|
||||
void githubRefWhenReleasedVersionIsTag() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("github-ref", "v1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void githubRefWhenLatestSnapshotVersionIsMainBranch() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3-SNAPSHOT", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("github-ref", "main");
|
||||
}
|
||||
|
||||
@Test
|
||||
void githubRefWhenOlderSnapshotVersionIsBranch() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3-SNAPSHOT", false, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("github-ref", "1.2.x");
|
||||
}
|
||||
|
||||
@Test
|
||||
void githubRefWhenOlderSnapshotHotFixVersionIsBranch() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3.1-SNAPSHOT", false, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("github-ref", "1.2.3.x");
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionReferenceFromLibrary() {
|
||||
Library library = mockLibrary(Collections.emptyMap());
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3.1-SNAPSHOT", false, List.of(library),
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("version-spring-framework", "1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionReferenceFromSpringDataDependencyVersion() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("version-spring-data-mongodb", "1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void versionNativeBuildTools() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3", true, null,
|
||||
mockDependencyVersions(), Map.of("nativeBuildToolsVersion", "3.4.5"));
|
||||
assertThat(attributes.get()).containsEntry("version-native-build-tools", "3.4.5");
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlArtifactReposiroryWhenRelease() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("url-artifact-repository", "https://repo.maven.apache.org/maven2");
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlArtifactReposiroryWhenMilestone() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3-M1", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("url-artifact-repository", "https://repo.spring.io/milestone");
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlArtifactReposiroryWhenSnapshot() {
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3-SNAPSHOT", true, null,
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("url-artifact-repository", "https://repo.spring.io/snapshot");
|
||||
}
|
||||
|
||||
@Test
|
||||
void urlLinksFromLibrary() {
|
||||
Map<String, Function<LibraryVersion, String>> links = new LinkedHashMap<>();
|
||||
links.put("site", (version) -> "https://example.com/site/" + version);
|
||||
links.put("docs", (version) -> "https://example.com/docs/" + version);
|
||||
Library library = mockLibrary(links);
|
||||
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes("1.2.3.1-SNAPSHOT", false, List.of(library),
|
||||
mockDependencyVersions(), null);
|
||||
assertThat(attributes.get()).containsEntry("url-spring-framework-site", "https://example.com/site/1.2.3")
|
||||
.containsEntry("url-spring-framework-docs", "https://example.com/docs/1.2.3");
|
||||
}
|
||||
|
||||
@Test
|
||||
void linksFromProperties() {
|
||||
Map<String, String> attributes = new AntoraAsciidocAttributes("1.2.3-SNAPSHOT", true, null,
|
||||
mockDependencyVersions(), null)
|
||||
.get();
|
||||
assertThat(attributes).containsEntry("include-java", "ROOT:example$java/org/springframework/boot/docs");
|
||||
assertThat(attributes).containsEntry("url-spring-data-cassandra-site",
|
||||
"https://spring.io/projects/spring-data-cassandra");
|
||||
List<String> keys = new ArrayList<>(attributes.keySet());
|
||||
assertThat(keys.indexOf("include-java")).isLessThan(keys.indexOf("code-spring-boot-latest"));
|
||||
}
|
||||
|
||||
private Library mockLibrary(Map<String, Function<LibraryVersion, String>> links) {
|
||||
String name = "Spring Framework";
|
||||
String calendarName = null;
|
||||
LibraryVersion version = new LibraryVersion(DependencyVersion.parse("1.2.3"));
|
||||
List<Group> groups = Collections.emptyList();
|
||||
List<ProhibitedVersion> prohibitedVersion = Collections.emptyList();
|
||||
boolean considerSnapshots = false;
|
||||
VersionAlignment versionAlignment = null;
|
||||
String linkRootName = null;
|
||||
Library library = new Library(name, calendarName, version, groups, prohibitedVersion, considerSnapshots,
|
||||
versionAlignment, linkRootName, links);
|
||||
return library;
|
||||
}
|
||||
|
||||
private Map<String, String> mockDependencyVersions() {
|
||||
Map<String, String> versions = new LinkedHashMap<>();
|
||||
addMockSpringDataVersion(versions, "spring-data-commons");
|
||||
addMockSpringDataVersion(versions, "spring-data-couchbase");
|
||||
addMockSpringDataVersion(versions, "spring-data-elasticsearch");
|
||||
addMockSpringDataVersion(versions, "spring-data-jdbc");
|
||||
addMockSpringDataVersion(versions, "spring-data-jpa");
|
||||
addMockSpringDataVersion(versions, "spring-data-mongodb");
|
||||
addMockSpringDataVersion(versions, "spring-data-neo4j");
|
||||
addMockSpringDataVersion(versions, "spring-data-r2dbc");
|
||||
addMockSpringDataVersion(versions, "spring-data-rest-core");
|
||||
return versions;
|
||||
}
|
||||
|
||||
private void addMockSpringDataVersion(Map<String, String> versions, String artifactId) {
|
||||
versions.put("org.springframework.data:" + artifactId, "1.2.3");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.build.antora;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gradle.api.Project;
|
||||
import org.gradle.testfixtures.ProjectBuilder;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import org.springframework.util.function.ThrowingConsumer;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link GenerateAntoraPlaybook}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class GenerateAntoraPlaybookTests {
|
||||
|
||||
@TempDir
|
||||
File temp;
|
||||
|
||||
@Test
|
||||
void writePlaybookGeneratesExpectedContent() throws Exception {
|
||||
writePlaybookYml((task) -> {
|
||||
task.getXrefStubs().addAll("appendix:.*", "api:.*", "reference:.*");
|
||||
task.getAlwaysInclude().set(Map.of("name", "test", "classifier", "local-aggregate-content"));
|
||||
});
|
||||
Path actual = this.temp.toPath()
|
||||
.resolve("rootproject/project/build/generated/docs/antora-playbook/antora-playbook.yml");
|
||||
System.out.println(Files.readString(actual));
|
||||
assertThat(actual).hasSameTextualContentAs(
|
||||
Path.of("src/test/resources/org/springframework/boot/build/antora/expected-playbook.yml"));
|
||||
}
|
||||
|
||||
private void writePlaybookYml(ThrowingConsumer<GenerateAntoraPlaybook> customizer) throws Exception {
|
||||
File rootProjectDir = new File(this.temp, "rootproject").getCanonicalFile();
|
||||
rootProjectDir.mkdirs();
|
||||
Project rootProject = ProjectBuilder.builder().withProjectDir(rootProjectDir).build();
|
||||
File projectDir = new File(rootProjectDir, "project");
|
||||
projectDir.mkdirs();
|
||||
Project project = ProjectBuilder.builder().withProjectDir(projectDir).withParent(rootProject).build();
|
||||
GenerateAntoraPlaybook task = project.getTasks().create("generateAntoraPlaybook", GenerateAntoraPlaybook.class);
|
||||
customizer.accept(task);
|
||||
task.writePlaybookYml();
|
||||
}
|
||||
|
||||
}
|
|
@ -153,7 +153,6 @@ class ArchitectureCheckTests {
|
|||
Resource root = resolver.getResource("classpath:org/springframework/boot/build/architecture/" + name);
|
||||
FileSystemUtils.copyRecursively(root.getFile(),
|
||||
new File(projectDir, "classes/org/springframework/boot/build/architecture/" + name));
|
||||
|
||||
}
|
||||
|
||||
private interface Callback<T> {
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
antora:
|
||||
extensions:
|
||||
- require: '@springio/antora-extensions/static-page-extension'
|
||||
- require: '@springio/antora-xref-extension'
|
||||
stub:
|
||||
- appendix:.*
|
||||
- api:.*
|
||||
- reference:.*
|
||||
- require: '@springio/antora-zip-contents-collector-extension'
|
||||
always_include:
|
||||
- classifier: local-aggregate-content
|
||||
name: test
|
||||
locations:
|
||||
- project/build/generated/docs/antora-content/test-${version}-${name}-${classifier}.zip
|
||||
- project/build/generated/docs/antora-dependencies-content/test-${version}-${name}-${classifier}.zip
|
||||
version_file: gradle.properties
|
||||
- require: '@springio/antora-extensions/root-component-extension'
|
||||
root_component_name: spring-boot
|
||||
site:
|
||||
title: Spring Boot
|
||||
content:
|
||||
sources:
|
||||
- url: ./../../../../..
|
||||
branches: HEAD
|
||||
version: unspecified
|
||||
start_paths:
|
||||
- project/src/docs/antora
|
||||
asciidoc:
|
||||
sourcemap: true
|
||||
attributes:
|
||||
chomp: all
|
||||
hide-uri-scheme: '@'
|
||||
page-pagination: ''
|
||||
page-stackoverflow-url: https://stackoverflow.com/tags/spring-boot
|
||||
tabs-sync-option: '@'
|
||||
extensions:
|
||||
- '@asciidoctor/tabs'
|
||||
- '@springio/asciidoctor-extensions'
|
||||
- '@springio/asciidoctor-extensions/configuration-properties-extension'
|
||||
- '@springio/asciidoctor-extensions/section-ids-extension'
|
||||
urls:
|
||||
latest_version_segment: ''
|
||||
runtime:
|
||||
log:
|
||||
failure_level: warn
|
||||
ui:
|
||||
bundle:
|
||||
url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.4.11/ui-bundle.zip
|
||||
output:
|
||||
dir: ./../../../site
|
|
@ -1,4 +1,5 @@
|
|||
version=3.3.0-SNAPSHOT
|
||||
latestVersion=true
|
||||
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
|
@ -6,6 +7,7 @@ org.gradle.jvmargs=-Xmx2g -Dfile.encoding=UTF-8
|
|||
|
||||
assertjVersion=3.25.3
|
||||
commonsCodecVersion=1.16.1
|
||||
graalVersion=22.3
|
||||
hamcrestVersion=2.2
|
||||
jacksonVersion=2.17.0
|
||||
junitJupiterVersion=5.10.2
|
||||
|
|
|
@ -194,14 +194,6 @@ bom {
|
|||
]
|
||||
}
|
||||
}
|
||||
library("Spring Asciidoctor Extensions", "0.6.3") {
|
||||
group("io.spring.asciidoctor") {
|
||||
modules = [
|
||||
"spring-asciidoctor-extensions-spring-boot",
|
||||
"spring-asciidoctor-extensions-section-ids"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
Loading…
Reference in New Issue
Block a user