diff --git a/docs/src/main/asciidoc/verifier_faq.adoc b/docs/src/main/asciidoc/verifier_faq.adoc index 7a4e2a3bdd..6a3c15cd8b 100644 --- a/docs/src/main/asciidoc/verifier_faq.adoc +++ b/docs/src/main/asciidoc/verifier_faq.adoc @@ -621,6 +621,32 @@ to find contracts. E.g. for `com.example:foo:1.0.0` the path would be * Once the tests pass, the stubs will be committed in the cloned repository * Finally, a push will be done to that repo's `origin` +==== Producer with contracts stored locally + +Another option to use the SCM as the destination for stubs and contracts is to store the contracts locally, with the producer, and only push the contracts and the stubs to SCM. Below, you can find the setup required to achieve this using Maven and Gradle. + +.Maven +[source,xml,indent=0] +---- +include::{samples_url}/producer_with_empty_git/pom.xml[tags=plugin,indent=0] +---- + +.Gradle +[source,xml,indent=0] +---- +include::{samples_url}/producer_with_empty_git/build.gradle[tags=plugin,indent=0] +---- + +With such a setup: + +* Contracts from the default `src/test/resources/contracts` directory will be picked +* Tests will be generated from the contracts +* Stubs will be created from the contracts +* Once the tests pass +** Git project will be cloned to a temporary directory +** The stubs and contracts will be committed in the cloned repository +* Finally, a push will be done to that repo's `origin` + ===== Keeping contracts with the producer and stubs in an external repository It is also possible to keep the contracts in the producer repository, but keep the stubs in an external git repo. diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerPropertyUtils.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerPropertyUtils.java index 53a5145371..02b99c5321 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerPropertyUtils.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerPropertyUtils.java @@ -29,7 +29,11 @@ import org.springframework.util.StringUtils; * @author Marcin Grzejszczak * @since 2.0.0 */ -class StubRunnerPropertyUtils { +public final class StubRunnerPropertyUtils { + + private StubRunnerPropertyUtils() { + throw new IllegalStateException("Can't instantiate a utility class"); + } private static final Log log = LogFactory.getLog(StubRunnerPropertyUtils.class); @@ -41,7 +45,7 @@ class StubRunnerPropertyUtils { * For Env vars takes the prop name, converts dots to underscores and applies upper * case */ - static boolean isPropertySet(String propName) { + public static boolean isPropertySet(String propName) { String value = getProperty(new HashMap<>(), propName); return StringUtils.hasText(value) && Boolean.parseBoolean(value); } @@ -49,7 +53,7 @@ class StubRunnerPropertyUtils { /** * For options, system props and env vars returns {@code true} when property is set */ - static boolean hasProperty(Map options, String propName) { + public static boolean hasProperty(Map options, String propName) { String value = getProperty(options, propName); return StringUtils.hasText(value); } @@ -58,7 +62,7 @@ class StubRunnerPropertyUtils { * Tries to pick a value from options, for Env vars takes the prop name, converts dots * to underscores and applies upper case */ - static String getProperty(Map options, String propName) { + public static String getProperty(Map options, String propName) { if (options != null && options.containsKey(propName)) { String value = options.get(propName); if (log.isTraceEnabled()) { diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierExtension.groovy b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierExtension.groovy index a0edf281e1..91eaa39f54 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierExtension.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ContractVerifierExtension.groovy @@ -28,7 +28,7 @@ import org.springframework.cloud.contract.verifier.config.TestMode * @author Marcin Grzejszczak */ @ToString -class ContractVerifierExtension { +class ContractVerifierExtension implements Cloneable { private static final Log log = LogFactory.getLog(ContractVerifierExtension) @@ -241,7 +241,7 @@ class ContractVerifierExtension { } @ToString(includeNames = true, includePackage = false) - static class Dependency { + static class Dependency implements Cloneable { String groupId String artifactId String classifier @@ -269,7 +269,7 @@ class ContractVerifierExtension { } } - static class BaseClassMapping { + static class BaseClassMapping implements Cloneable { private final Map delegate BaseClassMapping(Map delegate) { @@ -285,7 +285,7 @@ class ContractVerifierExtension { } } - static class ContractRepository { + static class ContractRepository implements Cloneable { /** * Repository URL */ diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ExtensionHolderSpec.groovy b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ExtensionHolderSpec.groovy new file mode 100644 index 0000000000..9a29bd1ec6 --- /dev/null +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ExtensionHolderSpec.groovy @@ -0,0 +1,29 @@ +/* + * Copyright 2013-2018 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.plugin + +/** + * Allows to set the {@link Closure} that will modify the existing + * {@link ContractVerifierExtension} + * + * @author Marcin Grzejszczak + * @since 2.1.0 + */ +interface ExtensionHolderSpec { + Closure getExtensionClosure() + void setExtensionClosure(Closure closure) +} \ No newline at end of file diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/PublishStubsToScmTask.groovy b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/PublishStubsToScmTask.groovy index e56152d78d..ff01af28ac 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/PublishStubsToScmTask.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/PublishStubsToScmTask.groovy @@ -16,12 +16,12 @@ package org.springframework.cloud.contract.verifier.plugin -import groovy.transform.CompileStatic -import groovy.transform.PackageScope + import org.gradle.api.internal.ConventionTask import org.gradle.api.tasks.TaskAction import org.springframework.cloud.contract.stubrunner.ContractProjectUpdater +import org.springframework.cloud.contract.stubrunner.ScmStubDownloaderBuilder import org.springframework.cloud.contract.stubrunner.StubRunnerOptions /** @@ -32,18 +32,46 @@ import org.springframework.cloud.contract.stubrunner.StubRunnerOptions * @author Marcin Grzejszczak * @since 2.0.0 */ -@PackageScope -@CompileStatic class PublishStubsToScmTask extends ConventionTask { File stubsOutputDir ContractVerifierExtension configProperties GradleContractsDownloader downloader + private final ExtensionHolderSpec closureHolder = new ClosureHolder() @TaskAction void publishStubsToScm() { + if (shouldRun()) { + return + } String projectName = project.group.toString() + ":" + project.name.toString() + ":" + this.project.version.toString() project.logger.info("Pushing Stubs to SCM for project [" + projectName + "]") - StubRunnerOptions options = getDownloader().options(getConfigProperties()) + ContractVerifierExtension clonedExtension = modifyExtension() + StubRunnerOptions options = getDownloader().options(clonedExtension) new ContractProjectUpdater(options).updateContractProject(projectName, getStubsOutputDir().toPath()) } + + private ContractVerifierExtension modifyExtension() { + ContractVerifierExtension clone = (ContractVerifierExtension) + getConfigProperties().clone() + this.closureHolder.extensionClosure.delegate = clone + this.closureHolder.extensionClosure.call(clone) + return clone + } + + private boolean shouldRun() { + String contractRepoUrl = getConfigProperties().contractRepository.repositoryUrl ?: "" + if (!contractRepoUrl || !ScmStubDownloaderBuilder.isProtocolAccepted(contractRepoUrl)) { + project.logger.info("Skipping pushing stubs to scm since your contracts repository URL doesn't match any of the accepted protocols") + return false + } + return true + } + + void customize(@DelegatesTo(ContractVerifierExtension) Closure closure) { + this.closureHolder.extensionClosure = closure + } + + private static class ClosureHolder implements ExtensionHolderSpec { + Closure extensionClosure = Closure.IDENTITY + } } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/SpringCloudContractVerifierGradlePlugin.groovy b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/SpringCloudContractVerifierGradlePlugin.groovy index d3dea18ac2..8899f07f9d 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/SpringCloudContractVerifierGradlePlugin.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/SpringCloudContractVerifierGradlePlugin.groovy @@ -24,9 +24,6 @@ import org.gradle.api.plugins.GroovyPlugin import org.gradle.api.publish.maven.MavenPublication import org.gradle.api.publish.maven.plugins.MavenPublishPlugin import org.gradle.jvm.tasks.Jar - -import org.springframework.cloud.contract.stubrunner.ScmStubDownloaderBuilder - /** * Gradle plugin for Spring Cloud Contract Verifier that from the DSL contract can *
    @@ -125,14 +122,6 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin { configProperties = { extension } stubsOutputDir = { extension.stubsOutputDir } } - task.onlyIf { - String contractRepoUrl = extension.contractRepository.repositoryUrl ?: "" - if (!contractRepoUrl || !ScmStubDownloaderBuilder.isProtocolAccepted(contractRepoUrl)) { - project.logger.info("Skipping pushing stubs to scm since your contracts repository URL doesn't match any of the accepted protocols") - return false - } - return true - } task.dependsOn DSL_TO_CLIENT_TASK_NAME }