HHH-17047 - Follow up tasks for Gradle 8.2 upgrade

- toolchains
- lazy Task creation
- documentation (documentation/ and release/) tasks
This commit is contained in:
Steve Ebersole 2023-08-10 16:15:57 -05:00 committed by Christian Beikov
parent 3a286fbde8
commit 87eec0a7b8
15 changed files with 257 additions and 66 deletions

View File

@ -584,9 +584,7 @@ tasks.register('renderQL', AsciidoctorTask) {task->
// User Guide ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def generateSettingsDocTask = tasks.named( "generateSettingsDoc" ) {
// dependsOn aggregateJavadocsTask
javadocDirectory = aggregateJavadocsTask.get().destinationDir
settingsDocumentation {
sections {
core {
settingsClassName = "org.hibernate.cfg.AvailableSettings"
@ -603,6 +601,10 @@ def generateSettingsDocTask = tasks.named( "generateSettingsDoc" ) {
}
}
def generateSettingsDocTask = tasks.named( "generateSettingsDoc" ) {
dependsOn aggregateJavadocsTask
}
def renderUserGuideHtmlTask = tasks.register( 'renderUserGuideHtml', AsciidoctorTask ) { task ->
group = "Documentation"
description = 'Renders the User Guides in HTML format using Asciidoctor.'

View File

@ -1,3 +1,7 @@
== List of all available configuration properties
:documentation-project-dir: ../../../..
:root-project-dir: {documentation-project-dir}/..
include::{documentation-project-dir}/target/asciidoc/fragments/config-settings.adoc
[[settings-ref]]
== List of all available configuration settings
include::{documentation-project-dir}/target/asciidoc/fragments/config-settings.adoc[]

View File

@ -26,7 +26,7 @@ public abstract class GenerateDescriptorTask extends DefaultTask {
private final Property<ReleaseFamilyIdentifier> currentlyBuildingFamily;
public GenerateDescriptorTask() {
setGroup( "Release" );
setGroup( "documentation" );
setDescription( "Generates the documentation publication descriptor (JSON)" );
jsonFile = getProject().getObjects().fileProperty();

View File

@ -26,7 +26,7 @@ public abstract class PublishDescriptorTask extends DefaultTask {
private final RegularFileProperty jsonFile;
public PublishDescriptorTask() {
setGroup( "Release" );
setGroup( "documentation" );
setDescription( "Publishes the documentation publication descriptor (JSON)" );
projectVersion = getProject().provider( () -> getProject().getVersion() );

View File

@ -24,7 +24,7 @@ public abstract class PublishMigrationGuide extends DefaultTask {
private final DirectoryProperty migrationGuideDirectory;
public PublishMigrationGuide() {
setGroup( "Release" );
setGroup( "documentation" );
setDescription( "Publishes the migration-guide associated with the current branch. " +
"Intended for incremental publishing of the guide for corrections, etc. without doing a full release. " +
"Note that this is not needed when doing a release as the migration-guide is published as part of that workflow." );

View File

@ -28,7 +28,7 @@ public abstract class PublishTask extends DefaultTask {
private final DirectoryProperty stagingDirectory;
public PublishTask() {
setGroup( "Release" );
setGroup( "documentation" );
setDescription( "Publish documentation to the doc server" );
buildingFamily = getProject().getObjects().property( ReleaseFamilyIdentifier.class );

View File

@ -19,6 +19,9 @@ import java.util.SortedSet;
import org.gradle.api.Project;
import org.gradle.api.file.RegularFile;
/**
* @author Marko Bekhta
*/
public class AsciiDocWriter {
public static final String ANCHOR_BASE = "settings-";
public static final String ANCHOR_START = "[[" + ANCHOR_BASE;
@ -55,7 +58,7 @@ public class AsciiDocWriter {
// write an anchor in the form `[[settings-{moduleName}]]`, e.g. `[[settings-hibernate-core]]`
tryToWriteLine( writer, ANCHOR_START, sourceProject.getName(), "]]" );
tryToWriteLine( writer, "=== ", sourceProject.getDescription() );
tryToWriteLine( writer, "=== ", "(", sourceProject.getName(), ") ", sourceProject.getDescription() );
writer.write( '\n' );
@ -72,6 +75,17 @@ public class AsciiDocWriter {
writer.write( settingDescriptor.getJavadoc() );
writer.write( '\n' );
writer.write(
String.format(
"**See:** %s[%s.%s]\n\n",
settingDescriptor.getJavadocLink(),
Utils.withoutPackagePrefix( settingDescriptor.getSettingsClassName() ),
settingDescriptor.getSettingFieldName()
)
);
writer.write( "'''\n" );
}
writer.write( '\n' );

View File

@ -17,11 +17,22 @@ public class SettingDescriptor {
public static final Comparator<SettingDescriptor> BY_NAME = comparing( SettingDescriptor::getName );
private final String name;
private final String settingsClassName;
private final String settingFieldName;
private final String javadoc;
private final String javadocLink;
public SettingDescriptor(String name, String javadoc) {
public SettingDescriptor(
String name,
String settingsClassName,
String settingFieldName,
String javadoc,
String javadocLink) {
this.name = name;
this.settingsClassName = settingsClassName;
this.settingFieldName = settingFieldName;
this.javadoc = javadoc;
this.javadocLink = javadocLink;
}
/**
@ -37,4 +48,16 @@ public class SettingDescriptor {
public String getJavadoc() {
return javadoc;
}
public String getSettingsClassName() {
return settingsClassName;
}
public String getSettingFieldName() {
return settingFieldName;
}
public String getJavadocLink() {
return javadocLink;
}
}

View File

@ -27,6 +27,9 @@ import org.jsoup.nodes.Node;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;
import static org.hibernate.orm.properties.Utils.packagePrefix;
import static org.hibernate.orm.properties.Utils.withoutPackagePrefix;
/**
* @author Marko Bekhta
* @author Steve Ebersole
@ -42,10 +45,12 @@ public class SettingsCollector {
// Load the constant-values.html file with Jsoup and start processing it
final Document constantValuesJson = loadConstants( javadocDirectory );
final Elements blockLists = constantValuesJson.select( "ul.block-list" );
final Map<String,Map<String, Element>> fieldJavadocsByClass = new HashMap<>();
for ( int bl = 0; bl < blockLists.size(); bl++ ) {
final Element blockList = blockLists.get( bl );
final String className = blockList.selectFirst( "span" ).text();
// find the doc section descriptor defined for this class, if one
final SettingsDocSection docSection = findMatchingDocSection( className, sections );
if ( docSection == null ) {
// does not match any defined sections, skip it
@ -53,7 +58,7 @@ public class SettingsCollector {
}
final SortedSet<SettingDescriptor> docSectionSettings = findSettingDescriptors( docSection, result );
final Map<String, Element> classFieldJavadocs = extractClassFieldJavadocs( className, javadocDirectory );
final Map<String, Element> classFieldJavadocs = extractClassFieldJavadocs( className, javadocDirectory, fieldJavadocsByClass );
final Element tableDiv = blockList.selectFirst( ".summary-table" );
final Elements constantFqnColumns = tableDiv.select( ".col-first" );
@ -85,18 +90,15 @@ public class SettingsCollector {
final SettingDescriptor settingDescriptor = new SettingDescriptor(
stripQuotes( constantValue ),
className,
simpleFieldName,
convertFieldJavadocHtmlToAsciidoc(
fieldJavadocElement,
className,
simpleFieldName,
publishedJavadocsUrl
)
// extractJavadoc(
// settingsClassJavadocJson,
// className,
// withoutPackagePrefix( constantFqn ),
// publishedJavadocsUrl
// )
),
Utils.fieldJavadocLink( publishedJavadocsUrl, className, simpleFieldName )
);
docSectionSettings.add( settingDescriptor );
}
@ -141,8 +143,13 @@ public class SettingsCollector {
private static Map<String, Element> extractClassFieldJavadocs(
String className,
Directory javadocDirectory) {
System.out.println( "Processing Javadoc for " + className );
Directory javadocDirectory,
Map<String, Map<String, Element>> fieldJavadocsByClass) {
final Map<String, Element> existing = fieldJavadocsByClass.get( className );
if ( existing != null ) {
return existing;
}
final Map<String, Element> result = new HashMap<>();
final Document document = loadClassJavadoc( className, javadocDirectory );
@ -455,12 +462,4 @@ public class SettingsCollector {
throw new IllegalStateException( "Unknown node: " + node );
}
}
private static String withoutPackagePrefix(String className) {
return className.substring( className.lastIndexOf( '.' ) + 1 );
}
private static String packagePrefix(String className) {
return className.substring( 0, className.lastIndexOf( '.' ) );
}
}

View File

@ -0,0 +1,94 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.properties;
import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.Project;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.util.internal.ConfigureUtil;
import org.hibernate.orm.env.HibernateVersion;
import groovy.lang.Closure;
/**
* DSL extension for configuring aspects of the settings documentation process
*
* @author Steve Ebersole
*/
public class SettingsDocExtension {
public static final String EXTENSION_NAME = "settingsDocumentation";
private final DirectoryProperty javadocDirectory;
private final Property<String> publishedDocsUrl;
private final NamedDomainObjectContainer<SettingsDocSection> sections;
private final RegularFileProperty outputFile;
@Inject
public SettingsDocExtension(Project project) {
javadocDirectory = project.getObjects().directoryProperty();
publishedDocsUrl = project.getObjects().property( String.class );
sections = project.getObjects().domainObjectContainer( SettingsDocSection.class, SettingsDocSection::create );
outputFile = project.getObjects().fileProperty();
}
/**
* The local directory which contains the Javadoc to be processed.
* <p/>
* Defaults to {@code ${build-dir}/javadocs}
*/
public DirectoryProperty getJavadocDirectory() {
return javadocDirectory;
}
/**
* The base URL for the published doc server. This is used to
* replace local hrefs with hrefs on the doc sever
* <p/>
* Defaults to {@code https://docs.jboss.org/hibernate/orm}
*/
public Property<String> getPublishedDocsUrl() {
return publishedDocsUrl;
}
/**
* Configuration of the sections within the generated document
*/
public NamedDomainObjectContainer<SettingsDocSection> getSections() {
return sections;
}
/**
* @see #getSections()
*/
public void sections(Action<NamedDomainObjectContainer<SettingsDocSection>> action) {
action.execute( getSections() );
}
/**
* @see #getSections()
*/
public void sections(Closure<NamedDomainObjectContainer<SettingsDocSection>> closure) {
ConfigureUtil.configure( closure, getSections() );
}
/**
* The file where the settings doc should be written
* <p/>
* Defaults to {@code ${build-dir}/asciidoc/fragments/config-settings.adoc}
*/
public RegularFileProperty getOutputFile() {
return outputFile;
}
}

View File

@ -15,24 +15,24 @@ import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.IgnoreEmptyDirectories;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.hibernate.orm.ReleaseFamilyIdentifier;
import org.hibernate.orm.env.HibernateVersion;
import static org.hibernate.orm.properties.SettingsDocumentationPlugin.TASK_GROUP_NAME;
/**
* @author Steve Ebersole
*/
public class SettingsDocGeneratorTask extends DefaultTask {
public class SettingsDocGenerationTask extends DefaultTask {
public static final String TASK_NAME = "generateSettingsDoc";
private final HibernateVersion hibernateVersion;
private final DirectoryProperty javadocDirectory;
private final Property<ReleaseFamilyIdentifier> releaseFamily;
private final Property<String> publishedDocsUrl;
private final NamedDomainObjectContainer<SettingsDocSection> sections;
@ -40,23 +40,23 @@ public class SettingsDocGeneratorTask extends DefaultTask {
private final RegularFileProperty outputFile;
@Inject
public SettingsDocGeneratorTask(Project project) {
public SettingsDocGenerationTask(SettingsDocExtension dslExtension, Project project) {
setGroup( TASK_GROUP_NAME );
setDescription( "Collects descriptions of Hibernate configuration properties in preparation for inclusion in the User Guide" );
javadocDirectory = project.getObjects().directoryProperty();
javadocDirectory.convention( project.getLayout().getBuildDirectory().dir( "javadocs" ) );
hibernateVersion = (HibernateVersion) project.getExtensions().getByName( HibernateVersion.EXT_KEY );
getInputs().property( "ormVersion", hibernateVersion );
releaseFamily = project.getObjects().property( ReleaseFamilyIdentifier.class );
releaseFamily.convention( project.provider( () -> ReleaseFamilyIdentifier.parse( project.getVersion().toString() ) ) );
javadocDirectory = project.getObjects().directoryProperty();
javadocDirectory.convention( dslExtension.getJavadocDirectory() );
publishedDocsUrl = project.getObjects().property( String.class );
publishedDocsUrl.convention( "https://docs.jboss.org/hibernate/orm" );
publishedDocsUrl.convention( dslExtension.getPublishedDocsUrl() );
sections = project.getObjects().domainObjectContainer( SettingsDocSection.class, SettingsDocSection::create );
sections = dslExtension.getSections();
outputFile = project.getObjects().fileProperty();
outputFile.convention( project.getLayout().getBuildDirectory().file( "asciidoc/fragments/config-settings.adoc" ) );
outputFile.convention( dslExtension.getOutputFile() );
}
@InputDirectory
@ -65,13 +65,7 @@ public class SettingsDocGeneratorTask extends DefaultTask {
return javadocDirectory;
}
@Input
public Property<ReleaseFamilyIdentifier> getReleaseFamily() {
return releaseFamily;
}
// @Nested
@Internal
@Nested
public NamedDomainObjectContainer<SettingsDocSection> getSections() {
return sections;
}
@ -85,7 +79,7 @@ public class SettingsDocGeneratorTask extends DefaultTask {
public void generateSettingsDocumentation() {
final String publishedJavadocUrl = publishedDocsUrl.get()
+ "/"
+ releaseFamily.get().toExternalForm()
+ hibernateVersion.getFamily()
+ "/javadocs/";
AsciiDocWriter.writeToFile(

View File

@ -8,6 +8,9 @@ package org.hibernate.orm.properties;
import java.util.Comparator;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import static java.util.Comparator.comparing;
/**
@ -38,10 +41,12 @@ public class SettingsDocSection {
this.name = name;
}
@Internal
public String getName() {
return name;
}
@Input
public String getProjectPath() {
return projectPath;
}
@ -50,6 +55,7 @@ public class SettingsDocSection {
this.projectPath = projectPath;
}
@Input
public String getSettingsClassName() {
return settingsClassName;
}

View File

@ -9,6 +9,12 @@ package org.hibernate.orm.properties;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.hibernate.orm.env.EnvironmentProjectPlugin;
import org.hibernate.orm.env.HibernateVersion;
import static org.hibernate.orm.properties.SettingsDocExtension.EXTENSION_NAME;
import static org.hibernate.orm.properties.SettingsDocGenerationTask.TASK_NAME;
/**
* Integrates collection of documentation about Hibernate configuration properties
* from the Javadoc of the project, and generates an Asciidoc document from it
@ -19,6 +25,17 @@ public class SettingsDocumentationPlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
project.getTasks().register( SettingsDocGeneratorTask.TASK_NAME, SettingsDocGeneratorTask.class );
// if not already, so we can access HibernateVersion
project.getPluginManager().apply( EnvironmentProjectPlugin.class );
// create and register the DSL extension
final SettingsDocExtension dslExtension = new SettingsDocExtension( project );
project.getExtensions().add( EXTENSION_NAME, dslExtension );
dslExtension.getJavadocDirectory().convention( project.getLayout().getBuildDirectory().dir( "javadocs" ) );
dslExtension.getPublishedDocsUrl().convention( "https://docs.jboss.org/hibernate/orm" );
dslExtension.getOutputFile().convention( project.getLayout().getBuildDirectory().file( "asciidoc/fragments/config-settings.adoc" ) );
// create the generation task
project.getTasks().register( TASK_NAME, SettingsDocGenerationTask.class, dslExtension, project );
}
}

View File

@ -0,0 +1,28 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html.
*/
package org.hibernate.orm.properties;
import java.io.File;
/**
* @author Steve Ebersole
*/
public class Utils {
public static String fieldJavadocLink(String publishedJavadocsUrl, String className, String simpleFieldName) {
final String packageRelativePath = packagePrefix( className ).replace( ".", File.separator );
final String classRelativePath = packageRelativePath + "/" + withoutPackagePrefix( className ) + ".html";
return publishedJavadocsUrl + classRelativePath + "#" + simpleFieldName;
}
public static String withoutPackagePrefix(String className) {
return className.substring( className.lastIndexOf( '.' ) + 1 );
}
public static String packagePrefix(String className) {
return className.substring( 0, className.lastIndexOf( '.' ) );
}
}

View File

@ -23,7 +23,7 @@ tasks.build.dependsOn.clear()
def stageIntegrationGuideTask = tasks.register( "stageIntegrationGuide", Copy ) {
group "Release"
group "documentation"
description "Stages the Integration Guide as part of preparing for release"
dependsOn ":documentation:renderIntegrationGuides"
@ -32,7 +32,7 @@ def stageIntegrationGuideTask = tasks.register( "stageIntegrationGuide", Copy )
}
def stageQuickstartTask = tasks.register( "stageQuickstart", Copy ) {
group 'Release'
group 'documentation'
description "Stages the Getting Started Guide as part of preparing for release"
dependsOn ':documentation:renderGettingStartedGuides'
@ -41,7 +41,7 @@ def stageQuickstartTask = tasks.register( "stageQuickstart", Copy ) {
}
def stageTopicalGuideTask = tasks.register( "stageTopicalGuide", Copy ) {
group 'Release'
group 'documentation'
description "Stages the Topical Guide as part of preparing for release"
dependsOn ':documentation:renderTopicalGuides'
@ -51,7 +51,7 @@ def stageTopicalGuideTask = tasks.register( "stageTopicalGuide", Copy ) {
}
def stageIntroductionGuideTask = tasks.register( "stageIntroductionGuide", Copy ) {
group 'Release'
group 'documentation'
description "Stages the Introduction Guide as part of preparing for release"
dependsOn ':documentation:renderIntroductionGuides'
@ -60,7 +60,7 @@ def stageIntroductionGuideTask = tasks.register( "stageIntroductionGuide", Copy
}
def stageQueryGuideTasks = tasks.register( "stageQueryGuide", Copy ) {
group 'Release'
group 'documentation'
description "Stages the Query Language Guide as part of preparing for release"
dependsOn ':documentation:renderQueryLanguageGuides'
@ -69,7 +69,7 @@ def stageQueryGuideTasks = tasks.register( "stageQueryGuide", Copy ) {
}
def stageUserGuideTask = tasks.register( "stageUserGuide", Copy ) {
group 'Release'
group 'documentation'
description "Stages the User Guide as part of preparing for release"
dependsOn ':documentation:renderUserGuides'
@ -79,7 +79,7 @@ def stageUserGuideTask = tasks.register( "stageUserGuide", Copy ) {
def stageMigrationGuideTask = tasks.register( "stageMigrationGuide", Copy ) {
group 'Release'
group 'documentation'
description "Stages the Migration Guide as part of preparing for release"
dependsOn ':documentation:renderMigrationGuide'
@ -92,7 +92,7 @@ tasks.named( "publishMigrationGuide" ).configure {
}
def stageIncubationReportTask = tasks.register( "stageIncubationReport", Copy ) { task ->
group 'Release'
group 'documentation'
description "Stages ORM @Incubating report"
dependsOn ':documentation:generateIncubationReport'
@ -103,7 +103,7 @@ def stageIncubationReportTask = tasks.register( "stageIncubationReport", Copy )
}
def stageInternalsReportTask = tasks.register( "stageInternalsReport", Copy ) { task ->
group 'Release'
group 'documentation'
description "Stages the @Internal report"
dependsOn ':documentation:generateInternalsReport'
@ -112,7 +112,7 @@ def stageInternalsReportTask = tasks.register( "stageInternalsReport", Copy ) {
}
def stageDeprecationReportTask = tasks.register( "stageDeprecationReport", Copy ) {
group 'Release'
group 'documentation'
description "Stages the @Deprecated/@Remove report"
dependsOn ':documentation:generateDeprecationReport'
@ -122,7 +122,7 @@ def stageDeprecationReportTask = tasks.register( "stageDeprecationReport", Copy
}
def stageLoggingReportTask = tasks.register( "stageLoggingReport", Copy ) { task ->
group 'Release'
group 'documentation'
description "Stages the logging report"
dependsOn ':documentation:renderLoggingReport'
@ -132,7 +132,7 @@ def stageLoggingReportTask = tasks.register( "stageLoggingReport", Copy ) { task
}
def stageDialectReportTask = tasks.register( "stageDialectReport", Copy ) { task ->
group 'Release'
group 'documentation'
description "Stages the supported Dialects report"
dependsOn ':documentation:renderDialectReport'
@ -141,7 +141,7 @@ def stageDialectReportTask = tasks.register( "stageDialectReport", Copy ) { task
}
def stageOrmReportsTask = tasks.register( "stageOrmReports" ) {
group 'Release'
group 'documentation'
description "Stages all ORM reports as part of preparing for release"
dependsOn ':documentation:generateReports'
@ -152,6 +152,14 @@ def stageOrmReportsTask = tasks.register( "stageOrmReports" ) {
dependsOn stageDialectReportTask
}
def stageJavadocsTask = tasks.register( "stageJavadocs", Copy ) {
group 'documentation'
description "Stages the aggregated Javadocs"
dependsOn ':documentation:aggregateJavadocs'
from project( ":documentation" ).tasks.aggregateJavadocs
into "${buildDir}/documentation/javadocs"
}
/**
* Assembles all documentation into the {buildDir}/documentation directory.
@ -159,11 +167,11 @@ def stageOrmReportsTask = tasks.register( "stageOrmReports" ) {
* Depends on building the docs
*/
def assembleDocumentationTask = tasks.register( "assembleDocumentation" ) {
group 'Release'
group 'documentation'
description 'Assembles all documentation into the {buildDir}/documentation directory'
dependsOn ':documentation:buildDocsForPublishing'
dependsOn aggregateJavadocsTask
dependsOn stageJavadocsTask
dependsOn stageQuickstartTask
dependsOn stageIntroductionGuideTask
dependsOn stageUserGuideTask
@ -175,6 +183,8 @@ def assembleDocumentationTask = tasks.register( "assembleDocumentation" ) {
}
tasks.named( "uploadDocumentation" ) {
group = "documentation"
description = "Uploads assembled documentation to the doc server"
dependsOn assembleDocumentationTask
doFirst {