Browse Source

Guard against new Spring modules in ApiDiff task

Prior to this commit, the ApiDiff Gradle task would be configured for
all submodules of the Spring Framework project and would assume that
they all existed for the baseline version considered for the API diff.

This would cause issues when:
* the sub-project is not published as it's not an official "spring-*"
  module
* the "spring-*" module is new and did not exist for the baseline
  version

This commit ensures that only "spring-*" modules are considered for this
task and that we trigger an early resolution of the baseline version -
if the version doesn't exist, a warn message is logged and we assume
that this is a new module, to be compared with an empty configuration.

This commit also renames the "spring-core-graalvm" project to
"graalvm-feature", since this sub-project is not an official module
published to Maven Central, but rather an internal dependency.

Fixes gh-28818
pull/28885/head
Brian Clozel 2 years ago
parent
commit
10e4965f99
  1. 30
      buildSrc/src/main/java/org/springframework/build/api/ApiDiffPlugin.java
  2. 2
      framework-bom/framework-bom.gradle
  3. 16
      gradle/docs.gradle
  4. 4
      settings.gradle
  5. 12
      spring-core/graalvm/graalvm-feature.gradle
  6. 2
      spring-core/spring-core.gradle

30
buildSrc/src/main/java/org/springframework/build/api/ApiDiffPlugin.java

@ -24,23 +24,22 @@ import java.util.List;
import me.champeau.gradle.japicmp.JapicmpPlugin; import me.champeau.gradle.japicmp.JapicmpPlugin;
import me.champeau.gradle.japicmp.JapicmpTask; import me.champeau.gradle.japicmp.JapicmpTask;
import org.gradle.api.Action; 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.artifacts.Configuration; import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency; import org.gradle.api.artifacts.Dependency;
import org.gradle.api.artifacts.repositories.ArtifactRepository;
import org.gradle.api.artifacts.repositories.MavenArtifactRepository;
import org.gradle.api.artifacts.repositories.RepositoryContentDescriptor;
import org.gradle.api.plugins.JavaBasePlugin; import org.gradle.api.plugins.JavaBasePlugin;
import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin; import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import org.gradle.api.tasks.TaskProvider; import org.gradle.api.tasks.TaskProvider;
import org.gradle.jvm.tasks.Jar; import org.gradle.jvm.tasks.Jar;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** /**
* {@link Plugin} that applies the {@code "japicmp-gradle-plugin"} * {@link Plugin} that applies the {@code "japicmp-gradle-plugin"}
* and create tasks for all subprojects, diffing the public API one by one * and create tasks for all subprojects named {@code "spring-*"}, diffing the public API one by one
* and creating the reports in {@code "build/reports/api-diff/$OLDVERSION_to_$NEWVERSION/"}. * and creating the reports in {@code "build/reports/api-diff/$OLDVERSION_to_$NEWVERSION/"}.
* <p>{@code "./gradlew apiDiff -PbaselineVersion=5.1.0.RELEASE"} will output the * <p>{@code "./gradlew apiDiff -PbaselineVersion=5.1.0.RELEASE"} will output the
* reports for the API diff between the baseline version and the current one for all modules. * reports for the API diff between the baseline version and the current one for all modules.
@ -51,6 +50,8 @@ import org.gradle.jvm.tasks.Jar;
*/ */
public class ApiDiffPlugin implements Plugin<Project> { public class ApiDiffPlugin implements Plugin<Project> {
private static final Logger logger = LoggerFactory.getLogger(ApiDiffPlugin.class);
public static final String TASK_NAME = "apiDiff"; public static final String TASK_NAME = "apiDiff";
private static final String BASELINE_VERSION_PROPERTY = "baselineVersion"; private static final String BASELINE_VERSION_PROPERTY = "baselineVersion";
@ -70,7 +71,11 @@ public class ApiDiffPlugin implements Plugin<Project> {
private void applyApiDiffConventions(Project project) { private void applyApiDiffConventions(Project project) {
String baselineVersion = project.property(BASELINE_VERSION_PROPERTY).toString(); String baselineVersion = project.property(BASELINE_VERSION_PROPERTY).toString();
project.subprojects(subProject -> createApiDiffTask(baselineVersion, subProject)); project.subprojects(subProject -> {
if (subProject.getName().startsWith("spring-")) {
createApiDiffTask(baselineVersion, subProject);
}
});
} }
private void createApiDiffTask(String baselineVersion, Project project) { private void createApiDiffTask(String baselineVersion, Project project) {
@ -83,7 +88,7 @@ public class ApiDiffPlugin implements Plugin<Project> {
apiDiff.setDescription("Generates an API diff report with japicmp"); apiDiff.setDescription("Generates an API diff report with japicmp");
apiDiff.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP); apiDiff.setGroup(JavaBasePlugin.DOCUMENTATION_GROUP);
apiDiff.setOldClasspath(project.files(createBaselineConfiguration(baselineVersion, project))); apiDiff.setOldClasspath(createBaselineConfiguration(baselineVersion, project));
TaskProvider<Jar> jar = project.getTasks().withType(Jar.class).named("jar"); TaskProvider<Jar> jar = project.getTasks().withType(Jar.class).named("jar");
apiDiff.setNewArchives(project.getLayout().files(jar.get().getArchiveFile().get().getAsFile())); apiDiff.setNewArchives(project.getLayout().files(jar.get().getArchiveFile().get().getAsFile()));
apiDiff.setNewClasspath(getRuntimeClassPath(project)); apiDiff.setNewClasspath(getRuntimeClassPath(project));
@ -109,7 +114,16 @@ public class ApiDiffPlugin implements Plugin<Project> {
String baseline = String.join(":", String baseline = String.join(":",
project.getGroup().toString(), project.getName(), baselineVersion); project.getGroup().toString(), project.getName(), baselineVersion);
Dependency baselineDependency = project.getDependencies().create(baseline + "@jar"); Dependency baselineDependency = project.getDependencies().create(baseline + "@jar");
return project.getRootProject().getConfigurations().detachedConfiguration(baselineDependency); Configuration baselineConfiguration = project.getRootProject().getConfigurations().detachedConfiguration(baselineDependency);
try {
// eagerly resolve the baseline configuration to check whether this is a new Spring module
baselineConfiguration.resolve();
return baselineConfiguration;
}
catch (GradleException exception) {
logger.warn("Could not resolve {} - assuming this is a new Spring module.", baseline);
}
return project.getRootProject().getConfigurations().detachedConfiguration();
} }
private Configuration getRuntimeClassPath(Project project) { private Configuration getRuntimeClassPath(Project project) {

2
framework-bom/framework-bom.gradle

@ -7,7 +7,7 @@ group = "org.springframework"
dependencies { dependencies {
constraints { constraints {
parent.moduleProjects.findAll{ it.name != 'spring-core-graalvm' }.sort { "$it.name" }.each { parent.moduleProjects.sort { "$it.name" }.each {
api it api it
} }
} }

16
gradle/docs.gradle

@ -1,7 +1,3 @@
ext {
documentedProjects = moduleProjects.findAll { it.name != 'spring-core-graalvm' }
}
configurations { configurations {
asciidoctorExt asciidoctorExt
} }
@ -28,7 +24,7 @@ task api(type: Javadoc) {
title = "${rootProject.description} ${version} API" title = "${rootProject.description} ${version} API"
dependsOn { dependsOn {
documentedProjects.collect { moduleProjects.collect {
it.tasks.getByName("jar") it.tasks.getByName("jar")
} }
} }
@ -37,7 +33,7 @@ task api(type: Javadoc) {
// ensure the javadoc process can resolve types compiled from .aj sources // ensure the javadoc process can resolve types compiled from .aj sources
project(":spring-aspects").sourceSets.main.output project(":spring-aspects").sourceSets.main.output
) )
classpath += files(documentedProjects.collect { it.sourceSets.main.compileClasspath }) classpath += files(moduleProjects.collect { it.sourceSets.main.compileClasspath })
} }
options { options {
@ -52,7 +48,7 @@ task api(type: Javadoc) {
addBooleanOption('Xdoclint:syntax', true) // only check syntax with doclint addBooleanOption('Xdoclint:syntax', true) // only check syntax with doclint
addBooleanOption('Werror', true) // fail build on Javadoc warnings addBooleanOption('Werror', true) // fail build on Javadoc warnings
} }
source documentedProjects.collect { project -> source moduleProjects.collect { project ->
project.sourceSets.main.allJava project.sourceSets.main.allJava
} }
maxMemory = "1024m" maxMemory = "1024m"
@ -184,7 +180,7 @@ task schemaZip(type: Zip) {
description = "Builds -${archiveClassifier} archive containing all " + description = "Builds -${archiveClassifier} archive containing all " +
"XSDs for deployment at https://springframework.org/schema." "XSDs for deployment at https://springframework.org/schema."
duplicatesStrategy DuplicatesStrategy.EXCLUDE duplicatesStrategy DuplicatesStrategy.EXCLUDE
documentedProjects.each { module -> moduleProjects.each { module ->
def Properties schemas = new Properties(); def Properties schemas = new Properties();
module.sourceSets.main.resources.find { module.sourceSets.main.resources.find {
@ -234,7 +230,7 @@ task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
into "${baseDir}/schema" into "${baseDir}/schema"
} }
documentedProjects.each { module -> moduleProjects.each { module ->
into ("${baseDir}/libs") { into ("${baseDir}/libs") {
from module.jar from module.jar
if (module.tasks.findByPath("sourcesJar")) { if (module.tasks.findByPath("sourcesJar")) {
@ -247,4 +243,4 @@ task distZip(type: Zip, dependsOn: [docsZip, schemaZip]) {
} }
} }
distZip.mustRunAfter documentedProjects.check distZip.mustRunAfter moduleProjects.check

4
settings.gradle

@ -18,8 +18,8 @@ include "spring-context"
include "spring-context-indexer" include "spring-context-indexer"
include "spring-context-support" include "spring-context-support"
include "spring-core" include "spring-core"
include "spring-core-graalvm" include "graalvm-feature"
project(':spring-core-graalvm').projectDir = file('spring-core/graalvm') project(':graalvm-feature').projectDir = file('spring-core/graalvm')
include "spring-core-test" include "spring-core-test"
include "spring-expression" include "spring-expression"
include "spring-instrument" include "spring-instrument"

12
spring-core/graalvm/spring-core-graalvm.gradle → spring-core/graalvm/graalvm-feature.gradle

@ -34,15 +34,3 @@ eclipse.classpath.file {
dependencies { dependencies {
compileOnly("org.graalvm.nativeimage:svm") compileOnly("org.graalvm.nativeimage:svm")
} }
tasks.withType(PublishToMavenRepository) {
enabled = false
}
tasks.withType(PublishToMavenLocal) {
enabled = false
}
tasks.withType(Javadoc) {
enabled = false
}

2
spring-core/spring-core.gradle

@ -45,7 +45,7 @@ dependencies {
cglib("cglib:cglib:${cglibVersion}@jar") cglib("cglib:cglib:${cglibVersion}@jar")
javapoet("com.squareup:javapoet:${javapoetVersion}@jar") javapoet("com.squareup:javapoet:${javapoetVersion}@jar")
objenesis("org.objenesis:objenesis:${objenesisVersion}@jar") objenesis("org.objenesis:objenesis:${objenesisVersion}@jar")
graalvm(project(path: ":spring-core-graalvm", configuration: 'classesOnlyElements')) graalvm(project(path: ":graalvm-feature", configuration: 'classesOnlyElements'))
api(files(cglibRepackJar)) api(files(cglibRepackJar))
api(files(javapoetRepackJar)) api(files(javapoetRepackJar))
api(files(objenesisRepackJar)) api(files(objenesisRepackJar))

Loading…
Cancel
Save