Gradle plugin - improve compatibility with Configuration Cache (#1825)
* fix javadoc * avoid use of Gradle Project by using properties and injected build services * tidy up buildRootPath * fix long message to use projectGroupNameVersion
This commit is contained in:
@@ -34,10 +34,12 @@ import org.gradle.api.DefaultTask;
|
||||
import org.gradle.api.GradleException;
|
||||
import org.gradle.api.file.ConfigurableFileCollection;
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.file.FileSystemOperations;
|
||||
import org.gradle.api.model.ObjectFactory;
|
||||
import org.gradle.api.provider.MapProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.provider.ProviderFactory;
|
||||
import org.gradle.api.tasks.CacheableTask;
|
||||
import org.gradle.api.tasks.Classpath;
|
||||
import org.gradle.api.tasks.Input;
|
||||
@@ -49,6 +51,7 @@ import org.gradle.api.tasks.OutputDirectory;
|
||||
import org.gradle.api.tasks.PathSensitive;
|
||||
import org.gradle.api.tasks.PathSensitivity;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.process.ExecOperations;
|
||||
import org.springframework.cloud.contract.stubrunner.ContractDownloader;
|
||||
import org.springframework.cloud.contract.stubrunner.ScmStubDownloaderBuilder;
|
||||
import org.springframework.cloud.contract.stubrunner.StubConfiguration;
|
||||
@@ -100,7 +103,7 @@ class ContractsCopyTask extends DefaultTask {
|
||||
private final Property<Boolean> excludeBuildFolders;
|
||||
|
||||
/**
|
||||
* @see ContractVerifierExtension#deleteStubsAfterTest
|
||||
* @see ContractVerifierExtension#getDeleteStubsAfterTest()
|
||||
*
|
||||
* This property will delete the temporary dependency or Git repository from which
|
||||
* stubs were copied to this task's output directory.
|
||||
@@ -114,8 +117,23 @@ class ContractsCopyTask extends DefaultTask {
|
||||
|
||||
private final DirectoryProperty backupContractsFolder;
|
||||
|
||||
private final Property<String> projectGroup;
|
||||
private final Property<String> projectName;
|
||||
private final Property<String> projectVersion;
|
||||
|
||||
private final ExecOperations executors;
|
||||
private final FileSystemOperations files;
|
||||
|
||||
@Inject
|
||||
public ContractsCopyTask(ObjectFactory objects) {
|
||||
public ContractsCopyTask(
|
||||
final ObjectFactory objects,
|
||||
final ProviderFactory providers,
|
||||
final ExecOperations executors,
|
||||
final FileSystemOperations files
|
||||
) {
|
||||
this.executors = executors;
|
||||
this.files = files;
|
||||
|
||||
convertToYaml = objects.property(Boolean.class);
|
||||
failOnNoContracts = objects.property(Boolean.class);
|
||||
contractsDirectory = objects.directoryProperty();
|
||||
@@ -140,6 +158,10 @@ class ContractsCopyTask extends DefaultTask {
|
||||
copiedContractsFolder = objects.directoryProperty();
|
||||
backupContractsFolder = objects.directoryProperty();
|
||||
|
||||
projectGroup = objects.property(String.class).convention(providers.provider(() -> getProject().getGroup().toString()));
|
||||
projectName = objects.property(String.class).convention(providers.provider(() -> getProject().getName()));
|
||||
projectVersion = objects.property(String.class).convention(providers.provider(() -> getProject().getVersion().toString()));
|
||||
|
||||
this.getOutputs().upToDateWhen(task -> !(this.shouldDownloadContracts()
|
||||
&& this.getContractDependency().toStubConfiguration().isVersionChanging()));
|
||||
}
|
||||
@@ -158,14 +180,13 @@ class ContractsCopyTask extends DefaultTask {
|
||||
contractsDirectory = this.contractsDirectory.getAsFile().getOrNull();
|
||||
antPattern = "**/";
|
||||
}
|
||||
getLogger().info("For project [{}] will use contracts provided in the folder [{}]", getProject().getName(),
|
||||
getLogger().info("For project [{}] will use contracts provided in the folder [{}]", projectName.get(),
|
||||
contractsDirectory);
|
||||
final String contractsRepository = this.contractRepository.getRepositoryUrl().getOrElse("");
|
||||
throwExceptionWhenFailOnNoContracts(contractsDirectory, contractsRepository);
|
||||
|
||||
final String slashSeparatedGroupId = getProject().getGroup().toString().replace(".", File.separator);
|
||||
final String dotSeparatedAntPattern = antPattern.replace(slashSeparatedGroupId,
|
||||
getProject().getGroup().toString());
|
||||
final String slashSeparatedGroupId = projectGroup.get().replace(".", File.separator);
|
||||
final String dotSeparatedAntPattern = antPattern.replace(slashSeparatedGroupId, projectGroup.get());
|
||||
File output = copiedContractsFolder.get().getAsFile();
|
||||
getLogger().info(
|
||||
"Downloading and unpacking files from [{}] to [{}]. The inclusion ant patterns are [{}] and [{}]",
|
||||
@@ -187,8 +208,8 @@ class ContractsCopyTask extends DefaultTask {
|
||||
os = NullOutputStream.INSTANCE;
|
||||
}
|
||||
try {
|
||||
getProject().javaexec(exec -> {
|
||||
exec.setMain("org.springframework.cloud.contract.verifier.converter.ToYamlConverterApplication");
|
||||
executors.javaexec(exec -> {
|
||||
exec.getMainClass().set("org.springframework.cloud.contract.verifier.converter.ToYamlConverterApplication");
|
||||
exec.classpath(classpath);
|
||||
exec.args(quoteAndEscape(outputContractsFolder.getAbsolutePath()));
|
||||
exec.setStandardOutput(os);
|
||||
@@ -206,7 +227,7 @@ class ContractsCopyTask extends DefaultTask {
|
||||
|
||||
private void sync(File file, String antPattern, String dotSeparatedAntPattern, boolean excludeBuildFolders,
|
||||
File outputContractsFolder) {
|
||||
getProject().sync(spec -> {
|
||||
files.sync(spec -> {
|
||||
spec.from(file);
|
||||
// by default group id is slash separated...
|
||||
spec.include(antPattern);
|
||||
@@ -220,8 +241,8 @@ class ContractsCopyTask extends DefaultTask {
|
||||
}
|
||||
|
||||
private DownloadedData downloadContracts() {
|
||||
String groupId = getProject().getGroup().toString();
|
||||
String artifactId = getProject().getName();
|
||||
String groupId = projectGroup.get();
|
||||
String artifactId = projectName.get();
|
||||
getLogger().info("Project has group id [{}], artifact id [{}]", groupId, artifactId);
|
||||
getLogger().info("For project [{}] Download dependency is provided - will download contract jars", artifactId);
|
||||
getLogger().info("Contract dependency [{}]", contractDependency);
|
||||
@@ -231,7 +252,7 @@ class ContractsCopyTask extends DefaultTask {
|
||||
|
||||
final StubDownloader downloader = new StubDownloaderBuilderProvider().get(createStubRunnerOptions());
|
||||
final ContractDownloader contractDownloader = new ContractDownloader(downloader, configuration,
|
||||
contractsPath.getOrNull(), groupId, artifactId, getProject().getVersion().toString());
|
||||
contractsPath.getOrNull(), groupId, artifactId, projectVersion.get());
|
||||
final File downloadedContracts = contractDownloader.unpackAndDownloadContracts();
|
||||
final ContractDownloader.InclusionProperties inclusionProperties = contractDownloader
|
||||
.createNewInclusionProperties(downloadedContracts);
|
||||
@@ -280,6 +301,10 @@ class ContractsCopyTask extends DefaultTask {
|
||||
|
||||
}
|
||||
|
||||
@Input protected Property<String> getProjectGroup() { return projectGroup; }
|
||||
@Input protected Property<String> getProjectName() { return projectName; }
|
||||
@Input protected Property<String> getProjectVersion() { return projectVersion; }
|
||||
|
||||
@Input
|
||||
Property<Boolean> getConvertToYaml() {
|
||||
return convertToYaml;
|
||||
|
||||
@@ -40,6 +40,7 @@ import org.gradle.api.tasks.PathSensitive;
|
||||
import org.gradle.api.tasks.PathSensitivity;
|
||||
import org.gradle.api.tasks.SkipWhenEmpty;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.process.ExecOperations;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
//TODO: Implement as an incremental task: https://gradle.org/docs/current/userguide/custom_tasks.html#incremental_tasks ?
|
||||
@@ -67,8 +68,15 @@ class GenerateClientStubsFromDslTask extends DefaultTask {
|
||||
|
||||
private final DirectoryProperty stubsOutputDir;
|
||||
|
||||
final ExecOperations executors;
|
||||
|
||||
@Inject
|
||||
public GenerateClientStubsFromDslTask(ObjectFactory objects) {
|
||||
public GenerateClientStubsFromDslTask(
|
||||
final ObjectFactory objects,
|
||||
final ExecOperations executors
|
||||
) {
|
||||
this.executors = executors;
|
||||
|
||||
contractsDslDir = objects.directoryProperty();
|
||||
excludedFiles = objects.listProperty(String.class);
|
||||
excludeBuildFolders = objects.property(Boolean.class);
|
||||
@@ -90,7 +98,7 @@ class GenerateClientStubsFromDslTask extends DefaultTask {
|
||||
os = NullOutputStream.INSTANCE;
|
||||
}
|
||||
try {
|
||||
getProject().javaexec(exec -> {
|
||||
executors.javaexec(exec -> {
|
||||
exec.getMainClass().set("org.springframework.cloud.contract.verifier.converter.RecursiveFilesConverterApplication");
|
||||
exec.classpath(classpath);
|
||||
exec.args(quoteAndEscape(output.getAbsolutePath()), quoteAndEscape(contractsDslDir.get().getAsFile().getAbsolutePath()),
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.gradle.api.tasks.PathSensitive;
|
||||
import org.gradle.api.tasks.PathSensitivity;
|
||||
import org.gradle.api.tasks.SkipWhenEmpty;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.process.ExecOperations;
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties;
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.config.TestMode;
|
||||
@@ -97,8 +98,15 @@ class GenerateServerTestsTask extends DefaultTask {
|
||||
|
||||
private final DirectoryProperty generatedTestResourcesDir;
|
||||
|
||||
final ExecOperations executors;
|
||||
|
||||
@Inject
|
||||
public GenerateServerTestsTask(ObjectFactory objects) {
|
||||
public GenerateServerTestsTask(
|
||||
final ObjectFactory objects,
|
||||
final ExecOperations executors
|
||||
) {
|
||||
this.executors = executors;
|
||||
|
||||
this.contractsDslDir = objects.directoryProperty();
|
||||
this.nameSuffixForTests = objects.property(String.class);
|
||||
this.basePackageForTests = objects.property(String.class);
|
||||
@@ -139,8 +147,8 @@ class GenerateServerTestsTask extends DefaultTask {
|
||||
}
|
||||
try {
|
||||
String propertiesJson = new ObjectMapper().writeValueAsString(properties);
|
||||
getProject().javaexec(exec -> {
|
||||
exec.setMain("org.springframework.cloud.contract.verifier.TestGeneratorApplication");
|
||||
executors.javaexec(exec -> {
|
||||
exec.getMainClass().set("org.springframework.cloud.contract.verifier.TestGeneratorApplication");
|
||||
exec.classpath(classpath);
|
||||
exec.args(quoteAndEscape(propertiesJson));
|
||||
exec.setStandardOutput(os);
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.model.ObjectFactory;
|
||||
import org.gradle.api.provider.MapProperty;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.ProviderFactory;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.InputDirectory;
|
||||
import org.gradle.api.tasks.Nested;
|
||||
@@ -40,7 +41,7 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* For SCM based repositories will copy the generated stubs to the cloned repo with
|
||||
* contracts and stubs. Will also commit the changes and push them to origin.
|
||||
*
|
||||
* <p>
|
||||
* NOTE: starting with 2.3.0.RELEASE the <code>customize{}</code> closure previously used
|
||||
* for {@link PublishStubsToScmTask} customisation is no longer available. The settings
|
||||
* should be applied directly within the <code>publishStubsToScm</code> closure as in the
|
||||
@@ -60,7 +61,7 @@ class PublishStubsToScmTask extends DefaultTask {
|
||||
private final Property<StubRunnerProperties.StubsMode> contractsMode;
|
||||
|
||||
/**
|
||||
* @see ContractVerifierExtension#deleteStubsAfterTest
|
||||
* @see ContractVerifierExtension#getDeleteStubsAfterTest()
|
||||
*
|
||||
* This property will delete the Git repository where the input stubs to this task
|
||||
* have been committed.
|
||||
@@ -73,8 +74,15 @@ class PublishStubsToScmTask extends DefaultTask {
|
||||
|
||||
private final DirectoryProperty stubsDir;
|
||||
|
||||
private final Property<String> projectGroup;
|
||||
private final Property<String> projectName;
|
||||
private final Property<String> projectVersion;
|
||||
|
||||
@Inject
|
||||
public PublishStubsToScmTask(ObjectFactory objects) {
|
||||
public PublishStubsToScmTask(
|
||||
final ObjectFactory objects,
|
||||
final ProviderFactory providers
|
||||
) {
|
||||
this.contractRepository = objects.newInstance(Repository.class);
|
||||
this.contractsMode = objects.property(StubRunnerProperties.StubsMode.class);
|
||||
this.deleteStubsAfterTest = objects.property(Boolean.class);
|
||||
@@ -82,6 +90,10 @@ class PublishStubsToScmTask extends DefaultTask {
|
||||
this.contractsProperties = objects.mapProperty(String.class, String.class);
|
||||
this.stubsDir = objects.directoryProperty();
|
||||
|
||||
projectGroup = objects.property(String.class).convention(providers.provider(() -> getProject().getGroup().toString()));
|
||||
projectName = objects.property(String.class).convention(providers.provider(() -> getProject().getName()));
|
||||
projectVersion = objects.property(String.class).convention(providers.provider(() -> getProject().getVersion().toString()));
|
||||
|
||||
this.onlyIf(task -> {
|
||||
String contractRepoUrl = contractRepository.repositoryUrl.getOrElse("");
|
||||
if (!StringUtils.hasText(contractRepoUrl) || !ScmStubDownloaderBuilder.isProtocolAccepted(contractRepoUrl)) {
|
||||
@@ -96,11 +108,10 @@ class PublishStubsToScmTask extends DefaultTask {
|
||||
|
||||
@TaskAction
|
||||
void publishStubsToScm() {
|
||||
String projectName = getProject().getGroup().toString() + ":" + getProject().getName() + ":"
|
||||
+ getProject().getVersion().toString();
|
||||
getLogger().info("Pushing Stubs to SCM for project [{}]", projectName);
|
||||
String projectGroupNameVersion = projectGroup.get() + ":" + projectName.get() + ":" + projectVersion.get();
|
||||
getLogger().info("Pushing Stubs to SCM for project [{}]", projectGroupNameVersion);
|
||||
StubRunnerOptions stubRunnerOptions = createStubRunnerOptions();
|
||||
new ContractProjectUpdater(stubRunnerOptions).updateContractProject(projectName,
|
||||
new ContractProjectUpdater(stubRunnerOptions).updateContractProject(projectGroupNameVersion,
|
||||
stubsDir.get().getAsFile().toPath());
|
||||
}
|
||||
|
||||
@@ -202,4 +213,7 @@ class PublishStubsToScmTask extends DefaultTask {
|
||||
return options.build();
|
||||
}
|
||||
|
||||
@Input protected Property<String> getProjectGroup() { return projectGroup; }
|
||||
@Input protected Property<String> getProjectName() { return projectName; }
|
||||
@Input protected Property<String> getProjectVersion() { return projectVersion; }
|
||||
}
|
||||
|
||||
@@ -24,19 +24,18 @@ import org.gradle.api.attributes.Bundling;
|
||||
import org.gradle.api.attributes.Category;
|
||||
import org.gradle.api.attributes.LibraryElements;
|
||||
import org.gradle.api.attributes.Usage;
|
||||
import org.gradle.api.file.Directory;
|
||||
import org.gradle.api.file.DirectoryProperty;
|
||||
import org.gradle.api.file.FileCollection;
|
||||
import org.gradle.api.file.*;
|
||||
import org.gradle.api.internal.HasConvention;
|
||||
import org.gradle.api.logging.Logger;
|
||||
import org.gradle.api.logging.Logging;
|
||||
import org.gradle.api.model.ObjectFactory;
|
||||
import org.gradle.api.plugins.GroovyPlugin;
|
||||
import org.gradle.api.plugins.JavaBasePlugin;
|
||||
import org.gradle.api.plugins.JavaPlugin;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.provider.Property;
|
||||
import org.gradle.api.provider.Provider;
|
||||
import org.gradle.api.publish.PublishingExtension;
|
||||
import org.gradle.api.publish.maven.MavenPublication;
|
||||
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
|
||||
import org.gradle.api.provider.ProviderFactory;
|
||||
import org.gradle.api.tasks.GroovySourceSet;
|
||||
import org.gradle.api.tasks.SourceSet;
|
||||
import org.gradle.api.tasks.SourceSetContainer;
|
||||
@@ -46,6 +45,7 @@ import org.gradle.api.tasks.bundling.Jar;
|
||||
import org.gradle.api.tasks.testing.Test;
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
@@ -63,6 +63,8 @@ import java.io.File;
|
||||
*/
|
||||
public class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
|
||||
|
||||
private static final Logger logger = Logging.getLogger(SpringCloudContractVerifierGradlePlugin.class);
|
||||
|
||||
private static final String SPRING_CLOUD_VERSION = VersionExtractor.forClass(SpringCloudContractVerifierGradlePlugin.class);
|
||||
|
||||
private static final String GROUP_NAME = "Verification";
|
||||
@@ -87,6 +89,21 @@ public class SpringCloudContractVerifierGradlePlugin implements Plugin<Project>
|
||||
|
||||
private Project project;
|
||||
|
||||
private final ProjectLayout layout;
|
||||
private final ProviderFactory providers;
|
||||
private final ObjectFactory objects;
|
||||
|
||||
@Inject
|
||||
public SpringCloudContractVerifierGradlePlugin(
|
||||
final ProjectLayout layout,
|
||||
final ProviderFactory providers,
|
||||
final ObjectFactory objects
|
||||
) {
|
||||
this.layout = layout;
|
||||
this.providers = providers;
|
||||
this.objects = objects;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void apply(Project project) {
|
||||
this.project = project;
|
||||
@@ -169,10 +186,10 @@ public class SpringCloudContractVerifierGradlePlugin implements Plugin<Project>
|
||||
conf.setCanBeResolved(true);
|
||||
conf.setCanBeConsumed(false);
|
||||
conf.attributes(attributes -> {
|
||||
attributes.attribute(Usage.USAGE_ATTRIBUTE, project.getObjects().named(Usage.class, Usage.JAVA_RUNTIME));
|
||||
attributes.attribute(Category.CATEGORY_ATTRIBUTE, project.getObjects().named(Category.class, Category.LIBRARY));
|
||||
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.getObjects().named(LibraryElements.class, LibraryElements.JAR));
|
||||
attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, project.getObjects().named(Bundling.class, Bundling.EXTERNAL));
|
||||
attributes.attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.class, Usage.JAVA_RUNTIME));
|
||||
attributes.attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.class, Category.LIBRARY));
|
||||
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.class, LibraryElements.JAR));
|
||||
attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling.class, Bundling.EXTERNAL));
|
||||
});
|
||||
conf.extendsFrom(configurations.getByName(CONTRACT_TEST_RUNTIME_CLASSPATH_CONFIGURATION_NAME));
|
||||
});
|
||||
@@ -316,7 +333,7 @@ public class SpringCloudContractVerifierGradlePlugin implements Plugin<Project>
|
||||
verifierStubsJar.configure(stubsJar -> {
|
||||
stubsJar.setDescription("Creates the stubs JAR task");
|
||||
stubsJar.setGroup(GROUP_NAME);
|
||||
stubsJar.getArchiveBaseName().convention(project.provider(project::getName));
|
||||
stubsJar.getArchiveBaseName().convention(providers.provider(project::getName));
|
||||
stubsJar.getArchiveClassifier().convention(extension.getStubsSuffix());
|
||||
stubsJar.from(extension.getStubsOutputDir());
|
||||
|
||||
@@ -335,15 +352,15 @@ public class SpringCloudContractVerifierGradlePlugin implements Plugin<Project>
|
||||
contractsCopyTask.getFailOnNoContracts().convention(extension.getFailOnNoContracts());
|
||||
contractsCopyTask.getContractsDirectory()
|
||||
.convention(extension.getContractsDslDir().flatMap(contractsDslDir -> {
|
||||
return project.provider(() -> {
|
||||
return providers.provider(() -> {
|
||||
if (contractsDslDir.getAsFile().exists()) {
|
||||
return contractsDslDir;
|
||||
}
|
||||
else {
|
||||
Directory legacyContractsDslDir = project.getLayout().getProjectDirectory()
|
||||
Directory legacyContractsDslDir = layout.getProjectDirectory()
|
||||
.dir("src/test/resources/contracts");
|
||||
if (legacyContractsDslDir.getAsFile().exists()) {
|
||||
project.getLogger().warn(
|
||||
logger.warn(
|
||||
"Spring Cloud Contract Verifier Plugin: Locating contracts in <src/test/resources/contracts> has been removed. Please move them to <src/contractTest/resources/contracts>. This warning message will be removed in a future release.");
|
||||
return contractsDslDir;
|
||||
}
|
||||
@@ -390,13 +407,17 @@ public class SpringCloudContractVerifierGradlePlugin implements Plugin<Project>
|
||||
}
|
||||
|
||||
private Provider<String> buildRootPath(String path) {
|
||||
return project.provider(() -> {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
builder.append("META-INF").append(File.separator).append(project.getGroup()).append(File.separator)
|
||||
.append(project.getName()).append(File.separator).append(project.getVersion())
|
||||
.append(File.separator).append(path);
|
||||
return builder.toString();
|
||||
});
|
||||
return providers.provider(() ->
|
||||
"META-INF"
|
||||
+ File.separator
|
||||
+ project.getGroup()
|
||||
+ File.separator
|
||||
+ project.getName()
|
||||
+ File.separator
|
||||
+ project.getVersion()
|
||||
+ File.separator
|
||||
+ path
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user