diff --git a/buildSrc/src/main/groovy/io/spring/gradle/convention/DeployDocsPlugin.groovy b/buildSrc/src/main/groovy/io/spring/gradle/convention/DeployDocsPlugin.groovy index 37d9da4..0aae3ae 100644 --- a/buildSrc/src/main/groovy/io/spring/gradle/convention/DeployDocsPlugin.groovy +++ b/buildSrc/src/main/groovy/io/spring/gradle/convention/DeployDocsPlugin.groovy @@ -31,23 +31,26 @@ class DeployDocsPlugin implements Plugin { 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 { 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 -> diff --git a/buildSrc/src/main/groovy/io/spring/gradle/convention/DocsPlugin.groovy b/buildSrc/src/main/groovy/io/spring/gradle/convention/DocsPlugin.groovy index 9834f10..e7b46c6 100644 --- a/buildSrc/src/main/groovy/io/spring/gradle/convention/DocsPlugin.groovy +++ b/buildSrc/src/main/groovy/io/spring/gradle/convention/DocsPlugin.groovy @@ -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 { 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 } } diff --git a/buildSrc/src/main/groovy/io/spring/gradle/convention/JavadocApiPlugin.groovy b/buildSrc/src/main/groovy/io/spring/gradle/convention/JavadocApiPlugin.groovy index ef864b0..fb6442c 100644 --- a/buildSrc/src/main/groovy/io/spring/gradle/convention/JavadocApiPlugin.groovy +++ b/buildSrc/src/main/groovy/io/spring/gradle/convention/JavadocApiPlugin.groovy @@ -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 { +class JavadocApiPlugin implements Plugin { + Logger logger = LoggerFactory.getLogger(getClass()); + Set 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 { } Set subprojects = rootProject.getSubprojects(); + for (Project subproject : subprojects) { addProject(api, subproject); } @@ -76,7 +73,7 @@ public class JavadocApiPlugin implements Plugin { 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 { } 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() { + @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() { + @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 { }); } } - diff --git a/buildSrc/src/main/java/io/spring/gradle/convention/AsciidoctorConventionPlugin.java b/buildSrc/src/main/java/io/spring/gradle/convention/AsciidoctorConventionPlugin.java index e51383d..754d476 100644 --- a/buildSrc/src/main/java/io/spring/gradle/convention/AsciidoctorConventionPlugin.java +++ b/buildSrc/src/main/java/io/spring/gradle/convention/AsciidoctorConventionPlugin.java @@ -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: * *
    *
  • All warnings are made fatal. - *
  • A task is created to resolve and unzip our documentation resources (CSS and - * Javascript). + *
  • A task is created to resolve and unzip our documentation resources (CSS and Javascript). *
  • For each {@link AsciidoctorTask} (HTML only): *
      *
    • A configuration named asciidoctorExtensions is ued to add the - * block - * switch extension + * block switch extension *
    • {@code doctype} {@link AsciidoctorTask#options(Map) option} is configured. - *
    • {@link AsciidoctorTask#attributes(Map) Attributes} are configured for syntax - * highlighting, CSS styling, docinfo, etc. + *
    • {@link AsciidoctorTask#attributes(Map) Attributes} are configured for syntax highlighting, CSS styling, + * docinfo, etc. *
    *
  • For each {@link AbstractAsciidoctorTask} (HTML and PDF): *
      - *
    • {@link AsciidoctorTask#attributes(Map) Attributes} are configured to enable - * warnings for references to missing attributes, the year is added as @{code today-year}, - * etc - *
    • {@link AbstractAsciidoctorTask#baseDirFollowsSourceDir() baseDirFollowsSourceDir()} - * is enabled. + *
    • {@link AsciidoctorTask#attributes(Map) Attributes} are configured to enable warnings for references to + * missing attributes, the year is added as @{code today-year}, etc + *
    • {@link AbstractAsciidoctorTask#baseDirFollowsSourceDir() baseDirFollowsSourceDir()} is enabled. *
    *
* @@ -74,34 +65,35 @@ import org.gradle.api.tasks.Sync; */ public class AsciidoctorConventionPlugin implements Plugin { + @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() { - @Override - public void execute(CopySpec resourcesSpec) { - resourcesSpec.from(unzipResources); - resourcesSpec.from(asciidoctorTask.getSourceDir(), new Action() { - @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 { } private void createDefaultAsciidoctorRepository(Project project) { - project.getGradle().afterProject(new Action() { - @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() { - @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() { - @Override - public void execute(Sync sync) { - sync.dependsOn(documentationResources); - sync.from(new Callable>() { - @Override - public List call() throws Exception { - List result = new ArrayList<>(); - documentationResources.getAsFileTree().forEach(new Consumer() { - @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 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 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 getAttributes() { - Object version = project.getVersion(); - Map 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 attributes = new HashMap<>(); + attributes.put("attribute-missing", "warn"); attributes.put("icons", "font"); attributes.put("idprefix", ""); @@ -204,6 +153,52 @@ public class AsciidoctorConventionPlugin implements Plugin { attributes.put("sectanchors", ""); attributes.put("sectnums", ""); attributes.put("today-year", LocalDate.now().getYear()); + asciidoctorTask.attributes(attributes); } + + private void configureHtmlOnlyAttributes(Project project, AbstractAsciidoctorTask asciidoctorTask) { + + Map 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 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(".*"); + } }