diff --git a/README.adoc b/README.adoc index bb5706f008..a488936dcd 100644 --- a/README.adoc +++ b/README.adoc @@ -342,13 +342,11 @@ Full test is generated by Spring Cloud Contract Verifier. Spring Cloud Contract Verifier moves TDD to the level of software architecture. -==== Spring Cloud Contract Webinar +==== Spring Cloud Contract video -You can check out the video from the Spring Cloud Contract Webinar to watch the -explanation of the project and the concept of Consuner Driven Contracts. Video was recorded -on 25.10.2016. +You can check out the video from the Warsaw JUG about Spring Cloud Contract: -video::4fJiz0woxAc[youtube] +video::sAAklvxmPmk[youtube,start=538,width=640,height=480] ==== Why? diff --git a/docs/src/main/asciidoc/verifier/introduction.adoc b/docs/src/main/asciidoc/verifier/introduction.adoc index 5f9939af55..bc215130ed 100644 --- a/docs/src/main/asciidoc/verifier/introduction.adoc +++ b/docs/src/main/asciidoc/verifier/introduction.adoc @@ -17,13 +17,11 @@ Full test is generated by Spring Cloud Contract Verifier. Spring Cloud Contract Verifier moves TDD to the level of software architecture. -==== Spring Cloud Contract Webinar +==== Spring Cloud Contract video -You can check out the video from the Spring Cloud Contract Webinar to watch the -explanation of the project and the concept of Consuner Driven Contracts. Video was recorded -on 25.10.2016. +You can check out the video from the Warsaw JUG about Spring Cloud Contract: -video::4fJiz0woxAc[youtube] +video::sAAklvxmPmk[youtube,start=538,width=640,height=480] ==== Why? diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverter.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverter.groovy index 49d33b0d14..38c6bc6a19 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverter.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverter.groovy @@ -67,6 +67,13 @@ class RecursiveFilesConverter { File sourceFile = contract.path.toFile() StubGenerator stubGenerator = holder.converterForName(sourceFile.name); try { + String path = sourceFile.path + if (properties.isExcludeBuildFolders() && (matchesPath(path, "target") || matchesPath(path, "build"))) { + if (log.isDebugEnabled()) { + log.debug("Exclude build folder is set. Path [${path}] contains [target] or [build] in its path") + } + return + } if (!contract.convertedContract && !stubGenerator) { return } @@ -90,6 +97,10 @@ class RecursiveFilesConverter { } } + private boolean matchesPath(String path, String folder) { + return path.matches("^.*${File.separator}${folder}${File.separator}.*\$") + } + private Path createAndReturnTargetDirectory(File sourceFile) { Path relativePath = Paths.get(properties.contractsDslDir.toURI()).relativize(sourceFile.parentFile.toPath()) Path absoluteTargetPath = outMappingsDir.toPath().resolve(relativePath) diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy index af860e0ff4..31380e4f74 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy @@ -80,13 +80,21 @@ class RecursiveFilesConverter { properties.excludedFiles as Set, [] as Set, properties.includedContracts) ListMultimap contracts = scanner.findContracts() if (log.isDebugEnabled()) { - log.debug("Found the following contracts $contracts") + log.debug("Found the following contracts ${contracts}") + log.debug("Exclude build folder: [${properties.isExcludeBuildFolders()}]") } contracts.asMap().entrySet().each { entry -> entry.value.each { ContractMetadata contract -> File sourceFile = contract.path.toFile() StubGenerator stubGenerator = holder.converterForName(sourceFile.name); try { + String path = sourceFile.path + if (properties.isExcludeBuildFolders() && (matchesPath(path, "target") || matchesPath(path, "build"))) { + if (log.isDebugEnabled()) { + log.debug("Exclude build folder is set. Path [${path}] contains [target] or [build] in its path") + } + return + } if (!contract.convertedContract && !stubGenerator) { return } @@ -110,6 +118,10 @@ class RecursiveFilesConverter { } } + private boolean matchesPath(String path, String folder) { + return path.matches("^.*${File.separator}${folder}${File.separator}.*\$") + } + private Path createAndReturnTargetDirectory(File sourceFile) { Path relativePath = Paths.get(properties.contractsDslDir.toURI()).relativize(sourceFile.parentFile.toPath()) Path absoluteTargetPath = outMappingsDir.toPath().resolve(relativePath) 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 0d2ceb634f..ca221c0908 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 @@ -134,6 +134,13 @@ class ContractVerifierExtension { */ Map baseClassMappings = [:] + /** + * If set to true then the {@code target} or {@code build} folders are getting + * excluded from any operations. This is used out of the box when working with + * common repo with contracts. + */ + boolean excludeBuildFolders + void contractDependency(@DelegatesTo(Dependency) Closure closure) { closure.delegate = contractDependency closure.call() diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ContractsCopyTask.groovy b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ContractsCopyTask.groovy index 6bd168ba94..0728e9e185 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ContractsCopyTask.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ContractsCopyTask.groovy @@ -32,6 +32,9 @@ class ContractsCopyTask extends ConventionTask { project.copy { from(file) include(antPattern) + if (props.isExcludeBuildFolders()) { + exclude "**/target/**", "**/build/**" + } into(outputContractsFolder) } } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ExtensionToProperties.groovy b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ExtensionToProperties.groovy index 83c6dca318..b9be34cb9a 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ExtensionToProperties.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/ExtensionToProperties.groovy @@ -27,7 +27,8 @@ class ExtensionToProperties { stubsSuffix: extension.stubsSuffix, assertJsonSize: extension.assertJsonSize, packageWithBaseClasses: extension.packageWithBaseClasses, - baseClassMappings: extension.baseClassMappings + baseClassMappings: extension.baseClassMappings, + excludeBuildFolders: extension.excludeBuildFolders ) } } 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 75027b06d3..d52164e878 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 @@ -90,6 +90,7 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin { } } + //TODO: Deprecate this since starting with 1.1.x private void addProjectDependencies(Project project) { //TODO: Consider removing this at some point project.dependencies.add("testCompile", "com.github.tomakehurst:wiremock:2.1.7") diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/ConvertMojo.java b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/ConvertMojo.java index cec6993725..373d00ad0d 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/ConvertMojo.java +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/ConvertMojo.java @@ -108,6 +108,13 @@ public class ConvertMojo extends AbstractMojo { @Parameter(property = "contractsWorkOffline", defaultValue = "false") private boolean contractsWorkOffline; + /** + * If {@code true} then any file laying in a path that contains {@code build} or {@code target} + * will get excluded in further processing. + */ + @Parameter(property = "excludeBuildFolders", defaultValue = "false") + private boolean excludeBuildFolders; + @Component(role = MavenResourcesFiltering.class, hint = "default") private MavenResourcesFiltering mavenResourcesFiltering; @@ -128,6 +135,7 @@ public class ConvertMojo extends AbstractMojo { } // download contracts, unzip them and pass as output directory ContractVerifierConfigProperties config = new ContractVerifierConfigProperties(); + config.setExcludeBuildFolders(this.excludeBuildFolders); File contractsDirectory = new MavenContractsDownloader(this.project, this.contractDependency, this.contractsPath, this.contractsRepositoryUrl, this.contractsWorkOffline, getLog(), this.aetherStubDownloaderFactory, this.repoSession).downloadAndUnpackContractsIfRequired(config, this.contractsDirectory); diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/CopyContracts.java b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/CopyContracts.java index f75b499f2c..54612cf8d6 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/CopyContracts.java +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/CopyContracts.java @@ -54,6 +54,10 @@ class CopyContracts { + "the final JAR with stubs."); Resource resource = new Resource(); resource.addInclude(this.config.getIncludedRootFolderAntPattern() + "*.*"); + if (this.config.isExcludeBuildFolders()) { + resource.addExclude("**/target/**"); + resource.addExclude("**/build/**"); + } resource.setDirectory(contractsDirectory.getAbsolutePath()); MavenResourcesExecution execution = new MavenResourcesExecution(); execution.setResources(Collections.singletonList(resource)); diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/java/org/springframework/cloud/contract/maven/verifier/PluginUnitTest.java b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/java/org/springframework/cloud/contract/maven/verifier/PluginUnitTest.java index 491a0da50a..01faf6555a 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/java/org/springframework/cloud/contract/maven/verifier/PluginUnitTest.java +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/java/org/springframework/cloud/contract/maven/verifier/PluginUnitTest.java @@ -243,4 +243,17 @@ public class PluginUnitTest { assertFilesPresent(basedir, "target/foo/mappings/com/hello/v1/should post a user.json"); then(FileUtils.readFileToString(test2)).contains("/users/2"); } + + @Test + public void shouldGenerateStubsForCommonRepoWithTargetFolder() throws Exception { + File basedir = this.resources.getBasedir("common-repo"); + + this.maven.executeMojo(basedir, "convert"); + + assertFilesNotPresent(basedir, "target/generated-test-sources/contracts/"); + // there will be no stubs cause all files are copied to `target` folder + assertFilesNotPresent(basedir, "target/stubs/mappings/"); + assertFilesPresent(basedir, "target/stubs/contracts/consumer1/Messaging.groovy"); + assertFilesPresent(basedir, "target/stubs/contracts/pom.xml"); + } } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/consumer1/Messaging.groovy b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/consumer1/Messaging.groovy new file mode 100644 index 0000000000..b21f448049 --- /dev/null +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/consumer1/Messaging.groovy @@ -0,0 +1,37 @@ +/** + * + * Copyright 2013-2016 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. + */ +org.springframework.cloud.contract.spec.Contract.make { + label 'some_label' + input { + messageFrom('jms:input') + messageBody([ + bookName: 'foo' + ]) + messageHeaders { + header('sample', 'header') + } + } + outputMessage { + sentTo('jms:output') + body([ + bookName: 'foo' + ]) + headers { + header('BOOK-NAME', 'foo') + } + } +} \ No newline at end of file diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/consumer1/Sample.groovy b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/consumer1/Sample.groovy new file mode 100644 index 0000000000..094820225b --- /dev/null +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/consumer1/Sample.groovy @@ -0,0 +1,34 @@ +/** + * + * Copyright 2013-2016 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. + */ +org.springframework.cloud.contract.spec.Contract.make { + request { + method 'POST' + url('/users') { + + } + headers { + header 'Content-Type': 'application/json' + } + body '''{ "login" : "john", "name": "John The Contract" }''' + } + response { + status 200 + headers { + header 'Location': '/users/john' + } + } +} \ No newline at end of file diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/consumer1/WithList.groovy b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/consumer1/WithList.groovy new file mode 100644 index 0000000000..f542a19e9a --- /dev/null +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/consumer1/WithList.groovy @@ -0,0 +1,34 @@ +/** + * + * Copyright 2013-2016 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. + */ +org.springframework.cloud.contract.spec.Contract.make { + request { + method 'POST' + url('/users') { + + } + headers { + header 'Content-Type': 'application/json' + } + } + response { + status 200 + headers { + header 'Location': '/users/john' + } + body '''{ "list" : [ "login", "john", "name", "John The Contract" ] }''' + } +} \ No newline at end of file diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/pom.xml b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/pom.xml new file mode 100644 index 0000000000..d692c6f623 --- /dev/null +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/pom.xml @@ -0,0 +1,46 @@ + + + + 4.0.0 + + org.springframework.cloud.verifier.sample + common-repo + 0.1 + + + true + true + + + + + + org.springframework.cloud + spring-cloud-contract-maven-plugin + + + ${project.basedir} + + + + + + \ No newline at end of file diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/target/IgnoreMe.groovy b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/target/IgnoreMe.groovy new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/ContractVerifierConfigProperties.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/ContractVerifierConfigProperties.groovy index 3592739126..f58dccd9a5 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/ContractVerifierConfigProperties.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/ContractVerifierConfigProperties.groovy @@ -110,8 +110,8 @@ class ContractVerifierConfigProperties { String includedContracts = ".*" /** - * A ant pattern to match files. Relates to contracts, stubs etc. You can append - * any kind of files you wish e.g {@code $includedRootFolderAntPattern/*.groovy} + * A ant pattern to match files. Gets updated when using repo with common contracts + * to reflect the path to proper folder with contracts. */ String includedRootFolderAntPattern = "**/" @@ -137,4 +137,11 @@ class ContractVerifierConfigProperties { */ Map baseClassMappings + /** + * If set to true then the {@code target} or {@code build} folders are getting + * excluded from any operations. This is used out of the box when working with + * common repo with contracts. + */ + boolean excludeBuildFolders + }