Refactor and polish build Gradle Plugins.

This commit is contained in:
John Blum
2021-11-30 21:50:04 -08:00
parent 09e8bea7d9
commit d69e316bf9
4 changed files with 155 additions and 162 deletions

View File

@@ -31,23 +31,26 @@ class DeployDocsPlugin implements Plugin<Project> {
project.remotes {
docs {
role 'docs'
if (project.hasProperty('deployDocsHost')) {
host = project.findProperty('deployDocsHost')
} else {
host = 'docs.af.pivotal.io'
}
retryCount = 5 // retry 5 times (default is 0)
retryWaitSec = 10 // wait 10 seconds between retries (default is 0)
role 'docs'
host = project.hasProperty('deployDocsHost')
? project.findProperty('deployDocsHost')
: 'docs-ip.spring.io'
user = project.findProperty('deployDocsSshUsername')
if (project.hasProperty('deployDocsSshKeyPath')) {
identity = project.file(project.findProperty('deployDocsSshKeyPath'))
} else if (project.hasProperty('deployDocsSshKey')) {
identity = project.findProperty('deployDocsSshKey')
}
if(project.hasProperty('deployDocsSshPassphrase')) {
passphrase = project.findProperty('deployDocsSshPassphrase')
}
identity = project.hasProperty('deployDocsSshKeyPath')
? project.file(project.findProperty('deployDocsSshKeyPath'))
: project.hasProperty('deployDocsSshKey')
? project.findProperty('deployDocsSshKey')
: identity
passphrase = project.hasProperty('deployDocsSshPassphrase')
? project.findProperty('deployDocsSshPassphrase')
: passphrase
}
}
@@ -56,10 +59,12 @@ class DeployDocsPlugin implements Plugin<Project> {
doFirst {
project.ssh.run {
session(project.remotes.docs) {
def now = System.currentTimeMillis()
def name = project.rootProject.name
def version = project.rootProject.version
def tempPath = "/tmp/${name}-${now}-docs/".replaceAll(' ', '_')
execute "mkdir -p $tempPath"
project.tasks.docsZip.outputs.each { o ->

View File

@@ -1,10 +1,8 @@
package io.spring.gradle.convention
import org.asciidoctor.gradle.jvm.AbstractAsciidoctorTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.plugins.BasePlugin
import org.gradle.api.plugins.PluginManager
import org.gradle.api.tasks.bundling.Zip
@@ -18,42 +16,34 @@ class DocsPlugin implements Plugin<Project> {
PluginManager pluginManager = project.getPluginManager();
pluginManager.apply(BasePlugin);
pluginManager.apply("org.asciidoctor.jvm.convert");
pluginManager.apply("org.asciidoctor.jvm.pdf");
pluginManager.apply(AsciidoctorConventionPlugin);
pluginManager.apply(DeployDocsPlugin);
pluginManager.apply(JavadocApiPlugin);
project.tasks.withType(AbstractAsciidoctorTask) { t ->
project.configure(t) {
sources {
include "**/*.adoc"
exclude '_*/**'
}
}
}
Task docsZip = project.tasks.create('docsZip', Zip) {
dependsOn 'api', 'asciidoctor'
group = 'Distribution'
archiveBaseName = project.rootProject.name
archiveClassifier = 'docs'
description = "Builds -${classifier} archive containing all " +
"Docs for deployment at docs.spring.io"
group = 'Distribution'
description = "Builds -${archiveClassifier} archive containing all Docs for deployment at docs.spring.io."
dependsOn 'api', 'asciidoctor'
from(project.tasks.api.outputs) {
into 'api'
}
into 'docs'
duplicatesStrategy 'exclude'
}
Task docs = project.tasks.create("docs") {
group = 'Documentation'
description 'An aggregator task to generate all the documentation'
description 'Aggregator Task to generate all documentation.'
dependsOn docsZip
}
project.tasks.assemble.dependsOn docs
}
}

View File

@@ -13,40 +13,36 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
package io.spring.gradle.convention
package io.spring.gradle.convention;
import java.util.regex.Pattern
import java.io.File;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.gradle.api.Action;
import org.gradle.api.Action
import org.gradle.api.JavaVersion
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.javadoc.Javadoc;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPluginConvention
import org.gradle.api.tasks.SourceSet
import org.gradle.api.tasks.javadoc.Javadoc
import org.slf4j.Logger
import org.slf4j.LoggerFactory
/**
* @author Rob Winch
*/
public class JavadocApiPlugin implements Plugin<Project> {
class JavadocApiPlugin implements Plugin<Project> {
Logger logger = LoggerFactory.getLogger(getClass());
Set<Pattern> excludes = Collections.singleton(Pattern.compile("test"));
@Override
public void apply(Project project) {
logger.info("Applied");
Project rootProject = project.getRootProject();
void apply(Project project) {
Project rootProject = project.getRootProject()
//Task docs = project.getTasks().findByPath("docs") ?: project.getTasks().create("docs");
Javadoc api = project.getTasks().create("api", Javadoc);
Javadoc api = project.tasks.create("api", Javadoc)
api.setGroup("Documentation");
api.setDescription("Generates aggregated Javadoc API documentation.");
@@ -62,6 +58,7 @@ public class JavadocApiPlugin implements Plugin<Project> {
}
Set<Project> subprojects = rootProject.getSubprojects();
for (Project subproject : subprojects) {
addProject(api, subproject);
}
@@ -76,7 +73,7 @@ public class JavadocApiPlugin implements Plugin<Project> {
project.getPluginManager().apply("io.spring.convention.javadoc-options");
}
public void setExcludes(String... excludes) {
void setExcludes(String... excludes) {
if(excludes == null) {
this.excludes = Collections.emptySet();
}
@@ -87,25 +84,32 @@ public class JavadocApiPlugin implements Plugin<Project> {
}
private void addProject(final Javadoc api, final Project project) {
for(Pattern exclude : excludes) {
if(exclude.matcher(project.getName()).matches()) {
logger.info("Skipping {} because it is excluded by {}", project, exclude);
return;
}
}
logger.info("Try add sources for {}", project);
project.getPlugins().withType(SpringModulePlugin.class).all(new Action<SpringModulePlugin>() {
@Override
public void execute(SpringModulePlugin plugin) {
void execute(SpringModulePlugin plugin) {
logger.info("Added sources for {}", project);
JavaPluginConvention java = project.getConvention().getPlugin(JavaPluginConvention.class);
SourceSet mainSourceSet = java.getSourceSets().getByName("main");
api.setSource(api.getSource().plus(mainSourceSet.getAllJava()));
project.getTasks().withType(Javadoc.class).all(new Action<Javadoc>() {
@Override
public void execute(Javadoc projectJavadoc) {
void execute(Javadoc projectJavadoc) {
api.setClasspath(api.getClasspath().plus(projectJavadoc.getClasspath()));
}
});
@@ -113,4 +117,3 @@ public class JavadocApiPlugin implements Plugin<Project> {
});
}
}

View File

@@ -13,7 +13,6 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.spring.gradle.convention;
import java.io.File;
@@ -25,47 +24,39 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import org.asciidoctor.gradle.base.AsciidoctorAttributeProvider;
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.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.DependencySet;
import org.gradle.api.artifacts.dsl.RepositoryHandler;
import org.gradle.api.file.CopySpec;
import org.gradle.api.file.FileTree;
import org.gradle.api.tasks.Sync;
/**
* Conventions that are applied in the presence of the {@link AsciidoctorJPlugin}. When
* the plugin is applied:
* Conventions that are applied in the presence of the {@link AsciidoctorJPlugin}.
*
* When the plugin is applied:
*
* <ul>
* <li>All warnings are made fatal.
* <li>A task is created to resolve and unzip our documentation resources (CSS and
* Javascript).
* <li>A task is created to resolve and unzip our documentation resources (CSS and Javascript).
* <li>For each {@link AsciidoctorTask} (HTML only):
* <ul>
* <li>A configuration named asciidoctorExtensions is ued to add the
* <a href="https://github.com/spring-io/spring-asciidoctor-extensions#block-switch">block
* switch</a> extension
* <a href="https://github.com/spring-io/spring-asciidoctor-extensions#block-switch">block switch</a> extension
* <li>{@code doctype} {@link AsciidoctorTask#options(Map) option} is configured.
* <li>{@link AsciidoctorTask#attributes(Map) Attributes} are configured for syntax
* highlighting, CSS styling, docinfo, etc.
* <li>{@link AsciidoctorTask#attributes(Map) Attributes} are configured for syntax highlighting, CSS styling,
* docinfo, etc.
* </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 year is added as @{code today-year},
* etc
* <li>{@link AbstractAsciidoctorTask#baseDirFollowsSourceDir() baseDirFollowsSourceDir()}
* is enabled.
* <li>{@link AsciidoctorTask#attributes(Map) Attributes} are configured to enable warnings for references to
* missing attributes, the year is added as @{code today-year}, etc
* <li>{@link AbstractAsciidoctorTask#baseDirFollowsSourceDir() baseDirFollowsSourceDir()} is enabled.
* </ul>
* </ul>
*
@@ -74,34 +65,35 @@ import org.gradle.api.tasks.Sync;
*/
public class AsciidoctorConventionPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getPlugins().withType(AsciidoctorJPlugin.class, (asciidoctorPlugin) -> {
project.getPlugins().withType(AsciidoctorJPlugin.class, asciidoctorPlugin -> {
createDefaultAsciidoctorRepository(project);
makeAllWarningsFatal(project);
Sync unzipResources = createUnzipDocumentationResourcesTask(project);
project.getTasks().withType(AbstractAsciidoctorTask.class, (asciidoctorTask) -> {
project.getTasks().withType(AbstractAsciidoctorTask.class, asciidoctorTask -> {
asciidoctorTask.dependsOn(unzipResources);
configureExtensions(project, asciidoctorTask);
configureCommonAttributes(project, asciidoctorTask);
configureOptions(asciidoctorTask);
asciidoctorTask.baseDirFollowsSourceDir();
asciidoctorTask.useIntermediateWorkDir();
asciidoctorTask.resources(new Action<CopySpec>() {
@Override
public void execute(CopySpec resourcesSpec) {
resourcesSpec.from(unzipResources);
resourcesSpec.from(asciidoctorTask.getSourceDir(), new Action<CopySpec>() {
@Override
public void execute(CopySpec resourcesSrcDirSpec) {
// https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/523
// For now copy the entire sourceDir over so that include files are
// available in the intermediateWorkDir
// resourcesSrcDirSpec.include("images/**");
}
});
}
asciidoctorTask.resources(resourcesSpec -> {
resourcesSpec.from(unzipResources);
resourcesSpec.from(asciidoctorTask.getSourceDir(), resourcesSrcDirSpec -> {
// https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/523
// For now copy the entire sourceDir over so that include files are
// available in the intermediateWorkDir
// resourcesSrcDirSpec.include("images/**");
});
});
if (asciidoctorTask instanceof AsciidoctorTask) {
configureHtmlOnlyAttributes(project, asciidoctorTask);
}
@@ -110,92 +102,49 @@ public class AsciidoctorConventionPlugin implements Plugin<Project> {
}
private void createDefaultAsciidoctorRepository(Project project) {
project.getGradle().afterProject(new Action<Project>() {
@Override
public void execute(Project project) {
RepositoryHandler repositories = project.getRepositories();
if (repositories.isEmpty()) {
repositories.mavenCentral();
repositories.maven(repo -> {
repo.setUrl(URI.create("https://repo.spring.io/release"));
});
}
project.getGradle().afterProject(it -> {
RepositoryHandler repositories = it.getRepositories();
if (repositories.isEmpty()) {
repositories.mavenCentral();
repositories.maven(repo -> repo.setUrl(URI.create("https://repo.spring.io/release")));
}
});
}
private void makeAllWarningsFatal(Project project) {
project.getExtensions().getByType(AsciidoctorJExtension.class).fatalWarnings(".*");
}
private void configureExtensions(Project project, AbstractAsciidoctorTask asciidoctorTask) {
Configuration extensionsConfiguration = project.getConfigurations().maybeCreate("asciidoctorExtensions");
extensionsConfiguration.defaultDependencies(new Action<DependencySet>() {
@Override
public void execute(DependencySet dependencies) {
dependencies.add(project.getDependencies().create("io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.4.2.RELEASE"));
}
});
asciidoctorTask.configurations(extensionsConfiguration);
}
@SuppressWarnings("all")
private Sync createUnzipDocumentationResourcesTask(Project project) {
Configuration documentationResources = project.getConfigurations().maybeCreate("documentationResources");
documentationResources.getDependencies()
.add(project.getDependencies().create("io.spring.docresources:spring-doc-resources:0.2.5"));
Sync unzipResources = project.getTasks().create("unzipDocumentationResources",
Sync.class, new Action<Sync>() {
@Override
public void execute(Sync sync) {
sync.dependsOn(documentationResources);
sync.from(new Callable<List<FileTree>>() {
@Override
public List<FileTree> call() throws Exception {
List<FileTree> result = new ArrayList<>();
documentationResources.getAsFileTree().forEach(new Consumer<File>() {
@Override
public void accept(File file) {
result.add(project.zipTree(file));
}
});
return result;
}
});
File destination = new File(project.getBuildDir(), "docs/resources");
sync.into(project.relativePath(destination));
}
Sync unzipResources = project.getTasks().create("unzipDocumentationResources", Sync.class, sync -> {
sync.dependsOn(documentationResources);
sync.from((Callable<List<FileTree>>) () -> {
List<FileTree> result = new ArrayList<>();
documentationResources.getAsFileTree().forEach(file -> result.add(project.zipTree(file)));
return result;
});
File destination = new File(project.getBuildDir(), "docs/resources");
sync.into(project.relativePath(destination));
});
return unzipResources;
}
private void configureOptions(AbstractAsciidoctorTask asciidoctorTask) {
asciidoctorTask.options(Collections.singletonMap("doctype", "book"));
}
private void configureHtmlOnlyAttributes(Project project, AbstractAsciidoctorTask asciidoctorTask) {
Map<String, Object> attributes = new HashMap<>();
attributes.put("source-highlighter", "highlight.js");
attributes.put("highlightjsdir", "js/highlight");
attributes.put("highlightjs-theme", "github");
attributes.put("linkcss", true);
attributes.put("icons", "font");
attributes.put("stylesheet", "css/spring.css");
asciidoctorTask.getAttributeProviders().add(new AsciidoctorAttributeProvider() {
@Override
public Map<String, Object> getAttributes() {
Object version = project.getVersion();
Map<String, Object> attrs = new HashMap<>();
if (version != null && version.toString() != Project.DEFAULT_VERSION) {
attrs.put("revnumber", version);
}
return attrs;
}
});
asciidoctorTask.attributes(attributes);
}
private void configureCommonAttributes(Project project, AbstractAsciidoctorTask asciidoctorTask) {
Map<String, Object> attributes = new HashMap<>();
attributes.put("attribute-missing", "warn");
attributes.put("icons", "font");
attributes.put("idprefix", "");
@@ -204,6 +153,52 @@ public class AsciidoctorConventionPlugin implements Plugin<Project> {
attributes.put("sectanchors", "");
attributes.put("sectnums", "");
attributes.put("today-year", LocalDate.now().getYear());
asciidoctorTask.attributes(attributes);
}
private void configureHtmlOnlyAttributes(Project project, AbstractAsciidoctorTask asciidoctorTask) {
Map<String, Object> attributes = new HashMap<>();
attributes.put("source-highlighter", "highlight.js");
attributes.put("highlightjsdir", "js/highlight");
attributes.put("highlightjs-theme", "github");
attributes.put("linkcss", true);
attributes.put("icons", "font");
attributes.put("stylesheet", "css/spring.css");
asciidoctorTask.getAttributeProviders().add(() -> {
Object version = project.getVersion();
Map<String, Object> localAttributes = new HashMap<>();
if (version != null && !Project.DEFAULT_VERSION.equals(version)) {
localAttributes.put("revnumber", version);
}
return localAttributes;
});
asciidoctorTask.attributes(attributes);
}
private void configureExtensions(Project project, AbstractAsciidoctorTask asciidoctorTask) {
Configuration extensionsConfiguration = project.getConfigurations().maybeCreate("asciidoctorExtensions");
extensionsConfiguration.defaultDependencies(dependencies -> dependencies.add(project.getDependencies()
.create("io.spring.asciidoctor:spring-asciidoctor-extensions-block-switch:0.4.2.RELEASE")));
asciidoctorTask.configurations(extensionsConfiguration);
}
private void configureOptions(AbstractAsciidoctorTask asciidoctorTask) {
asciidoctorTask.options(Collections.singletonMap("doctype", "book"));
}
private void makeAllWarningsFatal(Project project) {
project.getExtensions().getByType(AsciidoctorJExtension.class).fatalWarnings(".*");
}
}