Merge branch '3.3.x'

Closes gh-43649 in 3.4.x
Closes gh-43651
This commit is contained in:
Andy Wilkinson 2025-01-02 12:22:59 +00:00
commit 51d15c7c78
54 changed files with 353 additions and 261 deletions

View File

@ -8,7 +8,7 @@ description = "Spring Boot Build"
defaultTasks 'build' defaultTasks 'build'
allprojects { allprojects {
group "org.springframework.boot" group = "org.springframework.boot"
} }
subprojects { subprojects {
@ -18,10 +18,14 @@ subprojects {
mavenCentral() mavenCentral()
spring.mavenRepositories() spring.mavenRepositories()
if (version.contains('-')) { if (version.contains('-')) {
maven { url "https://repo.spring.io/milestone" } maven {
url = "https://repo.spring.io/milestone"
}
} }
if (version.endsWith('-SNAPSHOT')) { if (version.endsWith('-SNAPSHOT')) {
maven { url "https://repo.spring.io/snapshot" } maven {
url = "https://repo.spring.io/snapshot"
}
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2023-2024 the original author or authors. * Copyright 2023-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -41,6 +41,7 @@ import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.provider.Provider; import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Copy; import org.gradle.api.tasks.Copy;
import org.gradle.api.tasks.TaskContainer; import org.gradle.api.tasks.TaskContainer;
import org.gradle.api.tasks.TaskProvider;
import org.springframework.boot.build.antora.AntoraAsciidocAttributes; import org.springframework.boot.build.antora.AntoraAsciidocAttributes;
import org.springframework.boot.build.antora.GenerateAntoraPlaybook; import org.springframework.boot.build.antora.GenerateAntoraPlaybook;
@ -75,16 +76,16 @@ public class AntoraConventions {
} }
private void apply(Project project, AntoraPlugin antoraPlugin) { private void apply(Project project, AntoraPlugin antoraPlugin) {
ExtractVersionConstraints dependencyVersionsTask = addDependencyVersionsTask(project); TaskProvider<ExtractVersionConstraints> dependencyVersionsTask = addDependencyVersionsTask(project);
project.getPlugins().apply(GenerateAntoraYmlPlugin.class); project.getPlugins().apply(GenerateAntoraYmlPlugin.class);
TaskContainer tasks = project.getTasks(); TaskContainer tasks = project.getTasks();
GenerateAntoraPlaybook generateAntoraPlaybookTask = tasks.create(GENERATE_ANTORA_PLAYBOOK_TASK_NAME, TaskProvider<GenerateAntoraPlaybook> generateAntoraPlaybookTask = tasks.register(
GenerateAntoraPlaybook.class); GENERATE_ANTORA_PLAYBOOK_TASK_NAME, GenerateAntoraPlaybook.class,
configureGenerateAntoraPlaybookTask(project, generateAntoraPlaybookTask); (task) -> configureGenerateAntoraPlaybookTask(project, task));
Copy copyAntoraPackageJsonTask = tasks.create("copyAntoraPackageJson", Copy.class); TaskProvider<Copy> copyAntoraPackageJsonTask = tasks.register("copyAntoraPackageJson", Copy.class,
configureCopyAntoraPackageJsonTask(project, copyAntoraPackageJsonTask); (task) -> configureCopyAntoraPackageJsonTask(project, task));
NpmInstallTask npmInstallTask = tasks.create("antoraNpmInstall", NpmInstallTask.class); TaskProvider<NpmInstallTask> npmInstallTask = tasks.register("antoraNpmInstall", NpmInstallTask.class,
configureNpmInstallTask(project, npmInstallTask, copyAntoraPackageJsonTask); (task) -> configureNpmInstallTask(project, task, copyAntoraPackageJsonTask));
tasks.withType(GenerateAntoraYmlTask.class, (generateAntoraYmlTask) -> configureGenerateAntoraYmlTask(project, tasks.withType(GenerateAntoraYmlTask.class, (generateAntoraYmlTask) -> configureGenerateAntoraYmlTask(project,
generateAntoraYmlTask, dependencyVersionsTask)); generateAntoraYmlTask, dependencyVersionsTask));
tasks.withType(AntoraTask.class, tasks.withType(AntoraTask.class,
@ -107,7 +108,8 @@ public class AntoraConventions {
.into(getNodeProjectDir(project)); .into(getNodeProjectDir(project));
} }
private void configureNpmInstallTask(Project project, NpmInstallTask npmInstallTask, Copy copyAntoraPackageJson) { private void configureNpmInstallTask(Project project, NpmInstallTask npmInstallTask,
TaskProvider<Copy> copyAntoraPackageJson) {
npmInstallTask.dependsOn(copyAntoraPackageJson); npmInstallTask.dependsOn(copyAntoraPackageJson);
Map<String, String> environment = new HashMap<>(); Map<String, String> environment = new HashMap<>();
environment.put("npm_config_omit", "optional"); environment.put("npm_config_omit", "optional");
@ -116,14 +118,14 @@ public class AntoraConventions {
npmInstallTask.getNpmCommand().set(List.of("ci", "--silent", "--no-progress")); npmInstallTask.getNpmCommand().set(List.of("ci", "--silent", "--no-progress"));
} }
private ExtractVersionConstraints addDependencyVersionsTask(Project project) { private TaskProvider<ExtractVersionConstraints> addDependencyVersionsTask(Project project) {
return project.getTasks() return project.getTasks()
.create("dependencyVersions", ExtractVersionConstraints.class, .register("dependencyVersions", ExtractVersionConstraints.class,
(task) -> task.enforcedPlatform(DEPENDENCIES_PATH)); (task) -> task.enforcedPlatform(DEPENDENCIES_PATH));
} }
private void configureGenerateAntoraYmlTask(Project project, GenerateAntoraYmlTask generateAntoraYmlTask, private void configureGenerateAntoraYmlTask(Project project, GenerateAntoraYmlTask generateAntoraYmlTask,
ExtractVersionConstraints dependencyVersionsTask) { TaskProvider<ExtractVersionConstraints> dependencyVersionsTask) {
generateAntoraYmlTask.getOutputs().doNotCacheIf("getAsciidocAttributes() changes output", (task) -> true); generateAntoraYmlTask.getOutputs().doNotCacheIf("getAsciidocAttributes() changes output", (task) -> true);
generateAntoraYmlTask.dependsOn(dependencyVersionsTask); generateAntoraYmlTask.dependsOn(dependencyVersionsTask);
generateAntoraYmlTask.setProperty("componentName", "boot"); generateAntoraYmlTask.setProperty("componentName", "boot");
@ -150,17 +152,16 @@ public class AntoraConventions {
} }
private Provider<Map<String, String>> getAsciidocAttributes(Project project, private Provider<Map<String, String>> getAsciidocAttributes(Project project,
ExtractVersionConstraints dependencyVersionsTask) { TaskProvider<ExtractVersionConstraints> dependencyVersionsTask) {
return project.provider(() -> { return dependencyVersionsTask.map((task) -> task.getVersionConstraints()).map((constraints) -> {
BomExtension bom = (BomExtension) project.project(DEPENDENCIES_PATH).getExtensions().getByName("bom"); BomExtension bom = (BomExtension) project.project(DEPENDENCIES_PATH).getExtensions().getByName("bom");
Map<String, String> dependencyVersions = dependencyVersionsTask.getVersionConstraints(); return new AntoraAsciidocAttributes(project, bom, constraints).get();
AntoraAsciidocAttributes attributes = new AntoraAsciidocAttributes(project, bom, dependencyVersions);
return attributes.get();
}); });
} }
private void configureAntoraTask(Project project, AntoraTask antoraTask, NpmInstallTask npmInstallTask, private void configureAntoraTask(Project project, AntoraTask antoraTask,
GenerateAntoraPlaybook generateAntoraPlaybookTask) { TaskProvider<NpmInstallTask> npmInstallTask,
TaskProvider<GenerateAntoraPlaybook> generateAntoraPlaybookTask) {
antoraTask.setGroup("Documentation"); antoraTask.setGroup("Documentation");
antoraTask.dependsOn(npmInstallTask, generateAntoraPlaybookTask); antoraTask.dependsOn(npmInstallTask, generateAntoraPlaybookTask);
antoraTask.setPlaybook("antora-playbook.yml"); antoraTask.setPlaybook("antora-playbook.yml");

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -44,6 +44,7 @@ import org.gradle.api.plugins.quality.CheckstyleExtension;
import org.gradle.api.plugins.quality.CheckstylePlugin; import org.gradle.api.plugins.quality.CheckstylePlugin;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.bundling.Jar; import org.gradle.api.tasks.bundling.Jar;
import org.gradle.api.tasks.compile.JavaCompile; import org.gradle.api.tasks.compile.JavaCompile;
import org.gradle.api.tasks.javadoc.Javadoc; import org.gradle.api.tasks.javadoc.Javadoc;
@ -126,11 +127,12 @@ class JavaConventions {
} }
private void configureJarManifestConventions(Project project) { private void configureJarManifestConventions(Project project) {
ExtractResources extractLegalResources = project.getTasks() TaskProvider<ExtractResources> extractLegalResources = project.getTasks()
.create("extractLegalResources", ExtractResources.class); .register("extractLegalResources", ExtractResources.class, (task) -> {
extractLegalResources.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("legal")); task.getDestinationDirectory().set(project.getLayout().getBuildDirectory().dir("legal"));
extractLegalResources.getResourceNames().set(Arrays.asList("LICENSE.txt", "NOTICE.txt")); task.getResourceNames().set(Arrays.asList("LICENSE.txt", "NOTICE.txt"));
extractLegalResources.getProperties().put("version", project.getVersion().toString()); task.getProperties().put("version", project.getVersion().toString());
});
SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class); SourceSetContainer sourceSets = project.getExtensions().getByType(SourceSetContainer.class);
Set<String> sourceJarTaskNames = sourceSets.stream() Set<String> sourceJarTaskNames = sourceSets.stream()
.map(SourceSet::getSourcesJarTaskName) .map(SourceSet::getSourcesJarTaskName)
@ -295,10 +297,10 @@ class JavaConventions {
} }
private void createProhibitedDependenciesCheck(Configuration classpath, Project project) { private void createProhibitedDependenciesCheck(Configuration classpath, Project project) {
CheckClasspathForProhibitedDependencies checkClasspathForProhibitedDependencies = project.getTasks() TaskProvider<CheckClasspathForProhibitedDependencies> checkClasspathForProhibitedDependencies = project
.create("check" + StringUtils.capitalize(classpath.getName() + "ForProhibitedDependencies"), .getTasks()
CheckClasspathForProhibitedDependencies.class); .register("check" + StringUtils.capitalize(classpath.getName() + "ForProhibitedDependencies"),
checkClasspathForProhibitedDependencies.setClasspath(classpath); CheckClasspathForProhibitedDependencies.class, (task) -> task.setClasspath(classpath));
project.getTasks().getByName(JavaBasePlugin.CHECK_TASK_NAME).dependsOn(checkClasspathForProhibitedDependencies); project.getTasks().getByName(JavaBasePlugin.CHECK_TASK_NAME).dependsOn(checkClasspathForProhibitedDependencies);
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -86,7 +86,7 @@ public class AutoConfigurationPlugin implements Plugin<Project> {
.add(project.getDependencies() .add(project.getDependencies()
.project(Collections.singletonMap("path", .project(Collections.singletonMap("path",
":spring-boot-project:spring-boot-tools:spring-boot-configuration-processor"))); ":spring-boot-project:spring-boot-tools:spring-boot-configuration-processor")));
project.getTasks().create("autoConfigurationMetadata", AutoConfigurationMetadata.class, (task) -> { project.getTasks().register("autoConfigurationMetadata", AutoConfigurationMetadata.class, (task) -> {
SourceSet main = project.getExtensions() SourceSet main = project.getExtensions()
.getByType(JavaPluginExtension.class) .getByType(JavaPluginExtension.class)
.getSourceSets() .getSourceSets()

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -54,6 +54,7 @@ import org.gradle.api.plugins.JavaPlatformPlugin;
import org.gradle.api.publish.maven.tasks.GenerateMavenPom; import org.gradle.api.publish.maven.tasks.GenerateMavenPom;
import org.gradle.api.tasks.Sync; import org.gradle.api.tasks.Sync;
import org.gradle.api.tasks.TaskExecutionException; import org.gradle.api.tasks.TaskExecutionException;
import org.gradle.api.tasks.TaskProvider;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.w3c.dom.NodeList; import org.w3c.dom.NodeList;
@ -134,52 +135,56 @@ public class BomExtension {
this.project.getTasks() this.project.getTasks()
.matching((task) -> task.getName().equals(DeployedPlugin.GENERATE_POM_TASK_NAME)) .matching((task) -> task.getName().equals(DeployedPlugin.GENERATE_POM_TASK_NAME))
.all((task) -> { .all((task) -> {
Sync syncBom = this.project.getTasks().create("syncBom", Sync.class);
syncBom.dependsOn(task);
File generatedBomDir = this.project.getLayout() File generatedBomDir = this.project.getLayout()
.getBuildDirectory() .getBuildDirectory()
.dir("generated/bom") .dir("generated/bom")
.get() .get()
.getAsFile(); .getAsFile();
syncBom.setDestinationDir(generatedBomDir); TaskProvider<Sync> syncBom = this.project.getTasks().register("syncBom", Sync.class, (sync) -> {
syncBom.from(((GenerateMavenPom) task).getDestination(), (pom) -> pom.rename((name) -> "pom.xml")); sync.dependsOn(task);
try { sync.setDestinationDir(generatedBomDir);
String settingsXmlContent = FileCopyUtils sync.from(((GenerateMavenPom) task).getDestination(), (pom) -> pom.rename((name) -> "pom.xml"));
.copyToString(new InputStreamReader( sync.from(this.project.getResources().getText().fromString(loadSettingsXml()),
getClass().getClassLoader().getResourceAsStream("effective-bom-settings.xml"),
StandardCharsets.UTF_8))
.replace("localRepositoryPath",
this.project.getLayout()
.getBuildDirectory()
.dir("local-m2-repository")
.get()
.getAsFile()
.getAbsolutePath());
syncBom.from(this.project.getResources().getText().fromString(settingsXmlContent),
(settingsXml) -> settingsXml.rename((name) -> "settings.xml")); (settingsXml) -> settingsXml.rename((name) -> "settings.xml"));
} });
catch (IOException ex) {
throw new GradleException("Failed to prepare settings.xml", ex);
}
MavenExec generateEffectiveBom = this.project.getTasks()
.create("generateEffectiveBom", MavenExec.class);
generateEffectiveBom.getProjectDir().set(generatedBomDir);
File effectiveBom = this.project.getLayout() File effectiveBom = this.project.getLayout()
.getBuildDirectory() .getBuildDirectory()
.file("generated/effective-bom/" + this.project.getName() + "-effective-bom.xml") .file("generated/effective-bom/" + this.project.getName() + "-effective-bom.xml")
.get() .get()
.getAsFile(); .getAsFile();
generateEffectiveBom.args("--settings", "settings.xml", "help:effective-pom", TaskProvider<MavenExec> generateEffectiveBom = this.project.getTasks()
"-Doutput=" + effectiveBom); .register("generateEffectiveBom", MavenExec.class, (maven) -> {
generateEffectiveBom.dependsOn(syncBom); maven.getProjectDir().set(generatedBomDir);
generateEffectiveBom.getOutputs().file(effectiveBom); maven.args("--settings", "settings.xml", "help:effective-pom", "-Doutput=" + effectiveBom);
generateEffectiveBom.doLast(new StripUnrepeatableOutputAction(effectiveBom)); maven.dependsOn(syncBom);
maven.getOutputs().file(effectiveBom);
maven.doLast(new StripUnrepeatableOutputAction(effectiveBom));
});
this.project.getArtifacts() this.project.getArtifacts()
.add(effectiveBomConfiguration.getName(), effectiveBom, .add(effectiveBomConfiguration.getName(), effectiveBom,
(artifact) -> artifact.builtBy(generateEffectiveBom)); (artifact) -> artifact.builtBy(generateEffectiveBom));
}); });
} }
private String loadSettingsXml() {
try {
return FileCopyUtils
.copyToString(new InputStreamReader(
getClass().getClassLoader().getResourceAsStream("effective-bom-settings.xml"),
StandardCharsets.UTF_8))
.replace("localRepositoryPath",
this.project.getLayout()
.getBuildDirectory()
.dir("local-m2-repository")
.get()
.getAsFile()
.getAbsolutePath());
}
catch (IOException ex) {
throw new GradleException("Failed to prepare settings.xml", ex);
}
}
private String createDependencyNotation(String groupId, String artifactId, DependencyVersion version) { private String createDependencyNotation(String groupId, String artifactId, DependencyVersion version) {
return groupId + ":" + artifactId + ":" + version; return groupId + ":" + artifactId + ":" + version;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -32,6 +32,7 @@ import org.gradle.api.plugins.PluginContainer;
import org.gradle.api.publish.PublishingExtension; import org.gradle.api.publish.PublishingExtension;
import org.gradle.api.publish.maven.MavenPom; import org.gradle.api.publish.maven.MavenPom;
import org.gradle.api.publish.maven.MavenPublication; import org.gradle.api.publish.maven.MavenPublication;
import org.gradle.api.tasks.TaskProvider;
import org.springframework.boot.build.DeployedPlugin; import org.springframework.boot.build.DeployedPlugin;
import org.springframework.boot.build.MavenRepositoryPlugin; import org.springframework.boot.build.MavenRepositoryPlugin;
@ -61,10 +62,10 @@ public class BomPlugin implements Plugin<Project> {
javaPlatform.allowDependencies(); javaPlatform.allowDependencies();
createApiEnforcedConfiguration(project); createApiEnforcedConfiguration(project);
BomExtension bom = project.getExtensions().create("bom", BomExtension.class, project); BomExtension bom = project.getExtensions().create("bom", BomExtension.class, project);
CheckBom checkBom = project.getTasks().create("bomrCheck", CheckBom.class, bom); TaskProvider<CheckBom> checkBom = project.getTasks().register("bomrCheck", CheckBom.class, bom);
project.getTasks().named("check").configure((check) -> check.dependsOn(checkBom)); project.getTasks().named("check").configure((check) -> check.dependsOn(checkBom));
project.getTasks().create("bomrUpgrade", UpgradeBom.class, bom); project.getTasks().register("bomrUpgrade", UpgradeBom.class, bom);
project.getTasks().create("moveToSnapshots", MoveToSnapshots.class, bom); project.getTasks().register("moveToSnapshots", MoveToSnapshots.class, bom);
project.getTasks().register("checkLinks", CheckLinks.class, bom); project.getTasks().register("checkLinks", CheckLinks.class, bom);
new PublishingCustomizer(project, bom).customize(); new PublishingCustomizer(project, bom).customize();
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -45,7 +45,6 @@ import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException; import org.gradle.api.GradleException;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.Task;
import org.gradle.api.artifacts.ComponentMetadataContext; import org.gradle.api.artifacts.ComponentMetadataContext;
import org.gradle.api.artifacts.ComponentMetadataRule; import org.gradle.api.artifacts.ComponentMetadataRule;
import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
@ -62,6 +61,8 @@ import org.gradle.api.file.CopySpec;
import org.gradle.api.file.Directory; import org.gradle.api.file.Directory;
import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.FileCollection; import org.gradle.api.file.FileCollection;
import org.gradle.api.file.ProjectLayout;
import org.gradle.api.file.RegularFile;
import org.gradle.api.file.RegularFileProperty; import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.model.ObjectFactory; import org.gradle.api.model.ObjectFactory;
import org.gradle.api.plugins.JavaLibraryPlugin; import org.gradle.api.plugins.JavaLibraryPlugin;
@ -74,7 +75,6 @@ import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import org.gradle.api.publish.tasks.GenerateModuleMetadata; import org.gradle.api.publish.tasks.GenerateModuleMetadata;
import org.gradle.api.tasks.Classpath; import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.JavaExec;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive; import org.gradle.api.tasks.PathSensitive;
@ -120,8 +120,8 @@ public class MavenPluginPlugin implements Plugin<Project> {
Jar jarTask = (Jar) project.getTasks().getByName(JavaPlugin.JAR_TASK_NAME); Jar jarTask = (Jar) project.getTasks().getByName(JavaPlugin.JAR_TASK_NAME);
configurePomPackaging(project); configurePomPackaging(project);
addPopulateIntTestMavenRepositoryTask(project); addPopulateIntTestMavenRepositoryTask(project);
MavenExec generateHelpMojoTask = addGenerateHelpMojoTask(project, jarTask); TaskProvider<MavenExec> generateHelpMojoTask = addGenerateHelpMojoTask(project, jarTask);
MavenExec generatePluginDescriptorTask = addGeneratePluginDescriptorTask(project, jarTask, TaskProvider<MavenExec> generatePluginDescriptorTask = addGeneratePluginDescriptorTask(project, jarTask,
generateHelpMojoTask); generateHelpMojoTask);
addDocumentPluginGoalsTask(project, generatePluginDescriptorTask); addDocumentPluginGoalsTask(project, generatePluginDescriptorTask);
addPrepareMavenBinariesTask(project); addPrepareMavenBinariesTask(project);
@ -170,25 +170,30 @@ public class MavenPluginPlugin implements Plugin<Project> {
.extendsFrom(project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME)); .extendsFrom(project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME));
runtimeClasspathWithMetadata.attributes((attributes) -> attributes.attribute(DocsType.DOCS_TYPE_ATTRIBUTE, runtimeClasspathWithMetadata.attributes((attributes) -> attributes.attribute(DocsType.DOCS_TYPE_ATTRIBUTE,
project.getObjects().named(DocsType.class, "maven-repository"))); project.getObjects().named(DocsType.class, "maven-repository")));
RuntimeClasspathMavenRepository runtimeClasspathMavenRepository = project.getTasks() TaskProvider<RuntimeClasspathMavenRepository> runtimeClasspathMavenRepository = project.getTasks()
.create("runtimeClasspathMavenRepository", RuntimeClasspathMavenRepository.class); .register("runtimeClasspathMavenRepository", RuntimeClasspathMavenRepository.class,
runtimeClasspathMavenRepository.getOutputDir() (task) -> task.getOutputDir()
.set(project.getLayout().getBuildDirectory().dir("runtime-classpath-repository")); .set(project.getLayout().getBuildDirectory().dir("runtime-classpath-repository")));
project.getDependencies() project.getDependencies()
.components((components) -> components.all(MavenRepositoryComponentMetadataRule.class)); .components((components) -> components.all(MavenRepositoryComponentMetadataRule.class));
Sync task = project.getTasks().create("populateTestMavenRepository", Sync.class); TaskProvider<Sync> populateRepository = project.getTasks()
task.setDestinationDir(project.getLayout().getBuildDirectory().dir("test-maven-repository").get().getAsFile()); .register("populateTestMavenRepository", Sync.class, (task) -> {
task.with(copyIntTestMavenRepositoryFiles(project, runtimeClasspathMavenRepository)); task.setDestinationDir(
task.dependsOn(project.getTasks().getByName(MavenRepositoryPlugin.PUBLISH_TO_PROJECT_REPOSITORY_TASK_NAME)); project.getLayout().getBuildDirectory().dir("test-maven-repository").get().getAsFile());
project.getTasks().getByName(IntegrationTestPlugin.INT_TEST_TASK_NAME).dependsOn(task); task.with(copyIntTestMavenRepositoryFiles(project, runtimeClasspathMavenRepository));
task.dependsOn(
project.getTasks().getByName(MavenRepositoryPlugin.PUBLISH_TO_PROJECT_REPOSITORY_TASK_NAME));
});
project.getTasks().getByName(IntegrationTestPlugin.INT_TEST_TASK_NAME).dependsOn(populateRepository);
project.getPlugins() project.getPlugins()
.withType(DockerTestPlugin.class) .withType(DockerTestPlugin.class)
.all((dockerTestPlugin) -> project.getTasks() .all((dockerTestPlugin) -> project.getTasks()
.named(DockerTestPlugin.DOCKER_TEST_TASK_NAME, (dockerTest) -> dockerTest.dependsOn(task))); .named(DockerTestPlugin.DOCKER_TEST_TASK_NAME,
(dockerTest) -> dockerTest.dependsOn(populateRepository)));
} }
private CopySpec copyIntTestMavenRepositoryFiles(Project project, private CopySpec copyIntTestMavenRepositoryFiles(Project project,
RuntimeClasspathMavenRepository runtimeClasspathMavenRepository) { TaskProvider<RuntimeClasspathMavenRepository> runtimeClasspathMavenRepository) {
CopySpec copySpec = project.copySpec(); CopySpec copySpec = project.copySpec();
copySpec.from(project.getConfigurations().getByName(MavenRepositoryPlugin.MAVEN_REPOSITORY_CONFIGURATION_NAME)); copySpec.from(project.getConfigurations().getByName(MavenRepositoryPlugin.MAVEN_REPOSITORY_CONFIGURATION_NAME));
copySpec.from(project.getLayout().getBuildDirectory().dir("maven-repository")); copySpec.from(project.getLayout().getBuildDirectory().dir("maven-repository"));
@ -196,58 +201,65 @@ public class MavenPluginPlugin implements Plugin<Project> {
return copySpec; return copySpec;
} }
private void addDocumentPluginGoalsTask(Project project, MavenExec generatePluginDescriptorTask) { private void addDocumentPluginGoalsTask(Project project, TaskProvider<MavenExec> generatePluginDescriptorTask) {
DocumentPluginGoals task = project.getTasks().create("documentPluginGoals", DocumentPluginGoals.class); project.getTasks().register("documentPluginGoals", DocumentPluginGoals.class, (task) -> {
File pluginXml = new File(generatePluginDescriptorTask.getOutputs().getFiles().getSingleFile(), "plugin.xml"); ProjectLayout layout = project.getLayout();
task.getPluginXml().set(pluginXml); Provider<RegularFile> pluginXml = layout.file(generatePluginDescriptorTask
task.getOutputDir().set(project.getLayout().getBuildDirectory().dir("docs/generated/goals/")); .map((generateDescriptor) -> new File(generateDescriptor.getOutputs().getFiles().getSingleFile(),
task.dependsOn(generatePluginDescriptorTask); "plugin.xml")));
task.getPluginXml().set(pluginXml);
task.getOutputDir().set(layout.getBuildDirectory().dir("docs/generated/goals/"));
task.dependsOn(generatePluginDescriptorTask);
});
} }
private MavenExec addGenerateHelpMojoTask(Project project, Jar jarTask) { private TaskProvider<MavenExec> addGenerateHelpMojoTask(Project project, Jar jarTask) {
Provider<Directory> helpMojoDir = project.getLayout().getBuildDirectory().dir("help-mojo"); Provider<Directory> helpMojoDir = project.getLayout().getBuildDirectory().dir("help-mojo");
MavenExec task = createGenerateHelpMojoTask(project, helpMojoDir); TaskProvider<Sync> syncHelpMojoInputs = createSyncHelpMojoInputsTask(project, helpMojoDir);
task.dependsOn(createSyncHelpMojoInputsTask(project, helpMojoDir)); TaskProvider<MavenExec> task = createGenerateHelpMojoTask(project, helpMojoDir, syncHelpMojoInputs);
includeHelpMojoInJar(jarTask, task); includeHelpMojoInJar(jarTask, task);
return task; return task;
} }
private MavenExec createGenerateHelpMojoTask(Project project, Provider<Directory> helpMojoDir) { private TaskProvider<MavenExec> createGenerateHelpMojoTask(Project project, Provider<Directory> helpMojoDir,
MavenExec task = project.getTasks().create("generateHelpMojo", MavenExec.class); TaskProvider<Sync> syncHelpMojoInputs) {
task.getProjectDir().set(helpMojoDir); return project.getTasks().register("generateHelpMojo", MavenExec.class, (task) -> {
task.args("org.apache.maven.plugins:maven-plugin-plugin:3.6.1:helpmojo"); task.getProjectDir().set(helpMojoDir);
task.getOutputs().dir(helpMojoDir.map((directory) -> directory.dir("target/generated-sources/plugin"))); task.args("org.apache.maven.plugins:maven-plugin-plugin:3.6.1:helpmojo");
return task; task.getOutputs().dir(helpMojoDir.map((directory) -> directory.dir("target/generated-sources/plugin")));
task.dependsOn(syncHelpMojoInputs);
});
} }
private Sync createSyncHelpMojoInputsTask(Project project, Provider<Directory> helpMojoDir) { private TaskProvider<Sync> createSyncHelpMojoInputsTask(Project project, Provider<Directory> helpMojoDir) {
Sync task = project.getTasks().create("syncHelpMojoInputs", Sync.class); return project.getTasks().register("syncHelpMojoInputs", Sync.class, (task) -> {
task.setDestinationDir(helpMojoDir.get().getAsFile()); task.setDestinationDir(helpMojoDir.get().getAsFile());
File pomFile = new File(project.getProjectDir(), "src/maven/resources/pom.xml"); File pomFile = new File(project.getProjectDir(), "src/maven/resources/pom.xml");
task.from(pomFile, (copy) -> replaceVersionPlaceholder(copy, project)); task.from(pomFile, (copy) -> replaceVersionPlaceholder(copy, project));
return task; });
} }
private void includeHelpMojoInJar(Jar jarTask, JavaExec generateHelpMojoTask) { private void includeHelpMojoInJar(Jar jarTask, TaskProvider<MavenExec> generateHelpMojoTask) {
jarTask.from(generateHelpMojoTask).exclude("**/*.java"); jarTask.from(generateHelpMojoTask).exclude("**/*.java");
jarTask.dependsOn(generateHelpMojoTask); jarTask.dependsOn(generateHelpMojoTask);
} }
private MavenExec addGeneratePluginDescriptorTask(Project project, Jar jarTask, MavenExec generateHelpMojoTask) { private TaskProvider<MavenExec> addGeneratePluginDescriptorTask(Project project, Jar jarTask,
TaskProvider<MavenExec> generateHelpMojoTask) {
Provider<Directory> pluginDescriptorDir = project.getLayout().getBuildDirectory().dir("plugin-descriptor"); Provider<Directory> pluginDescriptorDir = project.getLayout().getBuildDirectory().dir("plugin-descriptor");
Provider<Directory> generatedHelpMojoDir = project.getLayout() Provider<Directory> generatedHelpMojoDir = project.getLayout()
.getBuildDirectory() .getBuildDirectory()
.dir("generated/sources/helpMojo"); .dir("generated/sources/helpMojo");
SourceSet mainSourceSet = getMainSourceSet(project); SourceSet mainSourceSet = getMainSourceSet(project);
project.getTasks().withType(Javadoc.class, this::setJavadocOptions); project.getTasks().withType(Javadoc.class, this::setJavadocOptions);
FormatHelpMojoSource formattedHelpMojoSource = createFormatHelpMojoSource(project, generateHelpMojoTask, TaskProvider<FormatHelpMojoSource> formattedHelpMojoSource = createFormatHelpMojoSource(project,
generatedHelpMojoDir); generateHelpMojoTask, generatedHelpMojoDir);
project.getTasks().getByName(mainSourceSet.getCompileJavaTaskName()).dependsOn(formattedHelpMojoSource); project.getTasks().getByName(mainSourceSet.getCompileJavaTaskName()).dependsOn(formattedHelpMojoSource);
mainSourceSet.java((javaSources) -> javaSources.srcDir(formattedHelpMojoSource)); mainSourceSet.java((javaSources) -> javaSources.srcDir(formattedHelpMojoSource));
Sync pluginDescriptorInputs = createSyncPluginDescriptorInputs(project, pluginDescriptorDir, mainSourceSet); TaskProvider<Sync> pluginDescriptorInputs = createSyncPluginDescriptorInputs(project, pluginDescriptorDir,
pluginDescriptorInputs.dependsOn(mainSourceSet.getClassesTaskName()); mainSourceSet);
MavenExec task = createGeneratePluginDescriptorTask(project, pluginDescriptorDir); TaskProvider<MavenExec> task = createGeneratePluginDescriptorTask(project, pluginDescriptorDir,
task.dependsOn(pluginDescriptorInputs); pluginDescriptorInputs);
includeDescriptorInJar(jarTask, task); includeDescriptorInJar(jarTask, task);
return task; return task;
} }
@ -262,41 +274,42 @@ public class MavenPluginPlugin implements Plugin<Project> {
options.addMultilineStringsOption("tag").setValue(Arrays.asList("goal:X", "requiresProject:X", "threadSafe:X")); options.addMultilineStringsOption("tag").setValue(Arrays.asList("goal:X", "requiresProject:X", "threadSafe:X"));
} }
private FormatHelpMojoSource createFormatHelpMojoSource(Project project, MavenExec generateHelpMojoTask, private TaskProvider<FormatHelpMojoSource> createFormatHelpMojoSource(Project project,
Provider<Directory> generatedHelpMojoDir) { TaskProvider<MavenExec> generateHelpMojoTask, Provider<Directory> generatedHelpMojoDir) {
FormatHelpMojoSource formatHelpMojoSource = project.getTasks() return project.getTasks().register("formatHelpMojoSource", FormatHelpMojoSource.class, (task) -> {
.create("formatHelpMojoSource", FormatHelpMojoSource.class); task.setGenerator(generateHelpMojoTask);
formatHelpMojoSource.setGenerator(generateHelpMojoTask); task.getOutputDir().set(generatedHelpMojoDir);
formatHelpMojoSource.getOutputDir().set(generatedHelpMojoDir); });
return formatHelpMojoSource;
} }
private Sync createSyncPluginDescriptorInputs(Project project, Provider<Directory> destination, private TaskProvider<Sync> createSyncPluginDescriptorInputs(Project project, Provider<Directory> destination,
SourceSet sourceSet) { SourceSet sourceSet) {
Sync pluginDescriptorInputs = project.getTasks().create("syncPluginDescriptorInputs", Sync.class); return project.getTasks().register("syncPluginDescriptorInputs", Sync.class, (task) -> {
pluginDescriptorInputs.setDestinationDir(destination.get().getAsFile()); task.setDestinationDir(destination.get().getAsFile());
File pomFile = new File(project.getProjectDir(), "src/maven/resources/pom.xml"); File pomFile = new File(project.getProjectDir(), "src/maven/resources/pom.xml");
pluginDescriptorInputs.from(pomFile, (copy) -> replaceVersionPlaceholder(copy, project)); task.from(pomFile, (copy) -> replaceVersionPlaceholder(copy, project));
pluginDescriptorInputs.from(sourceSet.getOutput().getClassesDirs(), (sync) -> sync.into("target/classes")); task.from(sourceSet.getOutput().getClassesDirs(), (sync) -> sync.into("target/classes"));
pluginDescriptorInputs.from(sourceSet.getAllJava().getSrcDirs(), (sync) -> sync.into("src/main/java")); task.from(sourceSet.getAllJava().getSrcDirs(), (sync) -> sync.into("src/main/java"));
pluginDescriptorInputs.getInputs().property("version", project.getVersion()); task.getInputs().property("version", project.getVersion());
return pluginDescriptorInputs; task.dependsOn(sourceSet.getClassesTaskName());
});
} }
private MavenExec createGeneratePluginDescriptorTask(Project project, Provider<Directory> mavenDir) { private TaskProvider<MavenExec> createGeneratePluginDescriptorTask(Project project, Provider<Directory> mavenDir,
MavenExec generatePluginDescriptor = project.getTasks().create("generatePluginDescriptor", MavenExec.class); TaskProvider<Sync> pluginDescriptorInputs) {
generatePluginDescriptor.args("org.apache.maven.plugins:maven-plugin-plugin:3.6.1:descriptor"); return project.getTasks().register("generatePluginDescriptor", MavenExec.class, (task) -> {
generatePluginDescriptor.getOutputs() task.args("org.apache.maven.plugins:maven-plugin-plugin:3.6.1:descriptor");
.dir(mavenDir.map((directory) -> directory.dir("target/classes/META-INF/maven"))); task.getOutputs().dir(mavenDir.map((directory) -> directory.dir("target/classes/META-INF/maven")));
generatePluginDescriptor.getInputs() task.getInputs()
.dir(mavenDir.map((directory) -> directory.dir("target/classes/org"))) .dir(mavenDir.map((directory) -> directory.dir("target/classes/org")))
.withPathSensitivity(PathSensitivity.RELATIVE) .withPathSensitivity(PathSensitivity.RELATIVE)
.withPropertyName("plugin classes"); .withPropertyName("plugin classes");
generatePluginDescriptor.getProjectDir().set(mavenDir); task.getProjectDir().set(mavenDir);
return generatePluginDescriptor; task.dependsOn(pluginDescriptorInputs);
});
} }
private void includeDescriptorInJar(Jar jar, JavaExec generatePluginDescriptorTask) { private void includeDescriptorInJar(Jar jar, TaskProvider<MavenExec> generatePluginDescriptorTask) {
jar.from(generatePluginDescriptorTask, (copy) -> copy.into("META-INF/maven/")); jar.from(generatePluginDescriptorTask, (copy) -> copy.into("META-INF/maven/"));
jar.dependsOn(generatePluginDescriptorTask); jar.dependsOn(generatePluginDescriptorTask);
} }
@ -323,14 +336,14 @@ public class MavenPluginPlugin implements Plugin<Project> {
} }
private void addExtractVersionPropertiesTask(Project project) { private void addExtractVersionPropertiesTask(Project project) {
ExtractVersionProperties extractVersionProperties = project.getTasks() project.getTasks().register("extractVersionProperties", ExtractVersionProperties.class, (task) -> {
.create("extractVersionProperties", ExtractVersionProperties.class); task.setEffectiveBoms(project.getConfigurations().create("versionProperties"));
extractVersionProperties.setEffectiveBoms(project.getConfigurations().create("versionProperties")); task.getDestination()
extractVersionProperties.getDestination() .set(project.getLayout()
.set(project.getLayout() .getBuildDirectory()
.getBuildDirectory() .dir("generated-resources")
.dir("generated-resources") .map((dir) -> dir.file("extracted-versions.properties")));
.map((dir) -> dir.file("extracted-versions.properties"))); });
} }
public abstract static class FormatHelpMojoSource extends DefaultTask { public abstract static class FormatHelpMojoSource extends DefaultTask {
@ -342,9 +355,9 @@ public class MavenPluginPlugin implements Plugin<Project> {
this.objectFactory = objectFactory; this.objectFactory = objectFactory;
} }
private Task generator; private TaskProvider<?> generator;
void setGenerator(Task generator) { void setGenerator(TaskProvider<?> generator) {
this.generator = generator; this.generator = generator;
getInputs().files(this.generator) getInputs().files(this.generator)
.withPathSensitivity(PathSensitivity.RELATIVE) .withPathSensitivity(PathSensitivity.RELATIVE)
@ -357,7 +370,7 @@ public class MavenPluginPlugin implements Plugin<Project> {
@TaskAction @TaskAction
void syncAndFormat() { void syncAndFormat() {
FileFormatter formatter = new FileFormatter(); FileFormatter formatter = new FileFormatter();
for (File output : this.generator.getOutputs().getFiles()) { for (File output : this.generator.get().getOutputs().getFiles()) {
formatter.formatFiles(this.objectFactory.fileTree().from(output), StandardCharsets.UTF_8) formatter.formatFiles(this.objectFactory.fileTree().from(output), StandardCharsets.UTF_8)
.forEach((edit) -> save(output, edit)); .forEach((edit) -> save(output, edit));
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -29,6 +29,7 @@ import org.gradle.api.plugins.JavaLibraryPlugin;
import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.PluginContainer; import org.gradle.api.plugins.PluginContainer;
import org.gradle.api.provider.Provider; import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.bundling.Jar; import org.gradle.api.tasks.bundling.Jar;
import org.springframework.boot.build.ConventionsPlugin; import org.springframework.boot.build.ConventionsPlugin;
@ -53,15 +54,19 @@ public class StarterPlugin implements Plugin<Project> {
plugins.apply(DeployedPlugin.class); plugins.apply(DeployedPlugin.class);
plugins.apply(JavaLibraryPlugin.class); plugins.apply(JavaLibraryPlugin.class);
plugins.apply(ConventionsPlugin.class); plugins.apply(ConventionsPlugin.class);
StarterMetadata starterMetadata = project.getTasks().create("starterMetadata", StarterMetadata.class);
ConfigurationContainer configurations = project.getConfigurations(); ConfigurationContainer configurations = project.getConfigurations();
Configuration runtimeClasspath = configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); Configuration runtimeClasspath = configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME);
starterMetadata.setDependencies(runtimeClasspath); TaskProvider<StarterMetadata> starterMetadata = project.getTasks()
Provider<RegularFile> destination = project.getLayout().getBuildDirectory().file("starter-metadata.properties"); .register("starterMetadata", StarterMetadata.class, (task) -> {
starterMetadata.getDestination().set(destination); task.setDependencies(runtimeClasspath);
Provider<RegularFile> destination = project.getLayout()
.getBuildDirectory()
.file("starter-metadata.properties");
task.getDestination().set(destination);
});
configurations.create("starterMetadata"); configurations.create("starterMetadata");
project.getArtifacts() project.getArtifacts()
.add("starterMetadata", project.provider(starterMetadata::getDestination), .add("starterMetadata", starterMetadata.map(StarterMetadata::getDestination),
(artifact) -> artifact.builtBy(starterMetadata)); (artifact) -> artifact.builtBy(starterMetadata));
createClasspathConflictsCheck(runtimeClasspath, project); createClasspathConflictsCheck(runtimeClasspath, project);
createUnnecessaryExclusionsCheck(runtimeClasspath, project); createUnnecessaryExclusionsCheck(runtimeClasspath, project);
@ -70,27 +75,24 @@ public class StarterPlugin implements Plugin<Project> {
} }
private void createClasspathConflictsCheck(Configuration classpath, Project project) { private void createClasspathConflictsCheck(Configuration classpath, Project project) {
CheckClasspathForConflicts checkClasspathForConflicts = project.getTasks() TaskProvider<CheckClasspathForConflicts> checkClasspathForConflicts = project.getTasks()
.create("check" + StringUtils.capitalize(classpath.getName() + "ForConflicts"), .register("check" + StringUtils.capitalize(classpath.getName() + "ForConflicts"),
CheckClasspathForConflicts.class); CheckClasspathForConflicts.class, (task) -> task.setClasspath(classpath));
checkClasspathForConflicts.setClasspath(classpath);
project.getTasks().getByName(JavaBasePlugin.CHECK_TASK_NAME).dependsOn(checkClasspathForConflicts); project.getTasks().getByName(JavaBasePlugin.CHECK_TASK_NAME).dependsOn(checkClasspathForConflicts);
} }
private void createUnnecessaryExclusionsCheck(Configuration classpath, Project project) { private void createUnnecessaryExclusionsCheck(Configuration classpath, Project project) {
CheckClasspathForUnnecessaryExclusions checkClasspathForUnnecessaryExclusions = project.getTasks() TaskProvider<CheckClasspathForUnnecessaryExclusions> checkClasspathForUnnecessaryExclusions = project.getTasks()
.create("check" + StringUtils.capitalize(classpath.getName() + "ForUnnecessaryExclusions"), .register("check" + StringUtils.capitalize(classpath.getName() + "ForUnnecessaryExclusions"),
CheckClasspathForUnnecessaryExclusions.class); CheckClasspathForUnnecessaryExclusions.class, (task) -> task.setClasspath(classpath));
checkClasspathForUnnecessaryExclusions.setClasspath(classpath);
project.getTasks().getByName(JavaBasePlugin.CHECK_TASK_NAME).dependsOn(checkClasspathForUnnecessaryExclusions); project.getTasks().getByName(JavaBasePlugin.CHECK_TASK_NAME).dependsOn(checkClasspathForUnnecessaryExclusions);
} }
private void createUnconstrainedDirectDependenciesCheck(Configuration classpath, Project project) { private void createUnconstrainedDirectDependenciesCheck(Configuration classpath, Project project) {
CheckClasspathForUnconstrainedDirectDependencies checkClasspathForUnconstrainedDirectDependencies = project TaskProvider<CheckClasspathForUnconstrainedDirectDependencies> checkClasspathForUnconstrainedDirectDependencies = project
.getTasks() .getTasks()
.create("check" + StringUtils.capitalize(classpath.getName() + "ForUnconstrainedDirectDependencies"), .register("check" + StringUtils.capitalize(classpath.getName() + "ForUnconstrainedDirectDependencies"),
CheckClasspathForUnconstrainedDirectDependencies.class); CheckClasspathForUnconstrainedDirectDependencies.class, (task) -> task.setClasspath(classpath));
checkClasspathForUnconstrainedDirectDependencies.setClasspath(classpath);
project.getTasks() project.getTasks()
.getByName(JavaBasePlugin.CHECK_TASK_NAME) .getByName(JavaBasePlugin.CHECK_TASK_NAME)
.dependsOn(checkClasspathForUnconstrainedDirectDependencies); .dependsOn(checkClasspathForUnconstrainedDirectDependencies);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -22,6 +22,7 @@ import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginExtension; import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.testing.Test; import org.gradle.api.tasks.testing.Test;
import org.gradle.language.base.plugins.LifecycleBasePlugin; import org.gradle.language.base.plugins.LifecycleBasePlugin;
import org.gradle.plugins.ide.eclipse.EclipsePlugin; import org.gradle.plugins.ide.eclipse.EclipsePlugin;
@ -51,7 +52,7 @@ public class IntegrationTestPlugin implements Plugin<Project> {
private void configureIntegrationTesting(Project project) { private void configureIntegrationTesting(Project project) {
SourceSet intTestSourceSet = createSourceSet(project); SourceSet intTestSourceSet = createSourceSet(project);
Test intTest = createTestTask(project, intTestSourceSet); TaskProvider<Test> intTest = createTestTask(project, intTestSourceSet);
project.getTasks().getByName(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(intTest); project.getTasks().getByName(LifecycleBasePlugin.CHECK_TASK_NAME).dependsOn(intTest);
project.getPlugins().withType(EclipsePlugin.class, (eclipsePlugin) -> { project.getPlugins().withType(EclipsePlugin.class, (eclipsePlugin) -> {
EclipseModel eclipse = project.getExtensions().getByType(EclipseModel.class); EclipseModel eclipse = project.getExtensions().getByType(EclipseModel.class);
@ -71,14 +72,14 @@ public class IntegrationTestPlugin implements Plugin<Project> {
return intTestSourceSet; return intTestSourceSet;
} }
private Test createTestTask(Project project, SourceSet intTestSourceSet) { private TaskProvider<Test> createTestTask(Project project, SourceSet intTestSourceSet) {
Test intTest = project.getTasks().create(INT_TEST_TASK_NAME, Test.class); return project.getTasks().register(INT_TEST_TASK_NAME, Test.class, (task) -> {
intTest.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP); task.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
intTest.setDescription("Runs integration tests."); task.setDescription("Runs integration tests.");
intTest.setTestClassesDirs(intTestSourceSet.getOutput().getClassesDirs()); task.setTestClassesDirs(intTestSourceSet.getOutput().getClassesDirs());
intTest.setClasspath(intTestSourceSet.getRuntimeClasspath()); task.setClasspath(intTestSourceSet.getRuntimeClasspath());
intTest.shouldRunAfter(JavaPlugin.TEST_TASK_NAME); task.shouldRunAfter(JavaPlugin.TEST_TASK_NAME);
return intTest; });
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2023 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -24,6 +24,7 @@ import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.specs.Spec; import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.SourceSet; import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.api.tasks.testing.Test; import org.gradle.api.tasks.testing.Test;
import org.gradle.language.base.plugins.LifecycleBasePlugin; import org.gradle.language.base.plugins.LifecycleBasePlugin;
import org.gradle.plugins.ide.eclipse.EclipsePlugin; import org.gradle.plugins.ide.eclipse.EclipsePlugin;
@ -76,17 +77,18 @@ public class SystemTestPlugin implements Plugin<Project> {
return systemTestSourceSet; return systemTestSourceSet;
} }
private void createTestTask(Project project, SourceSet systemTestSourceSet) { private TaskProvider<Test> createTestTask(Project project, SourceSet systemTestSourceSet) {
Test systemTest = project.getTasks().create(SYSTEM_TEST_TASK_NAME, Test.class); return project.getTasks().register(SYSTEM_TEST_TASK_NAME, Test.class, (task) -> {
systemTest.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP); task.setGroup(LifecycleBasePlugin.VERIFICATION_GROUP);
systemTest.setDescription("Runs system tests."); task.setDescription("Runs system tests.");
systemTest.setTestClassesDirs(systemTestSourceSet.getOutput().getClassesDirs()); task.setTestClassesDirs(systemTestSourceSet.getOutput().getClassesDirs());
systemTest.setClasspath(systemTestSourceSet.getRuntimeClasspath()); task.setClasspath(systemTestSourceSet.getRuntimeClasspath());
systemTest.shouldRunAfter(JavaPlugin.TEST_TASK_NAME); task.shouldRunAfter(JavaPlugin.TEST_TASK_NAME);
if (isCi()) { if (isCi()) {
systemTest.getOutputs().upToDateWhen(NEVER); task.getOutputs().upToDateWhen(NEVER);
systemTest.getOutputs().doNotCacheIf("System tests are always rerun on CI", (task) -> true); task.getOutputs().doNotCacheIf("System tests are always rerun on CI", (spec) -> true);
} }
});
} }
private boolean isCi() { private boolean isCi() {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -78,9 +78,10 @@ class GenerateAntoraPlaybookTests {
File projectDir = new File(rootProjectDir, "project"); File projectDir = new File(rootProjectDir, "project");
projectDir.mkdirs(); projectDir.mkdirs();
Project project = ProjectBuilder.builder().withProjectDir(projectDir).withParent(rootProject).build(); Project project = ProjectBuilder.builder().withProjectDir(projectDir).withParent(rootProject).build();
GenerateAntoraPlaybook task = project.getTasks().create("generateAntoraPlaybook", GenerateAntoraPlaybook.class); project.getTasks()
customizer.accept(task); .register("generateAntoraPlaybook", GenerateAntoraPlaybook.class, customizer::accept)
task.writePlaybookYml(); .get()
.writePlaybookYml();
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,6 +28,7 @@ import org.junit.jupiter.api.io.TempDir;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.FileSystemUtils; import org.springframework.util.FileSystemUtils;
import org.springframework.util.function.ThrowingConsumer;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -204,14 +205,15 @@ class ArchitectureCheckTests {
}); });
} }
private void prepareTask(String classes, Callback<ArchitectureCheck> callback) throws Exception { private void prepareTask(String classes, ThrowingConsumer<ArchitectureCheck> callback) throws Exception {
File projectDir = new File(this.temp, "project"); File projectDir = new File(this.temp, "project");
projectDir.mkdirs(); projectDir.mkdirs();
copyClasses(classes, projectDir); copyClasses(classes, projectDir);
Project project = ProjectBuilder.builder().withProjectDir(projectDir).build(); Project project = ProjectBuilder.builder().withProjectDir(projectDir).build();
ArchitectureCheck architectureCheck = project.getTasks() project.getTasks().register("checkArchitecture", ArchitectureCheck.class, (task) -> {
.create("checkArchitecture", ArchitectureCheck.class, (task) -> task.setClasses(project.files("classes"))); task.setClasses(project.files("classes"));
callback.accept(architectureCheck); callback.accept(task);
});
} }
private void copyClasses(String name, File projectDir) throws IOException { private void copyClasses(String name, File projectDir) throws IOException {
@ -221,10 +223,4 @@ class ArchitectureCheckTests {
new File(projectDir, "classes/org/springframework/boot/build/architecture/" + name)); new File(projectDir, "classes/org/springframework/boot/build/architecture/" + name));
} }
private interface Callback<T> {
void accept(T item) throws Exception;
}
} }

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME

3
gradlew vendored
View File

@ -86,8 +86,7 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
' "$PWD" ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum

View File

@ -26,7 +26,7 @@ dependencies {
} }
task syncIntegrationTestSources(type: Sync) { task syncIntegrationTestSources(type: Sync) {
destinationDir file(layout.buildDirectory.dir("it")) destinationDir = file(layout.buildDirectory.dir("it"))
from file("src/it") from file("src/it")
filter(springRepositoryTransformers.ant()) filter(springRepositoryTransformers.ant())
} }

View File

@ -116,8 +116,8 @@ if (BuildProperties.get(project).buildType() == BuildType.OPEN_SOURCE) {
} }
def homebrewFormulaArtifact = artifacts.add("archives", file(layout.buildDirectory.file("homebrew/spring-boot.rb"))) { def homebrewFormulaArtifact = artifacts.add("archives", file(layout.buildDirectory.file("homebrew/spring-boot.rb"))) {
type "rb" type = "rb"
classifier "homebrew" classifier = "homebrew"
builtBy "homebrewFormula" builtBy "homebrewFormula"
} }

View File

@ -1,6 +1,8 @@
buildscript { buildscript {
repositories { repositories {
maven { url 'https://repo.spring.io/libs-snapshot' } maven {
url = 'https://repo.spring.io/libs-snapshot'
}
} }
dependencies { dependencies {

View File

@ -1,6 +1,8 @@
pluginManagement { pluginManagement {
repositories { repositories {
maven { url 'https://repo.spring.io/milestone' } maven {
url = 'https://repo.spring.io/milestone'
}
gradlePluginPortal() gradlePluginPortal()
} }
} }

View File

@ -1,7 +1,11 @@
pluginManagement { pluginManagement {
repositories { repositories {
maven { url 'https://repo.spring.io/milestone' } maven {
maven { url 'https://repo.spring.io/snapshot' } url = 'https://repo.spring.io/milestone'
}
maven {
url = 'https://repo.spring.io/snapshot'
}
gradlePluginPortal() gradlePluginPortal()
} }
} }

View File

@ -8,8 +8,9 @@ apply(plugin = "io.spring.dependency-management")
// end::apply[] // end::apply[]
tasks.register("verify") { tasks.register("verify") {
val plugins = project.plugins
doLast { doLast {
project.plugins.getPlugin(JavaPlugin::class) plugins.getPlugin(JavaPlugin::class)
project.plugins.getPlugin(io.spring.gradle.dependencymanagement.DependencyManagementPlugin::class) plugins.getPlugin(io.spring.gradle.dependencymanagement.DependencyManagementPlugin::class)
} }
} }

View File

@ -24,5 +24,7 @@ dependencyManagement {
} }
repositories { repositories {
maven { url 'repository' } maven {
url = 'repository'
}
} }

View File

@ -14,7 +14,9 @@ dependencies {
} }
repositories { repositories {
maven { url 'repository' } maven {
url = 'repository'
}
} }
configurations.all { configurations.all {

View File

@ -9,7 +9,9 @@ dependencies {
} }
repositories { repositories {
maven { url 'repository' } maven {
url = 'repository'
}
} }
configurations.all { configurations.all {

View File

@ -19,7 +19,9 @@ ext['slf4j.version'] = '1.7.20'
// end::custom-version[] // end::custom-version[]
repositories { repositories {
maven { url 'repository' } maven {
url = 'repository'
}
} }
task slf4jVersion { task slf4jVersion {

View File

@ -27,7 +27,8 @@ the<DependencyManagementExtension>().apply {
} }
tasks.register("slf4jVersion") { tasks.register("slf4jVersion") {
val dependencyManagement = project.the<DependencyManagementExtension>()
doLast { doLast {
println(project.the<DependencyManagementExtension>().managedVersions["org.slf4j:slf4j-api"]) println(dependencyManagement.managedVersions["org.slf4j:slf4j-api"])
} }
} }

View File

@ -1,6 +1,8 @@
buildscript { buildscript {
repositories { repositories {
maven { url 'https://repo.spring.io/libs-milestone' } maven {
url = 'https://repo.spring.io/libs-milestone'
}
} }
dependencies { dependencies {

View File

@ -1,6 +1,8 @@
buildscript { buildscript {
repositories { repositories {
maven { url 'https://repo.spring.io/libs-snapshot' } maven {
url = 'https://repo.spring.io/libs-snapshot'
}
} }
dependencies { dependencies {

View File

@ -13,7 +13,7 @@ publishing {
} }
repositories { repositories {
maven { maven {
url 'https://repo.example.com' url = 'https://repo.example.com'
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -181,7 +181,7 @@ class BuildInfoTests {
} }
private BuildInfo createTask(Project project) { private BuildInfo createTask(Project project) {
return project.getTasks().create("testBuildInfo", BuildInfo.class); return project.getTasks().register("testBuildInfo", BuildInfo.class).get();
} }
private Properties buildInfoProperties(BuildInfo task) { private Properties buildInfoProperties(BuildInfo task) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -116,7 +116,7 @@ abstract class AbstractBootArchiveTests<T extends Jar & BootArchive> {
projectDir.mkdirs(); projectDir.mkdirs();
this.project = GradleProjectBuilder.builder().withProjectDir(projectDir).build(); this.project = GradleProjectBuilder.builder().withProjectDir(projectDir).build();
this.project.setDescription("Test project for " + this.taskClass.getSimpleName()); this.project.setDescription("Test project for " + this.taskClass.getSimpleName());
this.task = configure(this.project.getTasks().create("testArchive", this.taskClass)); this.task = this.project.getTasks().register("testArchive", this.taskClass, this::configure).get();
} }
@Test @Test

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2024 the original author or authors. * Copyright 2012-2025 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -58,7 +58,7 @@ class BootBuildImageTests {
projectDir.mkdirs(); projectDir.mkdirs();
this.project = GradleProjectBuilder.builder().withProjectDir(projectDir).withName("build-image-test").build(); this.project = GradleProjectBuilder.builder().withProjectDir(projectDir).withName("build-image-test").build();
this.project.setDescription("Test project for BootBuildImage"); this.project.setDescription("Test project for BootBuildImage");
this.buildImage = this.project.getTasks().create("buildImage", BootBuildImage.class); this.buildImage = this.project.getTasks().register("buildImage", BootBuildImage.class).get();
} }
@Test @Test

View File

@ -16,9 +16,9 @@ task('taskExists') {
} }
task('distributionExists') { task('distributionExists') {
def distributions = project.extensions.findByType(DistributionContainer)
doFirst { doFirst {
boolean found = project.hasProperty('distributions') && boolean found = distributions != null && distributions.findByName(distributionName) != null
distributions.findByName(distributionName) != null
println "${distributionName} exists = ${found}" println "${distributionName} exists = ${found}"
} }
} }

View File

@ -17,12 +17,15 @@ if (project.hasProperty('applyDependencyManagementPlugin')) {
} }
repositories { repositories {
maven { url 'repository' } maven {
url = 'repository'
}
} }
task doesNotHaveDependencyManagement { task doesNotHaveDependencyManagement {
def extensions = project.extensions
doLast { doLast {
if (project.extensions.findByName('dependencyManagement') != null) { if (extensions.findByName('dependencyManagement') != null) {
throw new GradleException('Found dependency management extension') throw new GradleException('Found dependency management extension')
} }
} }

View File

@ -17,7 +17,9 @@ dependencyManagement {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {
@ -25,8 +27,9 @@ dependencies {
} }
task kotlinVersion { task kotlinVersion {
def properties = project.properties
doLast { doLast {
def kotlinVersion = project.hasProperty('kotlin.version') ? project.getProperty('kotlin.version') : 'none' def kotlinVersion = properties.getOrDefault('kotlin.version', 'none')
println "Kotlin version: ${kotlinVersion}" println "Kotlin version: ${kotlinVersion}"
} }
} }

View File

@ -3,8 +3,9 @@ plugins {
} }
task kotlinVersion { task kotlinVersion {
def properties = project.properties
doLast { doLast {
def kotlinVersion = project.hasProperty('kotlin.version') ? project.getProperty('kotlin.version') : 'none' def kotlinVersion = properties.getOrDefault('kotlin.version', 'none')
println "Kotlin version: ${kotlinVersion}" println "Kotlin version: ${kotlinVersion}"
} }
} }

View File

@ -6,7 +6,9 @@ plugins {
apply plugin: 'io.spring.dependency-management' apply plugin: 'io.spring.dependency-management'
repositories { repositories {
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencyManagement { dependencyManagement {

View File

@ -7,7 +7,9 @@ apply plugin: 'org.springframework.boot.aot'
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
configurations.all { configurations.all {

View File

@ -6,7 +6,9 @@ plugins {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
configurations.all { configurations.all {

View File

@ -7,7 +7,9 @@ apply plugin: 'org.springframework.boot.aot'
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
configurations.all { configurations.all {

View File

@ -6,7 +6,9 @@ plugins {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
configurations.all { configurations.all {

View File

@ -27,7 +27,9 @@ bootJar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -5,7 +5,9 @@ plugins {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -9,7 +9,9 @@ bootJar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -13,7 +13,9 @@ bootJar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -42,7 +42,9 @@ bootJar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -20,7 +20,9 @@ bootJar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -10,7 +10,9 @@ task launch(type: JavaExec) {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -9,7 +9,9 @@ bootJar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -28,7 +28,9 @@ bootWar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -10,7 +10,9 @@ bootWar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -14,7 +14,9 @@ bootWar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -43,7 +43,9 @@ bootWar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -21,7 +21,9 @@ bootWar {
repositories { repositories {
mavenCentral() mavenCentral()
maven { url 'repository' } maven {
url = 'repository'
}
} }
dependencies { dependencies {

View File

@ -47,14 +47,14 @@ task syncTestRepository(type: Sync) {
} }
task syncAntSources(type: Sync) { task syncAntSources(type: Sync) {
destinationDir file(layout.buildDirectory.dir("ant")) destinationDir = file(layout.buildDirectory.dir("ant"))
from project.layout.projectDirectory from project.layout.projectDirectory
include "*.xml" include "*.xml"
filter(springRepositoryTransformers.ant()) filter(springRepositoryTransformers.ant())
} }
task antRun(type: JavaExec) { task antRun(type: JavaExec) {
workingDir layout.buildDirectory.dir("ant") workingDir = layout.buildDirectory.dir("ant")
dependsOn syncTestRepository, syncAntSources, configurations.antDependencies dependsOn syncTestRepository, syncAntSources, configurations.antDependencies
classpath = configurations.antDependencies; classpath = configurations.antDependencies;
mainClass = "org.apache.tools.ant.launch.Launcher" mainClass = "org.apache.tools.ant.launch.Launcher"