diff --git a/README.adoc b/README.adoc index 4f1d716521..5a341bbfc9 100644 --- a/README.adoc +++ b/README.adoc @@ -166,7 +166,7 @@ From the Consumer perspective, when shooting a request in the integration test: (2) - With the "PUT" method (3) - to the URL "/fraudcheck" (4) - with the JSON body that - * has a field `clientId` that matches a regular expression `[0-9]{10}` + * has a field `client.id` that matches a regular expression `[0-9]{10}` * has a field `loanAmount` that is equal to `99999` (5) - with header `Content-Type` equal to `application/json` (6) - then the response will be sent with @@ -181,7 +181,7 @@ From the Producer perspective, in the autogenerated producer-side test: (2) - With the "PUT" method (3) - to the URL "/fraudcheck" (4) - with the JSON body that - * has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}` + * has a field `client.id` that will have a generated value that matches a regular expression `[0-9]{10}` * has a field `loanAmount` that is equal to `99999` (5) - with header `Content-Type` equal to `application/json` (6) - then the test will assert if the response has been sent with @@ -223,7 +223,7 @@ response: # (7) #(2) - With the "PUT" method #(3) - to the URL "/fraudcheck" #(4) - with the JSON body that -# * has a field `clientId` +# * has a field `client.id` # * has a field `loanAmount` that is equal to `99999` #(5) - with header `Content-Type` equal to `application/json` #(6) - and a `client.id` json entry matches the regular expression `[0-9]{10}` @@ -239,7 +239,7 @@ response: # (7) #(2) - With the "PUT" method #(3) - to the URL "/fraudcheck" #(4) - with the JSON body that -# * has a field `clientId` `1234567890` +# * has a field `client.id` `1234567890` # * has a field `loanAmount` that is equal to `99999` #(5) - with header `Content-Type` equal to `application/json` #(7) - then the test will assert if the response has been sent with @@ -524,7 +524,7 @@ From the Consumer perspective, when shooting a request in the integration test: (2) - With the "PUT" method (3) - to the URL "/fraudcheck" (4) - with the JSON body that - * has a field `clientId` that matches a regular expression `[0-9]{10}` + * has a field `client.id` that matches a regular expression `[0-9]{10}` * has a field `loanAmount` that is equal to `99999` (5) - with header `Content-Type` equal to `application/json` (6) - then the response will be sent with @@ -539,7 +539,7 @@ From the Producer perspective, in the autogenerated producer-side test: (2) - With the "PUT" method (3) - to the URL "/fraudcheck" (4) - with the JSON body that - * has a field `clientId` that will have a generated value that matches a regular expression `[0-9]{10}` + * has a field `client.id` that will have a generated value that matches a regular expression `[0-9]{10}` * has a field `loanAmount` that is equal to `99999` (5) - with header `Content-Type` equal to `application/json` (6) - then the test will assert if the response has been sent with @@ -581,7 +581,7 @@ response: # (7) #(2) - With the "PUT" method #(3) - to the URL "/fraudcheck" #(4) - with the JSON body that -# * has a field `clientId` +# * has a field `client.id` # * has a field `loanAmount` that is equal to `99999` #(5) - with header `Content-Type` equal to `application/json` #(6) - and a `client.id` json entry matches the regular expression `[0-9]{10}` @@ -597,7 +597,7 @@ response: # (7) #(2) - With the "PUT" method #(3) - to the URL "/fraudcheck" #(4) - with the JSON body that -# * has a field `clientId` `1234567890` +# * has a field `client.id` `1234567890` # * has a field `loanAmount` that is equal to `99999` #(5) - with header `Content-Type` equal to `application/json` #(7) - then the test will assert if the response has been sent with diff --git a/docs/src/main/asciidoc/verifier_setup.adoc b/docs/src/main/asciidoc/verifier_setup.adoc index a242a0a348..da06dc72d6 100644 --- a/docs/src/main/asciidoc/verifier_setup.adoc +++ b/docs/src/main/asciidoc/verifier_setup.adoc @@ -255,9 +255,10 @@ closure to set it up. * *contractsPath*: Specifies the path to the jar. If contract dependencies are downloaded, the path defaults to `groupid/artifactid` where `groupid` is slash separated. Otherwise, it scans contracts under the provided directory. -* *contractsWorkOffline*: Specifies whether to download the dependencies each time, so -that you can work online. In other words, it specifies whether to reuses the local Maven -repo. +* *contractsMode*: Specifies the mode of downloading contracts (whether the +JAR is available offline, remotely etc.) +* *contractsSnapshotCheckSkip*: If set to `true` will not assert whether the +downloaded stubs / contract JAR was downloaded from a remote location or a local one [[gradle-single-base-class]] ==== Single Base Class for All Tests @@ -393,7 +394,6 @@ following sections: * <> * <> * <> -* <> [[maven-add-plugin]] ==== Add maven plugin @@ -581,8 +581,9 @@ the following options: * *contractDependency*: The contract dependency that contains all the packaged contracts. * *contractsPath*: The path to the concrete contracts in the JAR with packaged contracts. Defaults to `groupid/artifactid` where `gropuid` is slash separated. -* *contractsWorkOffline*: Dictates whether the dependencies should be downloaded or the -local Maven artifacts should be reused. +* *contractsMode*: Picks the mode in which stubs will be found and registered +* *contractsSnapshotCheckSkip*: If `true` then will not assert whether a stub / contract +JAR was downloaded from local or remote location * *contractsRepositoryUrl*: URL to a repo with the artifacts that have contracts. If it is not provided, use the current Maven ones. * *contractsRepositoryUsername*: The user name to be used to connect to the repo with contracts. @@ -767,67 +768,6 @@ In order to fix this issue, provide the following section in your `pom.xml`: ---- -[[maven-consumer]] -==== Spring Cloud Contract Verifier on the Consumer Side - -You can also use the Spring Cloud Contract Verifier for the consumer side. To do so, use -the plugin so that it only converts the contracts and generates the stubs. To achieve -that, you need to configure Spring Cloud Contract Verifier plugin in exactly the same way -as you would for a provider. You need to copy contracts stored in -`src/test/resources/contracts` and generate WireMock JSON stubs using the -`mvn generateStubs` command. By default, the generated WireMock mapping is stored in a -directory named `target/mappings`. From these generated mappings, your project should -create additional artifacts with a classifier of `stubs` for easy deployment to the maven -repository. - -Here is a sample configuration: - -[source,xml,indent=0] ----- - - org.springframework.cloud - spring-cloud-contract-maven-plugin - ${verifier-plugin.version} - - - - convert - generateStubs - - - - ----- - -When present, JSON stubs can be used in consumer automated tests, as shown here: - -[source,groovy,indent=0] ----- -@RunWith(SpringTestRunner.class) -@SpringBootTest -@AutoConfigureStubRunner -public class LoanApplicationServiceTests { - - @Autowired - LoanApplicationService service; - - @Test - public void shouldSuccessfullyApplyForLoan() { - //given: - LoanApplication application = - new LoanApplication(new Client("12345678901"), 123.123); - //when: - LoanApplicationResult loanApplication = service.loanApplication(application); - // then: - assertThat(loanApplication.loanApplicationStatus).isEqualTo(LoanApplicationStatus.LOAN_APPLIED); - assertThat(loanApplication.rejectionReason).isNull(); - } -} ----- -`LoanApplication` makes a call to the `FraudDetection` service. This request is handled -by a WireMock server configured with stubs generated by the Spring Cloud Contract -Verifier. - === Stubs and Transitive Dependencies The Maven and Gradle plugin that add the tasks that create the stubs jar for you. One @@ -872,6 +812,27 @@ For example, you might decide to have no dependencies at all. As a consumer, if you add the stub dependency to your classpath, you can explicitly exclude the unwanted dependencies. +=== CI Server setup + +When fetching stubs / contracts in a CI, shared environment, what might happen is that +both the producer and the consumer reuse the same local Maven repository. Due to this, +the framework, responsible for downloading a stub JAR from remote location, +can't decide which JAR should be picked, local or remote one. That caused +the `"The artifact was found in the local repository but you have explicitly +stated that it should be downloaded from a remote one"` exception +and failed the build. + +For such cases we're introducing the property and plugin setup mechanism: + +- via `stubrunner.snapshot-check-skip` system property +- via `STUBRUNNER_SNAPSHOT_CHECK_SKIP` environment variable + +if either of these values is set to `true`, then the stub downloader will not +verify the origin of the downloaded JAR. + +For the plugins you need to set the `contractsSnapshotSkipCheck` property +to `true`. + === Scenarios You can handle scenarios with Spring Cloud Contract Verifier. All you need to do is to diff --git a/samples/standalone/contracts/README.adoc b/samples/standalone/contracts/README.adoc index 38dfba2305..334cfdb08d 100644 --- a/samples/standalone/contracts/README.adoc +++ b/samples/standalone/contracts/README.adoc @@ -43,7 +43,7 @@ Example for Maven org.springframework.cloud spring-cloud-contract-maven-plugin - LOCAL + LOCAL com.example.standalone contracts diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/AetherStubDownloader.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/AetherStubDownloader.java index b554781b2a..2878020251 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/AetherStubDownloader.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/AetherStubDownloader.java @@ -73,11 +73,14 @@ public class AetherStubDownloader implements StubDownloader { private static final String ARTIFACT_EXTENSION = "jar"; private static final String LATEST_ARTIFACT_VERSION = "(,]"; private static final String LATEST_VERSION_IN_IVY = "+"; + private static final String STUBRUNNER_SNAPSHOT_CHECK_SKIP_SYSTEM_PROP = "stubrunner.snapshot-check-skip"; + private static final String STUBRUNNER_SNAPSHOT_CHECK_SKIP_ENV_VAR = "STUBRUNNER_SNAPSHOT_CHECK_SKIP"; private final List remoteRepos; private final RepositorySystem repositorySystem; private final RepositorySystemSession session; private final boolean workOffline; + private final boolean snapshotCheckSkip; public AetherStubDownloader(StubRunnerOptions stubRunnerOptions) { if (log.isDebugEnabled()) { @@ -86,19 +89,23 @@ public class AetherStubDownloader implements StubDownloader { this.remoteRepos = remoteRepositories(stubRunnerOptions); boolean remoteReposMissing = remoteReposMissing(); switch (stubRunnerOptions.stubsMode) { - case LOCAL: - log.info("Remote repos not passed but the switch to work offline was set. " - + "Stubs will be used from your local Maven repository."); - break; - case REMOTE: - if (remoteReposMissing) throw new IllegalStateException("Remote repositories for stubs are not specified and work offline flag wasn't passed"); - break; - case CLASSPATH: - throw new UnsupportedOperationException("You can't use Aether downloader when you use classpath to find stubs"); + case LOCAL: + log.info("Remote repos not passed but the switch to work offline was set. " + "Stubs will be used from your local Maven repository."); + break; + case REMOTE: + if (remoteReposMissing) + throw new IllegalStateException( + "Remote repositories for stubs are not specified and work offline flag wasn't passed"); + break; + case CLASSPATH: + throw new UnsupportedOperationException( + "You can't use Aether downloader when you use classpath to find stubs"); } this.repositorySystem = newRepositorySystem(); this.workOffline = stubRunnerOptions.stubsMode == StubRunnerProperties.StubsMode.LOCAL; this.session = newSession(this.repositorySystem, this.workOffline); + this.snapshotCheckSkip = + stubRunnerOptions.isSnapshotCheckSkip() || skipSnapshotCheck(); registerShutdownHook(); } @@ -122,6 +129,7 @@ public class AetherStubDownloader implements StubDownloader { log.error("Remote repositories for stubs are not specified and work offline flag wasn't passed"); } this.workOffline = false; + this.snapshotCheckSkip = skipSnapshotCheck(); registerShutdownHook(); } @@ -171,7 +179,7 @@ public class AetherStubDownloader implements StubDownloader { ArtifactResult result = this.repositorySystem.resolveArtifact(this.session, request); log.info("Resolved artifact [" + artifact + "] to " + result.getArtifact().getFile()); - if (resolvedFromLocalRepo(result) && shouldDownloadFromRemote()) { + if (!this.snapshotCheckSkip && resolvedFromLocalRepo(result) && shouldDownloadFromRemote()) { throw new IllegalStateException("The artifact was found in the local repository " + "but you have explicitly stated that it should be downloaded from a remote one"); } @@ -190,7 +198,23 @@ public class AetherStubDownloader implements StubDownloader { + "] and classifier [" + classifier + "] in " + this.remoteRepos, e); } + } + private boolean skipSnapshotCheck() { + // still checking the system / env props setting for backward compatibility + // when running this for plugins + String skipSnapCheckProp = System.getProperty(STUBRUNNER_SNAPSHOT_CHECK_SKIP_SYSTEM_PROP); + String skipSnapCheckEnv = getSkipSnapEnvProp(); + if (StringUtils.hasText(skipSnapCheckProp)) { + return Boolean.parseBoolean(skipSnapCheckProp); + } + return StringUtils.hasText(skipSnapCheckEnv) && Boolean + .parseBoolean(skipSnapCheckEnv); + } + + // Visible for testing + String getSkipSnapEnvProp() { + return System.getenv(STUBRUNNER_SNAPSHOT_CHECK_SKIP_ENV_VAR); } private boolean resolvedFromLocalRepo(ArtifactResult result) { diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRepository.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRepository.java index e2b973415a..360aadb561 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRepository.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRepository.java @@ -73,7 +73,7 @@ class StubRepository { } StubRepository(File repository) { - this(repository, new ArrayList(), new StubRunnerOptionsBuilder().build()); + this(repository, new ArrayList<>(), new StubRunnerOptionsBuilder().build()); } public File getPath() { diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerMain.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerMain.java index 2a35fcb764..737ae8958c 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerMain.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerMain.java @@ -27,6 +27,12 @@ import joptsimple.OptionParser; import joptsimple.OptionSet; import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties; +/** + * Class to run stub runner as a standalone process + * + * @deprecated - use Stub Runner Boot server + */ +@Deprecated public class StubRunnerMain { private static final Logger log = LoggerFactory.getLogger(StubRunnerMain.class); diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java index bb58a10d5f..c3bc9fd59c 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptions.java @@ -25,7 +25,7 @@ import org.springframework.cloud.contract.stubrunner.util.StringUtils; /** * Technical options related to running StubRunner * - * Use {@class StubRunnerOptionsBuilder} to build this object. + * Use {@see StubRunnerOptionsBuilder} to build this object. * * @see StubRunnerOptionsBuilder */ @@ -91,12 +91,18 @@ public class StubRunnerOptions { final StubRunnerProperties.StubsMode stubsMode; + /** + * If set to {@code true} will not assert whether the downloaded stubs / contract + * JAR was downloaded from a remote location or a local one + */ + private boolean snapshotCheckSkip; + StubRunnerOptions(Integer minPortValue, Integer maxPortValue, String stubRepositoryRoot, StubRunnerProperties.StubsMode stubsMode, String stubsClassifier, Collection dependencies, Map stubIdsToPortMapping, String username, String password, final StubRunnerProxyOptions stubRunnerProxyOptions, - boolean stubsPerConsumer, String consumerName, String mappingsOutputFolder) { + boolean stubsPerConsumer, String consumerName, String mappingsOutputFolder, boolean snapshotCheckSkip) { this.minPortValue = minPortValue; this.maxPortValue = maxPortValue; this.stubRepositoryRoot = stubRepositoryRoot; @@ -110,6 +116,7 @@ public class StubRunnerOptions { this.stubsPerConsumer = stubsPerConsumer; this.consumerName = consumerName; this.mappingsOutputFolder = mappingsOutputFolder; + this.snapshotCheckSkip = snapshotCheckSkip; } public Integer port(StubConfiguration stubConfiguration) { @@ -133,7 +140,8 @@ public class StubRunnerOptions { .withPassword(System.getProperty("stubrunner.password")) .withStubPerConsumer(Boolean.parseBoolean(System.getProperty("stubrunner.stubs-per-consumer", "false"))) .withConsumerName(System.getProperty("stubrunner.consumer-name")) - .withMappingsOutputFolder(System.getProperty("stubrunner.mappings-output-folder")); + .withMappingsOutputFolder(System.getProperty("stubrunner.mappings-output-folder")) + .withSnapshotCheckSkip(Boolean.parseBoolean(System.getProperty("stubrunner.snapshot-check-skip", "false"))); String proxyHost = System.getProperty("stubrunner.proxy.host"); if (proxyHost != null) { builder.withProxy(proxyHost, Integer.parseInt(System.getProperty("stubrunner.proxy.port"))); @@ -213,6 +221,14 @@ public class StubRunnerOptions { this.mappingsOutputFolder = mappingsOutputFolder; } + public boolean isSnapshotCheckSkip() { + return this.snapshotCheckSkip; + } + + public void setSnapshotCheckSkip(boolean snapshotCheckSkip) { + this.snapshotCheckSkip = snapshotCheckSkip; + } + public static class StubRunnerProxyOptions { private final String proxyHost; diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptionsBuilder.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptionsBuilder.java index 77d7fd165a..52017671fd 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptionsBuilder.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/StubRunnerOptionsBuilder.java @@ -47,6 +47,7 @@ public class StubRunnerOptionsBuilder { private String consumerName; private String mappingsOutputFolder; private StubRunnerProperties.StubsMode stubsMode; + private boolean snapshotCheckSkip = false; public StubRunnerOptionsBuilder() { } @@ -125,6 +126,7 @@ public class StubRunnerOptionsBuilder { options.dependencies : new ArrayList(); this.stubIdsToPortMapping = options.stubIdsToPortMapping != null ? options.stubIdsToPortMapping : new LinkedHashMap(); + this.snapshotCheckSkip = options.isSnapshotCheckSkip(); return this; } @@ -133,11 +135,16 @@ public class StubRunnerOptionsBuilder { return this; } + public StubRunnerOptionsBuilder withSnapshotCheckSkip(boolean snapshotCheckSkip) { + this.snapshotCheckSkip = snapshotCheckSkip; + return this; + } + public StubRunnerOptions build() { return new StubRunnerOptions(this.minPortValue, this.maxPortValue, this.stubRepositoryRoot, this.stubsMode, this.stubsClassifier, buildDependencies(), this.stubIdsToPortMapping, this.username, this.password, this.stubRunnerProxyOptions, this.stubsPerConsumer, this.consumerName, - this.mappingsOutputFolder); + this.mappingsOutputFolder, this.snapshotCheckSkip); } private Collection buildDependencies() { diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/junit/StubRunnerRule.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/junit/StubRunnerRule.java index f9b12fdc43..5705dd394f 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/junit/StubRunnerRule.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/junit/StubRunnerRule.java @@ -154,6 +154,11 @@ public class StubRunnerRule implements TestRule, StubFinder, StubRunnerRuleOptio return this.delegate; } + @Override public StubRunnerRule withSnapshotCheckSkip(boolean snapshotCheckSkip) { + builder().withSnapshotCheckSkip(snapshotCheckSkip); + return this.delegate; + } + @Override public URL findStubUrl(String groupId, String artifactId) { return this.stubFinder().findStubUrl(groupId, artifactId); diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/junit/StubRunnerRuleOptions.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/junit/StubRunnerRuleOptions.java index 6ab7c8ed51..123a862c49 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/junit/StubRunnerRuleOptions.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/junit/StubRunnerRuleOptions.java @@ -93,4 +93,10 @@ interface StubRunnerRuleOptions { * Allows setting the output folder for mappings */ StubRunnerRule withMappingsOutputFolder(String mappingsOutputFolder); + + /** + * If set to {@code true} will not assert whether the downloaded stubs / contract + * JAR was downloaded from a remote location or a local one + */ + StubRunnerRule withSnapshotCheckSkip(boolean snapshotCheckSkip); } diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/AutoConfigureStubRunner.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/AutoConfigureStubRunner.java index ab39d4ce9a..49cf48e9bd 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/AutoConfigureStubRunner.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/AutoConfigureStubRunner.java @@ -108,4 +108,10 @@ public @interface AutoConfigureStubRunner { * @return the type of stubs mode */ StubRunnerProperties.StubsMode stubsMode() default StubRunnerProperties.StubsMode.CLASSPATH; + + /** + * If set to {@code true} will not assert whether the downloaded stubs / contract + * JAR was downloaded from a remote location or a local one + */ + boolean snapshotCheckSkip() default false; } diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java index aba27afa57..48eb7d6bef 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfiguration.java @@ -93,7 +93,8 @@ public class StubRunnerConfiguration { .withPassword(this.props.getPassword()) .withStubPerConsumer(this.props.isStubsPerConsumer()) .withConsumerName(consumerName()) - .withMappingsOutputFolder(this.props.getMappingsOutputFolder()); + .withMappingsOutputFolder(this.props.getMappingsOutputFolder()) + .withSnapshotCheckSkip(this.props.isSnapshotCheckSkip()); } private String consumerName() { diff --git a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerProperties.java b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerProperties.java index 5be5fcad9e..d443f89ee7 100644 --- a/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerProperties.java +++ b/spring-cloud-contract-stub-runner/src/main/java/org/springframework/cloud/contract/stubrunner/spring/StubRunnerProperties.java @@ -90,8 +90,17 @@ public class StubRunnerProperties { */ private String mappingsOutputFolder; + /** + * Pick where the stubs should come from + */ private StubsMode stubsMode; + /** + * If set to {@code true} will not assert whether the downloaded stubs / contract + * JAR was downloaded from a remote location or a local one + */ + private boolean snapshotCheckSkip; + /** * An enumeration stub modes. */ @@ -221,12 +230,21 @@ public class StubRunnerProperties { this.stubsMode = stubsMode; } + public boolean isSnapshotCheckSkip() { + return this.snapshotCheckSkip; + } + + public void setSnapshotCheckSkip(boolean snapshotCheckSkip) { + this.snapshotCheckSkip = snapshotCheckSkip; + } + @Override public String toString() { return "StubRunnerProperties{" + "minPort=" + this.minPort + ", maxPort=" + this.maxPort + ", repositoryRoot=" + this.repositoryRoot + ", ids=" + Arrays.toString(this.ids) + ", classifier='" + this.classifier + '\'' + ", setStubsPerConsumer='" + this.stubsPerConsumer + "', consumerName='" + this.consumerName + '\'' + ", stubsMode='" + this.stubsMode + '\'' + + ", snapshotCheckSkip='" + this.snapshotCheckSkip + '\'' + '}'; } } diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/AetherStubDownloaderSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/AetherStubDownloaderSpec.groovy index 881ee25712..0bf2474060 100644 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/AetherStubDownloaderSpec.groovy +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/AetherStubDownloaderSpec.groovy @@ -11,66 +11,148 @@ import org.springframework.util.ResourceUtils class AetherStubDownloaderSpec extends Specification { - @Rule - HoverflyRule hoverflyRule = HoverflyRule.inSimulationMode("simulation.json") + @Rule + HoverflyRule hoverflyRule = HoverflyRule.inSimulationMode("simulation.json") - def 'Should throw an exception when artifact not found'() { - given: - StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() - .withStubsMode(StubRunnerProperties.StubsMode.LOCAL) - .build() + def 'Should throw an exception when artifact not found'() { + given: + StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() + .withStubsMode(StubRunnerProperties.StubsMode.LOCAL) + .build() - AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) + AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) - when: - def jar = aetherStubDownloader.downloadAndUnpackStubJar(new StubConfiguration("non.existing.group", "missing-artifact-id", "1.0-SNAPSHOT")) + when: + def jar = aetherStubDownloader.downloadAndUnpackStubJar(new StubConfiguration("non.existing.group", "missing-artifact-id", "1.0-SNAPSHOT")) - then: - IllegalStateException e = thrown(IllegalStateException) - e.message.contains("Exception occurred while trying to download a stub for group") - } + then: + IllegalStateException e = thrown(IllegalStateException) + e.message.contains("Exception occurred while trying to download a stub for group") + } - def 'Should throw an exception when a jar is in local m2 and not in remote repo'() { - given: - StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() - .withStubsMode(StubRunnerProperties.StubsMode.REMOTE) - .withStubRepositoryRoot("https://test.jfrog.io/test/libs-snapshot-local") - .build() + def 'Should throw an exception when a jar is in local m2 and not in remote repo'() { + given: + StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() + .withStubsMode(StubRunnerProperties.StubsMode.REMOTE) + .withStubRepositoryRoot("https://test.jfrog.io/test/libs-snapshot-local") + .build() - AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) + AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) - when: - def jar = aetherStubDownloader.downloadAndUnpackStubJar(new StubConfiguration("org.springframework.cloud", "spring-cloud-contract-spec", "+", "")) + when: + def jar = aetherStubDownloader.downloadAndUnpackStubJar(new StubConfiguration("org.springframework.cloud", "spring-cloud-contract-spec", "+", "")) - then: - IllegalStateException e = thrown(IllegalStateException) - e.message.contains("The artifact was found in the local repository but you have explicitly stated that it should be downloaded from a remote one") - } + then: + IllegalStateException e = thrown(IllegalStateException) + e.message.contains("The artifact was found in the local repository but you have explicitly stated that it should be downloaded from a remote one") + } - @RestoreSystemProperties - def 'Should use local repository from settings.xml'() { - given: - File tempSettings = File.createTempFile("settings", ".xml") - def m2repoFolder = 'm2repo' + File.separator + 'repository' - tempSettings.text = '' + - ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + m2repoFolder).getAbsolutePath() + '' - System.setProperty("org.apache.maven.user-settings", tempSettings.getAbsolutePath()) - RepositorySystemSession repositorySystemSession = - AetherFactories.newSession(AetherFactories.newRepositorySystem(), true); + @RestoreSystemProperties + def 'Should not throw an exception when a jar is in local m2 and not in remote repo and system property disabled snapshot check'() { + given: + StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() + .withStubsMode(StubRunnerProperties.StubsMode.REMOTE) + .withStubRepositoryRoot("https://test.jfrog.io/test/libs-snapshot-local") + .build() + System.properties.setProperty("stubrunner.snapshot-check-skip", "true") - and: - StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() - .withStubsMode(StubRunnerProperties.StubsMode.LOCAL) - .build() - AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) + and: + AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) - when: - def jar = aetherStubDownloader.downloadAndUnpackStubJar( - new StubConfiguration("org.springframework.cloud.contract.verifier.stubs", - "bootService", "0.0.1-SNAPSHOT")) + when: + def jar = aetherStubDownloader.downloadAndUnpackStubJar(new StubConfiguration("org.springframework.cloud", "spring-cloud-contract-spec", "+", "")) - then: - jar != null - repositorySystemSession.getLocalRepository().getBasedir().getAbsolutePath().endsWith(m2repoFolder) - } + then: + jar != null + } + + @RestoreSystemProperties + def 'Should throw an exception when a jar is in local m2 and not in remote repo and system property disabled takes precedence over env'() { + given: + StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() + .withStubsMode(StubRunnerProperties.StubsMode.REMOTE) + .withStubRepositoryRoot("https://test.jfrog.io/test/libs-snapshot-local") + .build() + System.properties.setProperty("stubrunner.snapshot-check-skip", "false") + + and: + AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) { + @Override + String getSkipSnapEnvProp() { + return "true" + } + } + + when: + def jar = aetherStubDownloader.downloadAndUnpackStubJar(new StubConfiguration("org.springframework.cloud", "spring-cloud-contract-spec", "+", "")) + + then: + IllegalStateException e = thrown(IllegalStateException) + e.message.contains("The artifact was found in the local repository but you have explicitly stated that it should be downloaded from a remote one") + } + + def 'Should not throw an exception when a jar is in local m2 and not in remote repo and env property disabled snapshot check'() { + given: + StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() + .withStubsMode(StubRunnerProperties.StubsMode.REMOTE) + .withStubRepositoryRoot("https://test.jfrog.io/test/libs-snapshot-local") + .build() + + AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) { + @Override + String getSkipSnapEnvProp() { + return "true" + } + } + + when: + def jar = aetherStubDownloader.downloadAndUnpackStubJar(new StubConfiguration("org.springframework.cloud", "spring-cloud-contract-spec", "+", "")) + + then: + jar != null + } + + def 'Should not throw an exception when a jar is in local m2 and not in remote repo and option disabled snapshot check'() { + given: + StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() + .withStubsMode(StubRunnerProperties.StubsMode.REMOTE) + .withStubRepositoryRoot("https://test.jfrog.io/test/libs-snapshot-local") + .withSnapshotCheckSkip(true) + .build() + + AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) + + when: + def jar = aetherStubDownloader.downloadAndUnpackStubJar(new StubConfiguration("org.springframework.cloud", "spring-cloud-contract-spec", "+", "")) + + then: + jar != null + } + + @RestoreSystemProperties + def 'Should use local repository from settings.xml'() { + given: + File tempSettings = File.createTempFile("settings", ".xml") + def m2repoFolder = 'm2repo' + File.separator + 'repository' + tempSettings.text = '' + + ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + m2repoFolder).getAbsolutePath() + '' + System.setProperty("org.apache.maven.user-settings", tempSettings.getAbsolutePath()) + RepositorySystemSession repositorySystemSession = + AetherFactories.newSession(AetherFactories.newRepositorySystem(), true); + + and: + StubRunnerOptions stubRunnerOptions = new StubRunnerOptionsBuilder() + .withStubsMode(StubRunnerProperties.StubsMode.LOCAL) + .build() + AetherStubDownloader aetherStubDownloader = new AetherStubDownloader(stubRunnerOptions) + + when: + def jar = aetherStubDownloader.downloadAndUnpackStubJar( + new StubConfiguration("org.springframework.cloud.contract.verifier.stubs", + "bootService", "0.0.1-SNAPSHOT")) + + then: + jar != null + repositorySystemSession.getLocalRepository().getBasedir().getAbsolutePath().endsWith(m2repoFolder) + } } diff --git a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubRunnerOptionsBuilderSpec.groovy b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubRunnerOptionsBuilderSpec.groovy index 2854009346..5ccfe16e3e 100644 --- a/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubRunnerOptionsBuilderSpec.groovy +++ b/spring-cloud-contract-stub-runner/src/test/groovy/org/springframework/cloud/contract/stubrunner/StubRunnerOptionsBuilderSpec.groovy @@ -143,7 +143,7 @@ class StubRunnerOptionsBuilderSpec extends Specification { given: StubRunnerOptionsBuilder builder = builder.withOptions(new StubRunnerOptions(1, 2, "root", StubRunnerProperties.StubsMode.LOCAL, "classifier", [new StubConfiguration("a:b:c")], [(new StubConfiguration("a:b:c")): 3], "foo", "bar", - new StubRunnerOptions.StubRunnerProxyOptions("host", 4), true, "consumer", "folder")) + new StubRunnerOptions.StubRunnerProxyOptions("host", 4), true, "consumer", "folder", true)) builder.withStubs("foo:bar:baz") when: StubRunnerOptions options = builder.build() @@ -162,6 +162,7 @@ class StubRunnerOptionsBuilderSpec extends Specification { options.stubsPerConsumer == true options.consumerName == "consumer" options.mappingsOutputFolder == "folder" + options.snapshotCheckSkip == true } def shouldNotPrintUsernameAndPassword() { @@ -169,7 +170,7 @@ class StubRunnerOptionsBuilderSpec extends Specification { StubRunnerOptionsBuilder builder = builder.withOptions(new StubRunnerOptions(1, 2, "root", StubRunnerProperties.StubsMode.CLASSPATH, "classifier", [new StubConfiguration("a:b:c")], [(new StubConfiguration("a:b:c")): 3], "username123", "password123", - new StubRunnerOptions.StubRunnerProxyOptions("host", 4), true, "consumer", "folder")) + new StubRunnerOptions.StubRunnerProxyOptions("host", 4), true, "consumer", "folder", true)) builder.withStubs("foo:bar:baz") when: String options = builder.build().toString() @@ -196,6 +197,7 @@ class StubRunnerOptionsBuilderSpec extends Specification { System.setProperty("stubrunner.proxy.host", "host") System.setProperty("stubrunner.proxy.port", "4") System.setProperty("stubrunner.mappings-output-folder", "folder") + System.setProperty("stubrunner.snapshot-check-skip", "true") when: StubRunnerOptions options = StubRunnerOptions.fromSystemProps() then: @@ -212,5 +214,6 @@ class StubRunnerOptionsBuilderSpec extends Specification { options.stubsPerConsumer == true options.consumerName == "consumer" options.mappingsOutputFolder == "folder" + options.snapshotCheckSkip == true } } 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 30ad26779a..fe85799545 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 @@ -125,7 +125,7 @@ class ContractVerifierExtension { /** * Picks the mode in which stubs will be found and registered */ - StubRunnerProperties.StubsMode stubsMode = StubRunnerProperties.StubsMode.CLASSPATH + StubRunnerProperties.StubsMode contractsMode = StubRunnerProperties.StubsMode.CLASSPATH /** * A package that contains all the base clases for generated tests. If your contract resides in a location @@ -154,7 +154,13 @@ class ContractVerifierExtension { * excluded from any operations. This is used out of the box when working with * common repo with contracts. */ - boolean excludeBuildFolders + boolean excludeBuildFolders = false + + /** + * If set to {@code true} will not assert whether the downloaded stubs / contract + * JAR was downloaded from a remote location or a local one + */ + boolean contractsSnapshotCheckSkip = false void contractDependency(@DelegatesTo(Dependency) Closure closure) { closure.delegate = contractDependency diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/GradleContractsDownloader.groovy b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/GradleContractsDownloader.groovy index b4b6e12269..8ecad038a3 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/GradleContractsDownloader.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/groovy/org/springframework/cloud/contract/verifier/plugin/GradleContractsDownloader.groovy @@ -65,7 +65,7 @@ class GradleContractsDownloader { private boolean shouldDownloadContracts(ContractVerifierExtension extension) { return [StubRunnerProperties.StubsMode.LOCAL, StubRunnerProperties.StubsMode.REMOTE].any { - it == extension.stubsMode } && (StringUtils.hasText(extension.contractDependency.artifactId) || + it == extension.contractsMode } && (StringUtils.hasText(extension.contractDependency.artifactId) || StringUtils.hasText(extension.contractDependency.stringNotation)) } @@ -79,9 +79,10 @@ class GradleContractsDownloader { StubRunnerOptionsBuilder options = new StubRunnerOptionsBuilder() .withOptions(StubRunnerOptions.fromSystemProps()) .withStubRepositoryRoot(extension.contractRepository.repositoryUrl) - .withStubsMode(extension.stubsMode) + .withStubsMode(extension.contractsMode) .withUsername(extension.contractRepository.username) .withPassword(extension.contractRepository.password) + .withSnapshotCheckSkip(extension.contractsSnapshotCheckSkip) if (extension.contractRepository.proxyPort) { options = options.withProxy(extension.contractRepository.proxyHost, extension.contractRepository.proxyPort) } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/GradleContractsDownloaderSpec.groovy b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/GradleContractsDownloaderSpec.groovy index 76fbdf16ee..24a83b1ebe 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/GradleContractsDownloaderSpec.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/groovy/org/springframework/cloud/contract/verifier/plugin/GradleContractsDownloaderSpec.groovy @@ -81,7 +81,7 @@ class GradleContractsDownloaderSpec extends Specification { given: ContractVerifierExtension ext = new ContractVerifierExtension() ext.with { - stubsMode = StubRunnerProperties.StubsMode.REMOTE + contractsMode = StubRunnerProperties.StubsMode.REMOTE contractDependency { groupId("com.example") artifactId("foo") @@ -109,7 +109,7 @@ class GradleContractsDownloaderSpec extends Specification { given: ContractVerifierExtension ext = new ContractVerifierExtension() ext.with { - stubsMode = StubRunnerProperties.StubsMode.REMOTE + contractsMode = StubRunnerProperties.StubsMode.REMOTE contractDependency { groupId("com.example") artifactId("foo") @@ -139,7 +139,7 @@ class GradleContractsDownloaderSpec extends Specification { given: ContractVerifierExtension ext = new ContractVerifierExtension() ext.with { - stubsMode = StubRunnerProperties.StubsMode.REMOTE + contractsMode = StubRunnerProperties.StubsMode.REMOTE contractDependency { groupId("com.example") artifactId("foo") @@ -174,7 +174,7 @@ class GradleContractsDownloaderSpec extends Specification { given: ContractVerifierExtension ext = new ContractVerifierExtension() ext.with { - stubsMode = StubRunnerProperties.StubsMode.REMOTE + contractsMode = StubRunnerProperties.StubsMode.REMOTE contractDependency { groupId("com.example") artifactId("foo") diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/build.gradle b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/build.gradle index d9065cb2f6..93049fc9b8 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/build.gradle +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/build.gradle @@ -44,7 +44,7 @@ dependencies { } contracts { - stubsMode = "REMOTE" + contractsMode = "REMOTE" baseClassForTests = 'org.springframework.cloud.contract.verifier.twitter.places.BaseMockMvcSpec' basePackageForTests = 'contracts' contractsDslDir = contractsDir diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/build.gradle b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/build.gradle index 827ee5fd53..074eef7af1 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/build.gradle +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleJerseyProject/build.gradle @@ -116,7 +116,7 @@ configure(project(':fraudDetectionService')) { } contracts { - stubsMode = "REMOTE" + contractsMode = "REMOTE" targetFramework = 'Spock' testMode = 'JaxRsClient' baseClassForTests = 'org.springframework.cloud.MvcSpec' diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle index 9607a4ecb5..b1399f74f3 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/sampleProject/build.gradle @@ -69,7 +69,7 @@ configure([project(':fraudDetectionService'), project(':loanApplicationService') } contracts { - stubsMode = "REMOTE" + contractsMode = "REMOTE" targetFramework = 'Spock' testMode = 'MockMvc' baseClassForTests = 'org.springframework.cloud.MvcSpec' diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/build.gradle b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/build.gradle index fc70bf974e..06a0a5b70e 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/build.gradle +++ b/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/build.gradle @@ -86,7 +86,7 @@ configure([project(':fraudDetectionService'), project(':loanApplicationService') // end::jar_setup[] contracts { - stubsMode = "REMOTE" + contractsMode = "REMOTE" // tag::target_framework[] targetFramework = 'Spock' // end::target_framework[] 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 aa615c9063..921b411394 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 @@ -107,8 +107,8 @@ public class ConvertMojo extends AbstractMojo { /** * Picks the mode in which stubs will be found and registered */ - @Parameter(property = "stubsMode", defaultValue = "CLASSPATH") - private StubRunnerProperties.StubsMode stubsMode; + @Parameter(property = "contractsMode", defaultValue = "CLASSPATH") + private StubRunnerProperties.StubsMode contractsMode; /** * If {@code true} then any file laying in a path that contains {@code build} or {@code target} @@ -141,6 +141,13 @@ public class ConvertMojo extends AbstractMojo { @Parameter(property = "contractsRepositoryProxyPort") private Integer contractsRepositoryProxyPort; + /** + * If {@code true} then will not assert whether a stub / contract + * JAR was downloaded from local or remote location + */ + @Parameter(property = "contractsSnapshotCheckSkip", defaultValue = "false") + private boolean contractsSnapshotCheckSkip; + @Component(role = MavenResourcesFiltering.class, hint = "default") private MavenResourcesFiltering mavenResourcesFiltering; @@ -166,9 +173,11 @@ public class ConvertMojo extends AbstractMojo { ContractVerifierConfigProperties config = new ContractVerifierConfigProperties(); config.setExcludeBuildFolders(this.excludeBuildFolders); File contractsDirectory = new MavenContractsDownloader(this.project, this.contractDependency, - this.contractsPath, this.contractsRepositoryUrl, this.stubsMode, getLog(), + this.contractsPath, this.contractsRepositoryUrl, this.contractsMode, getLog(), this.aetherStubDownloaderFactory, this.repoSession, this.contractsRepositoryUsername, - this.contractsRepositoryPassword, this.contractsRepositoryProxyHost, this.contractsRepositoryProxyPort).downloadAndUnpackContractsIfRequired(config, this.contractsDirectory); + this.contractsRepositoryPassword, this.contractsRepositoryProxyHost, this.contractsRepositoryProxyPort, + this.contractsSnapshotCheckSkip) + .downloadAndUnpackContractsIfRequired(config, this.contractsDirectory); getLog().info("Directory with contract is present at [" + contractsDirectory + "]"); new CopyContracts(this.project, this.mavenSession, this.mavenResourcesFiltering, config) diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java index 103efcc4da..4bb0aacb04 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java @@ -145,8 +145,8 @@ public class GenerateTestsMojo extends AbstractMojo { /** * Picks the mode in which stubs will be found and registered */ - @Parameter(property = "stubsMode", defaultValue = "CLASSPATH") - private StubRunnerProperties.StubsMode stubsMode; + @Parameter(property = "contractsMode", defaultValue = "CLASSPATH") + private StubRunnerProperties.StubsMode contractsMode; /** * A package that contains all the base clases for generated tests. If your contract resides in a location @@ -196,6 +196,13 @@ public class GenerateTestsMojo extends AbstractMojo { @Parameter(property = "contractsRepositoryProxyPort") private Integer contractsRepositoryProxyPort; + /** + * If {@code true} then will not assert whether a stub / contract + * JAR was downloaded from local or remote location + */ + @Parameter(property = "contractsSnapshotCheckSkip", defaultValue = "false") + private boolean contractsSnapshotCheckSkip; + private final AetherStubDownloaderFactory aetherStubDownloaderFactory; @Inject @@ -215,10 +222,11 @@ public class GenerateTestsMojo extends AbstractMojo { final ContractVerifierConfigProperties config = new ContractVerifierConfigProperties(); // download contracts, unzip them and pass as output directory File contractsDirectory = new MavenContractsDownloader(this.project, this.contractDependency, - this.contractsPath, this.contractsRepositoryUrl, this.stubsMode, getLog(), + this.contractsPath, this.contractsRepositoryUrl, this.contractsMode, getLog(), this.aetherStubDownloaderFactory, this.repoSession, this.contractsRepositoryUsername, this.contractsRepositoryPassword, - this.contractsRepositoryProxyHost, this.contractsRepositoryProxyPort).downloadAndUnpackContractsIfRequired(config, this.contractsDirectory); + this.contractsRepositoryProxyHost, this.contractsRepositoryProxyPort, + this.contractsSnapshotCheckSkip).downloadAndUnpackContractsIfRequired(config, this.contractsDirectory); getLog().info("Directory with contract is present at [" + contractsDirectory + "]"); setupConfig(config, contractsDirectory); this.project.addTestCompileSourceRoot(this.generatedTestSourcesDir.getAbsolutePath()); diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java index 4fcfd132dc..fe7385d1c6 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/MavenContractsDownloader.java @@ -44,6 +44,7 @@ class MavenContractsDownloader { private final String repositoryPassword; private final String repositoryProxyHost; private final Integer repositoryProxyPort; + private final boolean contractsSnapshotCheckSkip; MavenContractsDownloader(MavenProject project, Dependency contractDependency, String contractsPath, String contractsRepositoryUrl, @@ -51,7 +52,7 @@ class MavenContractsDownloader { AetherStubDownloaderFactory aetherStubDownloaderFactory, RepositorySystemSession repoSession, String repositoryUsername, String repositoryPassword, String repositoryProxyHost, - Integer repositoryProxyPort) { + Integer repositoryProxyPort, boolean contractsSnapshotCheckSkip) { this.project = project; this.contractDependency = contractDependency; this.contractsPath = contractsPath; @@ -65,6 +66,7 @@ class MavenContractsDownloader { this.repositoryProxyHost = repositoryProxyHost; this.repositoryProxyPort = repositoryProxyPort; this.stubDownloaderBuilderProvider = new StubDownloaderBuilderProvider(); + this.contractsSnapshotCheckSkip = contractsSnapshotCheckSkip; } File downloadAndUnpackContractsIfRequired(ContractVerifierConfigProperties config, File defaultContractsDir) { @@ -139,7 +141,8 @@ class MavenContractsDownloader { .withStubRepositoryRoot(this.contractsRepositoryUrl) .withStubsMode(this.stubsMode) .withUsername(this.repositoryUsername) - .withPassword(this.repositoryPassword); + .withPassword(this.repositoryPassword) + .withSnapshotCheckSkip(this.contractsSnapshotCheckSkip); if (this.repositoryProxyPort != null) { builder.withProxy(this.repositoryProxyHost, this.repositoryProxyPort); } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom-with-repo.xml b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom-with-repo.xml index 810c6ab7cf..55a028280b 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom-with-repo.xml +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom-with-repo.xml @@ -32,7 +32,7 @@ org.springframework.cloud spring-cloud-contract-maven-plugin - REMOTE + REMOTE http://link/to/your/nexus/or/artifactory/or/sth com.example.standalone diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom.xml b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom.xml index 15dd6a3afa..e2277036b0 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom.xml +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/basic-remote-contracts/pom.xml @@ -31,7 +31,7 @@ org.springframework.cloud spring-cloud-contract-maven-plugin - REMOTE + REMOTE com.example contracts diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-remote-contracts/pom.xml b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-remote-contracts/pom.xml index 1775fef118..228b144b2e 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-remote-contracts/pom.xml +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/complex-remote-contracts/pom.xml @@ -31,7 +31,7 @@ org.springframework.cloud spring-cloud-contract-maven-plugin - REMOTE + REMOTE com/example/server com.example