diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index ce69db0a99..0000000000 --- a/.editorconfig +++ /dev/null @@ -1,29 +0,0 @@ -root = true - -[*.java] -indent_style = tab -indent_size = 4 -continuation_indent_size = 8 - -[*.groovy] -indent_style = tab -indent_size = 4 -continuation_indent_size = 8 - -[*.kt] -indent_style = tab -indent_size = 4 -continuation_indent_size = 8 - -[*.xml] -indent_style = tab -indent_size = 4 -continuation_indent_size = 8 - -[*.yml] -indent_style = space -indent_size = 2 - -[*.yaml] -indent_style = space -indent_size = 2 diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md deleted file mode 100644 index 9eeac3b093..0000000000 --- a/.github/CONTRIBUTING.md +++ /dev/null @@ -1,45 +0,0 @@ - -# Contributing - -Spring Cloud is released under the non-restrictive Apache 2.0 license, -and follows a very standard Github development process, using Github -tracker for issues and merging pull requests into master. If you want -to contribute even something trivial please do not hesitate, but -follow the guidelines below. - -## Sign the Contributor License Agreement -Before we accept a non-trivial patch or pull request we will need you to sign the -[Contributor License Agreement](https://cla.pivotal.io/sign/spring). -Signing the contributor's agreement does not grant anyone commit rights to the main -repository, but it does mean that we can accept your contributions, and you will get an -author credit if we do. Active contributors might be asked to join the core team, and -given the ability to merge pull requests. - -## Code of Conduct -This project adheres to the Contributor Covenant [code of -conduct](https://github.com/spring-cloud/spring-cloud-build/blob/main/docs/src/main/asciidoc/code-of-conduct.adoc). By participating, you are expected to uphold this code. Please report -unacceptable behavior to spring-code-of-conduct@pivotal.io. - -## Code Conventions and Housekeeping -None of these is essential for a pull request, but they will all help. They can also be -added after the original pull request but before a merge. - -* Use the Spring Framework code format conventions. If you use Eclipse - you can import formatter settings using the - `eclipse-code-formatter.xml` file from the - [Spring Cloud Build](https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/spring-cloud-dependencies-parent/eclipse-code-formatter.xml) project. If using IntelliJ, you can use the - [Eclipse Code Formatter Plugin](https://plugins.jetbrains.com/plugin/6546) to import the same file. -* Make sure all new `.java` files to have a simple Javadoc class comment with at least an - `@author` tag identifying you, and preferably at least a paragraph on what the class is - for. -* Add the ASF license header comment to all new `.java` files (copy from existing files - in the project) -* Add yourself as an `@author` to the .java files that you modify substantially (more - than cosmetic changes). -* Add some Javadocs and, if you change the namespace, some XSD doc elements. -* A few unit tests would help a lot as well -- someone has to do it. -* If no-one else is using your branch, please rebase it against the current master (or - other target branch in the main project). -* When writing a commit message please follow [these conventions](https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html), - if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit - message (where XXXX is the issue number). diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index 0bc5ef4fa3..0000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,20 +0,0 @@ - diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index aeafef9d32..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: '' -labels: '' -assignees: '' - ---- - -**Describe the bug** -Please provide details of the problem, including the version of Spring Cloud that you -are using. - -**Sample** -If possible, please provide a test case or sample application that reproduces -the problem. This makes it much easier for us to diagnose the problem and to verify that -we have fixed it. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index bbcbbe7d61..0000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: '' -labels: '' -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 203f3c889b..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,6 +0,0 @@ -version: 2 -updates: -- package-ecosystem: "github-actions" - directory: "/" - schedule: - interval: "weekly" diff --git a/.github/workflows/codeql.yaml b/.github/workflows/codeql.yaml deleted file mode 100644 index 0b58baec64..0000000000 --- a/.github/workflows/codeql.yaml +++ /dev/null @@ -1,49 +0,0 @@ -name: "Code Scanning - Action" - -on: - pull_request: - push: - -jobs: - CodeQL-Build: - # CodeQL runs on ubuntu-latest, windows-latest, and macos-latest - runs-on: ubuntu-latest - - permissions: - # required for all workflows - security-events: write - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Set up JDK - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: 17 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - # Override language selection by uncommenting this and choosing your languages - # with: - # languages: go, javascript, csharp, python, cpp, java - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below). - # - name: Autobuild - # uses: github/codeql-action/autobuild@v2 - - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # âœī¸ If the Autobuild fails above, remove it and uncomment the following - # three lines and modify them (or add more) to build your code if your - # project uses a compiled language - - - run: | - ./mvnw clean install -B -U -Pspring -DskipTests - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/deploy-docs.yml b/.github/workflows/deploy-docs.yml new file mode 100644 index 0000000000..7a8535cec6 --- /dev/null +++ b/.github/workflows/deploy-docs.yml @@ -0,0 +1,53 @@ +name: Deploy Docs +run-name: ${{ format('{0} ({1})', github.workflow, github.event.inputs.build-refname || 'all') }} +on: + workflow_dispatch: + inputs: + build-refname: + description: Enter git refname to build (e.g., 5.7.x). + required: false + push: + branches: docs-build +env: + GRADLE_ENTERPRISE_SECRET_ACCESS_KEY: ${{ secrets.GRADLE_ENTERPRISE_SECRET_ACCESS_KEY }} +permissions: + contents: write +jobs: + build: + if: github.repository_owner == 'spring-cloud' + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 5 + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'temurin' + - name: Set up refname build + if: github.event.inputs.build-refname + run: | + git fetch --depth 1 https://github.com/$GITHUB_REPOSITORY ${{ github.event.inputs.build-refname }} + export BUILD_REFNAME=${{ github.event.inputs.build-refname }} + echo "BUILD_REFNAME=$BUILD_REFNAME" >> $GITHUB_ENV + export BUILD_VERSION=$(git cat-file --textconv FETCH_HEAD:pom.xml | python3 -c "import xml.etree.ElementTree as xml; from sys import stdin; print(xml.parse(stdin).getroot().find('{http://maven.apache.org/POM/4.0.0}version').text)") + echo BUILD_VERSION=$BUILD_VERSION >> $GITHUB_ENV + - name: Run Antora + run: | + ./mvnw --no-transfer-progress -B antora + - name: Publish Docs + uses: spring-io/spring-doc-actions/rsync-antora-reference@v0.0.11 + with: + docs-username: ${{ secrets.DOCS_USERNAME }} + docs-host: ${{ secrets.DOCS_HOST }} + docs-ssh-key: ${{ secrets.DOCS_SSH_KEY }} + docs-ssh-host-key: ${{ secrets.DOCS_SSH_HOST_KEY }} + site-path: target/antora/site + - name: Bust Cloudflare Cache + uses: spring-io/spring-doc-actions/bust-cloudflare-antora-cache@v0.0.11 + with: + context-root: spring-cloud-contract + cloudflare-zone-id: ${{ secrets.CLOUDFLARE_ZONE_ID }} + cloudflare-cache-token: ${{ secrets.CLOUDFLARE_CACHE_TOKEN }} diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml deleted file mode 100644 index 6abbd16d0b..0000000000 --- a/.github/workflows/maven.yml +++ /dev/null @@ -1,32 +0,0 @@ -# This workflow will build a Java project with Maven -# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven - -name: Build - -on: - push: - branches: [ main, 3.1.x, 3.0.x ] - pull_request: - branches: [ main, 3.1.x, 3.0.x ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - name: Set up JDK - uses: actions/setup-java@v3 - with: - distribution: 'temurin' - java-version: 17 - - name: Cache local Maven repository - uses: actions/cache@v3 - with: - path: ~/.m2/repository - key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} - restore-keys: | - ${{ runner.os }}-maven- - - name: Build with Maven - run: ./mvnw clean install -B -U -Pspring,integration,docs diff --git a/.gitignore b/.gitignore index 052b287229..6be8a4a166 100644 --- a/.gitignore +++ b/.gitignore @@ -1,46 +1,22 @@ -*~ -#* -*# -.#* -.factorypath -.classpath -.project +target/ .settings/ -.sts4-cache/ -target/ -build/ -bin/ -.gradle/ - -*.class -.attach* - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.war -*.ear -*.versionsBackup - -# virtual machine crash logs, see https://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* - -*.class -*.iml - -.idea/ -.gradle/ -target/ -build/ -out/ - -hs_err_pid* +.project +.classpath +*.orig +.springBeans +.factorypath +.sts4-cache +.ant-targets-build.xml +src/ant/.ant-targets-upload-dist.xml +*.sonar4clipse* .DS_Store -*.log -interpolated-settings.xml -interpolated-pom.xml -dependency-reduced-pom.xml - -.vscode/ -.flattened-pom.xml +*.iml +*.ipr +*.iws +/.idea/ +*.graphml +node +node_modules +build +package.json +package-lock.json diff --git a/.mvn/maven.config b/.mvn/maven.config deleted file mode 100644 index a682990566..0000000000 --- a/.mvn/maven.config +++ /dev/null @@ -1 +0,0 @@ --P spring diff --git a/.mvn/wrapper/maven-wrapper.jar b/.mvn/wrapper/maven-wrapper.jar index c1dd12f176..2cc7d4a55c 100644 Binary files a/.mvn/wrapper/maven-wrapper.jar and b/.mvn/wrapper/maven-wrapper.jar differ diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 015dfe6821..642d572ce9 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -1,18 +1,2 @@ -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you 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. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.3/apache-maven-3.8.3-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar diff --git a/.sdkmanrc b/.sdkmanrc deleted file mode 100644 index 415f90832f..0000000000 --- a/.sdkmanrc +++ /dev/null @@ -1,3 +0,0 @@ -# Enable auto-env through the sdkman_auto_env config -# Add key=value pairs of SDKs to use below -java=17.0.1-tem diff --git a/.settings.xml b/.settings.xml deleted file mode 100644 index 97c7a2cc95..0000000000 --- a/.settings.xml +++ /dev/null @@ -1,77 +0,0 @@ - - - - - repo.spring.io - ${env.CI_DEPLOY_USERNAME} - ${env.CI_DEPLOY_PASSWORD} - - - - - - spring - - true - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - - spring-snapshots - Spring Snapshots - https://repo.spring.io/snapshot - - true - - - - spring-milestones - Spring Milestones - https://repo.spring.io/milestone - - false - - - - - - - ide - - true - - - - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 8d50b18f32..0000000000 --- a/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ -Apache License - Version 2.0, January 2004 - https://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - 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 - - https://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. - diff --git a/README.adoc b/README.adoc index 40a6c4eb2a..6ecf6bdfc2 100644 --- a/README.adoc +++ b/README.adoc @@ -1,392 +1,23 @@ -//// -DO NOT EDIT THIS FILE. IT WAS GENERATED. -Manual changes to this file will be lost when it is generated again. -Edit the files in the src/main/asciidoc/ directory instead. -//// += Spring Cloud Contract Docs Build +You're currently viewing the Antora playbook branch. +The playbook branch hosts the docs build that is used to build and publish the production docs site. -== Spring Cloud Contract +The Spring Cloud Contract reference docs are built using https://antora.org[Antora]. +This README covers how to build the docs in a software branch as well as how to build the production docs site locally. -You always need confidence when pushing new features into a new application or service in -a distributed system. To that end, this project provides support for consumer-driven -contracts and service schemas in Spring applications, covering a range of options for -writing tests, publishing them as assets, and asserting that a contract is kept by -producers and consumers -- for both HTTP and message-based interactions. - -== Project page - -You can read more about Spring Cloud Contract by going to https://spring.io/projects/spring-cloud-contract[the project page] - -== Contributing - -:spring-cloud-build-branch: master - -Spring Cloud is released under the non-restrictive Apache 2.0 license, -and follows a very standard Github development process, using Github -tracker for issues and merging pull requests into master. If you want -to contribute even something trivial please do not hesitate, but -follow the guidelines below. - -=== Sign the Contributor License Agreement -Before we accept a non-trivial patch or pull request we will need you to sign the -https://cla.pivotal.io/sign/spring[Contributor License Agreement]. -Signing the contributor's agreement does not grant anyone commit rights to the main -repository, but it does mean that we can accept your contributions, and you will get an -author credit if we do. Active contributors might be asked to join the core team, and -given the ability to merge pull requests. - -=== Code of Conduct -This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of -conduct]. By participating, you are expected to uphold this code. Please report -unacceptable behavior to spring-code-of-conduct@pivotal.io. - -=== Code Conventions and Housekeeping -None of these is essential for a pull request, but they will all help. They can also be -added after the original pull request but before a merge. - -* Use the Spring Framework code format conventions. If you use Eclipse - you can import formatter settings using the - `eclipse-code-formatter.xml` file from the - https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring - Cloud Build] project. If using IntelliJ, you can use the - https://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter - Plugin] to import the same file. -* Make sure all new `.java` files to have a simple Javadoc class comment with at least an - `@author` tag identifying you, and preferably at least a paragraph on what the class is - for. -* Add the ASF license header comment to all new `.java` files (copy from existing files - in the project) -* Add yourself as an `@author` to the .java files that you modify substantially (more - than cosmetic changes). -* Add some Javadocs and, if you change the namespace, some XSD doc elements. -* A few unit tests would help a lot as well -- someone has to do it. -* If no-one else is using your branch, please rebase it against the current master (or - other target branch in the main project). -* When writing a commit message please follow https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html[these conventions], - if you are fixing an existing issue please add `Fixes gh-XXXX` at the end of the commit - message (where XXXX is the issue number). - -=== Checkstyle - -Spring Cloud Build comes with a set of checkstyle rules. You can find them in the `spring-cloud-build-tools` module. The most notable files under the module are: - -.spring-cloud-build-tools/ ----- -└── src -    ├── checkstyle -    │   └── checkstyle-suppressions.xml <3> -    └── main -    └── resources -    ├── checkstyle-header.txt <2> -    └── checkstyle.xml <1> ----- -<1> Default Checkstyle rules -<2> File header setup -<3> Default suppression rules - -==== Checkstyle configuration - -Checkstyle rules are *disabled by default*. To add checkstyle to your project just define the following properties and plugins. - -.pom.xml ----- - -true <1> - true - <2> - true - <3> - - - - - <4> - io.spring.javaformat - spring-javaformat-maven-plugin - - <5> - org.apache.maven.plugins - maven-checkstyle-plugin - - - - - - <5> - org.apache.maven.plugins - maven-checkstyle-plugin - - - - ----- -<1> Fails the build upon Checkstyle errors -<2> Fails the build upon Checkstyle violations -<3> Checkstyle analyzes also the test sources -<4> Add the Spring Java Format plugin that will reformat your code to pass most of the Checkstyle formatting rules -<5> Add checkstyle plugin to your build and reporting phases - -If you need to suppress some rules (e.g. line length needs to be longer), then it's enough for you to define a file under `${project.root}/src/checkstyle/checkstyle-suppressions.xml` with your suppressions. Example: - -.projectRoot/src/checkstyle/checkstyle-suppresions.xml ----- - - - - - - ----- - -It's advisable to copy the `${spring-cloud-build.rootFolder}/.editorconfig` and `${spring-cloud-build.rootFolder}/.springformat` to your project. That way, some default formatting rules will be applied. You can do so by running this script: - -```bash -$ curl https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/.editorconfig -o .editorconfig -$ touch .springformat -``` - -=== IDE setup - -==== Intellij IDEA - -In order to setup Intellij you should import our coding conventions, inspection profiles and set up the checkstyle plugin. -The following files can be found in the https://github.com/spring-cloud/spring-cloud-build/tree/master/spring-cloud-build-tools[Spring Cloud Build] project. - -.spring-cloud-build-tools/ ----- -└── src -    ├── checkstyle -    │   └── checkstyle-suppressions.xml <3> -    └── main -    └── resources -    ├── checkstyle-header.txt <2> -    ├── checkstyle.xml <1> -    └── intellij -       ├── Intellij_Project_Defaults.xml <4> -       └── Intellij_Spring_Boot_Java_Conventions.xml <5> ----- -<1> Default Checkstyle rules -<2> File header setup -<3> Default suppression rules -<4> Project defaults for Intellij that apply most of Checkstyle rules -<5> Project style conventions for Intellij that apply most of Checkstyle rules - -.Code style - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-code-style.png[Code style] - -Go to `File` -> `Settings` -> `Editor` -> `Code style`. There click on the icon next to the `Scheme` section. There, click on the `Import Scheme` value and pick the `Intellij IDEA code style XML` option. Import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Spring_Boot_Java_Conventions.xml` file. - -.Inspection profiles - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-inspections.png[Code style] - -Go to `File` -> `Settings` -> `Editor` -> `Inspections`. There click on the icon next to the `Profile` section. There, click on the `Import Profile` and import the `spring-cloud-build-tools/src/main/resources/intellij/Intellij_Project_Defaults.xml` file. - -.Checkstyle - -To have Intellij work with Checkstyle, you have to install the `Checkstyle` plugin. It's advisable to also install the `Assertions2Assertj` to automatically convert the JUnit assertions - -image::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/{spring-cloud-build-branch}/docs/src/main/asciidoc/images/intellij-checkstyle.png[Checkstyle] - -Go to `File` -> `Settings` -> `Other settings` -> `Checkstyle`. There click on the `+` icon in the `Configuration file` section. There, you'll have to define where the checkstyle rules should be picked from. In the image above, we've picked the rules from the cloned Spring Cloud Build repository. However, you can point to the Spring Cloud Build's GitHub repository (e.g. for the `checkstyle.xml` : `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle.xml`). We need to provide the following variables: - -- `checkstyle.header.file` - please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/main/resources/checkstyle-header.txt` URL. -- `checkstyle.suppressions.file` - default suppressions. Please point it to the Spring Cloud Build's, `spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` file either in your cloned repo or via the `https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-build-tools/src/checkstyle/checkstyle-suppressions.xml` URL. -- `checkstyle.additional.suppressions.file` - this variable corresponds to suppressions in your local project. E.g. you're working on `spring-cloud-contract`. Then point to the `project-root/src/checkstyle/checkstyle-suppressions.xml` folder. Example for `spring-cloud-contract` would be: `/home/username/spring-cloud-contract/src/checkstyle/checkstyle-suppressions.xml`. - -IMPORTANT: Remember to set the `Scan Scope` to `All sources` since we apply checkstyle rules for production and test sources. - -=== Duplicate Finder - -Spring Cloud Build brings along the `basepom:duplicate-finder-maven-plugin`, that enables flagging duplicate and conflicting classes and resources on the java classpath. - -==== Duplicate Finder configuration - -Duplicate finder is *enabled by default* and will run in the `verify` phase of your Maven build, but it will only take effect in your project if you add the `duplicate-finder-maven-plugin` to the `build` section of the projecst's `pom.xml`. - -.pom.xml -[source,xml] ----- - - - - org.basepom.maven - duplicate-finder-maven-plugin - - - ----- - -For other properties, we have set defaults as listed in the https://github.com/basepom/duplicate-finder-maven-plugin/wiki[plugin documentation]. - -You can easily override them but setting the value of the selected property prefixed with `duplicate-finder-maven-plugin`. For example, set `duplicate-finder-maven-plugin.skip` to `true` in order to skip duplicates check in your build. - -If you need to add `ignoredClassPatterns` or `ignoredResourcePatterns` to your setup, make sure to add them in the plugin configuration section of your project: - -[source,xml] ----- - - - - org.basepom.maven - duplicate-finder-maven-plugin - - - org.joda.time.base.BaseDateTime - .*module-info - - - changelog.txt - - - - - - - ----- - - -== How to Build Spring Cloud Contract - -=== Cloning the repository on Windows - -While cloning this project on Windows, some files in the git repository may exceed the Windows maximum file path limit of 255 characters, which may -result in an incorrectly (probably partially) checked out repository. - -To resolve this issue, you can set the `core.longPaths` attribute to `true` or clone the Spring Cloud Contract repository. - -To set the `core.longPaths` attribute to `true`, you have three options: - -- Change it for all users of the machine (doing so requires administrator privileges): +== Building the Site +You can build the entire site by invoking the following on the docs-build branch and then viewing the site at `target/site/index.html` [source,bash] ---- -git config --system core.longPaths true -git clone https://github.com/spring-cloud/spring-cloud-contract.git +./mvnw antora ---- -- Change it for the current user (no administrative privileges required): +== Building a Specific Branch [source,bash] ---- -git config --global core.longPaths true -git clone https://github.com/spring-cloud/spring-cloud-contract.git +./mvnw antora ---- - -- Change for just this repository (administrative privileges depend on where the repository is being cloned to): - -[source,bash] ----- -git clone -c core.longPaths=true https://github.com/spring-cloud/spring-cloud-contract.git ----- - -IMPORTANT: You need to have all the necessary Groovy plugins -installed for your IDE to properly resolve the sources. For example, in -Intellij IDEA, having both the Eclipse Groovy Compiler Plugin and the GMavenPlus Intellij -Plugin results in properly imported project. - -IMPORTANT: Spring Cloud Contract builds Docker images. Remember to -have Docker installed. - -IMPORTANT: If you want to run the build in offline mode, you must have Maven 3.5.2+ installed. - -=== Project structure - -The following listing shows the Spring Cloud Contract folder structure: - -``` -├── config -├── docker -├── samples -├── scripts -├── specs -├── spring-cloud-contract-dependencies -├── spring-cloud-contract-shade -├── spring-cloud-contract-starters -├── spring-cloud-contract-stub-runner -├── spring-cloud-contract-stub-runner-boot -├── spring-cloud-contract-tools -├── spring-cloud-contract-verifier -├── spring-cloud-contract-wiremock -└── tests -``` - -The following list describes each of the top-level folders in the project structure: - -- `config`: Folder contains setup for Spring Cloud Release Tools automated release process -- `docker`: Folder contains docker images -- `samples`: Folder contains test samples together with standalone ones used also to build documentation -- `scripts`: Contains scripts to build and test `Spring Cloud Contract` with Maven, Gradle and standalone projects -- `specs`: Contains specifications for the Contract DSL. -- `spring-cloud-contract-dependencies`: Contains Spring Cloud Contract BOM -- `spring-cloud-contract-shade`: Shaded dependencies used by the plugins -- `spring-cloud-contract-starters`: Contains Spring Cloud Contract Starters -- `spring-cloud-contract-spec`: Contains specification modules (contains concept of a Contract) -- `spring-cloud-contract-stub-runner`: Contains Stub Runner related modules -- `spring-cloud-contract-stub-runner-boot`: Contains Stub Runner Boot app -- `spring-cloud-contract-tools`: Gradle and Maven plugin for `Spring Cloud Contract Verifier` -- `spring-cloud-contract-verifier`: Core of the `Spring Cloud Contract Verifier` functionality -- `spring-cloud-contract-wiremock`: All WireMock related functionality -- `tests`: Integration tests for different messaging technologies - -=== Commands - -To build the core functionality together with the Maven Plugin, you can run the following -command: - -``` -./mvnw clean install -P integration -``` - -Calling that function builds the core, the Maven plugin, and the Gradle plugin and runs -end-to_end tests on the -standalone samples in the proper order (both for Maven and Gradle). - -To build only the Gradle Plugin, you can run the following commands: - -``` -cd spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin -./gradlew clean build -``` - -=== Helpful scripts - -We provide a couple of helpful scripts to build the project. - -To build the project in parallel (by default, it uses four cores, but you can change it), -run the following command: - -``` -./scripts/parallelBuild.sh -``` - -To use eight 8 cores, run the following command: - -``` -CORES=8 ./scripts/parallelBuild.sh -``` - -To build the project without any integration tests (by default, this uses one core), run -the following command: - -``` -./scripts/noIntegration.sh -``` - -To use eight cores, run the following command: - -``` -CORES=8 ./scripts/noIntegration.sh -``` - -To generate the documentation (for both the root project and the maven plugin), run the -following command: - -``` -./scripts/generateDocs.sh -``` diff --git a/docs/antora-playbook.yml b/antora-playbook.yml similarity index 61% rename from docs/antora-playbook.yml rename to antora-playbook.yml index 9a70e676ca..c4cef4bacf 100644 --- a/docs/antora-playbook.yml +++ b/antora-playbook.yml @@ -6,38 +6,39 @@ antora: - '@antora/collector-extension' - '@antora/atlas-extension' - require: '@springio/antora-extensions/root-component-extension' - root_component_name: 'PROJECT_WITHOUT_SPRING' - # FIXME: Run antora once using this extension to migrate to the Asciidoc Tabs syntax - # and then remove this extension - - require: '@springio/antora-extensions/tabs-migration-extension' - unwrap_example_block: always - save_result: true + root_component_name: 'cloud-contract' site: - title: PROJECT_FULL_NAME - url: https://docs.spring.io/PROJECT_NAME/reference/ + title: Spring Cloud Contract + url: https://docs.spring.io/spring-cloud-contract/reference + robots: allow +git: + ensure_git_suffix: false content: sources: - - url: ./.. - branches: HEAD + - url: https://github.com/spring-cloud/spring-cloud-contract + # Refname matching: + # https://docs.antora.org/antora/latest/playbook/content-refname-matching/ + branches: [ main ] + tags: [ '({4..9}).+({1..9}).+({0..9})?(-{RC,M}+({0..9}))', '!4.1.0-M1' ] start_path: docs - worktrees: true asciidoc: attributes: page-stackoverflow-url: https://stackoverflow.com/tags/spring-cloud page-pagination: '' hide-uri-scheme: '@' tabs-sync-option: '@' - chomp: 'all' extensions: - '@asciidoctor/tabs' - '@springio/asciidoctor-extensions' - sourcemap: true urls: + latest_version_segment_strategy: redirect:to latest_version_segment: '' + redirect_facility: httpd +ui: + bundle: + url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.5/ui-bundle.zip + snapshot: true runtime: log: failure_level: warn format: pretty -ui: - bundle: - url: https://github.com/spring-io/antora-ui-spring/releases/download/v0.3.5/ui-bundle.zip diff --git a/asciidoctor.css b/asciidoctor.css deleted file mode 100644 index dd1495848b..0000000000 --- a/asciidoctor.css +++ /dev/null @@ -1,2011 +0,0 @@ -/* Asciidoctor default stylesheet | MIT License | https://asciidoctor.org */ -/* Remove the comments around the @import statement below when using this as a custom stylesheet */ -/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic|Noto+Serif:400,400italic,700,700italic|Droid+Sans+Mono:400";*/ -article, aside, details, figcaption, figure, footer, header, hgroup, main, nav, section, summary { - display: block -} - -audio, canvas, video { - display: inline-block -} - -audio:not([controls]) { - display: none; - height: 0 -} - -[hidden], template { - display: none -} - -script { - display: none !important -} - -html { - font-family: sans-serif; - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100% -} - -body { - margin: 0 -} - -a { - background: transparent -} - -a:focus { - outline: thin dotted -} - -a:active, a:hover { - outline: 0 -} - -h1 { - font-size: 2em; - margin: .67em 0 -} - -abbr[title] { - border-bottom: 1px dotted -} - -b, strong { - font-weight: bold -} - -dfn { - font-style: italic -} - -hr { - -moz-box-sizing: content-box; - box-sizing: content-box; - height: 0 -} - -mark { - background: #ff0; - color: #000 -} - -code, kbd, pre, samp { - font-family: monospace; - font-size: 1em -} - -pre { - white-space: pre-wrap -} - -q { - quotes: "\201C" "\201D" "\2018" "\2019" -} - -small { - font-size: 80% -} - -sub, sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline -} - -sup { - top: -.5em -} - -sub { - bottom: -.25em -} - -img { - border: 0 -} - -svg:not(:root) { - overflow: hidden -} - -figure { - margin: 0 -} - -fieldset { - border: 1px solid silver; - margin: 0 2px; - padding: .35em .625em .75em -} - -legend { - border: 0; - padding: 0 -} - -button, input, select, textarea { - font-family: inherit; - font-size: 100%; - margin: 0 -} - -button, input { - line-height: normal -} - -button, select { - text-transform: none -} - -button, html input[type="button"], input[type="reset"], input[type="submit"] { - -webkit-appearance: button; - cursor: pointer -} - -button[disabled], html input[disabled] { - cursor: default -} - -input[type="checkbox"], input[type="radio"] { - box-sizing: border-box; - padding: 0 -} - -input[type="search"] { - -webkit-appearance: textfield; - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; - box-sizing: content-box -} - -input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none -} - -button::-moz-focus-inner, input::-moz-focus-inner { - border: 0; - padding: 0 -} - -textarea { - overflow: auto; - vertical-align: top -} - -table { - border-collapse: collapse; - border-spacing: 0 -} - -*, *:before, *:after { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box -} - -html, body { - font-size: 100% -} - -body { - background: #fff; - color: rgba(0, 0, 0, .8); - padding: 0; - margin: 0; - font-family: "Noto Serif", "DejaVu Serif", serif; - font-weight: 400; - font-style: normal; - line-height: 1; - position: relative; - cursor: auto -} - -a:hover { - cursor: pointer -} - -img, object, embed { - max-width: 100%; - height: auto -} - -object, embed { - height: 100% -} - -img { - -ms-interpolation-mode: bicubic -} - -#map_canvas img, #map_canvas embed, #map_canvas object, .map_canvas img, .map_canvas embed, .map_canvas object { - max-width: none !important -} - -.left { - float: left !important -} - -.right { - float: right !important -} - -.text-left { - text-align: left !important -} - -.text-right { - text-align: right !important -} - -.text-center { - text-align: center !important -} - -.text-justify { - text-align: justify !important -} - -.hide { - display: none -} - -.antialiased, body { - -webkit-font-smoothing: antialiased -} - -img { - display: inline-block; - vertical-align: middle -} - -textarea { - height: auto; - min-height: 50px -} - -select { - width: 100% -} - -p.lead, .paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { - font-size: 1.21875em; - line-height: 1.6 -} - -.subheader, .admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { - line-height: 1.45; - color: #7a2518; - font-weight: 400; - margin-top: 0; - margin-bottom: .25em -} - -div, dl, dt, dd, ul, ol, li, h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6, pre, form, p, blockquote, th, td { - margin: 0; - padding: 0; - direction: ltr -} - -a { - color: #2156a5; - text-decoration: underline; - line-height: inherit -} - -a:hover, a:focus { - color: #1d4b8f -} - -a img { - border: none -} - -p { - font-family: inherit; - font-weight: 400; - font-size: 1em; - line-height: 1.6; - margin-bottom: 1.25em; - text-rendering: optimizeLegibility -} - -p aside { - font-size: .875em; - line-height: 1.35; - font-style: italic -} - -h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { - font-family: "Open Sans", "DejaVu Sans", sans-serif; - font-weight: 300; - font-style: normal; - color: #ba3925; - text-rendering: optimizeLegibility; - margin-top: 1em; - margin-bottom: .5em; - line-height: 1.0125em -} - -h1 small, h2 small, h3 small, #toctitle small, .sidebarblock > .content > .title small, h4 small, h5 small, h6 small { - font-size: 60%; - color: #e99b8f; - line-height: 0 -} - -h1 { - font-size: 2.125em -} - -h2 { - font-size: 1.6875em -} - -h3, #toctitle, .sidebarblock > .content > .title { - font-size: 1.375em -} - -h4, h5 { - font-size: 1.125em -} - -h6 { - font-size: 1em -} - -hr { - border: solid #ddddd8; - border-width: 1px 0 0; - clear: both; - margin: 1.25em 0 1.1875em; - height: 0 -} - -em, i { - font-style: italic; - line-height: inherit -} - -strong, b { - font-weight: bold; - line-height: inherit -} - -small { - font-size: 60%; - line-height: inherit -} - -code { - font-family: "Droid Sans Mono", "DejaVu Sans Mono", monospace; - font-weight: 400; - color: rgba(0, 0, 0, .9) -} - -ul, ol, dl { - font-size: 1em; - line-height: 1.6; - margin-bottom: 1.25em; - list-style-position: outside; - font-family: inherit -} - -ul, ol, ul.no-bullet, ol.no-bullet { - margin-left: 1.5em -} - -ul li ul, ul li ol { - margin-left: 1.25em; - margin-bottom: 0; - font-size: 1em -} - -ul.square li ul, ul.circle li ul, ul.disc li ul { - list-style: inherit -} - -ul.square { - list-style-type: square -} - -ul.circle { - list-style-type: circle -} - -ul.disc { - list-style-type: disc -} - -ul.no-bullet { - list-style: none -} - -ol li ul, ol li ol { - margin-left: 1.25em; - margin-bottom: 0 -} - -dl dt { - margin-bottom: .3125em; - font-weight: bold -} - -dl dd { - margin-bottom: 1.25em -} - -abbr, acronym { - text-transform: uppercase; - font-size: 90%; - color: rgba(0, 0, 0, .8); - border-bottom: 1px dotted #ddd; - cursor: help -} - -abbr { - text-transform: none -} - -blockquote { - margin: 0 0 1.25em; - padding: .5625em 1.25em 0 1.1875em; - border-left: 1px solid #ddd -} - -blockquote cite { - display: block; - font-size: .9375em; - color: rgba(0, 0, 0, .6) -} - -blockquote cite:before { - content: "\2014 \0020" -} - -blockquote cite a, blockquote cite a:visited { - color: rgba(0, 0, 0, .6) -} - -blockquote, blockquote p { - line-height: 1.6; - color: rgba(0, 0, 0, .85) -} - -@media only screen and (min-width: 768px) { - h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { - line-height: 1.2 - } - - h1 { - font-size: 2.75em - } - - h2 { - font-size: 2.3125em - } - - h3, #toctitle, .sidebarblock > .content > .title { - font-size: 1.6875em - } - - h4 { - font-size: 1.4375em - } -} - -table { - background: #fff; - margin-bottom: 1.25em; - border: solid 1px #dedede -} - -table thead, table tfoot { - background: #f7f8f7; - font-weight: bold -} - -table thead tr th, table thead tr td, table tfoot tr th, table tfoot tr td { - padding: .5em .625em .625em; - font-size: inherit; - color: rgba(0, 0, 0, .8); - text-align: left -} - -table tr th, table tr td { - padding: .5625em .625em; - font-size: inherit; - color: rgba(0, 0, 0, .8) -} - -table tr.even, table tr.alt, table tr:nth-of-type(even) { - background: #f8f8f7 -} - -table thead tr th, table tfoot tr th, table tbody tr td, table tr td, table tfoot tr td { - display: table-cell; - line-height: 1.6 -} - -h1, h2, h3, #toctitle, .sidebarblock > .content > .title, h4, h5, h6 { - line-height: 1.2; - word-spacing: -.05em -} - -h1 strong, h2 strong, h3 strong, #toctitle strong, .sidebarblock > .content > .title strong, h4 strong, h5 strong, h6 strong { - font-weight: 400 -} - -.clearfix:before, .clearfix:after, .float-group:before, .float-group:after { - content: " "; - display: table -} - -.clearfix:after, .float-group:after { - clear: both -} - -*:not(pre) > code { - font-size: .9375em; - font-style: normal !important; - letter-spacing: 0; - padding: .1em .5ex; - word-spacing: -.15em; - background-color: #f7f7f8; - -webkit-border-radius: 4px; - border-radius: 4px; - line-height: 1.45; - text-rendering: optimizeSpeed -} - -pre, pre > code { - line-height: 1.45; - color: rgba(0, 0, 0, .9); - font-family: "Droid Sans Mono", "DejaVu Sans Mono", monospace; - font-weight: 400; - text-rendering: optimizeSpeed -} - -.keyseq { - color: rgba(51, 51, 51, .8) -} - -kbd { - display: inline-block; - color: rgba(0, 0, 0, .8); - font-size: .75em; - line-height: 1.4; - background-color: #f7f7f7; - border: 1px solid #ccc; - -webkit-border-radius: 3px; - border-radius: 3px; - -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, .2), 0 0 0 .1em white inset; - box-shadow: 0 1px 0 rgba(0, 0, 0, .2), 0 0 0 .1em #fff inset; - margin: -.15em .15em 0 .15em; - padding: .2em .6em .2em .5em; - vertical-align: middle; - white-space: nowrap -} - -.keyseq kbd:first-child { - margin-left: 0 -} - -.keyseq kbd:last-child { - margin-right: 0 -} - -.menuseq, .menu { - color: rgba(0, 0, 0, .8) -} - -b.button:before, b.button:after { - position: relative; - top: -1px; - font-weight: 400 -} - -b.button:before { - content: "["; - padding: 0 3px 0 2px -} - -b.button:after { - content: "]"; - padding: 0 2px 0 3px -} - -p a > code:hover { - color: rgba(0, 0, 0, .9) -} - -#header, #content, #footnotes, #footer { - width: 100%; - margin-left: auto; - margin-right: auto; - margin-top: 0; - margin-bottom: 0; - max-width: 62.5em; - *zoom: 1; - position: relative; - padding-left: .9375em; - padding-right: .9375em -} - -#header:before, #header:after, #content:before, #content:after, #footnotes:before, #footnotes:after, #footer:before, #footer:after { - content: " "; - display: table -} - -#header:after, #content:after, #footnotes:after, #footer:after { - clear: both -} - -#content { - margin-top: 1.25em -} - -#content:before { - content: none -} - -#header > h1:first-child { - color: rgba(0, 0, 0, .85); - margin-top: 2.25rem; - margin-bottom: 0 -} - -#header > h1:first-child + #toc { - margin-top: 8px; - border-top: 1px solid #ddddd8 -} - -#header > h1:only-child, body.toc2 #header > h1:nth-last-child(2) { - border-bottom: 1px solid #ddddd8; - padding-bottom: 8px -} - -#header .details { - border-bottom: 1px solid #ddddd8; - line-height: 1.45; - padding-top: .25em; - padding-bottom: .25em; - padding-left: .25em; - color: rgba(0, 0, 0, .6); - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - -ms-flex-flow: row wrap; - -webkit-flex-flow: row wrap; - flex-flow: row wrap -} - -#header .details span:first-child { - margin-left: -.125em -} - -#header .details span.email a { - color: rgba(0, 0, 0, .85) -} - -#header .details br { - display: none -} - -#header .details br + span:before { - content: "\00a0\2013\00a0" -} - -#header .details br + span.author:before { - content: "\00a0\22c5\00a0"; - color: rgba(0, 0, 0, .85) -} - -#header .details br + span#revremark:before { - content: "\00a0|\00a0" -} - -#header #revnumber { - text-transform: capitalize -} - -#header #revnumber:after { - content: "\00a0" -} - -#content > h1:first-child:not([class]) { - color: rgba(0, 0, 0, .85); - border-bottom: 1px solid #ddddd8; - padding-bottom: 8px; - margin-top: 0; - padding-top: 1rem; - margin-bottom: 1.25rem -} - -#toc { - border-bottom: 1px solid #efefed; - padding-bottom: .5em -} - -#toc > ul { - margin-left: .125em -} - -#toc ul.sectlevel0 > li > a { - font-style: italic -} - -#toc ul.sectlevel0 ul.sectlevel1 { - margin: .5em 0 -} - -#toc ul { - font-family: "Open Sans", "DejaVu Sans", sans-serif; - list-style-type: none -} - -#toc a { - text-decoration: none -} - -#toc a:active { - text-decoration: underline -} - -#toctitle { - color: #7a2518; - font-size: 1.2em -} - -@media only screen and (min-width: 768px) { - #toctitle { - font-size: 1.375em - } - - body.toc2 { - padding-left: 15em; - padding-right: 0 - } - - #toc.toc2 { - margin-top: 0 !important; - background-color: #f8f8f7; - position: fixed; - width: 15em; - left: 0; - top: 0; - border-right: 1px solid #efefed; - border-top-width: 0 !important; - border-bottom-width: 0 !important; - z-index: 1000; - padding: 1.25em 1em; - height: 100%; - overflow: auto - } - - #toc.toc2 #toctitle { - margin-top: 0; - font-size: 1.2em - } - - #toc.toc2 > ul { - font-size: .9em; - margin-bottom: 0 - } - - #toc.toc2 ul ul { - margin-left: 0; - padding-left: 1em - } - - #toc.toc2 ul.sectlevel0 ul.sectlevel1 { - padding-left: 0; - margin-top: .5em; - margin-bottom: .5em - } - - body.toc2.toc-right { - padding-left: 0; - padding-right: 15em - } - - body.toc2.toc-right #toc.toc2 { - border-right-width: 0; - border-left: 1px solid #efefed; - left: auto; - right: 0 - } -} - -@media only screen and (min-width: 1280px) { - body.toc2 { - padding-left: 20em; - padding-right: 0 - } - - #toc.toc2 { - width: 20em - } - - #toc.toc2 #toctitle { - font-size: 1.375em - } - - #toc.toc2 > ul { - font-size: .95em - } - - #toc.toc2 ul ul { - padding-left: 1.25em - } - - body.toc2.toc-right { - padding-left: 0; - padding-right: 20em - } -} - -#content #toc { - border-style: solid; - border-width: 1px; - border-color: #e0e0dc; - margin-bottom: 1.25em; - padding: 1.25em; - background: #f8f8f7; - -webkit-border-radius: 4px; - border-radius: 4px -} - -#content #toc > :first-child { - margin-top: 0 -} - -#content #toc > :last-child { - margin-bottom: 0 -} - -#footer { - max-width: 100%; - background-color: rgba(0, 0, 0, .8); - padding: 1.25em -} - -#footer-text { - color: rgba(255, 255, 255, .8); - line-height: 1.44 -} - -.sect1 { - padding-bottom: .625em -} - -@media only screen and (min-width: 768px) { - .sect1 { - padding-bottom: 1.25em - } -} - -.sect1 + .sect1 { - border-top: 1px solid #efefed -} - -#content h1 > a.anchor, h2 > a.anchor, h3 > a.anchor, #toctitle > a.anchor, .sidebarblock > .content > .title > a.anchor, h4 > a.anchor, h5 > a.anchor, h6 > a.anchor { - position: absolute; - z-index: 1001; - width: 1.5ex; - margin-left: -1.5ex; - display: block; - text-decoration: none !important; - visibility: hidden; - text-align: center; - font-weight: 400 -} - -#content h1 > a.anchor:before, h2 > a.anchor:before, h3 > a.anchor:before, #toctitle > a.anchor:before, .sidebarblock > .content > .title > a.anchor:before, h4 > a.anchor:before, h5 > a.anchor:before, h6 > a.anchor:before { - content: "\00A7"; - font-size: .85em; - display: block; - padding-top: .1em -} - -#content h1:hover > a.anchor, #content h1 > a.anchor:hover, h2:hover > a.anchor, h2 > a.anchor:hover, h3:hover > a.anchor, #toctitle:hover > a.anchor, .sidebarblock > .content > .title:hover > a.anchor, h3 > a.anchor:hover, #toctitle > a.anchor:hover, .sidebarblock > .content > .title > a.anchor:hover, h4:hover > a.anchor, h4 > a.anchor:hover, h5:hover > a.anchor, h5 > a.anchor:hover, h6:hover > a.anchor, h6 > a.anchor:hover { - visibility: visible -} - -#content h1 > a.link, h2 > a.link, h3 > a.link, #toctitle > a.link, .sidebarblock > .content > .title > a.link, h4 > a.link, h5 > a.link, h6 > a.link { - color: #ba3925; - text-decoration: none -} - -#content h1 > a.link:hover, h2 > a.link:hover, h3 > a.link:hover, #toctitle > a.link:hover, .sidebarblock > .content > .title > a.link:hover, h4 > a.link:hover, h5 > a.link:hover, h6 > a.link:hover { - color: #a53221 -} - -.audioblock, .imageblock, .literalblock, .listingblock, .stemblock, .videoblock { - margin-bottom: 1.25em -} - -.admonitionblock td.content > .title, .audioblock > .title, .exampleblock > .title, .imageblock > .title, .listingblock > .title, .literalblock > .title, .stemblock > .title, .openblock > .title, .paragraph > .title, .quoteblock > .title, table.tableblock > .title, .verseblock > .title, .videoblock > .title, .dlist > .title, .olist > .title, .ulist > .title, .qlist > .title, .hdlist > .title { - text-rendering: optimizeLegibility; - text-align: left; - font-family: "Noto Serif", "DejaVu Serif", serif; - font-size: 1rem; - font-style: italic -} - -table.tableblock > caption.title { - white-space: nowrap; - overflow: visible; - max-width: 0 -} - -.paragraph.lead > p, #preamble > .sectionbody > .paragraph:first-of-type p { - color: rgba(0, 0, 0, .85) -} - -table.tableblock #preamble > .sectionbody > .paragraph:first-of-type p { - font-size: inherit -} - -.admonitionblock > table { - border-collapse: separate; - border: 0; - background: none; - width: 100% -} - -.admonitionblock > table td.icon { - text-align: center; - width: 80px -} - -.admonitionblock > table td.icon img { - max-width: none -} - -.admonitionblock > table td.icon .title { - font-weight: bold; - font-family: "Open Sans", "DejaVu Sans", sans-serif; - text-transform: uppercase -} - -.admonitionblock > table td.content { - padding-left: 1.125em; - padding-right: 1.25em; - border-left: 1px solid #ddddd8; - color: rgba(0, 0, 0, .6) -} - -.admonitionblock > table td.content > :last-child > :last-child { - margin-bottom: 0 -} - -.exampleblock > .content { - border-style: solid; - border-width: 1px; - border-color: #e6e6e6; - margin-bottom: 1.25em; - padding: 1.25em; - background: #fff; - -webkit-border-radius: 4px; - border-radius: 4px -} - -.exampleblock > .content > :first-child { - margin-top: 0 -} - -.exampleblock > .content > :last-child { - margin-bottom: 0 -} - -.sidebarblock { - border-style: solid; - border-width: 1px; - border-color: #e0e0dc; - margin-bottom: 1.25em; - padding: 1.25em; - background: #f8f8f7; - -webkit-border-radius: 4px; - border-radius: 4px -} - -.sidebarblock > :first-child { - margin-top: 0 -} - -.sidebarblock > :last-child { - margin-bottom: 0 -} - -.sidebarblock > .content > .title { - color: #7a2518; - margin-top: 0; - text-align: center -} - -.exampleblock > .content > :last-child > :last-child, .exampleblock > .content .olist > ol > li:last-child > :last-child, .exampleblock > .content .ulist > ul > li:last-child > :last-child, .exampleblock > .content .qlist > ol > li:last-child > :last-child, .sidebarblock > .content > :last-child > :last-child, .sidebarblock > .content .olist > ol > li:last-child > :last-child, .sidebarblock > .content .ulist > ul > li:last-child > :last-child, .sidebarblock > .content .qlist > ol > li:last-child > :last-child { - margin-bottom: 0 -} - -.literalblock pre, .listingblock pre:not(.highlight), .listingblock pre[class="highlight"], .listingblock pre[class^="highlight "], .listingblock pre.CodeRay, .listingblock pre.prettyprint { - background: #f7f7f8 -} - -.sidebarblock .literalblock pre, .sidebarblock .listingblock pre:not(.highlight), .sidebarblock .listingblock pre[class="highlight"], .sidebarblock .listingblock pre[class^="highlight "], .sidebarblock .listingblock pre.CodeRay, .sidebarblock .listingblock pre.prettyprint { - background: #f2f1f1 -} - -.literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { - -webkit-border-radius: 4px; - border-radius: 4px; - word-wrap: break-word; - padding: 1em; - font-size: .8125em -} - -.literalblock pre.nowrap, .literalblock pre[class].nowrap, .listingblock pre.nowrap, .listingblock pre[class].nowrap { - overflow-x: auto; - white-space: pre; - word-wrap: normal -} - -@media only screen and (min-width: 768px) { - .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { - font-size: .90625em - } -} - -@media only screen and (min-width: 1280px) { - .literalblock pre, .literalblock pre[class], .listingblock pre, .listingblock pre[class] { - font-size: 1em - } -} - -.literalblock.output pre { - color: #f7f7f8; - background-color: rgba(0, 0, 0, .9) -} - -.listingblock pre.highlightjs { - padding: 0 -} - -.listingblock pre.highlightjs > code { - padding: 1em; - -webkit-border-radius: 4px; - border-radius: 4px -} - -.listingblock pre.prettyprint { - border-width: 0 -} - -.listingblock > .content { - position: relative -} - -.listingblock code[data-lang]:before { - display: none; - content: attr(data-lang); - position: absolute; - font-size: .75em; - top: .425rem; - right: .5rem; - line-height: 1; - text-transform: uppercase; - color: #999 -} - -.listingblock:hover code[data-lang]:before { - display: block -} - -.listingblock.terminal pre .command:before { - content: attr(data-prompt); - padding-right: .5em; - color: #999 -} - -.listingblock.terminal pre .command:not([data-prompt]):before { - content: "$" -} - -table.pyhltable { - border-collapse: separate; - border: 0; - margin-bottom: 0; - background: none -} - -table.pyhltable td { - vertical-align: top; - padding-top: 0; - padding-bottom: 0 -} - -table.pyhltable td.code { - padding-left: .75em; - padding-right: 0 -} - -pre.pygments .lineno, table.pyhltable td:not(.code) { - color: #999; - padding-left: 0; - padding-right: .5em; - border-right: 1px solid #ddddd8 -} - -pre.pygments .lineno { - display: inline-block; - margin-right: .25em -} - -table.pyhltable .linenodiv { - background: none !important; - padding-right: 0 !important -} - -.quoteblock { - margin: 0 1em 1.25em 1.5em; - display: table -} - -.quoteblock > .title { - margin-left: -1.5em; - margin-bottom: .75em -} - -.quoteblock blockquote, .quoteblock blockquote p { - color: rgba(0, 0, 0, .85); - font-size: 1.15rem; - line-height: 1.75; - word-spacing: .1em; - letter-spacing: 0; - font-style: italic; - text-align: justify -} - -.quoteblock blockquote { - margin: 0; - padding: 0; - border: 0 -} - -.quoteblock blockquote:before { - content: "\201c"; - float: left; - font-size: 2.75em; - font-weight: bold; - line-height: .6em; - margin-left: -.6em; - color: #7a2518; - text-shadow: 0 1px 2px rgba(0, 0, 0, .1) -} - -.quoteblock blockquote > .paragraph:last-child p { - margin-bottom: 0 -} - -.quoteblock .attribution { - margin-top: .5em; - margin-right: .5ex; - text-align: right -} - -.quoteblock .quoteblock { - margin-left: 0; - margin-right: 0; - padding: .5em 0; - border-left: 3px solid rgba(0, 0, 0, .6) -} - -.quoteblock .quoteblock blockquote { - padding: 0 0 0 .75em -} - -.quoteblock .quoteblock blockquote:before { - display: none -} - -.verseblock { - margin: 0 1em 1.25em 1em -} - -.verseblock pre { - font-family: "Open Sans", "DejaVu Sans", sans; - font-size: 1.15rem; - color: rgba(0, 0, 0, .85); - font-weight: 300; - text-rendering: optimizeLegibility -} - -.verseblock pre strong { - font-weight: 400 -} - -.verseblock .attribution { - margin-top: 1.25rem; - margin-left: .5ex -} - -.quoteblock .attribution, .verseblock .attribution { - font-size: .9375em; - line-height: 1.45; - font-style: italic -} - -.quoteblock .attribution br, .verseblock .attribution br { - display: none -} - -.quoteblock .attribution cite, .verseblock .attribution cite { - display: block; - letter-spacing: -.05em; - color: rgba(0, 0, 0, .6) -} - -.quoteblock.abstract { - margin: 0 0 1.25em 0; - display: block -} - -.quoteblock.abstract blockquote, .quoteblock.abstract blockquote p { - text-align: left; - word-spacing: 0 -} - -.quoteblock.abstract blockquote:before, .quoteblock.abstract blockquote p:first-of-type:before { - display: none -} - -table.tableblock { - max-width: 100%; - border-collapse: separate -} - -table.tableblock td > .paragraph:last-child p > p:last-child, table.tableblock th > p:last-child, table.tableblock td > p:last-child { - margin-bottom: 0 -} - -table.spread { - width: 100% -} - -table.tableblock, th.tableblock, td.tableblock { - border: 0 solid #dedede -} - -table.grid-all th.tableblock, table.grid-all td.tableblock { - border-width: 0 1px 1px 0 -} - -table.grid-all tfoot > tr > th.tableblock, table.grid-all tfoot > tr > td.tableblock { - border-width: 1px 1px 0 0 -} - -table.grid-cols th.tableblock, table.grid-cols td.tableblock { - border-width: 0 1px 0 0 -} - -table.grid-all * > tr > .tableblock:last-child, table.grid-cols * > tr > .tableblock:last-child { - border-right-width: 0 -} - -table.grid-rows th.tableblock, table.grid-rows td.tableblock { - border-width: 0 0 1px 0 -} - -table.grid-all tbody > tr:last-child > th.tableblock, table.grid-all tbody > tr:last-child > td.tableblock, table.grid-all thead:last-child > tr > th.tableblock, table.grid-rows tbody > tr:last-child > th.tableblock, table.grid-rows tbody > tr:last-child > td.tableblock, table.grid-rows thead:last-child > tr > th.tableblock { - border-bottom-width: 0 -} - -table.grid-rows tfoot > tr > th.tableblock, table.grid-rows tfoot > tr > td.tableblock { - border-width: 1px 0 0 0 -} - -table.frame-all { - border-width: 1px -} - -table.frame-sides { - border-width: 0 1px -} - -table.frame-topbot { - border-width: 1px 0 -} - -th.halign-left, td.halign-left { - text-align: left -} - -th.halign-right, td.halign-right { - text-align: right -} - -th.halign-center, td.halign-center { - text-align: center -} - -th.valign-top, td.valign-top { - vertical-align: top -} - -th.valign-bottom, td.valign-bottom { - vertical-align: bottom -} - -th.valign-middle, td.valign-middle { - vertical-align: middle -} - -table thead th, table tfoot th { - font-weight: bold -} - -tbody tr th { - display: table-cell; - line-height: 1.6; - background: #f7f8f7 -} - -tbody tr th, tbody tr th p, tfoot tr th, tfoot tr th p { - color: rgba(0, 0, 0, .8); - font-weight: bold -} - -p.tableblock > code:only-child { - background: none; - padding: 0 -} - -p.tableblock { - font-size: 1em -} - -td > div.verse { - white-space: pre -} - -ol { - margin-left: 1.75em -} - -ul li ol { - margin-left: 1.5em -} - -dl dd { - margin-left: 1.125em -} - -dl dd:last-child, dl dd:last-child > :last-child { - margin-bottom: 0 -} - -ol > li p, ul > li p, ul dd, ol dd, .olist .olist, .ulist .ulist, .ulist .olist, .olist .ulist { - margin-bottom: .625em -} - -ul.unstyled, ol.unnumbered, ul.checklist, ul.none { - list-style-type: none -} - -ul.unstyled, ol.unnumbered, ul.checklist { - margin-left: .625em -} - -ul.checklist li > p:first-child > .fa-check-square-o:first-child, ul.checklist li > p:first-child > input[type="checkbox"]:first-child { - margin-right: .25em -} - -ul.checklist li > p:first-child > input[type="checkbox"]:first-child { - position: relative; - top: 1px -} - -ul.inline { - margin: 0 auto .625em auto; - margin-left: -1.375em; - margin-right: 0; - padding: 0; - list-style: none; - overflow: hidden -} - -ul.inline > li { - list-style: none; - float: left; - margin-left: 1.375em; - display: block -} - -ul.inline > li > * { - display: block -} - -.unstyled dl dt { - font-weight: 400; - font-style: normal -} - -ol.arabic { - list-style-type: decimal -} - -ol.decimal { - list-style-type: decimal-leading-zero -} - -ol.loweralpha { - list-style-type: lower-alpha -} - -ol.upperalpha { - list-style-type: upper-alpha -} - -ol.lowerroman { - list-style-type: lower-roman -} - -ol.upperroman { - list-style-type: upper-roman -} - -ol.lowergreek { - list-style-type: lower-greek -} - -.hdlist > table, .colist > table { - border: 0; - background: none -} - -.hdlist > table > tbody > tr, .colist > table > tbody > tr { - background: none -} - -td.hdlist1 { - padding-right: .75em; - font-weight: bold -} - -td.hdlist1, td.hdlist2 { - vertical-align: top -} - -.literalblock + .colist, .listingblock + .colist { - margin-top: -.5em -} - -.colist > table tr > td:first-of-type { - padding: 0 .75em; - line-height: 1 -} - -.colist > table tr > td:last-of-type { - padding: .25em 0 -} - -.thumb, .th { - line-height: 0; - display: inline-block; - border: solid 4px #fff; - -webkit-box-shadow: 0 0 0 1px #ddd; - box-shadow: 0 0 0 1px #ddd -} - -.imageblock.left, .imageblock[style*="float: left"] { - margin: .25em .625em 1.25em 0 -} - -.imageblock.right, .imageblock[style*="float: right"] { - margin: .25em 0 1.25em .625em -} - -.imageblock > .title { - margin-bottom: 0 -} - -.imageblock.thumb, .imageblock.th { - border-width: 6px -} - -.imageblock.thumb > .title, .imageblock.th > .title { - padding: 0 .125em -} - -.image.left, .image.right { - margin-top: .25em; - margin-bottom: .25em; - display: inline-block; - line-height: 0 -} - -.image.left { - margin-right: .625em -} - -.image.right { - margin-left: .625em -} - -a.image { - text-decoration: none -} - -span.footnote, span.footnoteref { - vertical-align: super; - font-size: .875em -} - -span.footnote a, span.footnoteref a { - text-decoration: none -} - -span.footnote a:active, span.footnoteref a:active { - text-decoration: underline -} - -#footnotes { - padding-top: .75em; - padding-bottom: .75em; - margin-bottom: .625em -} - -#footnotes hr { - width: 20%; - min-width: 6.25em; - margin: -.25em 0 .75em 0; - border-width: 1px 0 0 0 -} - -#footnotes .footnote { - padding: 0 .375em; - line-height: 1.3; - font-size: .875em; - margin-left: 1.2em; - text-indent: -1.2em; - margin-bottom: .2em -} - -#footnotes .footnote a:first-of-type { - font-weight: bold; - text-decoration: none -} - -#footnotes .footnote:last-of-type { - margin-bottom: 0 -} - -#content #footnotes { - margin-top: -.625em; - margin-bottom: 0; - padding: .75em 0 -} - -.gist .file-data > table { - border: 0; - background: #fff; - width: 100%; - margin-bottom: 0 -} - -.gist .file-data > table td.line-data { - width: 99% -} - -div.unbreakable { - page-break-inside: avoid -} - -.big { - font-size: larger -} - -.small { - font-size: smaller -} - -.underline { - text-decoration: underline -} - -.overline { - text-decoration: overline -} - -.line-through { - text-decoration: line-through -} - -.aqua { - color: #00bfbf -} - -.aqua-background { - background-color: #00fafa -} - -.black { - color: #000 -} - -.black-background { - background-color: #000 -} - -.blue { - color: #0000bf -} - -.blue-background { - background-color: #0000fa -} - -.fuchsia { - color: #bf00bf -} - -.fuchsia-background { - background-color: #fa00fa -} - -.gray { - color: #606060 -} - -.gray-background { - background-color: #7d7d7d -} - -.green { - color: #006000 -} - -.green-background { - background-color: #007d00 -} - -.lime { - color: #00bf00 -} - -.lime-background { - background-color: #00fa00 -} - -.maroon { - color: #600000 -} - -.maroon-background { - background-color: #7d0000 -} - -.navy { - color: #000060 -} - -.navy-background { - background-color: #00007d -} - -.olive { - color: #606000 -} - -.olive-background { - background-color: #7d7d00 -} - -.purple { - color: #600060 -} - -.purple-background { - background-color: #7d007d -} - -.red { - color: #bf0000 -} - -.red-background { - background-color: #fa0000 -} - -.silver { - color: #909090 -} - -.silver-background { - background-color: #bcbcbc -} - -.teal { - color: #006060 -} - -.teal-background { - background-color: #007d7d -} - -.white { - color: #bfbfbf -} - -.white-background { - background-color: #fafafa -} - -.yellow { - color: #bfbf00 -} - -.yellow-background { - background-color: #fafa00 -} - -span.icon > .fa { - cursor: default -} - -.admonitionblock td.icon [class^="fa icon-"] { - font-size: 2.5em; - text-shadow: 1px 1px 2px rgba(0, 0, 0, .5); - cursor: default -} - -.admonitionblock td.icon .icon-note:before { - content: "\f05a"; - color: #19407c -} - -.admonitionblock td.icon .icon-tip:before { - content: "\f0eb"; - text-shadow: 1px 1px 2px rgba(155, 155, 0, .8); - color: #111 -} - -.admonitionblock td.icon .icon-warning:before { - content: "\f071"; - color: #bf6900 -} - -.admonitionblock td.icon .icon-caution:before { - content: "\f06d"; - color: #bf3400 -} - -.admonitionblock td.icon .icon-important:before { - content: "\f06a"; - color: #bf0000 -} - -.conum[data-value] { - display: inline-block; - color: #fff !important; - background-color: rgba(0, 0, 0, .8); - -webkit-border-radius: 100px; - border-radius: 100px; - text-align: center; - font-size: .75em; - width: 1.67em; - height: 1.67em; - line-height: 1.67em; - font-family: "Open Sans", "DejaVu Sans", sans-serif; - font-style: normal; - font-weight: bold -} - -.conum[data-value] * { - color: #fff !important -} - -.conum[data-value] + b { - display: none -} - -.conum[data-value]:after { - content: attr(data-value) -} - -pre .conum[data-value] { - position: relative; - top: -.125em -} - -b.conum * { - color: inherit !important -} - -.conum:not([data-value]):empty { - display: none -} - -h1, h2 { - letter-spacing: -.01em -} - -dt, th.tableblock, td.content { - text-rendering: optimizeLegibility -} - -p, td.content { - letter-spacing: -.01em -} - -p strong, td.content strong { - letter-spacing: -.005em -} - -p, blockquote, dt, td.content { - font-size: 1.0625rem -} - -p { - margin-bottom: 1.25rem -} - -.sidebarblock p, .sidebarblock dt, .sidebarblock td.content, p.tableblock { - font-size: 1em -} - -.exampleblock > .content { - background-color: #fffef7; - border-color: #e0e0dc; - -webkit-box-shadow: 0 1px 4px #e0e0dc; - box-shadow: 0 1px 4px #e0e0dc -} - -.print-only { - display: none !important -} - -@media print { - @page { - margin: 1.25cm .75cm - } - - * { - -webkit-box-shadow: none !important; - box-shadow: none !important; - text-shadow: none !important - } - - a { - color: inherit !important; - text-decoration: underline !important - } - - a.bare, a[href^="#"], a[href^="mailto:"] { - text-decoration: none !important - } - - a[href^="http:"]:not(.bare):after, a[href^="https:"]:not(.bare):after { - content: "(" attr(href) ")"; - display: inline-block; - font-size: .875em; - padding-left: .25em - } - - abbr[title]:after { - content: " (" attr(title) ")" - } - - pre, blockquote, tr, img { - page-break-inside: avoid - } - - thead { - display: table-header-group - } - - img { - max-width: 100% !important - } - - p, blockquote, dt, td.content { - font-size: 1em; - orphans: 3; - widows: 3 - } - - h2, h3, #toctitle, .sidebarblock > .content > .title { - page-break-after: avoid - } - - #toc, .sidebarblock, .exampleblock > .content { - background: none !important - } - - #toc { - border-bottom: 1px solid #ddddd8 !important; - padding-bottom: 0 !important - } - - .sect1 { - padding-bottom: 0 !important - } - - .sect1 + .sect1 { - border: 0 !important - } - - #header > h1:first-child { - margin-top: 1.25rem - } - - body.book #header { - text-align: center - } - - body.book #header > h1:first-child { - border: 0 !important; - margin: 2.5em 0 1em 0 - } - - body.book #header .details { - border: 0 !important; - display: block; - padding: 0 !important - } - - body.book #header .details span:first-child { - margin-left: 0 !important - } - - body.book #header .details br { - display: block - } - - body.book #header .details br + span:before { - content: none !important - } - - body.book #toc { - border: 0 !important; - text-align: left !important; - padding: 0 !important; - margin: 0 !important - } - - body.book #toc, body.book #preamble, body.book h1.sect0, body.book .sect1 > h2 { - page-break-before: always - } - - .listingblock code[data-lang]:before { - display: block - } - - #footer { - background: none !important; - padding: 0 .9375em - } - - #footer-text { - color: rgba(0, 0, 0, .6) !important; - font-size: .9em - } - - .hide-on-print { - display: none !important - } - - .print-only { - display: block !important - } - - .hide-for-print { - display: none !important - } - - .show-for-print { - display: inherit !important - } -} diff --git a/config/releaser.yml b/config/releaser.yml deleted file mode 100644 index 19daad1dce..0000000000 --- a/config/releaser.yml +++ /dev/null @@ -1,5 +0,0 @@ -releaser.maven.buildCommand: ./scripts/noIntegration.sh {{systemProps}} -releaser.maven.deployCommand: ./mvnw deploy -DskipTests -B -Pfast,deploy -Dgradle.publish-plugins.task=-Phello=world {{systemProps}} -releaser.gradle.gradlePropsSubstitution: - verifierVersion: spring-cloud-contract - bootVersion: spring-boot diff --git a/docker/pom.xml b/docker/pom.xml deleted file mode 100644 index 1ed2a272eb..0000000000 --- a/docker/pom.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - 4.0.0 - - - org.springframework.cloud - spring-cloud-contract-parent - 4.1.0-SNAPSHOT - .. - - - spring-cloud-contract-docker-parent - pom - 4.1.0-SNAPSHOT - Spring Cloud Contract Docker Parent - Spring Cloud Contract Docker Parent - - - springcloud - - - - - skip - - true - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - false - - - - maven-deploy-plugin - 2.8.2 - - true - - - - - - diff --git a/docker/spring-cloud-contract-docker/Dockerfile b/docker/spring-cloud-contract-docker/Dockerfile deleted file mode 100644 index cfd5083044..0000000000 --- a/docker/spring-cloud-contract-docker/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -FROM ubuntu:20.04 - -ARG SDKMAN_JAVA_INSTALLATION=17.0.1-tem - -LABEL Author="Marcin Grzejszczak " -LABEL Author="Bastian Doetsch " - -RUN apt-get update && apt-get install -y curl \ - unzip \ - zip \ - && apt-get clean - -RUN useradd -u1000 -m scc - -# Install sdkman and java -COPY sdkman/ /usr/local/bin/ -RUN chmod +x /usr/local/bin/sdkman-wrapper.sh - -# provide output & contract directories and change owner to scc -RUN mkdir -p /contracts -RUN mkdir -p /spring-cloud-contract-output -RUN mkdir -p /spring-cloud-contract -RUN chown -R scc:scc /contracts -RUN chown -R scc:scc /spring-cloud-contract-output /spring-cloud-contract -RUN chown -R scc:scc /spring-cloud-contract - -USER scc -RUN curl -s https://get.sdkman.io/ | bash -COPY --chown=scc:scc sdkman.config /home/scc/.sdkman/etc/config -RUN bash -c "source /home/scc/.sdkman/bin/sdkman-init.sh" -RUN bash -c "sdkman-wrapper.sh install java ${SDKMAN_JAVA_INSTALLATION}" -ENV JAVA_HOME /home/scc/.sdkman/candidates/java/current/ -ENV PATH "${PATH}:${JAVA_HOME}/bin" - -# Spring Cloud Contract -COPY --chown=scc:scc project /spring-cloud-contract/ -WORKDIR /spring-cloud-contract/ - -# Let's copy the downloaded deps to .m2 and the gradle cache -COPY --chown=scc:scc target/maven_dependencies /home/scc/.m2/repository/ -COPY --chown=scc:scc target/gradle_dependencies /home/scc/.gradle/ - -# Let's download gradle wrapper if for some reason it hasn't been downloaded -RUN ./gradlew clean resolveDependencies build --stacktrace -x copyOutput || echo "Expected to fail" -CMD ["./build.sh"] diff --git a/docker/spring-cloud-contract-docker/build_adocs.sh b/docker/spring-cloud-contract-docker/build_adocs.sh deleted file mode 100755 index 2b337b3d31..0000000000 --- a/docker/spring-cloud-contract-docker/build_adocs.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -set -e - -CURRENT_DIR="$( pwd )" -ADOC_OUTPUT_DIR="${CURRENT_DIR}/target/adoc/" -pushd project - mkdir -p "${ADOC_OUTPUT_DIR}" - ./gradlew dumpAllProps - cp "$( pwd )/build/props.adoc" "${ADOC_OUTPUT_DIR}/" - cp "$( pwd )/build/appProps.adoc" "${ADOC_OUTPUT_DIR}/" -popd diff --git a/docker/spring-cloud-contract-docker/get_dependencies.sh b/docker/spring-cloud-contract-docker/get_dependencies.sh deleted file mode 100755 index 30aacef4fb..0000000000 --- a/docker/spring-cloud-contract-docker/get_dependencies.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -set -e - -WRAPPER_VERSION="8.3" -GRADLE_BIN_DIR="gradle-${WRAPPER_VERSION}-bin" -GRADLE_WRAPPER_DIR="${HOME}/.gradle/wrapper/dists/${GRADLE_BIN_DIR}" -CURRENT_DIR="$( pwd )" -GRADLE_OUTPUT_DIR="${CURRENT_DIR}/target/gradle_dependencies/" -pushd project - rm -rf .gradle - ./gradlew wrapper --gradle-version "${WRAPPER_VERSION}" - ./gradlew clean resolveDependencies build -g "${GRADLE_OUTPUT_DIR}" -x copyOutput || echo "Expected to fail the build" - if [ -d "${GRADLE_WRAPPER_DIR}" ]; then - echo "Copying Gradle Wrapper version [${WRAPPER_VERSION}]" - mkdir -p "${GRADLE_OUTPUT_DIR}/wrapper/dists/" - cp -r "${GRADLE_WRAPPER_DIR}" "${GRADLE_OUTPUT_DIR}/wrapper/dists/" - else - echo "Gradle Wrapper [${GRADLE_WRAPPER_DIR}] not found. Will not copy it" - fi -popd - -./build_adocs.sh - -pushd project - rm -rf build -popd diff --git a/docker/spring-cloud-contract-docker/pom.xml b/docker/spring-cloud-contract-docker/pom.xml deleted file mode 100644 index 40837bb45e..0000000000 --- a/docker/spring-cloud-contract-docker/pom.xml +++ /dev/null @@ -1,231 +0,0 @@ - - - 4.0.0 - - 1.0.8.RELEASE - 4.2.5 - 17.0.1-tem - - - - org.springframework.cloud - spring-cloud-contract-docker-parent - 4.1.0-SNAPSHOT - .. - - - spring-cloud-contract-docker - pom - 4.1.0-SNAPSHOT - Spring Cloud Contract Docker - Spring Cloud Contract Docker - - - - org.springframework.cloud - spring-cloud-contract-dependencies - ${project.version} - pom - runtime - - - - org.apache.groovy - groovy - compile - - - org.apache.groovy - groovy-ant - compile - - - org.apache.groovy - groovy-groovydoc - compile - - - org.springframework.cloud - spring-cloud-starter-contract-verifier - compile - - - org.springframework.cloud - spring-cloud-contract-gradle-plugin - runtime - - - org.springframework.cloud - spring-cloud-contract-wiremock - compile - - - org.springframework.cloud - spring-cloud-contract-spec - compile - - - org.springframework.cloud - spring-cloud-contract-tools - ${project.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-contract-spec-java - compile - - - org.springframework.cloud - spring-cloud-contract-spec-groovy - compile - - - org.springframework.cloud - spring-cloud-contract-spec-kotlin - compile - - - org.springframework.cloud - spring-cloud-contract-verifier - compile - - - org.springframework.cloud - spring-cloud-contract-converters - compile - - - org.springframework.cloud - spring-cloud-contract-stub-runner - compile - - - org.springframework.cloud - spring-cloud-contract-stub-runner-boot - compile - - - org.springframework.cloud - spring-cloud-contract-shade - compile - - - org.springframework.cloud - spring-cloud-starter-contract-stub-runner - compile - - - org.springframework.cloud - spring-cloud-starter-contract-stub-runner-jetty - compile - - - org.springframework.cloud - spring-cloud-contract-maven-plugin - compile - - - io.spring.gradle - dependency-management-plugin - ${dependency-management-plugin.version} - runtime - - - org.springframework.cloud - spring-cloud-build - ${spring-cloud-build.version} - pom - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - false - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-dependencies - package - - copy-dependencies - - - - ${project.build.directory}/maven_dependencies - - false - true - true - true - true - false - - - - - - org.codehaus.mojo - exec-maven-plugin - ${exec-maven-plugin.version} - - - gradle - package - - ./get_dependencies.sh - - - exec - - - - - - com.spotify - dockerfile-maven-plugin - 1.4.13 - - - default - - build - push - - - - - ${docker.registry.organization}/spring-cloud-contract - - ${project.version} - ${env.DOCKER_HUB_USERNAME} - ${env.DOCKER_HUB_PASSWORD} - - true - - - ${sdkman-java-installation.version} - - - - - org.codehaus.plexus - plexus-archiver - ${plexus-archiver.version} - - - - - - diff --git a/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/checksums/checksums.lock b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/checksums/checksums.lock new file mode 100644 index 0000000000..c7e0c7aa34 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/checksums/checksums.lock differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/checksums/md5-checksums.bin b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/checksums/md5-checksums.bin new file mode 100644 index 0000000000..64c95f4312 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/checksums/md5-checksums.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/checksums/sha1-checksums.bin b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/checksums/sha1-checksums.bin new file mode 100644 index 0000000000..667d2f3147 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/checksums/sha1-checksums.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock new file mode 100644 index 0000000000..e9a6f98769 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock differ diff --git a/.springformat b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/dependencies-accessors/gc.properties similarity index 100% rename from .springformat rename to docker/spring-cloud-contract-docker/project/.gradle/7.5.1/dependencies-accessors/gc.properties diff --git a/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/fileChanges/last-build.bin b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/fileChanges/last-build.bin new file mode 100644 index 0000000000..f76dd238ad Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/fileChanges/last-build.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/fileHashes/fileHashes.bin b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/fileHashes/fileHashes.bin new file mode 100644 index 0000000000..650a480997 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/fileHashes/fileHashes.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/fileHashes/fileHashes.lock b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/fileHashes/fileHashes.lock new file mode 100644 index 0000000000..c6b253a557 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/fileHashes/fileHashes.lock differ diff --git a/docs/modules/ROOT/pages/index.adoc b/docker/spring-cloud-contract-docker/project/.gradle/7.5.1/gc.properties similarity index 100% rename from docs/modules/ROOT/pages/index.adoc rename to docker/spring-cloud-contract-docker/project/.gradle/7.5.1/gc.properties diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/checksums/checksums.lock b/docker/spring-cloud-contract-docker/project/.gradle/8.3/checksums/checksums.lock new file mode 100644 index 0000000000..d927ae1293 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/checksums/checksums.lock differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/checksums/md5-checksums.bin b/docker/spring-cloud-contract-docker/project/.gradle/8.3/checksums/md5-checksums.bin new file mode 100644 index 0000000000..f2db6959ce Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/checksums/md5-checksums.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/checksums/sha1-checksums.bin b/docker/spring-cloud-contract-docker/project/.gradle/8.3/checksums/sha1-checksums.bin new file mode 100644 index 0000000000..b9c3c09746 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/checksums/sha1-checksums.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/dependencies-accessors/dependencies-accessors.lock b/docker/spring-cloud-contract-docker/project/.gradle/8.3/dependencies-accessors/dependencies-accessors.lock new file mode 100644 index 0000000000..68d9117041 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/dependencies-accessors/dependencies-accessors.lock differ diff --git a/samples/standalone/restdocs/http-server/src/main/resources/application.yml b/docker/spring-cloud-contract-docker/project/.gradle/8.3/dependencies-accessors/gc.properties similarity index 100% rename from samples/standalone/restdocs/http-server/src/main/resources/application.yml rename to docker/spring-cloud-contract-docker/project/.gradle/8.3/dependencies-accessors/gc.properties diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/executionHistory/executionHistory.bin b/docker/spring-cloud-contract-docker/project/.gradle/8.3/executionHistory/executionHistory.bin new file mode 100644 index 0000000000..b60380691d Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/executionHistory/executionHistory.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/executionHistory/executionHistory.lock b/docker/spring-cloud-contract-docker/project/.gradle/8.3/executionHistory/executionHistory.lock new file mode 100644 index 0000000000..89596f254d Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/executionHistory/executionHistory.lock differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileChanges/last-build.bin b/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileChanges/last-build.bin new file mode 100644 index 0000000000..f76dd238ad Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileChanges/last-build.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileHashes/fileHashes.bin b/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileHashes/fileHashes.bin new file mode 100644 index 0000000000..e9c68bfd63 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileHashes/fileHashes.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileHashes/fileHashes.lock b/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileHashes/fileHashes.lock new file mode 100644 index 0000000000..72f6f750e7 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileHashes/fileHashes.lock differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileHashes/resourceHashesCache.bin b/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileHashes/resourceHashesCache.bin new file mode 100644 index 0000000000..0aafb45156 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/8.3/fileHashes/resourceHashesCache.bin differ diff --git a/spring-cloud-contract-stub-runner/src/test/resources/emptyrepo/.gitkeep b/docker/spring-cloud-contract-docker/project/.gradle/8.3/gc.properties similarity index 100% rename from spring-cloud-contract-stub-runner/src/test/resources/emptyrepo/.gitkeep rename to docker/spring-cloud-contract-docker/project/.gradle/8.3/gc.properties diff --git a/docker/spring-cloud-contract-docker/project/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/docker/spring-cloud-contract-docker/project/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000000..80f0593cd8 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/buildOutputCleanup/cache.properties b/docker/spring-cloud-contract-docker/project/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000000..6abff7f80f --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Wed Sep 06 14:28:25 CEST 2023 +gradle.version=8.3 diff --git a/docker/spring-cloud-contract-docker/project/.gradle/buildOutputCleanup/outputFiles.bin b/docker/spring-cloud-contract-docker/project/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000000..c083ce394a Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/docker/spring-cloud-contract-docker/project/.gradle/file-system.probe b/docker/spring-cloud-contract-docker/project/.gradle/file-system.probe new file mode 100644 index 0000000000..4d77bf81f0 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/.gradle/file-system.probe differ diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/fake/.gitkeep b/docker/spring-cloud-contract-docker/project/.gradle/vcs-1/gc.properties similarity index 100% rename from spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/main/fake/.gitkeep rename to docker/spring-cloud-contract-docker/project/.gradle/vcs-1/gc.properties diff --git a/docker/spring-cloud-contract-docker/project/.idea/.gitignore b/docker/spring-cloud-contract-docker/project/.idea/.gitignore new file mode 100644 index 0000000000..13566b81b0 --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/docker/spring-cloud-contract-docker/project/.idea/codeStyles/Project.xml b/docker/spring-cloud-contract-docker/project/.idea/codeStyles/Project.xml new file mode 100644 index 0000000000..17c6134ebd --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.idea/codeStyles/Project.xml @@ -0,0 +1,89 @@ + + + + + \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/project/.idea/codeStyles/codeStyleConfig.xml b/docker/spring-cloud-contract-docker/project/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000000..0adac017fe --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/project/.idea/compiler.xml b/docker/spring-cloud-contract-docker/project/.idea/compiler.xml new file mode 100644 index 0000000000..b589d56e9f --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/project/.idea/gradle.xml b/docker/spring-cloud-contract-docker/project/.idea/gradle.xml new file mode 100644 index 0000000000..c40aef8ac6 --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/project/.idea/jarRepositories.xml b/docker/spring-cloud-contract-docker/project/.idea/jarRepositories.xml new file mode 100644 index 0000000000..49bd6f6e98 --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.idea/jarRepositories.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/project/.idea/misc.xml b/docker/spring-cloud-contract-docker/project/.idea/misc.xml new file mode 100644 index 0000000000..f1854e4b53 --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.idea/misc.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/loanApplicationService/mappings/.gitkeep b/docker/spring-cloud-contract-docker/project/.idea/sonarlint/issuestore/5/9/59f81c123b3abbcb97274545796dd18706c3e106 similarity index 100% rename from spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/loanApplicationService/mappings/.gitkeep rename to docker/spring-cloud-contract-docker/project/.idea/sonarlint/issuestore/5/9/59f81c123b3abbcb97274545796dd18706c3e106 diff --git a/spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProjectKotlin/loanApplicationService/mappings/.gitkeep b/docker/spring-cloud-contract-docker/project/.idea/sonarlint/issuestore/f/0/f07866736216be0ee2aba49e392191aeae700a35 similarity index 100% rename from spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProjectKotlin/loanApplicationService/mappings/.gitkeep rename to docker/spring-cloud-contract-docker/project/.idea/sonarlint/issuestore/f/0/f07866736216be0ee2aba49e392191aeae700a35 diff --git a/docker/spring-cloud-contract-docker/project/.idea/sonarlint/issuestore/index.pb b/docker/spring-cloud-contract-docker/project/.idea/sonarlint/issuestore/index.pb new file mode 100644 index 0000000000..6b9b0e4f40 --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.idea/sonarlint/issuestore/index.pb @@ -0,0 +1,5 @@ + +8 +build.sh,5/9/59f81c123b3abbcb97274545796dd18706c3e106 +< + build.gradle,f/0/f07866736216be0ee2aba49e392191aeae700a35 \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/project/.idea/vcs.xml b/docker/spring-cloud-contract-docker/project/.idea/vcs.xml new file mode 100644 index 0000000000..c2365ab11f --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/project/README.adoc b/docker/spring-cloud-contract-docker/project/README.adoc deleted file mode 100644 index 1aed4cdfa0..0000000000 --- a/docker/spring-cloud-contract-docker/project/README.adoc +++ /dev/null @@ -1,24 +0,0 @@ -# Spring Cloud Contract Verifier Docker Project - -## Developer tips - -### Environment variables -In order to use a new environment variable inside the Gradle script, you need to add it to the `envVars` map together with a description and a default value. Otherwise, any attempt to resolve such an environment variable will lead to an exception being thrown. - -If you're referencing any environment variables from inside the Java code please follow the following convention. - -```java -/** - * Some description. - **/ -@Value("${ENV_VAR_NAME:defaultValue}") -String envVar; -``` - -If you provide Javadocs, we will automatically parse any `@Value` annotated fields and build a table of environment variables with description and default values. - -### Customizing the gradle build - -You can provide a customized `gradle.build` to be run in the container by mounting your customized build file as a volume when running the container: - -`docker run -v :/spring-cloud-contract/build.gradle springcloud/spring-cloud-contract:` diff --git a/docker/spring-cloud-contract-docker/project/build.gradle b/docker/spring-cloud-contract-docker/project/build.gradle deleted file mode 100644 index dc5c77042f..0000000000 --- a/docker/spring-cloud-contract-docker/project/build.gradle +++ /dev/null @@ -1,269 +0,0 @@ -import contracts.DocsFromSources - -buildscript { - repositories { - mavenLocal() - mavenCentral() - if ("${verifierVersion}".contains("SNAPSHOT")) { - maven { url "https://repo.spring.io/snapshot" } - } else if ("${verifierVersion}".contains("M") || "${verifierVersion}".contains("RC")) { - maven { url "https://repo.spring.io/milestone" } - } - } - - dependencies { - classpath "org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}" - classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifierVersion}" - } -} - -Map envVars = [ - PROJECT_GROUP: new EnvVar("Your project's group ID", "com.example"), - PROJECT_VERSION: new EnvVar("Your project's version", "0.0.1-SNAPSHOT"), - PROJECT_NAME: new EnvVar("Your project's artifact id", "example"), - STANDALONE_PROTOCOL: new EnvVar("For standalone version, which additional protocol should be added", ""), - PRODUCER_STUBS_CLASSIFIER: new EnvVar("Archive classifier used for generated producer stubs", "stubs"), - FAIL_ON_NO_CONTRACTS: new EnvVar("Should the build fail if there are no contracts present?", false), - REPO_WITH_BINARIES_URL: new EnvVar("URL of your Artifact Manager (defaults to the default URL of https://jfrog.com/artifactory/[Artifactory] when running locally)", "http://localhost:8081/artifactory/libs-release-local"), - REPO_WITH_BINARIES_USERNAME: new EnvVar("(optional) Username when the Artifact Manager is secured", "admin"), - REPO_WITH_BINARIES_PASSWORD: new EnvVar("(optional) Password when the Artifact Manager is secured", "password"), - REPO_ALLOW_INSECURE_PROTOCOL: new EnvVar("(optional) If allows to publish artifacts to Artifact Manager over insecure HTTP", "false"), - PUBLISH_ARTIFACTS: new EnvVar("If set to `true`, publishes the artifact to binary storage", "true"), - PUBLISH_ARTIFACTS_OFFLINE: new EnvVar("If set to `true`, publishes the artifacts to local m2", "false"), - EXTERNAL_CONTRACTS_GROUP_ID: new EnvVar("Group ID of the project with contracts", "com.example"), - EXTERNAL_CONTRACTS_ARTIFACT_ID: new EnvVar("Artifact ID of the project with contracts", ""), - EXTERNAL_CONTRACTS_CLASSIFIER: new EnvVar("Classifier of the project with contracts", ""), - EXTERNAL_CONTRACTS_VERSION: new EnvVar("Version of the project with contracts. Defautls to an equivalent of picking the latest", "+"), - EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL: new EnvVar("URL of your Artifact Manager. It defaults to the value of `REPO_WITH_BINARIES_URL` environment variable and if that is not set, it defaults to `http://localhost:8081/artifactory/libs-release-local`", ""), - EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_USERNAME: new EnvVar("(optional) Username if the `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL` requires authentication. It defaults to `REPO_WITH_BINARIES_USERNAME`. If that is not set, it defaults to `admin", ""), - EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_PASSWORD: new EnvVar("(optional) Password if the `EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL` requires authentication. It defaults to `REPO_WITH_BINARIES_PASSWORD, If that is not set, it defaults to `password", ""), - EXTERNAL_CONTRACTS_PATH: new EnvVar("Path to contracts for the given project, inside the project with contracts. Defaults to slash-separated `EXTERNAL_CONTRACTS_GROUP_ID` concatenated with `/` and `EXTERNAL_CONTRACTS_ARTIFACT_ID. For example,\n" + - "for group id `cat-server-side.dog` and artifact ID `fish`, would result in `cat/dog/fish` for the contracts path.", ""), - EXTERNAL_CONTRACTS_WORK_OFFLINE: new EnvVar("If set to `true`, retrieves the artifact with contracts from the container's `.m2`. Mount your local `.m2` as a volume available at the container's `/root/.m2` path", "false"), - PUBLISH_STUBS_TO_SCM: new EnvVar("If set to `true` will run the task to publish stubs to scm", false), - MESSAGING_TYPE: new EnvVar("Type of messaging. Can be either [rabbit] or [kafka].", ""), - DEBUG: new EnvVar("(Docker Image only) Applicable for Docker Image - turns on debug mode for the Gradle build", "false"), - ADDITIONAL_FLAGS: new EnvVar("(Docker Image only) Additional flags to be passed to the Gradle build", ""), -] - -group = getProp(envVars, "PROJECT_GROUP") ?: 'com.example' -version = getProp(envVars, "PROJECT_VERSION") ?: '0.0.1-SNAPSHOT' - -repositories { - mavenLocal() - mavenCentral() - if ("${verifierVersion}".contains("SNAPSHOT")) { - maven { url "https://repo.spring.io/snapshot" } - } else if ("${verifierVersion}".contains("M") || "${verifierVersion}".contains("RC")) { - maven { url "https://repo.spring.io/milestone" } - } -} - -apply plugin: 'groovy' -apply plugin: "io.spring.dependency-management" -apply plugin: "org.springframework.boot" -apply plugin: 'spring-cloud-contract' -apply plugin: 'maven-publish' - -bootJar.enabled = false - -class EnvVar { - final Object defaultValue - final String description - - EnvVar(String description, Object defaultValue) { - this.defaultValue = defaultValue - this.description = description - } - - boolean equals(o) { - if (this.is(o)) { - return true - } - if (getClass() != o.class) { - return false - } - EnvVar envVar = (EnvVar) o - if (defaultValue != envVar.defaultValue) { - return false - } - if (description != envVar.description) { - return false - } - return true - } - - int hashCode() { - int result - result = (defaultValue != null ? defaultValue.hashCode() : 0) - result = 31 * result + (description != null ? description.hashCode() : 0) - return result - } -} - -dependencies { - testImplementation(platform("org.springframework.cloud:spring-cloud-contract-dependencies:${verifierVersion}")) - testImplementation(platform("org.apache.camel.springboot:camel-spring-boot-dependencies:${camelVersion}")) - - testImplementation("org.springframework.boot:spring-boot-starter-web") - testImplementation("org.springframework.cloud:spring-cloud-starter-contract-verifier") - testImplementation("org.springframework.amqp:spring-rabbit") - testImplementation("org.apache.camel.springboot:camel-spring-boot-starter") - testImplementation("org.apache.camel.springboot:camel-kafka-starter") - testImplementation("org.apache.camel.springboot:camel-rabbitmq-starter") - if (getProp(envVars, "STANDALONE_PROTOCOL")) { - testImplementation("org.apache.camel.springboot:camel-${getProp(envVars, "STANDALONE_PROTOCOL")}-starter") - } -} - -contractTest { - useJUnitPlatform() - if (getProp(envVars, "MESSAGING_TYPE") != "") { - systemProperty("spring.profiles.active", "messagingtype") - } else if (getProp(envVars, "STANDALONE_PROTOCOL") != "") { - systemProperty("spring.profiles.active", "standalone") - } - testLogging { - exceptionFormat = 'full' - afterSuite { desc, result -> - if (!desc.parent) { - println "Results: (${result.testCount} tests, ${result.successfulTestCount} successes, ${result.failedTestCount} failures, ${result.skippedTestCount} skipped)" - if (result.testCount == 0) { - throw new IllegalStateException("No tests were found. Failing the build") - } - } - } - } -} - -contracts { - baseClassForTests = "contracts.ContractTestsBase" - testMode = "EXPLICIT" - stubsSuffix = getProp(envVars, "PRODUCER_STUBS_CLASSIFIER") ?: "stubs" - failOnNoContracts = Boolean.parseBoolean(getProp(envVars, "FAIL_ON_NO_CONTRACTS") ?: "false") - if (getProp(envVars, "EXTERNAL_CONTRACTS_ARTIFACT_ID")) { - logger. - lifecycle("Will use an artifact with contracts [${getProp(envVars, "EXTERNAL_CONTRACTS_GROUP_ID")}:${getProp(envVars, "EXTERNAL_CONTRACTS_ARTIFACT_ID")}]") - // tests - contracts from an artifact - contractsPath = getProp(envVars, "EXTERNAL_CONTRACTS_PATH") ?: "" - if (!Boolean.parseBoolean(getProp(envVars, "EXTERNAL_CONTRACTS_WORK_OFFLINE").toString())) { - contractRepository { - repositoryUrl = getProp(envVars, 'EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_URL') ?: - getProp(envVars, 'REPO_WITH_BINARIES_URL') ?: 'http://localhost:8081/artifactory/libs-release-local' - username = getProp(envVars, 'EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_USERNAME') ?: - getProp(envVars, 'REPO_WITH_BINARIES_USERNAME') ?: 'admin' - password = getProp(envVars, 'EXTERNAL_CONTRACTS_REPO_WITH_BINARIES_PASSWORD') ?: - getProp(envVars, 'REPO_WITH_BINARIES_PASSWORD') ?: 'password' - } - } - contractDependency { - groupId = getProp(envVars, "EXTERNAL_CONTRACTS_GROUP_ID") ?: "com.example" - artifactId = getProp(envVars, "EXTERNAL_CONTRACTS_ARTIFACT_ID") - delegate.classifier = getProp(envVars, "EXTERNAL_CONTRACTS_CLASSIFIER") ?: "" - delegate.version = getProp(envVars, "EXTERNAL_CONTRACTS_VERSION") ?: "+" - } - contractsMode = Boolean. - parseBoolean(getProp(envVars, "EXTERNAL_CONTRACTS_WORK_OFFLINE")) ? "LOCAL" : "REMOTE" - } - else { - logger.lifecycle("Will use contracts from the mounted [/contracts] folder") - // tests - contracts in this repo - contractsDslDir = new File("/contracts") - } -} - -task cleanOutput(type: Delete) { - def dirName = "/spring-cloud-contract-output" - file(dirName).list().each { - f -> delete "${dirName}/${f}" - } -} - -task copyOutput(type: Copy) { - dependsOn("cleanOutput") - from 'build' - into '/spring-cloud-contract-output' -} - -test { - finalizedBy("copyOutput") -} - -publishing { - publications { - maven(MavenPublication) { - artifact verifierStubsJar - } - } - repositories { - maven { - allowInsecureProtocol Boolean.parseBoolean(getProp(envVars, 'REPO_ALLOW_INSECURE_PROTOCOL') ?: "false") - url getProp(envVars, 'REPO_WITH_BINARIES_URL') ?: 'http://localhost:8081/artifactory/libs-release-local' - credentials { - username getProp(envVars, 'REPO_WITH_BINARIES_USERNAME') ?: 'admin' - password getProp(envVars, 'REPO_WITH_BINARIES_PASSWORD') ?: 'password' - } - } - } -} - -// explicitly disable artifacts publication -boolean publishEnabled = Boolean.parseBoolean(getProp(envVars, "PUBLISH_ARTIFACTS") ?: "true") -boolean publishOffline = Boolean.parseBoolean(getProp(envVars, "PUBLISH_ARTIFACTS_OFFLINE") ?: "false") -publish.setEnabled(publishEnabled) -publishToMavenLocal.setEnabled(publishOffline) - -gradle.taskGraph.whenReady { graph -> - graph.allTasks. - findAll { it.name.startsWith("publish") && "publishStubsToScm" != it.name }*. - setEnabled(publishEnabled) - graph.allTasks. - findAll { it.name.startsWith("publish") && it.name.endsWith("ToMavenLocal") }*.setEnabled(publishOffline) -} - -if (Boolean.parseBoolean(getProp(envVars, "PUBLISH_STUBS_TO_SCM") ?: "false")) { - publish.dependsOn("publishStubsToScm") -} - -String getProp(Map envVars, String propName) { - if (!envVars.containsKey(propName)) { - throw new IllegalStateException("You've referenced a property with name [${propName}] but it's not in the list of accepatble props ${envVars.keySet()}") - } - return hasProperty(propName) ? - (getProperty(propName) ?: System.properties[propName]) : System.properties[propName] ?: - System.getenv(propName) ?: envVars.get(propName)?.defaultValue -} - -task resolveDependencies { - description "Pre-downloads *most* dependencies" - doLast { - configurations.getAsMap().each { name, config -> - println "Retrieving dependencies for $name" - try { - config.files - } - catch (e) { - project.logger.info e.message // some cannot be resolved, silently skip them - } - } - } -} - -task dumpAllProps() { - doLast { - // TODO: Parse the java code for env vars - File output = new File("build", "props.adoc") - if (!output.exists()) { - output.parentFile.mkdirs() - output.createNewFile() - } - String table = """\ -.Docker environment variables -|=== -|Name | Description | Default -""" - output.text = table + envVars.sort().collect { '|' + it.key + '|' + it.value.description + '|' + it.value.defaultValue }.join("\n") + "\n|===" - - new DocsFromSources(project).buildApplicationEnvVars() - } -} diff --git a/docker/spring-cloud-contract-docker/project/build.sh b/docker/spring-cloud-contract-docker/project/build.sh deleted file mode 100755 index 007e993eef..0000000000 --- a/docker/spring-cloud-contract-docker/project/build.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -set -o errexit -set -o errtrace -set -o nounset -set -o pipefail - -export PROJECT_NAME="${PROJECT_NAME:-example}" -export DEBUG="${DEBUG:-false}" -echo "Setting project name to [${PROJECT_NAME}]" -echo "rootProject.name='${PROJECT_NAME}'" >> settings.gradle -echo "Running the build" -export ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS:-}" -if [[ "${DEBUG}" == "true" ]]; then - ADDITIONAL_FLAGS="${ADDITIONAL_FLAGS} --debug" -fi -./gradlew clean build publishToMavenLocal publish --stacktrace ${ADDITIONAL_FLAGS} diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.2/executionHistory/executionHistory.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.2/executionHistory/executionHistory.bin new file mode 100644 index 0000000000..abf26f7f77 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.2/executionHistory/executionHistory.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.2/executionHistory/executionHistory.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.2/executionHistory/executionHistory.lock new file mode 100644 index 0000000000..e3599eade0 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.2/executionHistory/executionHistory.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3.3/executionHistory/executionHistory.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3.3/executionHistory/executionHistory.bin new file mode 100644 index 0000000000..920090b0e8 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3.3/executionHistory/executionHistory.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3.3/executionHistory/executionHistory.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3.3/executionHistory/executionHistory.lock new file mode 100644 index 0000000000..f35862e40c Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3.3/executionHistory/executionHistory.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3/executionHistory/executionHistory.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3/executionHistory/executionHistory.bin new file mode 100644 index 0000000000..75330ced47 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3/executionHistory/executionHistory.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3/executionHistory/executionHistory.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3/executionHistory/executionHistory.lock new file mode 100644 index 0000000000..7694a3d559 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.3/executionHistory/executionHistory.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/checksums/checksums.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/checksums/checksums.lock new file mode 100644 index 0000000000..db064db1ad Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/checksums/checksums.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/checksums/md5-checksums.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/checksums/md5-checksums.bin new file mode 100644 index 0000000000..97b49fd113 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/checksums/md5-checksums.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/checksums/sha1-checksums.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/checksums/sha1-checksums.bin new file mode 100644 index 0000000000..df68b662c6 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/checksums/sha1-checksums.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/dependencies-accessors/dependencies-accessors.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/dependencies-accessors/dependencies-accessors.lock new file mode 100644 index 0000000000..693d24ef12 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/dependencies-accessors/dependencies-accessors.lock differ diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/target/IgnoreMe.groovy b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/dependencies-accessors/gc.properties similarity index 100% rename from spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/test/projects/common-repo/target/IgnoreMe.groovy rename to docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/dependencies-accessors/gc.properties diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/executionHistory/executionHistory.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/executionHistory/executionHistory.bin new file mode 100644 index 0000000000..8efb9a112f Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/executionHistory/executionHistory.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/executionHistory/executionHistory.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/executionHistory/executionHistory.lock new file mode 100644 index 0000000000..2b07eefcde Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/executionHistory/executionHistory.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/fileChanges/last-build.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/fileChanges/last-build.bin new file mode 100644 index 0000000000..f76dd238ad Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/fileChanges/last-build.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/fileHashes/fileHashes.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/fileHashes/fileHashes.lock new file mode 100644 index 0000000000..28862c1620 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/fileHashes/fileHashes.lock differ diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/stubsRepositoryIndicator b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/gc.properties similarity index 100% rename from spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/stubsRepositoryIndicator rename to docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.4.1/gc.properties diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/checksums/checksums.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/checksums/checksums.lock new file mode 100644 index 0000000000..d8ecbb281c Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/checksums/checksums.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/checksums/md5-checksums.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/checksums/md5-checksums.bin new file mode 100644 index 0000000000..97b49fd113 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/checksums/md5-checksums.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/checksums/sha1-checksums.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/checksums/sha1-checksums.bin new file mode 100644 index 0000000000..df68b662c6 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/checksums/sha1-checksums.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock new file mode 100644 index 0000000000..92776a10fd Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/dependencies-accessors/dependencies-accessors.lock differ diff --git a/tests/spring-cloud-contract-stub-runner-integration/.jdk8 b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/dependencies-accessors/gc.properties similarity index 100% rename from tests/spring-cloud-contract-stub-runner-integration/.jdk8 rename to docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/dependencies-accessors/gc.properties diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/executionHistory/executionHistory.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/executionHistory/executionHistory.bin new file mode 100644 index 0000000000..efe3302cb4 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/executionHistory/executionHistory.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/executionHistory/executionHistory.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/executionHistory/executionHistory.lock new file mode 100644 index 0000000000..6973512de3 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/executionHistory/executionHistory.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/fileChanges/last-build.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/fileChanges/last-build.bin new file mode 100644 index 0000000000..f76dd238ad Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/fileChanges/last-build.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/fileHashes/fileHashes.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/fileHashes/fileHashes.lock new file mode 100644 index 0000000000..a396846131 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/fileHashes/fileHashes.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/gc.properties b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/7.5.1/gc.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/8.3/executionHistory/executionHistory.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/8.3/executionHistory/executionHistory.bin new file mode 100644 index 0000000000..6c3478d3e8 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/8.3/executionHistory/executionHistory.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/8.3/executionHistory/executionHistory.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/8.3/executionHistory/executionHistory.lock new file mode 100644 index 0000000000..81d2aaba3f Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/8.3/executionHistory/executionHistory.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/buildOutputCleanup/buildOutputCleanup.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/buildOutputCleanup/buildOutputCleanup.lock new file mode 100644 index 0000000000..cf4e509084 Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/buildOutputCleanup/buildOutputCleanup.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/buildOutputCleanup/cache.properties b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/buildOutputCleanup/cache.properties new file mode 100644 index 0000000000..6a2b4d3e85 --- /dev/null +++ b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/buildOutputCleanup/cache.properties @@ -0,0 +1,2 @@ +#Wed Sep 06 14:28:19 CEST 2023 +gradle.version=8.3 diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/buildOutputCleanup/outputFiles.bin b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/buildOutputCleanup/outputFiles.bin new file mode 100644 index 0000000000..7ae9e89b2c Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/buildOutputCleanup/outputFiles.bin differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/file-system.probe b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/file-system.probe new file mode 100644 index 0000000000..0c5cb079aa Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/file-system.probe differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/noVersion/buildSrc.lock b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/noVersion/buildSrc.lock new file mode 100644 index 0000000000..35a038769b Binary files /dev/null and b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/noVersion/buildSrc.lock differ diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/vcs-1/gc.properties b/docker/spring-cloud-contract-docker/project/buildSrc/.gradle/vcs-1/gc.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/build.gradle b/docker/spring-cloud-contract-docker/project/buildSrc/build.gradle deleted file mode 100644 index 6b3fe7015f..0000000000 --- a/docker/spring-cloud-contract-docker/project/buildSrc/build.gradle +++ /dev/null @@ -1,21 +0,0 @@ -repositories { - mavenLocal() - mavenCentral() - maven { url "https://repo.spring.io/snapshot" } - maven { url "https://repo.spring.io/milestone" } -// maven { url "https://repo.spring.io/release" } -} - -ext { - roasterVersion = "2.22.3.Final" - junit5Version = "5.6.2" -} - -dependencies { - implementation "org.jboss.forge.roaster:roaster-api:${roasterVersion}" - implementation "org.jboss.forge.roaster:roaster-jdt:${roasterVersion}" -} - -test { - useJUnitPlatform() -} diff --git a/docker/spring-cloud-contract-docker/project/buildSrc/src/main/java/contracts/DocsFromSources.java b/docker/spring-cloud-contract-docker/project/buildSrc/src/main/java/contracts/DocsFromSources.java deleted file mode 100644 index 1d1e2aa168..0000000000 --- a/docker/spring-cloud-contract-docker/project/buildSrc/src/main/java/contracts/DocsFromSources.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2013-2020 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 - * - * https://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 contracts; - -import java.io.File; -import java.io.IOException; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; - -import org.gradle.api.Project; -import org.jboss.forge.roaster.Roaster; -import org.jboss.forge.roaster.model.JavaUnit; -import org.jboss.forge.roaster.model.source.AnnotationSource; -import org.jboss.forge.roaster.model.source.FieldSource; -import org.jboss.forge.roaster.model.source.JavaClassSource; -import org.jboss.forge.roaster.model.source.JavaDocSource; - -public class DocsFromSources { - - private static final String ADOC_HEADER = - ".Docker environment variables - read at runtime\n" - + "|===\n" - + "|Name | Description | Default\n"; - - private final Project project; - - public DocsFromSources(Project project) { - this.project = project; - } - - public void buildApplicationEnvVars() { - Path path = new File(rootDir(), sourcePath()).toPath(); - List envVars = new ArrayList<>(); - FileVisitor fv = new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - if (!file.toString().endsWith(".java")) { - info("Skipping [" + file.toString() + "]"); - return FileVisitResult.CONTINUE; - } - JavaUnit unit = Roaster.parseUnit(Files.newInputStream(file)); - JavaClassSource myClass = unit.getGoverningType(); - info("Checking [" + myClass.getName() + "]"); - List> fields = myClass.getFields(); - for (FieldSource field : fields) { - List> annotations = field.getAnnotations(); - for (AnnotationSource annotation : annotations) { - if ("org.springframework.beans.factory.annotation.Value".equals(annotation.getQualifiedName())) { - info("Field [" + field.getName() + "] has @Value annotation"); - JavaDocSource> javaDoc = field.getJavaDoc(); - String description = javaDoc.getFullText(); - // ${foo:asd} - String annotationValue = annotation.getStringValue(); - // foo:asd - annotationValue = annotationValue.substring(2, annotationValue.length() - 1); - String[] parsed = annotationValue.split(":"); - String defaultValue = ""; - String name = parsed[0]; - if (parsed.length == 2) { - defaultValue = parsed[1]; - } - envVars.add(new EnvVar(name, description, defaultValue)); - } - } - } - info("Found [" + envVars.size() + "] env var field entries"); - return FileVisitResult.CONTINUE; - } - }; - - try { - Files.walkFileTree(path, fv); - Path output = new File(rootDir(), "build/appProps.adoc").toPath(); - StringBuilder stringBuilder = new StringBuilder().append(ADOC_HEADER); - Collections.sort(envVars); - envVars.forEach(envVar -> stringBuilder.append(envVar.toString()).append("\n")); - stringBuilder.append("|==="); - Files.write(output, stringBuilder.toString().getBytes()); - } - catch (IOException e) { - throw new IllegalStateException(e); - } - } - - String sourcePath() { - return "src/test/java/contracts"; - } - - File rootDir() { - return project.getRootDir(); - } - - void info(String log) { - this.project.getLogger().info(log); - } -} - -class EnvVar implements Comparable { - final String name; - final String description; - final String defaultValue; - - EnvVar(String name, String description, String defaultValue) { - this.name = name; - this.description = description; - this.defaultValue = defaultValue; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - EnvVar envVar = (EnvVar) o; - return Objects.equals(name, envVar.name) && - Objects.equals(description, envVar.description) && - Objects.equals(defaultValue, envVar.defaultValue); - } - - @Override - public int hashCode() { - return Objects.hash(name, description, defaultValue); - } - - @Override - public int compareTo(EnvVar o) { - return name.compareTo(o.name); - } - - @Override - public String toString() { - return "|" + name + "|" + description + "|" + defaultValue; - } -} \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/project/gradle.properties b/docker/spring-cloud-contract-docker/project/gradle.properties deleted file mode 100644 index fedc2636e7..0000000000 --- a/docker/spring-cloud-contract-docker/project/gradle.properties +++ /dev/null @@ -1,4 +0,0 @@ -org.gradle.daemon=false -verifierVersion=4.1.0-SNAPSHOT -springBootVersion=3.2.0-SNAPSHOT -camelVersion=3.11.0 diff --git a/docker/spring-cloud-contract-docker/project/gradle/wrapper/gradle-wrapper.jar b/docker/spring-cloud-contract-docker/project/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index 7f93135c49..0000000000 Binary files a/docker/spring-cloud-contract-docker/project/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/docker/spring-cloud-contract-docker/project/gradle/wrapper/gradle-wrapper.properties b/docker/spring-cloud-contract-docker/project/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index ac72c34e8a..0000000000 --- a/docker/spring-cloud-contract-docker/project/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/docker/spring-cloud-contract-docker/project/gradlew b/docker/spring-cloud-contract-docker/project/gradlew deleted file mode 100755 index 0adc8e1a53..0000000000 --- a/docker/spring-cloud-contract-docker/project/gradlew +++ /dev/null @@ -1,249 +0,0 @@ -#!/bin/sh - -# -# Copyright Š 2015-2021 the original 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 -# -# https://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. -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions ÂĢ$varÂģ, ÂĢ${var}Âģ, ÂĢ${var:-default}Âģ, ÂĢ${var+SET}Âģ, -# ÂĢ${var#prefix}Âģ, ÂĢ${var%suffix}Âģ, and ÂĢ$( cmd )Âģ; -# * compound commands having a testable exit status, especially ÂĢcaseÂģ; -# * various built-in commands including ÂĢcommandÂģ, ÂĢsetÂģ, and ÂĢulimitÂģ. -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/docker/spring-cloud-contract-docker/project/gradlew.bat b/docker/spring-cloud-contract-docker/project/gradlew.bat deleted file mode 100644 index 6689b85bee..0000000000 --- a/docker/spring-cloud-contract-docker/project/gradlew.bat +++ /dev/null @@ -1,92 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/docker/spring-cloud-contract-docker/project/src/test/java/contracts/ContractTestsBase.java b/docker/spring-cloud-contract-docker/project/src/test/java/contracts/ContractTestsBase.java deleted file mode 100644 index 7606736283..0000000000 --- a/docker/spring-cloud-contract-docker/project/src/test/java/contracts/ContractTestsBase.java +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Copyright 2013-2020 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 - * - * https://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 contracts; - -import java.time.Duration; -import java.util.concurrent.TimeUnit; - -import io.restassured.RestAssured; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.TestInfo; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.web.client.RestTemplateBuilder; -import org.springframework.cloud.contract.verifier.converter.YamlContract; -import org.springframework.cloud.contract.verifier.messaging.MessageVerifierReceiver; -import org.springframework.cloud.contract.verifier.messaging.amqp.AmqpMetadata; -import org.springframework.cloud.contract.verifier.messaging.boot.AutoConfigureMessageVerifier; -import org.springframework.cloud.contract.verifier.messaging.camel.StandaloneMetadata; -import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessageMetadata; -import org.springframework.cloud.contract.verifier.util.ContractVerifierUtil; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; -import org.springframework.util.StringUtils; -import org.springframework.web.client.RestTemplate; - -/** - * @author Marcin Grzejszczak - */ -@SpringBootTest(classes = ContractTestsBase.Config.class, webEnvironment = SpringBootTest.WebEnvironment.NONE) -@AutoConfigureMessageVerifier -public abstract class ContractTestsBase { - - private static final Logger log = LoggerFactory.getLogger(ContractTestsBase.class); - - /** - * URL at which the application is running. - */ - @Value("${APPLICATION_BASE_URL}") - String url; - - /** - * Optional username to access the application. - */ - @Value("${APPLICATION_USERNAME:}") - String username; - - /** - * Optional password to access the application. - */ - @Value("${APPLICATION_PASSWORD:}") - String password; - - /** - * Timeout to connect to the application to trigger a message. - */ - @Value("${MESSAGING_TRIGGER_CONNECT_TIMEOUT:5000}") - Integer connectTimeout; - - /** - * Timeout to read the response from the application to trigger a message. - */ - @Value("${MESSAGING_TRIGGER_READ_TIMEOUT:5000}") - Integer readTimeout; - - /** - * Defines the messaging type when dealing with message based contracts. - */ - @Value("${MESSAGING_TYPE:}") - String messagingType; - - @Autowired - MessageVerifierReceiver messageVerifier; - - @BeforeEach - public void setup(TestInfo testInfo) { - RestAssured.baseURI = this.url; - if (StringUtils.hasText(this.username)) { - RestAssured.authentication = RestAssured.basic(this.username, this.password); - } - setupMessagingFromContract(testInfo); - } - - private void setupMessagingFromContract(TestInfo testInfo) { - try { - YamlContract contract = ContractVerifierUtil.contract(this, testInfo.getDisplayName()); - setupMessagingIfPresent(contract); - } catch (Exception e) { - log.warn("An exception occurred while trying to setup messaging from contract", e); - } - } - - private void setupMessagingIfPresent(YamlContract contract) { - if (contract.input == null && contract.outputMessage == null) { - return; - } - setupAmqpIfPresent(contract); - setupStandaloneIfPresent(contract); - } - - private void setupAmqpIfPresent(YamlContract contract) { - AmqpMetadata amqpMetadata = AmqpMetadata.fromMetadata(contract.metadata); - if (isMessagingType("rabbit") && hasDeclaredOutputQueue(amqpMetadata) || isMessagingType("kafka")) { - log.info("First will try to receive a message to setup the connection with the broker"); - if (contract.outputMessage != null && StringUtils.hasText(contract.outputMessage.sentTo)){ - setupConnection(contract.outputMessage.sentTo, contract); - } - } - } - - private void setupStandaloneIfPresent(YamlContract contract) { - StandaloneMetadata metadata = StandaloneMetadata.fromMetadata(contract.metadata); - if (StringUtils.hasText(metadata.getSetup().getOptions())) { - log.info("First will try to receive a message to setup the connection with the broker"); - setMessageType(contract, ContractVerifierMessageMetadata.MessageType.SETUP); - setupConnection(metadata.getSetup().getOptions(), contract); - } - } - - private void setMessageType(YamlContract contract, - ContractVerifierMessageMetadata.MessageType output) { - contract.metadata.put(ContractVerifierMessageMetadata.METADATA_KEY, - new ContractVerifierMessageMetadata(output)); - } - - private void setupConnection(String destination, YamlContract contract) { - if (!StringUtils.hasText(destination)) { - return; - } - log.info("Setting up destination [{}]", destination); - this.messageVerifier.receive(destination, 100, TimeUnit.MILLISECONDS, contract); - } - - private boolean hasDeclaredOutputQueue(AmqpMetadata amqpMetadata) { - return StringUtils.hasText(amqpMetadata.getOutputMessage().getConnectToBroker().getDeclareQueueWithName()); - } - - private boolean isMessagingType(String rabbit) { - return rabbit.equalsIgnoreCase(this.messagingType); - } - - public void triggerMessage(String label) { - String url = this.url + "/springcloudcontract/" + label; - log.info("Will send a request to [{}] in order to trigger a message", url); - restTemplate().postForObject(url, "", String.class); - } - - private RestTemplate restTemplate() { - RestTemplateBuilder builder = new RestTemplateBuilder() - .setConnectTimeout(Duration.ofMillis(this.connectTimeout)) - .setReadTimeout(Duration.ofMillis(this.readTimeout)); - if (StringUtils.hasText(this.username)) { - builder = builder.basicAuthentication(this.username, this.password); - } - return builder.build(); - } - - @Configuration - @Import(MessagingAutoConfig.class) - @EnableAutoConfiguration - protected static class Config { - - } - -} diff --git a/docker/spring-cloud-contract-docker/project/src/test/java/contracts/MessagingAutoConfig.java b/docker/spring-cloud-contract-docker/project/src/test/java/contracts/MessagingAutoConfig.java deleted file mode 100644 index 2491dffb61..0000000000 --- a/docker/spring-cloud-contract-docker/project/src/test/java/contracts/MessagingAutoConfig.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2013-2020 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 - * - * https://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 contracts; - -import java.util.Map; -import java.util.concurrent.TimeUnit; - -import org.apache.camel.ConsumerTemplate; -import org.apache.camel.Exchange; -import org.apache.camel.Message; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import org.springframework.amqp.core.MessageProperties; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.cloud.contract.verifier.converter.YamlContract; -import org.springframework.cloud.contract.verifier.messaging.MessageVerifierReceiver; -import org.springframework.cloud.contract.verifier.messaging.MessageVerifierSender; -import org.springframework.cloud.contract.verifier.messaging.amqp.AmqpMetadata; -import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; -import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessageMetadata; -import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; -import org.springframework.cloud.contract.verifier.messaging.kafka.KafkaMetadata; -import org.springframework.cloud.contract.verifier.messaging.noop.NoOpStubMessages; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Profile; -import org.springframework.util.StringUtils; - -/** - * @author Marcin Grzejszczak - */ -@Configuration -@ConditionalOnProperty("MESSAGING_TYPE") -@Profile("messagingtype") -public class MessagingAutoConfig { - - /** - * Type of messaging. Can be either [rabbit] or [kafka]. - */ - @Value("${MESSAGING_TYPE:}") - String messagingType; - - /** - * For RabbitMQ - brokers addresses. - */ - @Value("${SPRING_RABBITMQ_ADDRESSES:}") - String springRabbitmqAddresses; - - /** - * For Kafka - brokers addresses. - */ - @Value("${SPRING_KAFKA_BOOTSTRAP_SERVERS:}") - String springKafkaBootstrapServers; - - @Bean - public ContractVerifierMessaging contractVerifierMessaging(MessageVerifierReceiver receiver) { - return new ContractVerifierCamelHelper(new NoOpStubMessages(), receiver); - } - - @Bean - MessageVerifierReceiver manualMessageVerifier(ConsumerTemplate consumerTemplate) { - return new MessageVerifierReceiver() { - - private final Logger log = LoggerFactory.getLogger(MessageVerifierReceiver.class); - - @Override - public Message receive(String destination, long timeout, TimeUnit timeUnit, YamlContract yamlContract) { - String uri = messagingType() + "://" + destination + additionalOptions(yamlContract); - log.info("Camel URI [{}]", uri); - Exchange exchange = consumerTemplate.receive(uri, timeUnit.toMillis(timeout)); - if (exchange == null) { - return null; - } - return exchange.getMessage(); - } - - private String messagingType() { - if (messagingType.equalsIgnoreCase("kafka")) { - return "kafka"; - } - return "rabbitmq"; - } - - private String additionalOptions(YamlContract contract) { - if (contract == null) { - return ""; - } - if (messagingType.equalsIgnoreCase("kafka")) { - return setKafkaOpts(contract); - } - return setRabbitOpts(contract); - } - - private String setKafkaOpts(YamlContract contract) { - String opts = defaultOpts(contract); - KafkaMetadata metadata = KafkaMetadata.fromMetadata(contract.metadata); - ContractVerifierMessageMetadata messageMetadata = ContractVerifierMessageMetadata.fromMetadata(contract.metadata); - if (inputMessage(messageMetadata) && StringUtils.hasText(metadata.getInput().getConnectToBroker().getAdditionalOptions())) { - return opts + "&" + metadata.getInput().getConnectToBroker().getAdditionalOptions(); - } - else if (StringUtils.hasText(metadata.getOutputMessage().getConnectToBroker().getAdditionalOptions())) { - return opts + "&" + metadata.getOutputMessage().getConnectToBroker().getAdditionalOptions(); - } - return opts; - } - - private String defaultOpts(YamlContract contract) { - String consumerGroup = sameConsumerGroupForSameContract(contract); - return "?brokers=" + getRequiredProperty("SPRING_KAFKA_BOOTSTRAP_SERVERS", springKafkaBootstrapServers) + "&autoOffsetReset=latest&groupId=" + consumerGroup + "&shutdownTimeout=5"; - } - - private String sameConsumerGroupForSameContract(YamlContract contract) { - return contract.input.hashCode() + "_" + contract.outputMessage.hashCode(); - } - - private String setRabbitOpts(YamlContract contract) { - String opts = "?addresses=" + getRequiredProperty("SPRING_RABBITMQ_ADDRESSES", springRabbitmqAddresses); - AmqpMetadata metadata = AmqpMetadata.fromMetadata(contract.metadata); - ContractVerifierMessageMetadata messageMetadata = ContractVerifierMessageMetadata.fromMetadata(contract.metadata); - if (inputMessage(messageMetadata) && StringUtils.hasText(metadata.getInput().getConnectToBroker().getAdditionalOptions())) { - return opts + "&" + metadata.getInput().getConnectToBroker().getAdditionalOptions(); - } - else if (StringUtils.hasText(metadata.getOutputMessage().getConnectToBroker().getAdditionalOptions())) { - return opts + "&" + metadata.getOutputMessage().getConnectToBroker().getAdditionalOptions(); - } - return defaultOpts(opts, metadata, messageMetadata); - } - - private String getRequiredProperty(String name, String value) { - if (!StringUtils.hasText(value)) { - throw new IllegalStateException("The property [" + name + "] must not be empty!"); - } - return value; - } - - private boolean inputMessage(ContractVerifierMessageMetadata messageMetadata) { - return messageMetadata.getMessageType() == ContractVerifierMessageMetadata.MessageType.INPUT; - } - - private String defaultOpts(String opts, AmqpMetadata amqpMetadata, ContractVerifierMessageMetadata messageMetadata) { - AmqpMetadata.ConnectToBroker connectToBroker = inputMessage(messageMetadata) ? amqpMetadata.getInput().getConnectToBroker() : amqpMetadata.getOutputMessage().getConnectToBroker(); - MessageProperties messageProperties = inputMessage(messageMetadata) ? amqpMetadata.getInput().getMessageProperties() : amqpMetadata.getOutputMessage().getMessageProperties(); - if (StringUtils.hasText(connectToBroker.getDeclareQueueWithName())) { - opts = opts + "&queue=" + connectToBroker.getDeclareQueueWithName(); - } - if (messageProperties != null && StringUtils.hasText(messageProperties.getReceivedRoutingKey())) { - opts = opts + "&routingKey=" + messageProperties.getReceivedRoutingKey(); - } - return opts; - } - - @Override - public Message receive(String destination, YamlContract yamlContract) { - return receive(destination, 5, TimeUnit.SECONDS, yamlContract); - } - - }; - } - -} - -class ContractVerifierCamelHelper extends ContractVerifierMessaging { - - ContractVerifierCamelHelper(MessageVerifierSender sender, MessageVerifierReceiver receiver) { - super(sender, receiver); - } - - @Override - protected ContractVerifierMessage convert(Message receive) { - if (receive == null) { - return null; - } - return new ContractVerifierMessage(receive.getBody(), receive.getHeaders()); - } - -} diff --git a/docker/spring-cloud-contract-docker/project/src/test/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/docker/spring-cloud-contract-docker/project/src/test/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 45330bbdc5..0000000000 --- a/docker/spring-cloud-contract-docker/project/src/test/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -contracts.MessagingAutoConfig diff --git a/docker/spring-cloud-contract-docker/project/src/test/resources/application-messagingtype.yml b/docker/spring-cloud-contract-docker/project/src/test/resources/application-messagingtype.yml deleted file mode 100644 index 462cdc5878..0000000000 --- a/docker/spring-cloud-contract-docker/project/src/test/resources/application-messagingtype.yml +++ /dev/null @@ -1 +0,0 @@ -stubrunner.camel.enabled: false \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/sdkman.config b/docker/spring-cloud-contract-docker/sdkman.config deleted file mode 100644 index b6578f6f4b..0000000000 --- a/docker/spring-cloud-contract-docker/sdkman.config +++ /dev/null @@ -1,8 +0,0 @@ -# make gvm non-interactive, great for CI environments -sdkman_auto_answer=true - -# don't prompt user to selfupdate on new shell -sdkman_suggestive_selfupdate=false - -# don't perform automatic selfupdates -sdkman_auto_selfupdate=false \ No newline at end of file diff --git a/docker/spring-cloud-contract-docker/sdkman/sdkman-wrapper.sh b/docker/spring-cloud-contract-docker/sdkman/sdkman-wrapper.sh deleted file mode 100755 index 673ffaaf78..0000000000 --- a/docker/spring-cloud-contract-docker/sdkman/sdkman-wrapper.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -# A quick wrapper to source the gvm env and run it -# This is used to run gvm in Dockerfile RUN commands -# since the RUN commands does not use interactive shells - -[[ -s "/home/scc/.sdkman/bin/sdkman-init.sh" ]] && source "/home/scc/.sdkman/bin/sdkman-init.sh" && sdk $@ diff --git a/docker/spring-cloud-contract-stub-runner-docker/Dockerfile b/docker/spring-cloud-contract-stub-runner-docker/Dockerfile deleted file mode 100644 index 509f6148b1..0000000000 --- a/docker/spring-cloud-contract-stub-runner-docker/Dockerfile +++ /dev/null @@ -1,40 +0,0 @@ -FROM ubuntu:20.04 - -ARG SDKMAN_JAVA_INSTALLATION=17.0.1-tem -ARG THIN_REPO=https://repo.spring.io/snapshot - -LABEL Author="Marcin Grzejszczak " -LABEL Author="Bastian Doetsch " - -RUN apt-get update && apt-get install -y curl \ - unzip \ - zip \ - && apt-get clean - -RUN useradd -u1000 -m scc - -# Install sdkman and java -COPY sdkman/ /usr/local/bin/ -RUN chmod +x /usr/local/bin/sdkman-wrapper.sh - -USER scc -WORKDIR /home/scc - -RUN curl -s https://get.sdkman.io/ | bash -COPY --chown=scc sdkman.config /home/scc/.sdkman/etc/config -RUN bash -c "source /home/scc/.sdkman/bin/sdkman-init.sh" -RUN bash -c "sdkman-wrapper.sh install java ${SDKMAN_JAVA_INSTALLATION}" -ENV JAVA_HOME /home/scc/.sdkman/candidates/java/current/ -ENV PATH "${PATH}:${JAVA_HOME}/bin" - -# Spring Cloud Contract -ENV SERVER_PORT 8750 -VOLUME /tmp -COPY --chown=scc:scc target/maven_dependencies /home/scc/.m2/repository/ -COPY --chown=scc:scc target/libs/stub-runner-boot.jar stub-runner-boot.jar -RUN echo "Fetching dependencies, please wait..." -RUN java -Dthin.dryrun=true -jar stub-runner-boot.jar --thin.repo=${THIN_REPO} -RUN java -Dthin.dryrun=true -jar stub-runner-boot.jar --thin.profile=rabbit --thin.repo=${THIN_REPO} -RUN java -Dthin.dryrun=true -jar stub-runner-boot.jar --thin.profile=kafka --thin.repo=${THIN_REPO} -COPY --chown=scc:scc run.sh run.sh -ENTRYPOINT ["./run.sh"] diff --git a/docker/spring-cloud-contract-stub-runner-docker/log.log b/docker/spring-cloud-contract-stub-runner-docker/log.log new file mode 100644 index 0000000000..713025d269 --- /dev/null +++ b/docker/spring-cloud-contract-stub-runner-docker/log.log @@ -0,0 +1,176 @@ +[INFO] Scanning for projects... +[INFO] +[INFO] --< org.springframework.cloud:spring-cloud-contract-stub-runner-docker >-- +[INFO] Building Spring Cloud Contract Stub Runner Docker 4.0.0-SNAPSHOT +[INFO] --------------------------------[ pom ]--------------------------------- +[INFO] +[INFO] --- maven-dependency-plugin:3.1.2:tree (default-cli) @ spring-cloud-contract-stub-runner-docker --- +[INFO] org.springframework.cloud:spring-cloud-contract-stub-runner-docker:pom:4.0.0-SNAPSHOT +[INFO] +- org.springframework.cloud:spring-cloud-contract-parent:pom:4.0.0-SNAPSHOT:runtime +[INFO] +- org.springframework.cloud:spring-cloud-commons-dependencies:pom:4.0.0-SNAPSHOT:runtime +[INFO] +- org.springframework.cloud:spring-cloud-contract-dependencies:pom:4.0.0-SNAPSHOT:runtime +[INFO] +- org.springframework.cloud:spring-cloud-netflix-dependencies:pom:4.0.0-SNAPSHOT:runtime +[INFO] +- org.springframework.cloud:spring-cloud-zookeeper-dependencies:pom:4.0.0-SNAPSHOT:runtime +[INFO] +- org.springframework.cloud:spring-cloud-consul-dependencies:pom:4.0.0-SNAPSHOT:runtime +[INFO] +- org.springframework.cloud:spring-cloud-stream-dependencies:pom:4.0.0-SNAPSHOT:runtime +[INFO] +- org.springframework.cloud:spring-cloud-contract-stub-runner-boot:jar:4.0.0-SNAPSHOT:compile +[INFO] | +- org.springframework.cloud:spring-cloud-starter-contract-stub-runner:jar:4.0.0-SNAPSHOT:compile +[INFO] | | +- org.springframework.cloud:spring-cloud-contract-stub-runner:jar:4.0.0-SNAPSHOT:compile +[INFO] | | | +- org.springframework.cloud:spring-cloud-contract-verifier:jar:4.0.0-SNAPSHOT:compile +[INFO] | | | | +- javax.inject:javax.inject:jar:1:compile +[INFO] | | | | +- com.toomuchcoding.jsonassert:jsonassert:jar:0.6.2:compile +[INFO] | | | | +- com.rackspace.eclipse.webtools.sourceediting:org.eclipse.wst.xml.xpath2.processor:jar:2.1.100:compile +[INFO] | | | | | +- edu.princeton.cup:java-cup:jar:10k:compile +[INFO] | | | | | \- com.ibm.icu:icu4j:jar:4.6:compile +[INFO] | | | | +- org.apache.groovy:groovy-nio:jar:4.0.0:compile +[INFO] | | | | +- org.apache.groovy:groovy-json:jar:4.0.0:compile +[INFO] | | | | +- org.apache.groovy:groovy-xml:jar:4.0.0:compile +[INFO] | | | | +- com.github.jknack:handlebars:jar:4.3.0:compile +[INFO] | | | | +- commons-beanutils:commons-beanutils:jar:1.9.4:compile +[INFO] | | | | | +- commons-logging:commons-logging:jar:1.2:compile +[INFO] | | | | | \- commons-collections:commons-collections:jar:3.2.2:compile +[INFO] | | | | +- com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:jar:2.14.0-rc3:compile +[INFO] | | | | +- net.javacrumbs.json-unit:json-unit-assertj:jar:2.32.0:compile +[INFO] | | | | | +- net.javacrumbs.json-unit:json-unit-core:jar:2.32.0:compile +[INFO] | | | | | | \- org.hamcrest:hamcrest-core:jar:1.3:test +[INFO] | | | | | \- net.javacrumbs.json-unit:json-unit-json-path:jar:2.32.0:compile +[INFO] | | | | \- org.junit.jupiter:junit-jupiter-api:jar:5.9.1:compile +[INFO] | | | | +- org.opentest4j:opentest4j:jar:1.2.0:compile +[INFO] | | | | +- org.junit.platform:junit-platform-commons:jar:1.9.1:compile +[INFO] | | | | \- org.apiguardian:apiguardian-api:jar:1.1.2:compile +[INFO] | | | +- org.springframework.cloud:spring-cloud-contract-shade:jar:4.0.0-SNAPSHOT:compile +[INFO] | | | +- org.springframework.cloud:spring-cloud-contract-converters:jar:4.0.0-SNAPSHOT:compile +[INFO] | | | +- org.springframework.cloud:spring-cloud-contract-spec:jar:4.0.0-SNAPSHOT:compile +[INFO] | | | | \- org.springframework.cloud:spring-cloud-contract-spec-groovy:jar:4.0.0-SNAPSHOT:compile +[INFO] | | | +- org.eclipse.jgit:org.eclipse.jgit:jar:6.1.0.202203080745-r:compile +[INFO] | | | | \- com.googlecode.javaewah:JavaEWAH:jar:1.1.13:compile +[INFO] | | | +- org.eclipse.jgit:org.eclipse.jgit.ssh.jsch:jar:6.1.0.202203080745-r:compile +[INFO] | | | | +- com.jcraft:jsch:jar:0.1.55:compile +[INFO] | | | | \- com.jcraft:jzlib:jar:1.1.1:compile +[INFO] | | | +- com.jcraft:jsch.agentproxy.sshagent:jar:0.0.9:compile +[INFO] | | | | \- com.jcraft:jsch.agentproxy.core:jar:0.0.9:compile +[INFO] | | | +- com.jcraft:jsch.agentproxy.jsch:jar:0.0.9:compile +[INFO] | | | \- com.jcraft:jsch.agentproxy.usocket-jna:jar:0.0.9:compile +[INFO] | | | \- net.java.dev.jna:jna-platform:jar:4.1.0:compile +[INFO] | | +- org.springframework.boot:spring-boot-starter-test:jar:3.0.0-RC2:compile +[INFO] | | | +- org.springframework.boot:spring-boot-test:jar:3.0.0-RC2:compile +[INFO] | | | +- org.springframework.boot:spring-boot-test-autoconfigure:jar:3.0.0-RC2:compile +[INFO] | | | +- com.jayway.jsonpath:json-path:jar:2.7.0:compile +[INFO] | | | | \- net.minidev:json-smart:jar:2.4.8:compile +[INFO] | | | | \- net.minidev:accessors-smart:jar:2.4.8:compile +[INFO] | | | | \- org.ow2.asm:asm:jar:9.1:compile +[INFO] | | | +- jakarta.xml.bind:jakarta.xml.bind-api:jar:4.0.0:compile +[INFO] | | | | \- jakarta.activation:jakarta.activation-api:jar:2.1.0:compile +[INFO] | | | +- org.assertj:assertj-core:jar:3.23.1:compile +[INFO] | | | | \- net.bytebuddy:byte-buddy:jar:1.12.18:compile +[INFO] | | | +- org.hamcrest:hamcrest:jar:2.2:compile +[INFO] | | | +- org.junit.jupiter:junit-jupiter:jar:5.9.1:compile +[INFO] | | | | +- org.junit.jupiter:junit-jupiter-params:jar:5.9.1:compile +[INFO] | | | | \- org.junit.jupiter:junit-jupiter-engine:jar:5.9.1:runtime +[INFO] | | | | \- org.junit.platform:junit-platform-engine:jar:1.9.1:runtime +[INFO] | | | +- org.mockito:mockito-core:jar:2.23.0:test +[INFO] | | | | +- net.bytebuddy:byte-buddy-agent:jar:1.12.18:test +[INFO] | | | | \- org.objenesis:objenesis:jar:2.6:test +[INFO] | | | +- org.mockito:mockito-junit-jupiter:jar:4.8.1:compile +[INFO] | | | +- org.skyscreamer:jsonassert:jar:1.5.1:compile +[INFO] | | | | \- com.vaadin.external.google:android-json:jar:0.0.20131108.vaadin1:compile +[INFO] | | | +- org.springframework:spring-core:jar:6.0.0-RC4:compile +[INFO] | | | +- org.springframework:spring-test:jar:6.0.0-RC4:compile +[INFO] | | | \- org.xmlunit:xmlunit-core:jar:2.9.0:compile +[INFO] | | +- org.springframework.cloud:spring-cloud-contract-wiremock:jar:4.0.0-SNAPSHOT:compile +[INFO] | | | +- jakarta.servlet:jakarta.servlet-api:jar:6.0.0:compile +[INFO] | | | +- com.github.tomakehurst:wiremock-jre8-standalone:jar:2.35.0:compile +[INFO] | | | +- org.apache.httpcomponents.client5:httpclient5:jar:5.1.3:compile +[INFO] | | | | +- org.apache.httpcomponents.core5:httpcore5:jar:5.1.4:compile +[INFO] | | | | +- org.apache.httpcomponents.core5:httpcore5-h2:jar:5.1.4:compile +[INFO] | | | | \- commons-codec:commons-codec:jar:1.15:compile +[INFO] | | | \- org.springframework.cloud:spring-cloud-test-support:jar:4.0.0-SNAPSHOT:compile +[INFO] | | | +- org.apache.maven.resolver:maven-resolver-connector-basic:jar:1.4.1:compile +[INFO] | | | | +- org.apache.maven.resolver:maven-resolver-spi:jar:1.4.1:compile +[INFO] | | | | \- org.apache.maven.resolver:maven-resolver-util:jar:1.4.1:compile +[INFO] | | | +- org.apache.maven.resolver:maven-resolver-impl:jar:1.4.1:compile +[INFO] | | | +- org.apache.maven:maven-resolver-provider:jar:3.6.3:compile +[INFO] | | | | +- org.apache.maven:maven-model:jar:3.6.3:compile +[INFO] | | | | +- org.apache.maven:maven-model-builder:jar:3.6.3:compile +[INFO] | | | | | +- org.codehaus.plexus:plexus-interpolation:jar:1.25:compile +[INFO] | | | | | +- org.apache.maven:maven-artifact:jar:3.6.3:compile +[INFO] | | | | | \- org.apache.maven:maven-builder-support:jar:3.6.3:compile +[INFO] | | | | \- org.apache.maven:maven-repository-metadata:jar:3.6.3:compile +[INFO] | | | \- org.apache.maven.resolver:maven-resolver-transport-http:jar:1.4.1:compile +[INFO] | | | +- org.apache.httpcomponents:httpclient:jar:4.5.13:compile +[INFO] | | | \- org.apache.httpcomponents:httpcore:jar:4.4.15:compile +[INFO] | | +- org.apache.maven.resolver:maven-resolver-api:jar:1.4.1:compile +[INFO] | | \- org.sonatype.sisu:sisu-inject-plexus:jar:2.6.0:compile +[INFO] | | +- org.codehaus.plexus:plexus-component-annotations:jar:1.7.1:compile +[INFO] | | +- org.codehaus.plexus:plexus-classworlds:jar:2.5.2:compile +[INFO] | | +- org.codehaus.plexus:plexus-utils:jar:3.0.18:compile +[INFO] | | +- org.sonatype.sisu:sisu-inject-bean:jar:2.6.0:compile +[INFO] | | | +- javax.enterprise:cdi-api:jar:1.0:compile +[INFO] | | | | \- javax.annotation:jsr250-api:jar:1.0:compile +[INFO] | | | +- org.sonatype.sisu:sisu-guice:jar:no_aop:3.2.6:compile +[INFO] | | | | \- com.google.guava:guava:jar:16.0.1:compile +[INFO] | | | \- org.eclipse.sisu:org.eclipse.sisu.inject:jar:0.3.3:compile +[INFO] | | \- org.eclipse.sisu:org.eclipse.sisu.plexus:jar:0.3.3:compile +[INFO] | +- org.springframework.cloud:spring-cloud-contract-spec-kotlin:jar:4.0.0-SNAPSHOT:compile +[INFO] | | +- org.springframework.cloud:spring-cloud-contract-spec-java:jar:4.0.0-SNAPSHOT:compile +[INFO] | | | +- org.apache.groovy:groovy:jar:4.0.0:compile +[INFO] | | | +- dk.brics:automaton:jar:1.12-4:compile +[INFO] | | | +- org.apache.commons:commons-text:jar:1.10.0:compile +[INFO] | | | | \- org.apache.commons:commons-lang3:jar:3.12.0:compile +[INFO] | | | \- org.springframework:spring-jcl:jar:6.0.0-RC4:compile +[INFO] | | +- org.jetbrains.kotlin:kotlin-stdlib-jdk8:jar:1.6.21:compile +[INFO] | | | +- org.jetbrains.kotlin:kotlin-stdlib:jar:1.6.21:compile +[INFO] | | | | +- org.jetbrains.kotlin:kotlin-stdlib-common:jar:1.6.21:compile +[INFO] | | | | \- org.jetbrains:annotations:jar:13.0:compile +[INFO] | | | \- org.jetbrains.kotlin:kotlin-stdlib-jdk7:jar:1.6.21:compile +[INFO] | | +- org.jetbrains.kotlin:kotlin-compiler-embeddable:jar:1.6.21:compile +[INFO] | | | +- org.jetbrains.kotlin:kotlin-script-runtime:jar:1.6.21:compile +[INFO] | | | +- org.jetbrains.kotlin:kotlin-reflect:jar:1.6.21:runtime +[INFO] | | | +- org.jetbrains.kotlin:kotlin-daemon-embeddable:jar:1.6.21:runtime +[INFO] | | | +- org.jetbrains.intellij.deps:trove4j:jar:1.0.20200330:compile +[INFO] | | | \- net.java.dev.jna:jna:jar:5.6.0:compile +[INFO] | | +- org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:jar:1.6.21:compile +[INFO] | | | \- org.jetbrains.kotlin:kotlin-scripting-compiler-impl-embeddable:jar:1.6.21:runtime +[INFO] | | | \- org.jetbrains.kotlin:kotlin-scripting-common:jar:1.6.21:compile +[INFO] | | \- org.jetbrains.kotlin:kotlin-script-util:jar:1.6.21:compile +[INFO] | | +- org.jetbrains.kotlin:kotlin-scripting-jvm:jar:1.6.21:compile +[INFO] | | \- org.jetbrains.kotlin:kotlin-daemon-client:jar:1.6.21:compile +[INFO] | | \- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:jar:1.6.4:compile +[INFO] | \- org.springframework.boot:spring-boot-starter-web:jar:3.0.0-RC2:compile +[INFO] | +- org.springframework.boot:spring-boot-starter:jar:3.0.0-RC2:compile +[INFO] | | +- org.springframework.boot:spring-boot:jar:3.0.0-RC2:compile +[INFO] | | +- org.springframework.boot:spring-boot-autoconfigure:jar:3.0.0-RC2:compile +[INFO] | | +- org.springframework.boot:spring-boot-starter-logging:jar:3.0.0-RC2:compile +[INFO] | | | +- ch.qos.logback:logback-classic:jar:1.4.4:compile +[INFO] | | | | \- ch.qos.logback:logback-core:jar:1.4.4:compile +[INFO] | | | +- org.apache.logging.log4j:log4j-to-slf4j:jar:2.19.0:compile +[INFO] | | | | \- org.apache.logging.log4j:log4j-api:jar:2.19.0:compile +[INFO] | | | \- org.slf4j:jul-to-slf4j:jar:2.0.3:compile +[INFO] | | +- jakarta.annotation:jakarta.annotation-api:jar:2.1.1:compile +[INFO] | | \- org.yaml:snakeyaml:jar:1.33:compile +[INFO] | +- org.springframework.boot:spring-boot-starter-json:jar:3.0.0-RC2:compile +[INFO] | | +- com.fasterxml.jackson.core:jackson-databind:jar:2.14.0-rc3:compile +[INFO] | | | +- com.fasterxml.jackson.core:jackson-annotations:jar:2.14.0-rc3:compile +[INFO] | | | \- com.fasterxml.jackson.core:jackson-core:jar:2.14.0-rc3:compile +[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jdk8:jar:2.14.0-rc3:compile +[INFO] | | +- com.fasterxml.jackson.datatype:jackson-datatype-jsr310:jar:2.14.0-rc3:compile +[INFO] | | \- com.fasterxml.jackson.module:jackson-module-parameter-names:jar:2.14.0-rc3:compile +[INFO] | +- org.springframework.boot:spring-boot-starter-tomcat:jar:3.0.0-RC2:compile +[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-core:jar:10.1.1:compile +[INFO] | | +- org.apache.tomcat.embed:tomcat-embed-el:jar:10.1.1:compile +[INFO] | | \- org.apache.tomcat.embed:tomcat-embed-websocket:jar:10.1.1:compile +[INFO] | +- org.springframework:spring-web:jar:6.0.0-RC4:compile +[INFO] | | +- org.springframework:spring-beans:jar:6.0.0-RC4:compile +[INFO] | | \- io.micrometer:micrometer-observation:jar:1.10.0:compile +[INFO] | | \- io.micrometer:micrometer-commons:jar:1.10.0:compile +[INFO] | \- org.springframework:spring-webmvc:jar:6.0.0-RC4:compile +[INFO] | +- org.springframework:spring-aop:jar:6.0.0-RC4:compile +[INFO] | +- org.springframework:spring-context:jar:6.0.0-RC4:compile +[INFO] | \- org.springframework:spring-expression:jar:6.0.0-RC4:compile +[INFO] \- org.slf4j:slf4j-api:jar:2.0.3:compile +[INFO] ------------------------------------------------------------------------ +[INFO] BUILD SUCCESS +[INFO] ------------------------------------------------------------------------ +[INFO] Total time: 0.694 s +[INFO] Finished at: 2022-11-16T14:05:27+01:00 +[INFO] ------------------------------------------------------------------------ diff --git a/docker/spring-cloud-contract-stub-runner-docker/pom.xml b/docker/spring-cloud-contract-stub-runner-docker/pom.xml deleted file mode 100644 index d85f56a027..0000000000 --- a/docker/spring-cloud-contract-stub-runner-docker/pom.xml +++ /dev/null @@ -1,301 +0,0 @@ - - - 4.0.0 - - - org.springframework.cloud - spring-cloud-contract-docker-parent - 4.1.0-SNAPSHOT - .. - - - spring-cloud-contract-stub-runner-docker - pom - 4.1.0-SNAPSHOT - Spring Cloud Contract Stub Runner Docker - Spring Cloud Contract Stub Runner Docker - - - https://repo.spring.io/snapshot - - - - - - org.springframework.cloud - spring-cloud-contract-parent - ${project.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-commons-dependencies - ${spring-cloud-commons.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-contract-dependencies - ${project.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-netflix-dependencies - ${spring-cloud-netflix.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-zookeeper-dependencies - ${spring-cloud-zookeeper.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-consul-dependencies - ${spring-cloud-consul.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-stream-dependencies - ${spring-cloud-stream.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-dependencies-parent - ${spring-cloud-build.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-build-dependencies - ${spring-cloud-build.version} - pom - runtime - - - org.springframework.boot.experimental - spring-boot-thin-layout - ${thin-jar.version} - - - org.springframework.boot.experimental - spring-boot-thin-launcher - ${thin-jar.version} - exec - - - - - org.springframework.cloud - spring-cloud-contract-stub-runner-boot - compile - - - org.springframework.cloud - spring-cloud-contract-wiremock - compile - - - org.springframework.cloud - spring-cloud-contract-tools - ${project.version} - pom - runtime - - - org.springframework.cloud - spring-cloud-contract-spec - compile - - - org.springframework.cloud - spring-cloud-contract-spec-java - compile - - - org.springframework.cloud - spring-cloud-contract-spec-groovy - compile - - - org.springframework.cloud - spring-cloud-contract-spec-kotlin - compile - - - org.springframework.cloud - spring-cloud-contract-verifier - compile - - - org.springframework.cloud - spring-cloud-contract-converters - compile - - - org.springframework.cloud - spring-cloud-contract-stub-runner - compile - - - org.springframework.cloud - spring-cloud-contract-shade - compile - - - org.springframework.cloud - spring-cloud-starter-contract-verifier - compile - - - org.springframework.cloud - spring-cloud-starter-contract-stub-runner - compile - - - org.springframework.cloud - spring-cloud-starter-contract-stub-runner-jetty - compile - - - org.springframework.boot.experimental - spring-boot-thin-launcher - ${thin-jar.version} - exec - compile - - - - - org.slf4j - slf4j-api - ${slf4j.version} - compile - - - org.springframework.cloud - spring-cloud-build - ${spring-cloud-build.version} - pom - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - false - - - - - org.apache.maven.plugins - maven-dependency-plugin - - - copy-all-dependencies - package - - copy-dependencies - - - - ${project.build.directory}/maven_dependencies - - false - true - true - true - true - false - - - - copy-dependencies - package - - copy - - - - - ${project.groupId} - spring-cloud-contract-stub-runner-boot - - ${project.version} - jar - true - ${project.build.directory}/libs - - stub-runner-boot.jar - - - - - - - - com.spotify - dockerfile-maven-plugin - 1.4.13 - - - default - - build - push - - - - - - ${docker.registry.organization}/spring-cloud-contract-stub-runner - - ${project.version} - ${env.DOCKER_HUB_USERNAME} - ${env.DOCKER_HUB_PASSWORD} - - ${thin.repo} - - - - - org.codehaus.plexus - plexus-archiver - 3.6.0 - - - - - - - - milestone - - https://repo.spring.io/milestone - - - - central - - https://repo.maven.apache.org/maven2 - - - - diff --git a/docker/spring-cloud-contract-stub-runner-docker/run.sh b/docker/spring-cloud-contract-stub-runner-docker/run.sh deleted file mode 100755 index 53c0252dbe..0000000000 --- a/docker/spring-cloud-contract-stub-runner-docker/run.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash - -set -o errexit -set -o errtrace -set -o nounset -set -o pipefail - -echo "Running Spring Cloud Contract Stub Runner" -ADDITIONAL_OPTS="${ADDITIONAL_OPTS:-}" -MESSAGING_TYPE="${MESSAGING_TYPE:-}" - -if [[ "${MESSAGING_TYPE}" != "" ]]; then - echo "Messaging type passed, will active thin profile [${MESSAGING_TYPE}]" - ADDITIONAL_OPTS="${ADDITIONAL_OPTS} --thin.profile=${MESSAGING_TYPE}" -fi - -echo "Please wait for the dependencies to be downloaded..." -java -Djava.security.egd=file:/dev/./urandom -jar /home/scc/stub-runner-boot.jar ${ADDITIONAL_OPTS} diff --git a/docker/spring-cloud-contract-stub-runner-docker/sdkman.config b/docker/spring-cloud-contract-stub-runner-docker/sdkman.config deleted file mode 100644 index b6578f6f4b..0000000000 --- a/docker/spring-cloud-contract-stub-runner-docker/sdkman.config +++ /dev/null @@ -1,8 +0,0 @@ -# make gvm non-interactive, great for CI environments -sdkman_auto_answer=true - -# don't prompt user to selfupdate on new shell -sdkman_suggestive_selfupdate=false - -# don't perform automatic selfupdates -sdkman_auto_selfupdate=false \ No newline at end of file diff --git a/docker/spring-cloud-contract-stub-runner-docker/sdkman/sdkman-wrapper.sh b/docker/spring-cloud-contract-stub-runner-docker/sdkman/sdkman-wrapper.sh deleted file mode 100755 index 673ffaaf78..0000000000 --- a/docker/spring-cloud-contract-stub-runner-docker/sdkman/sdkman-wrapper.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -# A quick wrapper to source the gvm env and run it -# This is used to run gvm in Dockerfile RUN commands -# since the RUN commands does not use interactive shells - -[[ -s "/home/scc/.sdkman/bin/sdkman-init.sh" ]] && source "/home/scc/.sdkman/bin/sdkman-init.sh" && sdk $@ diff --git a/docs/.github/workflows/deploy-docs.yml b/docs/.github/workflows/deploy-docs.yml deleted file mode 100644 index be4b92dfc0..0000000000 --- a/docs/.github/workflows/deploy-docs.yml +++ /dev/null @@ -1,32 +0,0 @@ -name: Deploy Docs -on: - push: - branches-ignore: [ gh-pages ] - tags: '**' - repository_dispatch: - types: request-build-reference # legacy - #schedule: - #- cron: '0 10 * * *' # Once per day at 10am UTC - workflow_dispatch: -permissions: - actions: write -jobs: - build: - runs-on: ubuntu-latest - # if: github.repository_owner == 'spring-cloud' - steps: - - name: Checkout - uses: actions/checkout@v3 - with: - ref: docs-build - fetch-depth: 1 - - name: Dispatch (partial build) - if: github.ref_type == 'branch' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) -f build-refname=${{ github.ref_name }} - - name: Dispatch (full build) - if: github.ref_type == 'tag' - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: gh workflow run deploy-docs.yml -r $(git rev-parse --abbrev-ref HEAD) diff --git a/docs/antora.yml b/docs/antora.yml deleted file mode 100644 index 15b346da04..0000000000 --- a/docs/antora.yml +++ /dev/null @@ -1,12 +0,0 @@ -name: PROJECT_WITHOUT_SPRING -version: true -title: PROJECT_NAME -nav: - - modules/ROOT/nav.adoc -ext: - collector: - run: - command: ./mvnw --no-transfer-progress -B process-resources -Pdocs -pl docs -Dantora-maven-plugin.phase=none -Dgenerate-docs.phase=none -Dgenerate-readme.phase=none -Dgenerate-cloud-resources.phase=none -Dmaven-dependency-plugin-for-docs.phase=none -Dmaven-dependency-plugin-for-docs-classes.phase=none -DskipTests - local: true - scan: - dir: ./target/classes/antora-resources/ diff --git a/docs/modules/ROOT/assets/images/Deps.png b/docs/modules/ROOT/assets/images/Deps.png deleted file mode 100644 index 1426814308..0000000000 Binary files a/docs/modules/ROOT/assets/images/Deps.png and /dev/null differ diff --git a/docs/modules/ROOT/assets/images/Stubs1.png b/docs/modules/ROOT/assets/images/Stubs1.png deleted file mode 100644 index ebadfdb910..0000000000 Binary files a/docs/modules/ROOT/assets/images/Stubs1.png and /dev/null differ diff --git a/docs/modules/ROOT/assets/images/Stubs2.png b/docs/modules/ROOT/assets/images/Stubs2.png deleted file mode 100644 index e4bad24987..0000000000 Binary files a/docs/modules/ROOT/assets/images/Stubs2.png and /dev/null differ diff --git a/docs/modules/ROOT/assets/images/start_spring_io_dependencies.png b/docs/modules/ROOT/assets/images/start_spring_io_dependencies.png deleted file mode 100644 index 0b4784234b..0000000000 Binary files a/docs/modules/ROOT/assets/images/start_spring_io_dependencies.png and /dev/null differ diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc deleted file mode 100644 index d4e53eadee..0000000000 --- a/docs/modules/ROOT/nav.adoc +++ /dev/null @@ -1,84 +0,0 @@ -* xref:index.adoc[] -* xref:spring-cloud-contract.adoc[] -* xref:_attributes.adoc[] -* xref:README.adoc[] -* xref:_additional-stubrunner-configprops.adoc[] -* xref:_building.adoc[] -* xref:_configprops.adoc[] -* xref:_index.adoc[] -* xref:_index_pdf.adoc[] -* xref:_index_single.adoc[] -* xref:_project-features-contract.adoc[] -** xref:_project-features-contract/groovy.adoc[] -** xref:_project-features-contract/java.adoc[] -** xref:_project-features-contract/kotlin.adoc[] -** xref:_project-features-contract/yml.adoc[] -** xref:_project-features-contract/limitations.adoc[] -** xref:_project-features-contract/common-top-elements.adoc[] -** xref:_project-features-contract/dsl-http-top-level-elements.adoc[] -** xref:_project-features-contract/dsl-request.adoc[] -** xref:_project-features-contract/dsl-response.adoc[] -** xref:_project-features-contract/dsl-dynamic-properties.adoc[] -** xref:_project-features-contract/dsl-async.adoc[] -** xref:_project-features-contract/dsl-xml.adoc[] -** xref:_project-features-contract/dsl-multiple.adoc[] -** xref:_project-features-contract/stateful-contracts.adoc[] -* xref:_project-features-flows.adoc[] -** xref:_project-features-flows/jax-rs.adoc[] -** xref:_project-features-flows/feature-webflux.adoc[] -** xref:_project-features-flows/feature-webflux-explicit.adoc[] -** xref:_project-features-flows/custom-mode.adoc[] -** xref:_project-features-flows/context-paths.adoc[] -** xref:_project-features-flows/rest-docs.adoc[] -** xref:_project-features-flows/graphql.adoc[] -** xref:_project-features-flows/grpc.adoc[] -* xref:_project-features-messaging.adoc[] -* xref:_project-features-stubrunner.adoc[] -** xref:_project-features-stubrunner/stub-runner-snapshot-versions.adoc[] -** xref:_project-features-stubrunner/stub-runner-publishing-stubs-as-jars.adoc[] -** xref:_project-features-stubrunner/stub-runner-core.adoc[] -** xref:_project-features-stubrunner/stub-runner-junit.adoc[] -** xref:_project-features-stubrunner/stub-runner-cloud.adoc[] -** xref:_project-features-stubrunner/stub-runner-boot.adoc[] -** xref:_project-features-stubrunner/stub-runner-stubs-per-consumer.adoc[] -** xref:_project-features-stubrunner/stub-runner-stubs-protocol.adoc[] -** xref:_project-features-stubrunner/stub-runner-generate-stubs-at-runtime.adoc[] -** xref:_project-features-stubrunner/stub-runner-fail-on-no-stubs.adoc[] -** xref:_project-features-stubrunner/stub-runner-common.adoc[] -* xref:_project-features-wiremock.adoc[] -* xref:advanced.adoc[] -* xref:appendix.adoc[] -* xref:docker-project.adoc[] -* xref:documentation-overview.adoc[] -* xref:getting-started.adoc[] -** xref:getting-started/introducing-spring-cloud-contract.adoc[] -** xref:getting-started/three-second-tour.adoc[] -** xref:getting-started/first-application.adoc[] -** xref:getting-started/cdc.adoc[] -** xref:getting-started/whats-next.adoc[] -* xref:gradle-project.adoc[] -* xref:howto.adoc[] -** xref:howto/why-spring-cloud-contract.adoc[] -** xref:howto/how-to-not-write-contracts-in-groovy.adoc[] -** xref:howto/how-to-provide-dynamic-values.adoc[] -** xref:howto/how-to-do-stubs-versioning.adoc[] -** xref:howto/how-to-common-repo-with-contracts.adoc[] -** xref:howto/how-to-use-git-as-storage.adoc[] -** xref:howto/how-to-debug.adoc[] -** xref:howto/how-to-debug-wiremock.adoc[] -** xref:howto/how-to-see-registered-stubs.adoc[] -** xref:howto/how-to-reference-text-from-file.adoc[] -** xref:howto/how-to-generate-pact-from-scc.adoc[] -** xref:howto/how-to-work-with-transitivie.adoc[] -** xref:howto/contract-dsl-rest-docs.adoc[] -** xref:howto/how-to-use-stubs-from-a-location.adoc[] -** xref:howto/how-to-generate-stubs-at-runtime.adoc[] -** xref:howto/how-to-use-the-failonnostubs-feature.adoc[] -** xref:howto/how-to-mark-contract-in-progress.adoc[] -* xref:legal.adoc[] -* xref:maven-project.adoc[] -* xref:project-features.adoc[] -* xref:sagan-boot.adoc[] -* xref:sagan-index.adoc[] -* xref:using.adoc[] -* xref:yml-schema.adoc[] diff --git a/docs/modules/ROOT/pages/README.adoc b/docs/modules/ROOT/pages/README.adoc deleted file mode 100644 index 3bb7a70cf1..0000000000 --- a/docs/modules/ROOT/pages/README.adoc +++ /dev/null @@ -1,22 +0,0 @@ -[[spring-cloud-contract]] -= Spring Cloud Contract -:page-section-summary-toc: 1 - -You always need confidence when pushing new features into a new application or service in -a distributed system. To that end, this project provides support for consumer-driven -contracts and service schemas in Spring applications, covering a range of options for -writing tests, publishing them as assets, and asserting that a contract is kept by -producers and consumers -- for both HTTP and message-based interactions. - -[[project-page]] -= Project page -:page-section-summary-toc: 1 - -You can read more about Spring Cloud Contract by going to https://spring.io/projects/spring-cloud-contract[the project page] - -[[contributing]] -= Contributing -:page-section-summary-toc: 1 - -include::https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/main/docs/src/main/asciidoc/contributing.adoc[] - diff --git a/docs/modules/ROOT/pages/_additional-stubrunner-configprops.adoc b/docs/modules/ROOT/pages/_additional-stubrunner-configprops.adoc deleted file mode 100644 index cf35b933e8..0000000000 --- a/docs/modules/ROOT/pages/_additional-stubrunner-configprops.adoc +++ /dev/null @@ -1,17 +0,0 @@ -IMPORTANT: The following properties can be passed as a system property (for example, `stubrunner.properties.git.branch`), as an environment variable (for example, `STUBRUNNER_PROPERTIES_GIT_BRANCH`), or as a property inside stub runner's annotation or a JUnit Rule (JUnit 4) or Extension (JUnit 5). In the latter case, you can pass the `git.branch` property instead of `stubrunner.properties.git.branch`. - -.Stubrunner Properties Options -|=== -|Name | Default | Description - -|`stubrunner.properties.git.branch` | | When using the SCM-based approach, you can customize the branch name to check out. -|`stubrunner.properties.git.commit-message` | Updating project [$project] with stubs | When using the SCM based approach, you can customize the commit message for created stubs. The `$project` text is replaced with the project name. -|`stubrunner.properties.git.no-of-attempts` | `10` | When using the-SCM based approach, you can customize the number of retries to push the stubs to Git. -|`stubrunner.properties.git.username` | | When using the SCM-based approach, you can pass the username to connect to the git repository. -|`stubrunner.properties.git.password` | | When using the SCM-based approach, you can pass the password to connect to the git repository. -|`stubrunner.properties.git.wait-between-attempts` | `1000` | When using the SCM-based approach, you can customize waiting time in ms between attempts to push the stubs to git. -|`stubrunner.properties.git.ensure-git-suffix` | `true` | When using the SCM based approach, you can prevent stubrunner from adding `.git` to the repository URL by setting this property to `false`. This adds compatibility with git repositories which do not support such URLs, for example Azure DevOps. - -|`stubrunner.properties.stubs.find-producer` | `false` | When using the `stubs` protocol, you can toggle this flag to search for contracts in the `group id / artifact id` instead of taking the stubs directly from the provided folder. - -|=== diff --git a/docs/modules/ROOT/pages/_attributes.adoc b/docs/modules/ROOT/pages/_attributes.adoc deleted file mode 100644 index 3462a070a2..0000000000 --- a/docs/modules/ROOT/pages/_attributes.adoc +++ /dev/null @@ -1,36 +0,0 @@ -:doctype: book -:idprefix: -:idseparator: - -:tabsize: 4 -:numbered: -:sectanchors: -:sectnums: -:icons: font -:hide-uri-scheme: -:docinfo: shared,private - -:sc-ext: java -:project-full-name: Spring Cloud Contract - -// project-specific attributes -:core_path: {project-root} -:plugins_path: {project-root}/spring-cloud-contract-tools -:converters_path: {plugins_path}/spring-cloud-contract-converters -:verifier_root_path: {core_path}/spring-cloud-contract-verifier -:contract_spec_path: {core_path}/specs/spring-cloud-contract-spec-java -:contract_spec_tests_path: {core_path}/specs/spring-cloud-contract-spec -:contract_kotlin_spec_path: {core_path}/specs/spring-cloud-contract-spec-kotlin -:samples_path: {core_path}/samples -:verifier_core_path: {verifier_root_path} -:stubrunner_core_path: {core_path}/spring-cloud-contract-stub-runner -:standalone_samples_path: {samples_path}/standalone/dsl -:standalone_messaging_samples_path: {samples_path}/standalone/dsl -:standalone_restdocs_path: {samples_path}/standalone/restdocs -:tests_path: {core_path}/tests -:samples_branch: main -:samples_url: https://raw.githubusercontent.com/spring-cloud-samples/spring-cloud-contract-samples/{samples_branch} -:samples_code: https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/{samples_branch} -:doc_samples: {samples_code}/wiremock-for-contract-docs -:doc_samples_url: {samples_url}/wiremock-for-contract-docs -:wiremock_tests: {core_path}/spring-cloud-contract-wiremock -:introduction_url: {core_path} diff --git a/docs/modules/ROOT/pages/_building.adoc b/docs/modules/ROOT/pages/_building.adoc deleted file mode 100644 index ced98ca14e..0000000000 --- a/docs/modules/ROOT/pages/_building.adoc +++ /dev/null @@ -1,145 +0,0 @@ -[[how-to-build-spring-cloud-contract]] -= How to Build Spring Cloud Contract - -[[cloning-the-repository-on-windows]] -== Cloning the repository on Windows - -While cloning this project on Windows, some files in the git repository may exceed the Windows maximum file path limit of 255 characters, which may -result in an incorrectly (probably partially) checked out repository. - -To resolve this issue, you can set the `core.longPaths` attribute to `true` or clone the Spring Cloud Contract repository. - -To set the `core.longPaths` attribute to `true`, you have three options: - -- Change it for all users of the machine (doing so requires administrator privileges): - - -[source,bash] ----- -git config --system core.longPaths true -git clone https://github.com/spring-cloud/spring-cloud-contract.git ----- - -- Change it for the current user (no administrative privileges required): - -[source,bash] ----- -git config --global core.longPaths true -git clone https://github.com/spring-cloud/spring-cloud-contract.git ----- - -- Change for just this repository (administrative privileges depend on where the repository is being cloned to): - -[source,bash] ----- -git clone -c core.longPaths=true https://github.com/spring-cloud/spring-cloud-contract.git ----- - -IMPORTANT: You need to have all the necessary Groovy plugins -installed for your IDE to properly resolve the sources. For example, in -Intellij IDEA, having both the Eclipse Groovy Compiler Plugin and the GMavenPlus Intellij -Plugin results in properly imported project. - -IMPORTANT: Spring Cloud Contract builds Docker images. Remember to -have Docker installed. - -IMPORTANT: If you want to run the build in offline mode, you must have Maven 3.5.2+ installed. - -[[project-structure]] -== Project structure - -The following listing shows the Spring Cloud Contract folder structure: - -``` -├── config -├── docker -├── samples -├── scripts -├── specs -├── spring-cloud-contract-dependencies -├── spring-cloud-contract-shade -├── spring-cloud-contract-starters -├── spring-cloud-contract-stub-runner -├── spring-cloud-contract-stub-runner-boot -├── spring-cloud-contract-tools -├── spring-cloud-contract-verifier -├── spring-cloud-contract-wiremock -└── tests -``` - -The following list describes each of the top-level folders in the project structure: - -- `config`: Folder contains setup for Spring Cloud Release Tools automated release process -- `docker`: Folder contains docker images -- `samples`: Folder contains test samples together with standalone ones used also to build documentation -- `scripts`: Contains scripts to build and test `Spring Cloud Contract` with Maven, Gradle and standalone projects -- `specs`: Contains specifications for the Contract DSL. -- `spring-cloud-contract-dependencies`: Contains Spring Cloud Contract BOM -- `spring-cloud-contract-shade`: Shaded dependencies used by the plugins -- `spring-cloud-contract-starters`: Contains Spring Cloud Contract Starters -- `spring-cloud-contract-spec`: Contains specification modules (contains concept of a Contract) -- `spring-cloud-contract-stub-runner`: Contains Stub Runner related modules -- `spring-cloud-contract-stub-runner-boot`: Contains Stub Runner Boot app -- `spring-cloud-contract-tools`: Gradle and Maven plugin for `Spring Cloud Contract Verifier` -- `spring-cloud-contract-verifier`: Core of the `Spring Cloud Contract Verifier` functionality -- `spring-cloud-contract-wiremock`: All WireMock related functionality -- `tests`: Integration tests for different messaging technologies - -[[commands]] -== Commands - -To build the core functionality together with the Maven Plugin, you can run the following -command: - -``` -./mvnw clean install -P integration -``` - -Calling that function builds the core, the Maven plugin, and the Gradle plugin and runs -end-to_end tests on the -standalone samples in the proper order (both for Maven and Gradle). - -To build only the Gradle Plugin, you can run the following commands: - -``` -cd spring-cloud-contract-tools/spring-cloud-contract-gradle-plugin -./gradlew clean build -``` - -[[helpful-scripts]] -== Helpful scripts - -We provide a couple of helpful scripts to build the project. - -To build the project in parallel (by default, it uses four cores, but you can change it), -run the following command: - -``` -./scripts/parallelBuild.sh -``` - -To use eight 8 cores, run the following command: - -``` -CORES=8 ./scripts/parallelBuild.sh -``` - -To build the project without any integration tests (by default, this uses one core), run -the following command: - -``` -./scripts/noIntegration.sh -``` - -To use eight cores, run the following command: - -``` -CORES=8 ./scripts/noIntegration.sh -``` - -To generate the documentation (for both the root project and the maven plugin), run the -following command: - -``` -./scripts/generateDocs.sh -``` diff --git a/docs/modules/ROOT/pages/_configprops.adoc b/docs/modules/ROOT/pages/_configprops.adoc deleted file mode 100644 index 444298319f..0000000000 --- a/docs/modules/ROOT/pages/_configprops.adoc +++ /dev/null @@ -1,47 +0,0 @@ -|=== -|Name | Default | Description - -|stubrunner.amqp.enabled | `+++false+++` | Whether to enable support for Stub Runner and AMQP. -|stubrunner.amqp.mockCOnnection | `+++true+++` | Whether to enable support for Stub Runner and AMQP mocked connection factory. -|stubrunner.classifier | `+++stubs+++` | The classifier to use by default in ivy co-ordinates for a stub. -|stubrunner.cloud.consul.enabled | `+++true+++` | Whether to enable stubs registration in Consul. -|stubrunner.cloud.delegate.enabled | `+++true+++` | Whether to enable DiscoveryClient's Stub Runner implementation. -|stubrunner.cloud.enabled | `+++true+++` | Whether to enable Spring Cloud support for Stub Runner. -|stubrunner.cloud.eureka.enabled | `+++true+++` | Whether to enable stubs registration in Eureka. -|stubrunner.cloud.loadbalancer.enabled | `+++true+++` | Whether to enable Stub Runner's Spring Cloud Load Balancer integration. -|stubrunner.cloud.stubbed.discovery.enabled | `+++true+++` | Whether Service Discovery should be stubbed for Stub Runner. If set to false, stubs will get registered in real service discovery. -|stubrunner.cloud.zookeeper.enabled | `+++true+++` | Whether to enable stubs registration in Zookeeper. -|stubrunner.consumer-name | | You can override the default {@code spring.application.name} of this field by setting a value to this parameter. -|stubrunner.delete-stubs-after-test | `+++true+++` | If set to {@code false} will NOT delete stubs from a temporary folder after running tests. -|stubrunner.fail-on-no-stubs | `+++true+++` | When enabled, this flag will tell stub runner to throw an exception when no stubs / contracts were found. -|stubrunner.generate-stubs | `+++false+++` | When enabled, this flag will tell stub runner to not load the generated stubs, but convert the found contracts at runtime to a stub format and run those stubs. -|stubrunner.http-server-stub-configurer | | Configuration for an HTTP server stub. -|stubrunner.ids | `+++[]+++` | The ids of the stubs to run in "ivy" notation ([groupId]:artifactId:[version]:[classifier][:port]). {@code groupId}, {@code classifier}, {@code version} and {@code port} can be optional. -|stubrunner.ids-to-service-ids | | Mapping of Ivy notation based ids to serviceIds inside your application. Example "a:b" -> "myService" "artifactId" -> "myOtherService" -|stubrunner.integration.enabled | `+++true+++` | Whether to enable Stub Runner integration with Spring Integration. -|stubrunner.jms.enabled | `+++true+++` | Whether to enable Stub Runner integration with Spring JMS. -|stubrunner.kafka.enabled | `+++true+++` | Whether to enable Stub Runner integration with Spring Kafka. -|stubrunner.kafka.initializer.enabled | `+++true+++` | Whether to allow Stub Runner to take care of polling for messages instead of the KafkaStubMessages component. The latter should be used only on the producer side. -|stubrunner.mappings-output-folder | | Dumps the mappings of each HTTP server to the selected folder. -|stubrunner.max-port | `+++15000+++` | Max value of a port for the automatically started WireMock server. -|stubrunner.min-port | `+++10000+++` | Min value of a port for the automatically started WireMock server. -|stubrunner.password | | Repository password. -|stubrunner.properties | | Map of properties that can be passed to custom {@link org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder}. -|stubrunner.proxy-host | | Repository proxy host. -|stubrunner.proxy-port | | Repository proxy port. -|stubrunner.server-id | | -|stubrunner.stream.enabled | `+++true+++` | Whether to enable Stub Runner integration with Spring Cloud Stream. -|stubrunner.stubs-mode | | Pick where the stubs should come from. -|stubrunner.stubs-per-consumer | `+++false+++` | Should only stubs for this particular consumer get registered in HTTP server stub. -|stubrunner.username | | Repository username. -|wiremock.placeholders.enabled | `+++true+++` | Flag to indicate that http URLs in generated wiremock stubs should be filtered to add or resolve a placeholder for a dynamic port. -|wiremock.reset-mappings-after-each-test | `+++false+++` | -|wiremock.rest-template-ssl-enabled | `+++false+++` | -|wiremock.server.files | `+++[]+++` | -|wiremock.server.https-port | `+++-1+++` | -|wiremock.server.https-port-dynamic | `+++false+++` | -|wiremock.server.port | `+++8080+++` | -|wiremock.server.port-dynamic | `+++false+++` | -|wiremock.server.stubs | `+++[]+++` | - -|=== diff --git a/docs/modules/ROOT/pages/_index.adoc b/docs/modules/ROOT/pages/_index.adoc deleted file mode 100644 index b2a57fca62..0000000000 --- a/docs/modules/ROOT/pages/_index.adoc +++ /dev/null @@ -1,18 +0,0 @@ -[[spring-cloud-contract-reference-documentation]] -= Spring Cloud Contract Reference Documentation -:page-section-summary-toc: 1 -Adam Dudczak, Mathias DÃŧsterhÃļft, Marcin Grzejszczak, Dennis Kieselhorst, Jakub Kubryński, Karol Lassak, Olga Maciaszek-Sharma, Mariusz Smykuła, Dave Syer, Jay Bryant - -:docinfo: shared - -The reference documentation consists of the following sections: - -[horizontal] -<> :: Legal information. -<> :: About the Documentation, Getting Help, First Steps, and more. -xref:getting-started.adoc[Getting Started] :: Introducing {project-full-name}, Developing Your First {project-full-name}-based Application -xref:using.adoc[Using {project-full-name}] :: {project-full-name} usage examples and workflows. -xref:project-features.adoc[{project-full-name} Features] :: Contract DSL, Messaging, Spring Cloud Contract Stub Runner, and Spring Cloud Contract WireMock. -xref:project-features.adoc#features-build-tools[Build Tools] :: Maven Plugin, Gradle Plugin, and Docker. -xref:howto.adoc["`How-to`" Guides] :: Stubs versioning, Debugging, and more. -<> :: Properties, Metadata, Configuration, Dependencies, and more. diff --git a/docs/modules/ROOT/pages/_index_pdf.adoc b/docs/modules/ROOT/pages/_index_pdf.adoc deleted file mode 100644 index 07072dfaa3..0000000000 --- a/docs/modules/ROOT/pages/_index_pdf.adoc +++ /dev/null @@ -1,6 +0,0 @@ -[[spring-cloud-contract-reference-documentation]] -= Spring Cloud Contract Reference Documentation -:page-section-summary-toc: 1 -Adam Dudczak, Mathias DÃŧsterhÃļft, Marcin Grzejszczak, Dennis Kieselhorst, Jakub Kubryński, Karol Lassak, Olga Maciaszek-Sharma, Mariusz Smykuła, Dave Syer, Jay Bryant - - diff --git a/docs/modules/ROOT/pages/_index_single.adoc b/docs/modules/ROOT/pages/_index_single.adoc deleted file mode 100644 index 332ec80b0b..0000000000 --- a/docs/modules/ROOT/pages/_index_single.adoc +++ /dev/null @@ -1,7 +0,0 @@ -[[spring-cloud-contract-reference-documentation]] -= Spring Cloud Contract Reference Documentation -:page-section-summary-toc: 1 -Adam Dudczak, Mathias DÃŧsterhÃļft, Marcin Grzejszczak, Dennis Kieselhorst, Jakub Kubryński, Karol Lassak, Olga Maciaszek-Sharma, Mariusz Smykuła, Dave Syer, Jay Bryant - -:docinfo: shared - diff --git a/docs/modules/ROOT/pages/_project-features-contract.adoc b/docs/modules/ROOT/pages/_project-features-contract.adoc deleted file mode 100644 index e5dbd42061..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract.adoc +++ /dev/null @@ -1,50 +0,0 @@ -[[contract-dsl]] -= Contract DSL - - -Spring Cloud Contract supports DSLs written in the following languages: - -* Groovy -* YAML -* Java -* Kotlin - -TIP: Spring Cloud Contract supports defining multiple contracts in a single file (In Groovy return a list instead of a single contract). - -The following example shows a contract definition: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy[tags=dsl_example,indent=0] ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -include::{verifier_core_path}/src/test/resources/yml/contract_rest.yml[indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include::{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest.java[tags=class,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include::{verifier_core_path}/src/test/resources/kotlin/contract_rest.kts[tags=class,indent=0] ----- -==== - -[TIP] -==== -You can compile contracts to stubs mapping by using the following standalone Maven command: - ----- -mvn org.springframework.cloud:spring-cloud-contract-maven-plugin:convert ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-contract/common-top-elements.adoc b/docs/modules/ROOT/pages/_project-features-contract/common-top-elements.adoc deleted file mode 100644 index dcf8fc1b48..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/common-top-elements.adoc +++ /dev/null @@ -1,305 +0,0 @@ -[[contract-common-top-elements]] -= Common Top-Level Elements - -The following sections describe the most common top-level elements: - -* xref:_project-features-contract/common-top-elements.adoc#contract-dsl-description[Description] -* xref:_project-features-contract/common-top-elements.adoc#contract-dsl-name[Name] -* xref:_project-features-contract/common-top-elements.adoc#contract-dsl-ignoring-contracts[Ignoring Contracts] -* xref:_project-features-contract/common-top-elements.adoc#contract-dsl-in-progress[Contracts in Progress] -* xref:_project-features-contract/common-top-elements.adoc#contract-dsl-passing-values-from-files[Passing Values from Files] -* xref:_project-features-contract/common-top-elements.adoc#contract-dsl-metadata[Metadata] - -[[contract-dsl-description]] -== Description - -You can add a `description` to your contract. The description is arbitrary text. The -following code shows an example: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{contract_spec_tests_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=description,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract_rest.yml[indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_with_tags.java[tags=description,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{contract_kotlin_spec_path}/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt[tags=description,indent=0] ----- -==== - -[[contract-dsl-name]] -== Name - -You can provide a name for your contract. Assume that you provide the following name: -`should register a user`. If you do so, the name of the autogenerated test is -`validate_should_register_a_user`. Also, the name of the stub in a WireMock stub is -`should_register_a_user.json`. - -IMPORTANT: You must ensure that the name does not contain any characters that make the -generated test not compile. Also, remember that, if you provide the same name for -multiple contracts, your autogenerated tests fail to compile and your generated stubs -override each other. - -The following example shows how to add a name to a contract: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{contract_spec_tests_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=name,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=name,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_with_tags.java[tags=name,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{contract_kotlin_spec_path}/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt[tags=name,indent=0] ----- -==== - -[[contract-dsl-ignoring-contracts]] -== Ignoring Contracts - -If you want to ignore a contract, you can either set a value for ignored contracts in the -plugin configuration or set the `ignored` property on the contract itself. The following -example shows how to do so: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{contract_spec_tests_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=ignored,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=ignored,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_with_tags.java[tags=ignored,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{contract_kotlin_spec_path}/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt[tags=ignored,indent=0] ----- -==== - -[[contract-dsl-in-progress]] -== Contracts in Progress - -A contract in progress does not generate tests on the producer side but does allow generation of stubs. - -IMPORTANT: Use this feature with caution as it may lead to false positives, because you generate stubs for your consumers to use without actually having the implementation in place. - -If you want to set a contract in progress, the following -example shows how to do so: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{contract_spec_tests_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=in_progress,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=in_progress,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_with_tags.java[tags=in_progress,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{contract_kotlin_spec_path}/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt[tags=in_progress,indent=0] ----- -==== - -You can set the value of the `failOnInProgress` Spring Cloud Contract plugin property to ensure that your build breaks when at least one contract in progress remains in your sources. - -[[contract-dsl-passing-values-from-files]] -== Passing Values from Files - -Starting with version `1.2.0`, you can pass values from files. Assume that you have the -following resources in your project: - -[source,bash,indent=0] ----- -└── src -    └── test -       └── resources -          └── contracts -    ├── readFromFile.groovy -    ├── request.json -    └── response.json ----- - -Further assume that your contract is as follows: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/resources/classpath/readFromFile.groovy[indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract_from_file.yml[indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_from_file.java[tags=class,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/readFromFile.kts[tags=class,indent=0] ----- -==== - -Further assume that the JSON files are as follows: - -==== -[source,json,indent=0,subs="verbatim,attributes",role="primary"] -.request.json ----- -include:../:{verifier_core_path}/src/test/resources/classpath/request.json[indent=0] ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.response.json ----- -include:../:{verifier_core_path}/src/test/resources/classpath/response.json[indent=0] ----- -==== - -When test or stub generation takes place, the contents of the `request.json` and `response.json` files are passed to the body -of a request or a response. The name of the file needs to be a file in a location -relative to the folder in which the contract resides. - -If you need to pass the contents of a file in binary form, -you can use the `fileAsBytes` method in the coded DSL or a `bodyFromFileAsBytes` field in YAML. - -The following example shows how to pass the contents of binary files: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/resources/body_builder/worksWithPdf.groovy[indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract_pdf.yml[indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_from_pdf.java[tags=class,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{contract_kotlin_spec_path}/src/test/resources/contracts/shouldWorkWithBinaryPayload.kts[tags=class,indent=0] ----- -==== - -IMPORTANT: You should use this approach whenever you want to work with binary payloads, -both for HTTP and messaging. - -[[contract-dsl-metadata]] -== Metadata - -You can add `metadata` to your contract. Via the metadata you can pass in configuration to extensions. Below you can find -an example of using the `wiremock` key. Its value is a map whose key is `stubMapping` and value being WireMock's `StubMapping` object. Spring Cloud Contract is able to -patch parts of your generated stub mapping with your custom code. You may want to do that in order to add webhooks, custom -delays or integrate with third party WireMock extensions. - -==== -[source,groovy,indent=0,role="primary"] -.groovy ----- -include:../:{standalone_samples_path}/http-server/src/test/resources/contracts/fraud/shouldReturnFraudStats.groovy[tags=metadata,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.yml ----- -include:../:{standalone_samples_path}/http-server/src/test/resources/contracts/yml/fraud/shouldReturnFraudStats.yml[tags=metadata,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_rest_with_tags.java[tags=metadata,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.kotlin ----- -include:../:{contract_kotlin_spec_path}/src/test/kotlin/org/springframework/cloud/contract/spec/ContractTests.kt[tags=metadata,indent=0] ----- -==== - -In the following sections you can find examples of the supported metadata entries. - -//// -include:../:{project-root}/docs/target/metadata.adoc[indent=0] -//// - -[[features-http]] -= Contracts for HTTP - -Spring Cloud Contract lets you verify applications that use REST or HTTP as a -means of communication. Spring Cloud Contract verifies that, for a request that matches the -criteria from the `request` part of the contract, the server provides a response that is in -keeping with the `response` part of the contract. Subsequently, the contracts are used to -generate WireMock stubs that, for any request matching the provided criteria, provide a -suitable response. - diff --git a/docs/modules/ROOT/pages/_project-features-contract/dsl-async.adoc b/docs/modules/ROOT/pages/_project-features-contract/dsl-async.adoc deleted file mode 100644 index c1763f0314..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/dsl-async.adoc +++ /dev/null @@ -1,134 +0,0 @@ -[[contract-dsl-async]] -= Asynchronous Support - -If you use asynchronous communication on the server side (your controllers are -returning `Callable`, `DeferredResult`, and so on), then, inside your contract, you must -provide an `async()` method in the `response` section. The following code shows an example: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -org.springframework.cloud.contract.spec.Contract.make { - request { - method GET() - url '/get' - } - response { - status OK() - body 'Passed' - async() - } -} ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -response: - async: true ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -class contract implements Supplier> { - - @Override - public Collection get() { - return Collections.singletonList(Contract.make(c -> { - c.request(r -> { - // ... - }); - c.response(r -> { - r.async(); - // ... - }); - })); - } - -} ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract - -contract { - request { - // ... - } - response { - async = true - // ... - } -} ----- -==== - -You can also use the `fixedDelayMilliseconds` method or property to add delay to your stubs. -The following example shows how to do so: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -org.springframework.cloud.contract.spec.Contract.make { - request { - method GET() - url '/get' - } - response { - status 200 - body 'Passed' - fixedDelayMilliseconds 1000 - } -} ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -response: - fixedDelayMilliseconds: 1000 ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -class contract implements Supplier> { - - @Override - public Collection get() { - return Collections.singletonList(Contract.make(c -> { - c.request(r -> { - // ... - }); - c.response(r -> { - r.fixedDelayMilliseconds(1000); - // ... - }); - })); - } - -} ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract - -contract { - request { - // ... - } - response { - delay = fixedMilliseconds(1000) - // ... - } -} ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-contract/dsl-dynamic-properties.adoc b/docs/modules/ROOT/pages/_project-features-contract/dsl-dynamic-properties.adoc deleted file mode 100644 index 0a38b44f02..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/dsl-dynamic-properties.adoc +++ /dev/null @@ -1,797 +0,0 @@ -[[contract-dsl-dynamic-properties]] -= Dynamic properties - -The contract can contain some dynamic properties: timestamps, IDs, and so on. You do not -want to force the consumers to stub their clocks to always return the same value of time -so that it gets matched by the stub. - -For the Groovy DSL, you can provide the dynamic parts in your contracts -in two ways: pass them directly in the body or set them in a separate section called -`bodyMatchers`. - -NOTE: Before 2.0.0, these were set by using `testMatchers` and `stubMatchers`. -See the https://github.com/spring-cloud/spring-cloud-contract/wiki/Spring-Cloud-Contract-2.0-Migration-Guide[migration guide] for more information. - -For YAML, you can use only the `matchers` section. - -IMPORTANT: Entries inside the `matchers` must reference existing elements of the payload. For more information, see https://github.com/spring-cloud/spring-cloud-contract/issues/722[this issue]. - -[[contract-dsl-dynamic-properties-in-body]] -== Dynamic Properties inside the Body - -IMPORTANT: This section is valid only for the Coded DSL (Groovy, Java, and so on). See the -xref:_project-features-contract/dsl-dynamic-properties.adoc#contract-dsl-matchers[Dynamic Properties in the Matchers Sections] section for YAML examples of a similar feature. - -You can set the properties inside the body either with the `value` method or, if you use -the Groovy map notation, with `$()`. The following example shows how to set dynamic -properties with the value method: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.value ----- -value(consumer(...), producer(...)) -value(c(...), p(...)) -value(stub(...), test(...)) -value(client(...), server(...)) ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.$ ----- -$(consumer(...), producer(...)) -$(c(...), p(...)) -$(stub(...), test(...)) -$(client(...), server(...)) ----- -==== - -Both approaches work equally well. The `stub` and `client` methods are aliases over the `consumer` -method. Subsequent sections take a closer look at what you can do with those values. - -[[contract-dsl-regex]] -== Regular Expressions - -IMPORTANT: This section is valid only for the Groovy DSL. See the -xref:_project-features-contract/dsl-dynamic-properties.adoc#contract-dsl-matchers[Dynamic Properties in the Matchers Sections] section for YAML examples of a similar feature. - -You can use regular expressions to write your requests in the contract DSL. Doing so is -particularly useful when you want to indicate that a given response should be provided -for requests that follow a given pattern. Also, you can use regular expressions when you -need to use patterns and not exact values both for your tests and your server-side tests. - -Make sure that regex matches a whole region of a sequence, as, internally, -https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher.html#matches[`Pattern.matches()`] -is called. For instance, `abc` does not match `aabc`, but `.abc` does. -There are several additional xref:_project-features-contract/dsl-dynamic-properties.adoc#contract-dsl-regex-limitations[known limitations] as well. - -The following example shows how to use regular expressions to write a request: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=regex,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=regex,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=regex,indent=0] ----- -==== - -You can also provide only one side of the communication with a regular expression. If you -do so, then the contract engine automatically provides the generated string that matches -the provided regular expression. The following code shows an example for Groovy: - -[source,groovy,indent=0] ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy[tags=dsl_one_side_data_generation_example,indent=0] ----- - -In the preceding example, the opposite side of the communication has the respective data -generated for request and response. - -Spring Cloud Contract comes with a series of predefined regular expressions that you can -use in your contracts, as the following example shows: - -[source,java,indent=0] ----- -include:../:{contract_spec_path}/src/main/java/org/springframework/cloud/contract/spec/internal/RegexPatterns.java[tags=regexps,indent=0] ----- - -In your contract, you can use it as follows (example for the Groovy DSL): - -[source,groovy,indent=0] ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy[tags=contract_with_regex,indent=0] ----- - -To make matters even simpler, you can use a set of predefined objects that automatically -assume that you want a regular expression to be passed. -All of those methods start with the `any` prefix, as follows: - -[source,java,indent=0] ----- -include:../:{contract_spec_path}/src/main/java/org/springframework/cloud/contract/spec/internal/RegexCreatingProperty.java[tags=regex_creating_props,indent=0] ----- - -The following example shows how you can reference those methods: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=regex_creating_props,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=regex_creating_props,indent=0] ----- -==== - -[[contract-dsl-regex-limitations]] -=== Limitations - -CAUTION: Due to certain limitations of the `Xeger` library that generates a string out of -a regex, do not use the `$` and `^` signs in your regex if you rely on automatic -generation. See https://github.com/spring-cloud/spring-cloud-contract/issues/899[Issue 899]. - -CAUTION: Do not use a `LocalDate` instance as a value for `$` (for example, `$(consumer(LocalDate.now()))`). -It causes a `java.lang.StackOverflowError`. Use `$(consumer(LocalDate.now().toString()))` instead. -See https://github.com/spring-cloud/spring-cloud-contract/issues/900[Issue 900]. - -[[contract-dsl-optional-params]] -== Passing Optional Parameters - -IMPORTANT: This section is valid only for Groovy DSL. See the -xref:_project-features-contract/dsl-dynamic-properties.adoc#contract-dsl-matchers[Dynamic Properties in the Matchers Sections] section for YAML examples of a similar feature. - -You can provide optional parameters in your contract. However, you can provide -optional parameters only for the following: - -* The STUB side of the Request -* The TEST side of the Response - -The following example shows how to provide optional parameters: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=optionals,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=optionals,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=optionals,indent=0] ----- -==== - -By wrapping a part of the body with the `optional()` method, you create a regular -expression that must be present 0 or more times. - -If you use Spock, the following test would be generated from the previous example: - -==== -[source,groovy,indent=0] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=optionals_test,indent=0] ----- -==== - -The following stub would also be generated: - -[source,groovy,indent=0] ----- -include:../:{plugins_path}/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy[tags=wiremock,indent=0] ----- - -[[contract-dsl-custom-methods]] -== Calling Custom Methods on the Server Side - -IMPORTANT: This section is valid only for the Groovy DSL. See the -xref:_project-features-contract/dsl-dynamic-properties.adoc#contract-dsl-matchers[Dynamic Properties in the Matchers Sections] section for YAML examples of a similar feature. - -You can define a method call that runs on the server side during the test. Such a -method can be added to the class defined as `baseClassForTests` in the configuration. The -following code shows an example of the contract portion of the test case: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=method,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=method,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=method,indent=0] ----- -==== - -The following code shows the base class portion of the test case: - -[source,groovy,indent=0] ----- -include:../:{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/bootSimple/src/test/groovy/org/springframework/cloud/contract/verifier/twitter/places/BaseMockMvcSpec.groovy[tags=base_class,indent=0] ----- - -IMPORTANT: You cannot use both a `String` and `execute` to perform concatenation. For -example, calling `header('Authorization', 'Bearer ' + execute('authToken()'))` leads to -improper results. Instead, call `header('Authorization', execute('authToken()'))` and -ensure that the `authToken()` method returns everything you need. - -The type of the object read from the JSON can be one of the following, depending on the -JSON path: - -* `String`: If you point to a `String` value in the JSON. -* `JSONArray`: If you point to a `List` in the JSON. -* `Map`: If you point to a `Map` in the JSON. -* `Number`: If you point to `Integer`, `Double`, and other numeric type in the JSON. -* `Boolean`: If you point to a `Boolean` in the JSON. - -In the request part of the contract, you can specify that the `body` should be taken from -a method. - -IMPORTANT: You must provide both the consumer and the producer side. The `execute` part -is applied for the whole body, not for parts of it. - -The following example shows how to read an object from JSON: - -[source,groovy,indent=0] ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy[tags=body_execute,indent=0] ----- - -The preceding example results in calling the `hashCode()` method in the request body. -It should resemble the following code: - -[source,java,indent=0] ----- - // given: - MockMvcRequestSpecification request = given() - .body(hashCode()); - - // when: - ResponseOptions response = given().spec(request) - .get("/something"); - - // then: - assertThat(response.statusCode()).isEqualTo(200); ----- - -[[contract-dsl-referencing-request-from-response]] -== Referencing the Request from the Response - -The best situation is to provide fixed values, but sometimes you need to reference a -request in your response. - -If you write contracts in the Groovy DSL, you can use the `fromRequest()` method, which lets -you reference a bunch of elements from the HTTP request. You can use the following -options: - -* `fromRequest().url()`: Returns the request URL and query parameters. -* `fromRequest().query(String key)`: Returns the first query parameter with the given name. -* `fromRequest().query(String key, int index)`: Returns the nth query parameter with the -given name. -* `fromRequest().path()`: Returns the full path. -* `fromRequest().path(int index)`: Returns the nth path element. -* `fromRequest().header(String key)`: Returns the first header with the given name. -* `fromRequest().header(String key, int index)`: Returns the nth header with the given name. -* `fromRequest().body()`: Returns the full request body. -* `fromRequest().body(String jsonPath)`: Returns the element from the request that -matches the JSON Path. - -If you use the YAML contract definition or the Java one, you have to use the -https://handlebarsjs.com/[Handlebars] `{{{ }}}` notation with custom Spring Cloud Contract -functions to achieve this. In that case, you can use the following options: - -* `{{{ request.url }}}`: Returns the request URL and query parameters. -* `{{{ request.query.key.[index] }}}`: Returns the nth query parameter with the given name. -For example, for a key of `thing`, the first entry is `{{{ request.query.thing.[0] }}}` -* `{{{ request.path }}}`: Returns the full path. -* `{{{ request.path.[index] }}}`: Returns the nth path element. For example, -the first entry is ```{{{ request.path.[0] }}} -* `{{{ request.headers.key }}}`: Returns the first header with the given name. -* `{{{ request.headers.key.[index] }}}`: Returns the nth header with the given name. -* `{{{ request.body }}}`: Returns the full request body. -* `{{{ jsonpath this 'your.json.path' }}}`: Returns the element from the request that -matches the JSON Path. For example, for a JSON path of `$.here`, use `{{{ jsonpath this '$.here' }}}` - -Consider the following contract: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy[tags=template_contract,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract_reference_request.yml[indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -package contracts.beer.rest; - -import java.util.function.Supplier; - -import org.springframework.cloud.contract.spec.Contract; - -import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.map; - -class shouldReturnStatsForAUser implements Supplier { - - @Override - public Contract get() { - return Contract.make(c -> { - c.request(r -> { - r.method("POST"); - r.url("/stats"); - r.body(map().entry("name", r.anyAlphaUnicode())); - r.headers(h -> { - h.contentType(h.applicationJson()); - }); - }); - c.response(r -> { - r.status(r.OK()); - r.body(map() - .entry("text", - "Dear {{{jsonPath request.body '$.name'}}} thanks for your interested in drinking beer") - .entry("quantity", r.$(r.c(5), r.p(r.anyNumber())))); - r.headers(h -> { - h.contentType(h.applicationJson()); - }); - }); - }); - } - -} ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -package contracts.beer.rest - -import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract - -contract { - request { - method = method("POST") - url = url("/stats") - body(mapOf( - "name" to anyAlphaUnicode - )) - headers { - contentType = APPLICATION_JSON - } - } - response { - status = OK - body(mapOf( - "text" to "Don't worry ${fromRequest().body("$.name")} thanks for your interested in drinking beer", - "quantity" to v(c(5), p(anyNumber)) - )) - headers { - contentType = fromRequest().header(CONTENT_TYPE) - } - } -} ----- -==== - -Running a JUnit test generation leads to a test that resembles the following example: - -==== -[source,java,indent=0] ----- - // given: - MockMvcRequestSpecification request = given() - .header("Authorization", "secret") - .header("Authorization", "secret2") - .body("{\"foo\":\"bar\",\"baz\":5}"); - - // when: - ResponseOptions response = given().spec(request) - .queryParam("foo","bar") - .queryParam("foo","bar2") - .get("/api/v1/xxxx"); - - // then: - assertThat(response.statusCode()).isEqualTo(200); - assertThat(response.header("Authorization")).isEqualTo("foo secret bar"); - // and: - DocumentContext parsedJson = JsonPath.parse(response.getBody().asString()); - assertThatJson(parsedJson).field("['fullBody']").isEqualTo("{\"foo\":\"bar\",\"baz\":5}"); - assertThatJson(parsedJson).field("['authorization']").isEqualTo("secret"); - assertThatJson(parsedJson).field("['authorization2']").isEqualTo("secret2"); - assertThatJson(parsedJson).field("['path']").isEqualTo("/api/v1/xxxx"); - assertThatJson(parsedJson).field("['param']").isEqualTo("bar"); - assertThatJson(parsedJson).field("['paramIndex']").isEqualTo("bar2"); - assertThatJson(parsedJson).field("['pathIndex']").isEqualTo("v1"); - assertThatJson(parsedJson).field("['responseBaz']").isEqualTo(5); - assertThatJson(parsedJson).field("['responseFoo']").isEqualTo("bar"); - assertThatJson(parsedJson).field("['url']").isEqualTo("/api/v1/xxxx?foo=bar&foo=bar2"); - assertThatJson(parsedJson).field("['responseBaz2']").isEqualTo("Bla bla bar bla bla"); ----- -==== - -As you can see, elements from the request have been properly referenced in the response. - -The generated WireMock stub should resemble the following example: - -==== -[source,json,indent=0] ----- -{ - "request" : { - "urlPath" : "/api/v1/xxxx", - "method" : "POST", - "headers" : { - "Authorization" : { - "equalTo" : "secret2" - } - }, - "queryParameters" : { - "foo" : { - "equalTo" : "bar2" - } - }, - "bodyPatterns" : [ { - "matchesJsonPath" : "$[?(@.['baz'] == 5)]" - }, { - "matchesJsonPath" : "$[?(@.['foo'] == 'bar')]" - } ] - }, - "response" : { - "status" : 200, - "body" : "{\"authorization\":\"{{{request.headers.Authorization.[0]}}}\",\"path\":\"{{{request.path}}}\",\"responseBaz\":{{{jsonpath this '$.baz'}}} ,\"param\":\"{{{request.query.foo.[0]}}}\",\"pathIndex\":\"{{{request.path.[1]}}}\",\"responseBaz2\":\"Bla bla {{{jsonpath this '$.foo'}}} bla bla\",\"responseFoo\":\"{{{jsonpath this '$.foo'}}}\",\"authorization2\":\"{{{request.headers.Authorization.[1]}}}\",\"fullBody\":\"{{{escapejsonbody}}}\",\"url\":\"{{{request.url}}}\",\"paramIndex\":\"{{{request.query.foo.[1]}}}\"}", - "headers" : { - "Authorization" : "{{{request.headers.Authorization.[0]}}};foo" - }, - "transformers" : [ "response-template" ] - } -} ----- -==== - -Sending a request such as the one presented in the `request` part of the contract results -in sending the following response body: - -==== -[source,json,indent=0] ----- -{ - "url" : "/api/v1/xxxx?foo=bar&foo=bar2", - "path" : "/api/v1/xxxx", - "pathIndex" : "v1", - "param" : "bar", - "paramIndex" : "bar2", - "authorization" : "secret", - "authorization2" : "secret2", - "fullBody" : "{\"foo\":\"bar\",\"baz\":5}", - "responseFoo" : "bar", - "responseBaz" : 5, - "responseBaz2" : "Bla bla bar bla bla" -} ----- -==== - -IMPORTANT: This feature works only with WireMock versions greater than or equal -to 2.5.1. The Spring Cloud Contract Verifier uses WireMock's -`response-template` response transformer. It uses Handlebars to convert the Mustache `{{{ }}}` templates into -proper values. Additionally, it registers two helper functions: - -* `escapejsonbody`: Escapes the request body in a format that can be embedded in JSON. -* `jsonpath`: For a given parameter, finds an object in the request body. - -[[contract-dsl-matchers]] -== Dynamic Properties in the Matchers Sections - -If you work with https://docs.pact.io/[Pact], the following discussion may seem familiar. -Quite a few users are used to having a separation between the body and setting the -dynamic parts of a contract. - -You can use the `bodyMatchers` section for two reasons: - -* Define the dynamic values that should end up in a stub. -You can set it in the `request` part of your contract. -* Verify the result of your test. -This section is present in the `response` or `outputMessage` side of the -contract. - -Currently, Spring Cloud Contract Verifier supports only JSON path-based matchers with the -following matching possibilities: - -[[coded-dsl]] -=== Coded DSL - -For the stubs (in tests on the consumer's side): - -* `byEquality()`: The value taken from the consumer's request in the provided JSON path must be -equal to the value provided in the contract. -* `byRegex(...)`: The value taken from the consumer's request in the provided JSON path must -match the regex. You can also pass the type of the expected matched value (for example, `asString()`, `asLong()`, and so on). -* `byDate()`: The value taken from the consumer's request in the provided JSON path must -match the regex for an ISO Date value. -* `byTimestamp()`: The value taken from the consumer's request in the provided JSON path must -match the regex for an ISO DateTime value. -* `byTime()`: The value taken from the consumer's request in the provided JSON path must -match the regex for an ISO Time value. - -For the verification (in generated tests on the Producer's side): - -* `byEquality()`: The value taken from the producer's response in the provided JSON path must be -equal to the provided value in the contract. -* `byRegex(...)`: The value taken from the producer's response in the provided JSON path must -match the regex. -* `byDate()`: The value taken from the producer's response in the provided JSON path must match -the regex for an ISO Date value. -* `byTimestamp()`: The value taken from the producer's response in the provided JSON path must -match the regex for an ISO DateTime value. -* `byTime()`: The value taken from the producer's response in the provided JSON path must match -the regex for an ISO Time value. -* `byType()`: The value taken from the producer's response in the provided JSON path needs to be -of the same type as the type defined in the body of the response in the contract. -`byType` can take a closure, in which you can set `minOccurrence` and `maxOccurrence`. For the -request side, you should use the closure to assert size of the collection. -That way, you can assert the size of the flattened collection. To check the size of an -unflattened collection, use a custom method with the `byCommand(...)` `testMatcher`. -* `byCommand(...)`: The value taken from the producer's response in the provided JSON path is -passed as an input to the custom method that you provide. For example, -`byCommand('thing($it)')` results in calling a `thing` method to which the value matching the -JSON Path gets passed. The type of the object read from the JSON can be one of the -following, depending on the JSON path: -** `String`: If you point to a `String` value. -** `JSONArray`: If you point to a `List`. -** `Map`: If you point to a `Map`. -** `Number`: If you point to `Integer`, `Double`, or another kind of number. -** `Boolean`: If you point to a `Boolean`. -* `byNull()`: The value taken from the response in the provided JSON path must be null. - -[[yaml]] -=== YAML - -NOTE: See the Groovy section for a detailed explanation of -what the types mean. - -For YAML, the structure of a matcher resembles the following example: - -[source,yml,indent=0] ----- -- path: $.thing1 - type: by_regex - value: thing2 - regexType: as_string ----- - -Alternatively, if you want to use one of the predefined regular expressions -`[only_alpha_unicode, number, any_boolean, ip_address, hostname, -email, url, uuid, iso_date, iso_date_time, iso_time, iso_8601_with_offset, non_empty, -non_blank]`, you can use something similar to the following example: - -[source,yml,indent=0] ----- -- path: $.thing1 - type: by_regex - predefined: only_alpha_unicode ----- - -The following list shows the allowed list of `type` values: - -* For `stubMatchers`: -** `by_equality` -** `by_regex` -** `by_date` -** `by_timestamp` -** `by_time` -** `by_type` -*** Two additional fields (`minOccurrence` and `maxOccurrence`) are accepted. -* For `testMatchers`: -** `by_equality` -** `by_regex` -** `by_date` -** `by_timestamp` -** `by_time` -** `by_type` -*** Two additional fields (`minOccurrence` and `maxOccurrence`) are accepted. -** `by_command` -** `by_null` - -You can also define which type the regular expression corresponds to in the `regexType` -field. The following list shows the allowed regular expression types: - -* `as_integer` -* `as_double` -* `as_float` -* `as_long` -* `as_short` -* `as_boolean` -* `as_string` - -Consider the following example: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy[tags=matchers,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract_matchers.yml[indent=0] ----- -==== - -In the preceding example, you can see the dynamic portions of the contract in the -`matchers` sections. For the request part, you can see that, for all fields but -`valueWithoutAMatcher`, the values of the regular expressions that the stub should -contain are explicitly set. For `valueWithoutAMatcher`, the verification takes place -in the same way as without the use of matchers. In that case, the test performs an -equality check. - -For the response side in the `bodyMatchers` section, we define the dynamic parts in a -similar manner. The only difference is that the `byType` matchers are also present. The -verifier engine checks four fields to verify whether the response from the test -has a value for which the JSON path matches the given field, is of the same type as the one -defined in the response body, and passes the following check (based on the method being called): - -* For `$.valueWithTypeMatch`, the engine checks whether the type is the same. -* For `$.valueWithMin`, the engine checks the type and asserts whether the size is greater -than or equal to the minimum occurrence. -* For `$.valueWithMax`, the engine checks the type and asserts whether the size is -smaller than or equal to the maximum occurrence. -* For `$.valueWithMinMax`, the engine checks the type and asserts whether the size is -between the minimum and maximum occurrence. - -The resulting test resembles the following example (note that an `and` section -separates the autogenerated assertions and the assertion from matchers): - -[source,java,indent=0] ----- - // given: - MockMvcRequestSpecification request = given() - .header("Content-Type", "application/json") - .body("{\"duck\":123,\"alpha\":\"abc\",\"number\":123,\"aBoolean\":true,\"date\":\"2017-01-01\",\"dateTime\":\"2017-01-01T01:23:45\",\"time\":\"01:02:34\",\"valueWithoutAMatcher\":\"foo\",\"valueWithTypeMatch\":\"string\",\"key\":{\"complex.key\":\"foo\"}}"); - - // when: - ResponseOptions response = given().spec(request) - .get("/get"); - - // then: - assertThat(response.statusCode()).isEqualTo(200); - assertThat(response.header("Content-Type")).matches("application/json.*"); - // and: - DocumentContext parsedJson = JsonPath.parse(response.getBody().asString()); - assertThatJson(parsedJson).field("['valueWithoutAMatcher']").isEqualTo("foo"); - // and: - assertThat(parsedJson.read("$.duck", String.class)).matches("[0-9]{3}"); - assertThat(parsedJson.read("$.duck", Integer.class)).isEqualTo(123); - assertThat(parsedJson.read("$.alpha", String.class)).matches("[\\p{L}]*"); - assertThat(parsedJson.read("$.alpha", String.class)).isEqualTo("abc"); - assertThat(parsedJson.read("$.number", String.class)).matches("-?(\\d*\\.\\d+|\\d+)"); - assertThat(parsedJson.read("$.aBoolean", String.class)).matches("(true|false)"); - assertThat(parsedJson.read("$.date", String.class)).matches("(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])"); - assertThat(parsedJson.read("$.dateTime", String.class)).matches("([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])"); - assertThat(parsedJson.read("$.time", String.class)).matches("(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])"); - assertThat((Object) parsedJson.read("$.valueWithTypeMatch")).isInstanceOf(java.lang.String.class); - assertThat((Object) parsedJson.read("$.valueWithMin")).isInstanceOf(java.util.List.class); - assertThat((java.lang.Iterable) parsedJson.read("$.valueWithMin", java.util.Collection.class)).as("$.valueWithMin").hasSizeGreaterThanOrEqualTo(1); - assertThat((Object) parsedJson.read("$.valueWithMax")).isInstanceOf(java.util.List.class); - assertThat((java.lang.Iterable) parsedJson.read("$.valueWithMax", java.util.Collection.class)).as("$.valueWithMax").hasSizeLessThanOrEqualTo(3); - assertThat((Object) parsedJson.read("$.valueWithMinMax")).isInstanceOf(java.util.List.class); - assertThat((java.lang.Iterable) parsedJson.read("$.valueWithMinMax", java.util.Collection.class)).as("$.valueWithMinMax").hasSizeBetween(1, 3); - assertThat((Object) parsedJson.read("$.valueWithMinEmpty")).isInstanceOf(java.util.List.class); - assertThat((java.lang.Iterable) parsedJson.read("$.valueWithMinEmpty", java.util.Collection.class)).as("$.valueWithMinEmpty").hasSizeGreaterThanOrEqualTo(0); - assertThat((Object) parsedJson.read("$.valueWithMaxEmpty")).isInstanceOf(java.util.List.class); - assertThat((java.lang.Iterable) parsedJson.read("$.valueWithMaxEmpty", java.util.Collection.class)).as("$.valueWithMaxEmpty").hasSizeLessThanOrEqualTo(0); - assertThatValueIsANumber(parsedJson.read("$.duck")); - assertThat(parsedJson.read("$.['key'].['complex.key']", String.class)).isEqualTo("foo"); ----- - -IMPORTANT: Notice that, for the `byCommand` method, the example calls the -`assertThatValueIsANumber`. This method must be defined in the test base class or be -statically imported to your tests. Notice that the `byCommand` call was converted to -`assertThatValueIsANumber(parsedJson.read("$.duck"));`. That means that the engine took -the method name and passed the proper JSON path as a parameter to it. - -The resulting WireMock stub is in the following example: - -[source,json,indent=0] ----- -include:../:{plugins_path}/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy[tags=matchers,indent=0] ----- - -IMPORTANT: If you use a `matcher`, the part of the request and response that the -`matcher` addresses with the JSON Path gets removed from the assertion. In the case of -verifying a collection, you must create matchers for *all* the elements of the -collection. - -Consider the following example: - -==== -[source,groovy,indent=0] ----- -Contract.make { - request { - method 'GET' - url("/foo") - } - response { - status OK() - body(events: [[ - operation : 'EXPORT', - eventId : '16f1ed75-0bcc-4f0d-a04d-3121798faf99', - status : 'OK' - ], [ - operation : 'INPUT_PROCESSING', - eventId : '3bb4ac82-6652-462f-b6d1-75e424a0024a', - status : 'OK' - ] - ] - ) - bodyMatchers { - jsonPath('$.events[0].operation', byRegex('.+')) - jsonPath('$.events[0].eventId', byRegex('^([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})$')) - jsonPath('$.events[0].status', byRegex('.+')) - } - } -} ----- -==== - -The preceding code leads to creating the following test (the code block shows only the assertion section): - -==== -[source,java,indent=0] ----- - and: - DocumentContext parsedJson = JsonPath.parse(response.body.asString()) - assertThatJson(parsedJson).array("['events']").contains("['eventId']").isEqualTo("16f1ed75-0bcc-4f0d-a04d-3121798faf99") - assertThatJson(parsedJson).array("['events']").contains("['operation']").isEqualTo("EXPORT") - assertThatJson(parsedJson).array("['events']").contains("['operation']").isEqualTo("INPUT_PROCESSING") - assertThatJson(parsedJson).array("['events']").contains("['eventId']").isEqualTo("3bb4ac82-6652-462f-b6d1-75e424a0024a") - assertThatJson(parsedJson).array("['events']").contains("['status']").isEqualTo("OK") - and: - assertThat(parsedJson.read("\$.events[0].operation", String.class)).matches(".+") - assertThat(parsedJson.read("\$.events[0].eventId", String.class)).matches("^([a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12})\$") - assertThat(parsedJson.read("\$.events[0].status", String.class)).matches(".+") ----- -==== - -Note that the assertion is malformed. Only the first element of the array got -asserted. To fix this, apply the assertion to the whole `$.events` -collection and assert it with the `byCommand(...)` method. - diff --git a/docs/modules/ROOT/pages/_project-features-contract/dsl-http-top-level-elements.adoc b/docs/modules/ROOT/pages/_project-features-contract/dsl-http-top-level-elements.adoc deleted file mode 100644 index 557f079f78..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/dsl-http-top-level-elements.adoc +++ /dev/null @@ -1,45 +0,0 @@ -[[contract-dsl-http-top-level-elements]] -= HTTP Top-Level Elements - -You can call the following methods in the top-level closure of a contract definition: - -* `request`: Mandatory -* `response` : Mandatory -* `priority`: Optional - -The following example shows how to define an HTTP request contract: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=http_dsl,indent=0] ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=priority,indent=0] -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request,indent=0] -... -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=response,indent=0] -... ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=http_dsl,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=http_dsl,indent=0] ----- -==== - -IMPORTANT: If you want to make your contract have a higher priority, -you need to pass a lower number to the `priority` tag or method. For example, a `priority` with -a value of `5` has higher priority than a `priority` with a value of `10`. - diff --git a/docs/modules/ROOT/pages/_project-features-contract/dsl-multiple.adoc b/docs/modules/ROOT/pages/_project-features-contract/dsl-multiple.adoc deleted file mode 100644 index e3d3f70ce2..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/dsl-multiple.adoc +++ /dev/null @@ -1,134 +0,0 @@ -[[contract-dsl-multiple]] -= Multiple Contracts in One File - -You can define multiple contracts in one file. Such a contract might resemble the -following example: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{plugins_path}/spring-cloud-contract-maven-plugin/src/test/projects/multiple-contracts/src/test/resources/contracts/com/hello/v1/WithList.groovy[lines=18..-1,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/multiple_contracts.yml[indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -class contract implements Supplier> { - - @Override - public Collection get() { - return Arrays.asList( - Contract.make(c -> { - c.name("should post a user"); - // ... - }), Contract.make(c -> { - // ... - }), Contract.make(c -> { - // ... - }) - ); - } - -} ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract - -arrayOf( - contract { - name("should post a user") - // ... - }, - contract { - // ... - }, - contract { - // ... - } -} ----- -==== - -In the preceding example, one contract has the `name` field and the other does not. This -leads to generation of two tests that look like the following: - -==== -[source,java,indent=0] ----- -package org.springframework.cloud.contract.verifier.tests.com.hello; - -import com.example.TestBase; -import com.jayway.jsonpath.DocumentContext; -import com.jayway.jsonpath.JsonPath; -import com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification; -import com.jayway.restassured.response.ResponseOptions; -import org.junit.Test; - -import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*; -import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; -import static org.assertj.core.api.Assertions.assertThat; - -public class V1Test extends TestBase { - - @Test - public void validate_should_post_a_user() throws Exception { - // given: - MockMvcRequestSpecification request = given(); - - // when: - ResponseOptions response = given().spec(request) - .post("/users/1"); - - // then: - assertThat(response.statusCode()).isEqualTo(200); - } - - @Test - public void validate_withList_1() throws Exception { - // given: - MockMvcRequestSpecification request = given(); - - // when: - ResponseOptions response = given().spec(request) - .post("/users/2"); - - // then: - assertThat(response.statusCode()).isEqualTo(200); - } - -} ----- -==== - -Notice that, for the contract that has the `name` field, the generated test method is named -`validate_should_post_a_user`. The one that does not have the `name` field is called -`validate_withList_1`. It corresponds to the name of the file `WithList.groovy` and the -index of the contract in the list. - -The generated stubs are shown in the following example: - -==== -[source] ----- -should post a user.json -1_WithList.json ----- -==== - -The first file got the `name` parameter from the contract. The second -got the name of the contract file (`WithList.groovy`) prefixed with the index (in this -case, the contract had an index of `1` in the list of contracts in the file). - -TIP: It is much better to name your contracts, because doing so makes -your tests far more meaningful. - diff --git a/docs/modules/ROOT/pages/_project-features-contract/dsl-request.adoc b/docs/modules/ROOT/pages/_project-features-contract/dsl-request.adoc deleted file mode 100644 index 906600ca8b..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/dsl-request.adoc +++ /dev/null @@ -1,271 +0,0 @@ -[[contract-dsl-request]] -= HTTP Request - -The HTTP protocol requires only the method and the URL to be specified in a request. The -same information is mandatory in request definition of the contract. - -The following example shows a contract for a request: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=request,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request_obligatory,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=request,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=request,indent=0] ----- -==== - -You can specify an absolute rather than a relative `url`, but using `urlPath` is -the recommended way, as doing so makes the tests be host-independent. - -The following example uses `url`: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=url,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract_rest_with_path.yml[tags=url_path,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=url,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=url,indent=0] ----- -==== - -`request` may contain query parameters, as the following example (which uses `urlPath`) shows: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=urlpath,indent=0] ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request,indent=0] -... -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=query_params,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=urlpath,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=urlpath,indent=0] ----- -==== - -`request` can contain additional request headers, as the following example shows: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=headers,indent=0] ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request,indent=0] -... -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=headers,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=headers,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=headers,indent=0] ----- -==== - -`request` may contain additional request cookies, as the following example shows: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=cookies,indent=0] ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request,indent=0] -... -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=cookies,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=cookies,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=cookies,indent=0] ----- -==== - -`request` may contain a request body, as the following example shows: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=body,indent=0] ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=request,indent=0] -... -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=body,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=body,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=body,indent=0] ----- -==== - -`request` can contain multipart elements. To include multipart elements, use the -`multipart` method/section, as the following examples show: - -==== -[source,groovy,indent=0,role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy[tags=multipartdsl,indent=0] ----- - -[source,yaml,indent=0,role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract_multipart.yml[indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_multipart.java[tags=class,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/multipart.kts[tags=class,indent=0] ----- -==== - -In the preceding example, we defined parameters in either of two ways: - -.Coded DSL -* Directly, by using the map notation, where the value can be a dynamic property (such as -`formParameter: $(consumer(...), producer(...))`). -* By using the `named(...)` method that lets you set a named parameter. A named parameter -can set a `name` and `content`. You can call it either by using a method with two arguments, -such as `named("fileName", "fileContent")`, or by using a map notation, such as -`named(name: "fileName", content: "fileContent")`. - -.YAML -* The multipart parameters are set in the `multipart.params` section. -* The named parameters (the `fileName` and `fileContent` for a given parameter name) -can be set in the `multipart.named` section. That section contains -the `paramName` (the name of the parameter), `fileName` (the name of the file), -`fileContent` (the content of the file) fields. -* The dynamic bits can be set in the `matchers.multipart` section. -** For parameters, use the `params` section, which can accept -`regex` or a `predefined` regular expression. -** For named parameters, use the `named` section where you first -define the parameter name with `paramName`. Then you can pass the -parametrization of either `fileName` or `fileContent` in a -`regex` or in a `predefined` regular expression. - -IMPORTANT: For the `named(...)` section you always have to add a pair of -`value(producer(...), consumer(...))` calls. Just setting DSL properties such -as just `value(producer(...))` or just `file(...)` will not work. -Check this https://github.com/spring-cloud/spring-cloud-contract/issues/1886[issue] for more information. - -From the contract in the preceding example, the generated test and stub look as follows: - -==== -[source,java,indent=0,subs="verbatim,attributes",role="primary"] -.Test ----- -// given: - MockMvcRequestSpecification request = given() - .header("Content-Type", "multipart/form-data;boundary=AaB03x") - .param("formParameter", "\"formParameterValue\"") - .param("someBooleanParameter", "true") - .multiPart("file", "filename.csv", "file content".getBytes()); - - // when: - ResponseOptions response = given().spec(request) - .put("/multipart"); - - // then: - assertThat(response.statusCode()).isEqualTo(200); ----- - -[source,json,indent=0,subs="verbatim,attributes",role="secondary"] -.Stub ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/WireMockGroovyDslSpec.groovy[tags=multipartwiremock,indent=0] ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-contract/dsl-response.adoc b/docs/modules/ROOT/pages/_project-features-contract/dsl-response.adoc deleted file mode 100644 index e656e4e802..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/dsl-response.adoc +++ /dev/null @@ -1,41 +0,0 @@ -[[contract-dsl-response]] -= HTTP Response - -The response must contain an HTTP status code and may contain other information. The -following code shows an example: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=response,indent=0] ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=response,indent=0] -... -include:../:{verifier_core_path}/src/test/resources/yml/contract.yml[tags=response_obligatory,indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_docs_examples.java[tags=response,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_docs_examples.kts[tags=response,indent=0] ----- -==== - -Besides status, the response may contain headers, cookies, and a body, which are -specified the same way as in the request (see xref:_project-features-contract/dsl-request.adoc[HTTP Request]). - -TIP: In the Groovy DSL, you can reference the `org.springframework.cloud.contract.spec.internal.HttpStatus` -methods to provide a meaningful status instead of a digit. For example, you can call -`OK()` for a status `200` or `BAD_REQUEST()` for `400`. - diff --git a/docs/modules/ROOT/pages/_project-features-contract/dsl-xml.adoc b/docs/modules/ROOT/pages/_project-features-contract/dsl-xml.adoc deleted file mode 100644 index 4d8166088c..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/dsl-xml.adoc +++ /dev/null @@ -1,121 +0,0 @@ -[[contract-dsl-xml]] -= XML Support for HTTP - -For HTTP contracts, we also support using XML in the request and response body. -The XML body has to be passed within the `body` element -as a `String` or `GString`. Also, body matchers can be provided for -both the request and the response. In place of the `jsonPath(...)` method, the `org.springframework.cloud.contract.spec.internal.BodyMatchers.xPath` -method should be used, with the desired `xPath` provided as the first argument -and the appropriate `MatchingType` as the second argument. All the body matchers apart from `byType()` are supported. - -The following example shows a Groovy DSL contract with XML in the response body: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/XmlMethodBodyBuilderSpec.groovy[tags=xmlgroovy] ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -include:../:{verifier_core_path}/src/test/resources/yml/contract_rest_xml.yml[indent=0] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Java ----- -include:../:{verifier_core_path}/src/test/resources/contractsToCompile/contract_xml.java[tags=class,indent=0] ----- - -[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"] -.Kotlin ----- -include:../:{verifier_core_path}/src/test/resources/kotlin/contract_xml.kts[tags=class,indent=0] ----- -==== - -The following example shows an automatically generated test for XML in the response body: - -==== -[source,java,indent=0] ----- -@Test -public void validate_xmlMatches() throws Exception { - // given: - MockMvcRequestSpecification request = given() - .header("Content-Type", "application/xml"); - - // when: - ResponseOptions response = given().spec(request).get("/get"); - - // then: - assertThat(response.statusCode()).isEqualTo(200); - // and: - DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance() - .newDocumentBuilder(); - Document parsedXml = documentBuilder.parse(new InputSource( - new StringReader(response.getBody().asString()))); - // and: - assertThat(valueFromXPath(parsedXml, "/test/list/elem/text()")).isEqualTo("abc"); - assertThat(valueFromXPath(parsedXml,"/test/list/elem[2]/text()")).isEqualTo("def"); - assertThat(valueFromXPath(parsedXml, "/test/duck/text()")).matches("[0-9]{3}"); - assertThat(nodeFromXPath(parsedXml, "/test/duck/xxx")).isNull(); - assertThat(valueFromXPath(parsedXml, "/test/alpha/text()")).matches("[\\p{L}]*"); - assertThat(valueFromXPath(parsedXml, "/test/*/complex/text()")).isEqualTo("foo"); - assertThat(valueFromXPath(parsedXml, "/test/duck/@type")).isEqualTo("xtype"); - } ----- -==== - -[[xml-support-for-namespaces]] -== XML Support for Namespaces -Namespaced XML is supported. However, any XPath expresssions used to select namespaced content must be updated. - -Consider the following explicitly namespaced XML document: - -[source,xml,indent=0] ----- - - customer@test.com - ----- -The XPath expression to select the email address is: `/ns1:customer/email/text()`. - -WARNING: Beware as the unqualified expression (`/customer/email/text()`) results in `""`. - -For content that uses an unqualified namespace, the expression is more verbose. Consider the following XML document that -uses an unqualified namespace: - -[source,xml,indent=0] ----- - - customer@test.com - ----- -The XPath expression to select the email address is -``` -*/[local-name()='customer' and namespace-uri()='http://demo.com/customer']/*[local-name()='email']/text() -``` -WARNING: Beware, as the unqualified expressions (`/customer/email/text()` or `*/[local-name()='customer' and namespace-uri()='http://demo.com/customer']/email/text()`) -result in `""`. Even the child elements have to be referenced with the `local-name` syntax. - -[[general-namespaced-node-expression-syntax]] -=== General Namespaced Node Expression Syntax -- Node using qualified namespace: -``` -/ -``` -- Node using and defining an unqualified namespace: -``` -/*[local-name=()='' and namespace-uri=()=''] -``` -NOTE: In some cases, you can omit the `namespace_uri` portion, but doing so may lead to ambiguity. - -- Node using an unqualified namespace (one of its ancestor's defines the xmlns attribute): -``` -/*[local-name=()=''] -``` - - diff --git a/docs/modules/ROOT/pages/_project-features-contract/groovy.adoc b/docs/modules/ROOT/pages/_project-features-contract/groovy.adoc deleted file mode 100644 index 640b9a8f97..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/groovy.adoc +++ /dev/null @@ -1,18 +0,0 @@ -[[contract-groovy]] -= Contract DSL in Groovy -:page-section-summary-toc: 1 - -If you are not familiar with Groovy, do not worry. You can use Java syntax in the -Groovy DSL files as well. - -If you decide to write the contract in Groovy, do not be alarmed if you have not used Groovy -before. Knowledge of the language is not really needed, as the Contract DSL uses only a -tiny subset of it (only literals, method calls, and closures). Also, the DSL is statically -typed, to make it programmer-readable without any knowledge of the DSL itself. - -IMPORTANT: Remember that, inside the Groovy contract file, you have to provide the fully -qualified name to the `Contract` class and `make` static imports, such as -`org.springframework.cloud.spec.Contract.make { ... }`. You can also provide an import to -the `Contract` class (`import org.springframework.cloud.spec.Contract`) and then call -`Contract.make { ... }`. - diff --git a/docs/modules/ROOT/pages/_project-features-contract/java.adoc b/docs/modules/ROOT/pages/_project-features-contract/java.adoc deleted file mode 100644 index fba47a5c12..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/java.adoc +++ /dev/null @@ -1,33 +0,0 @@ -[[contract-java]] -= Contract DSL in Java - -To write a contract definition in Java, you need to create a class that implements either the `Supplier` interface (for a single contract) or `Supplier>` (for multiple contracts). - -You can also write the contract definitions under `src/test/java` (for example, `src/test/java/contracts`) so that you do not have to modify the classpath of your project. In this case, you have to provide a new location of contract definitions to your Spring Cloud Contract plugin. - -The following example (in both Maven and Gradle) has the contract definitions under `src/test/java`: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - org.springframework.cloud - spring-cloud-contract-maven-plugin - ${spring-cloud-contract.version} - true - - src/test/java/contracts - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -contracts { - contractsDslDir = new File(project.rootDir, "src/test/java/contracts") -} ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-contract/kotlin.adoc b/docs/modules/ROOT/pages/_project-features-contract/kotlin.adoc deleted file mode 100644 index 5621cb7d0e..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/kotlin.adoc +++ /dev/null @@ -1,73 +0,0 @@ -[[contract-kotlin]] -= Contract DSL in Kotlin - -To get started with writing contracts in Kotlin, you need to start with a (newly created) Kotlin Script file (`.kts`). -As with the Java DSL, you can put your contracts in any directory of your choice. -By default, the Maven plugin will look at the `src/test/resources/contracts` directory and Gradle plugin will -look at the `src/contractTest/resources/contracts` directory. - -NOTE: Since 3.0.0, the Gradle plugin will also look at the legacy -directory `src/test/resources/contracts` for migration purposes. When contracts are found in this directory, a warning -will be logged during your build. - -You need to explicitly pass the `spring-cloud-contract-spec-kotlin` dependency to your project plugin setup. -The following example (in both Maven and Gradle) shows how to do so: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - org.springframework.cloud - spring-cloud-contract-maven-plugin - ${spring-cloud-contract.version} - true - - - - - - org.springframework.cloud - spring-cloud-contract-spec-kotlin - ${spring-cloud-contract.version} - - - - - - - - org.springframework.cloud - spring-cloud-contract-spec-kotlin - test - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -buildscript { - repositories { - // ... - } - dependencies { - classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:${scContractVersion}" - } -} - -dependencies { - // ... - - // Remember to add this for the DSL support in the IDE and on the consumer side - testImplementation "org.springframework.cloud:spring-cloud-contract-spec-kotlin" - // Kotlin versions are very particular down to the patch version. The needs to be the same as you have imported for your project. - testImplementation "org.jetbrains.kotlin:kotlin-scripting-compiler-embeddable:" -} ----- -==== - -IMPORTANT: Remember that, inside the Kotlin Script file, you have to provide the fully qualified name to the `ContractDSL` class. -Generally you would use its contract function as follows: `org.springframework.cloud.contract.spec.ContractDsl.contract { ... }`. -You can also provide an import to the `contract` function (`import org.springframework.cloud.contract.spec.ContractDsl.Companion.contract`) and then call `contract { ... }`. - diff --git a/docs/modules/ROOT/pages/_project-features-contract/limitations.adoc b/docs/modules/ROOT/pages/_project-features-contract/limitations.adoc deleted file mode 100644 index 0191619c34..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/limitations.adoc +++ /dev/null @@ -1,13 +0,0 @@ -[[contract-limitations]] -= Limitations -:page-section-summary-toc: 1 - -WARNING: The support for verifying the size of JSON arrays is experimental. If you want -to turn it on, set the value of the following system property to `true`: -`spring.cloud.contract.verifier.assert.size`. By default, this feature is set to `false`. -You can also set the `assertJsonSize` property in the plugin configuration. - -WARNING: Because JSON structure can have any form, it can be impossible to parse it -properly when using the Groovy DSL and the `value(consumer(...), producer(...))` notation in `GString`. That -is why you should use the Groovy Map notation. - diff --git a/docs/modules/ROOT/pages/_project-features-contract/stateful-contracts.adoc b/docs/modules/ROOT/pages/_project-features-contract/stateful-contracts.adoc deleted file mode 100644 index c141a8b00b..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/stateful-contracts.adoc +++ /dev/null @@ -1,38 +0,0 @@ -[[contract-stateful-contracts]] -= Stateful Contracts - -Stateful contracts (also known as scenarios) are contract definitions that should be read -in order. This might be useful in the following situations: - -* You want to invoke the contract in a precisely defined order, since you use Spring -Cloud Contract to test your stateful application. - -TIP: We really discourage you from doing that, since contract tests should be stateless. - -* You want the same endpoint to return different results for the same request. - -To create stateful contracts (or scenarios), you need to -use the proper naming convention while creating your contracts. The convention -requires including an order number followed by an underscore. This works regardless -of whether you work with YAML or Groovy. The following listing shows an example: - -==== -[source,indent=0] ----- -my_contracts_dir\ - scenario1\ - 1_login.groovy - 2_showCart.groovy - 3_logout.groovy ----- -==== - -Such a tree causes Spring Cloud Contract Verifier to generate WireMock's scenario with a -name of `scenario1` and the three following steps: - -. `login`, marked as `Started` pointing to... -. `showCart`, marked as `Step1` pointing to... -. `logout`, marked as `Step2` (which closes the scenario). - -You can find more details about WireMock scenarios at -https://wiremock.org/docs/stateful-behaviour/[https://wiremock.org/docs/stateful-behaviour/]. diff --git a/docs/modules/ROOT/pages/_project-features-contract/yml.adoc b/docs/modules/ROOT/pages/_project-features-contract/yml.adoc deleted file mode 100644 index 3198fc1d10..0000000000 --- a/docs/modules/ROOT/pages/_project-features-contract/yml.adoc +++ /dev/null @@ -1,6 +0,0 @@ -[[contract-yml]] -= Contract DSL in YAML -:page-section-summary-toc: 1 - -To see a schema of a YAML contract, visit the {docs-url}/reference/html/yml-schema.html[YML Schema] page. - diff --git a/docs/modules/ROOT/pages/_project-features-flows.adoc b/docs/modules/ROOT/pages/_project-features-flows.adoc deleted file mode 100644 index 027ad53950..0000000000 --- a/docs/modules/ROOT/pages/_project-features-flows.adoc +++ /dev/null @@ -1,5 +0,0 @@ -[[feature-integrations]] -= Integrations -:page-section-summary-toc: 1 - - diff --git a/docs/modules/ROOT/pages/_project-features-flows/context-paths.adoc b/docs/modules/ROOT/pages/_project-features-flows/context-paths.adoc deleted file mode 100644 index 8f806362d6..0000000000 --- a/docs/modules/ROOT/pages/_project-features-flows/context-paths.adoc +++ /dev/null @@ -1,62 +0,0 @@ -[[features-context-paths]] -= Working with Context Paths - -Spring Cloud Contract supports context paths. - -[IMPORTANT] -===== -The only change needed to fully support context paths is the switch on the -producer side. Also, the autogenerated tests must use explicit mode. The consumer -side remains untouched. In order for the generated test to pass, you must use explicit -mode. The following example shows how to set the test mode to `EXPLICIT`: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - org.springframework.cloud - spring-cloud-contract-maven-plugin - ${spring-cloud-contract.version} - true - - EXPLICIT - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -contracts { - testMode = 'EXPLICIT' -} ----- -==== -===== - -That way, you generate a test that does not use MockMvc. It means that you generate -real requests and you need to set up your generated test's base class to work on a real -socket. - -Consider the following contract: - -[source,groovy,indent=0] ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy[tags=context_path_contract,indent=0] ----- - -The following example shows how to set up a base class and RestAssured: - -[source,groovy,indent=0] ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy[tags=context_path_baseclass,indent=0] ----- - -If you do it this way: - -* All of your requests in the autogenerated tests are sent to the real endpoint with your -context path included (for example, `/my-context-path/url`). -* Your contracts reflect that you have a context path. Your generated stubs also have -that information (for example, in the stubs, you have to call `/my-context-path/url`). - diff --git a/docs/modules/ROOT/pages/_project-features-flows/custom-mode.adoc b/docs/modules/ROOT/pages/_project-features-flows/custom-mode.adoc deleted file mode 100644 index 5258dd6741..0000000000 --- a/docs/modules/ROOT/pages/_project-features-flows/custom-mode.adoc +++ /dev/null @@ -1,104 +0,0 @@ -[[features-custom-mode]] -= Custom Mode - -IMPORTANT: This mode is experimental and can change in the future. - -The Spring Cloud Contract lets you provide your own, custom, implementation of the -`org.springframework.cloud.contract.verifier.http.HttpVerifier`. That way, you can use any client you want to send and receive a request. The default implementation in Spring Cloud Contract is `OkHttpHttpVerifier` and it uses OkHttp3 http client. - -To get started, set `testMode` to `CUSTOM`: - -==== -[source,groovy,indent=0] ----- -testMode = 'CUSTOM' ----- -==== - -The following example shows a generated test: - -==== -[source,java,indent=0] ----- -package com.example.beer; - -import com.example.BeerRestBase; -import javax.inject.Inject; -import org.springframework.cloud.contract.verifier.http.HttpVerifier; -import org.springframework.cloud.contract.verifier.http.Request; -import org.springframework.cloud.contract.verifier.http.Response; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; -import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; -import static org.springframework.cloud.contract.verifier.http.Request.given; - -@SuppressWarnings("rawtypes") -public class RestTest extends BeerRestBase { - @Inject HttpVerifier httpVerifier; - - @Test - public void validate_shouldGrantABeerIfOldEnough() throws Exception { - // given: - Request request = given() - .post("/beer.BeerService/check") - .scheme("HTTP") - .protocol("h2_prior_knowledge") - .header("Content-Type", "application/grpc") - .header("te", "trailers") - .body(fileToBytes(this, "shouldGrantABeerIfOldEnough_request_PersonToCheck_old_enough.bin")) - .build(); - - - // when: - Response response = httpVerifier.exchange(request); - - - // then: - assertThat(response.statusCode()).isEqualTo(200); - assertThat(response.header("Content-Type")).matches("application/grpc.*"); - assertThat(response.header("grpc-encoding")).isEqualTo("identity"); - assertThat(response.header("grpc-accept-encoding")).isEqualTo("gzip"); - - // and: - assertThat(response.getBody().asByteArray()).isEqualTo(fileToBytes(this, "shouldGrantABeerIfOldEnough_response_Response_old_enough.bin")); - } - -} ----- -==== - -The following example shows a corresponding base class: - -==== -[source,java,indent=0] ----- -@SpringBootTest(classes = BeerRestBase.Config.class, - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public abstract class BeerRestBase { - - @Configuration - @EnableAutoConfiguration - static class Config { - - @Bean - ProducerController producerController(PersonCheckingService personCheckingService) { - return new ProducerController(personCheckingService); - } - - @Bean - PersonCheckingService testPersonCheckingService() { - return argument -> argument.getAge() >= 20; - } - - @Bean - HttpVerifier httpOkVerifier(@LocalServerPort int port) { - return new OkHttpHttpVerifier("localhost:" + port); - } - - } -} ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-flows/feature-webflux-explicit.adoc b/docs/modules/ROOT/pages/_project-features-flows/feature-webflux-explicit.adoc deleted file mode 100644 index d33bf0da45..0000000000 --- a/docs/modules/ROOT/pages/_project-features-flows/feature-webflux-explicit.adoc +++ /dev/null @@ -1,46 +0,0 @@ -[[feature-webflux-explicit]] -= WebFlux with Explicit Mode - -You can also use WebFlux with the explicit mode in your generated tests -to work with WebFlux. The following example shows how to configure using explicit mode: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - org.springframework.cloud - spring-cloud-contract-maven-plugin - ${spring-cloud-contract.version} - true - - EXPLICIT - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -contracts { - testMode = 'EXPLICIT' -} ----- -==== - -The following example shows how to set up a base class and RestAssured for Web Flux: - -==== -[source,groovy,indent=0] ----- -include:../:{samples_url}/producer_webflux/src/test/java/com/example/BeerRestBase.java[tags=annotations,indent=0] - - // your tests go here - - // in this config class you define all controllers and mocked services -include:../:{samples_url}/producer_webflux/src/test/java/com/example/BeerRestBase.java[tags=config,indent=0] - -} ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-flows/feature-webflux.adoc b/docs/modules/ROOT/pages/_project-features-flows/feature-webflux.adoc deleted file mode 100644 index 016113e6d0..0000000000 --- a/docs/modules/ROOT/pages/_project-features-flows/feature-webflux.adoc +++ /dev/null @@ -1,53 +0,0 @@ -[[feature-webflux]] -= WebFlux with WebTestClient - -You can work with WebFlux by using WebTestClient. The following listing shows how to -configure WebTestClient as the test mode: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - org.springframework.cloud - spring-cloud-contract-maven-plugin - ${spring-cloud-contract.version} - true - - WEBTESTCLIENT - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -contracts { - testMode = 'WEBTESTCLIENT' -} ----- -==== - -The following example shows how to set up a WebTestClient base class and RestAssured -for WebFlux: - -==== -[source,groovy,indent=0] ----- -import io.restassured.module.webtestclient.RestAssuredWebTestClient; -import org.junit.Before; - -public abstract class BeerRestBase { - - @Before - public void setup() { - RestAssuredWebTestClient.standaloneSetup( - new ProducerController(personToCheck -> personToCheck.age >= 20)); - } -} -} ----- -==== - -TIP: The `WebTestClient` mode is faster than the `EXPLICIT` mode. - diff --git a/docs/modules/ROOT/pages/_project-features-flows/graphql.adoc b/docs/modules/ROOT/pages/_project-features-flows/graphql.adoc deleted file mode 100644 index f4c67cbca3..0000000000 --- a/docs/modules/ROOT/pages/_project-features-flows/graphql.adoc +++ /dev/null @@ -1,185 +0,0 @@ -[[features-graphql]] -= GraphQL - -Since https://graphql.org/[GraphQL] is essentially HTTP you can write a contract for it by creating a standard HTTP contract with an additional `metadata` entry with key `verifier` and a mapping `tool=graphql`. - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -import org.springframework.cloud.contract.spec.Contract - -Contract.make { - - request { - method(POST()) - url("/graphql") - headers { - contentType("application/json") - } - body(''' -{ - "query":"query queryName($personName: String!) {\\n personToCheck(name: $personName) {\\n name\\n age\\n }\\n}\\n\\n\\n\\n", - "variables":{"personName":"Old Enough"}, - "operationName":"queryName" -} -''') - } - - response { - status(200) - headers { - contentType("application/json") - } - body('''\ -{ - "data": { - "personToCheck": { - "name": "Old Enough", - "age": "40" - } - } -} -''') - } - metadata(verifier: [ - tool: "graphql" - ]) -} ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- ---- -request: - method: "POST" - url: "/graphql" - headers: - Content-Type: "application/json" - body: - query: "query queryName($personName: String!) { personToCheck(name: $personName) - { name age } }" - variables: - personName: "Old Enough" - operationName: "queryName" - matchers: - headers: - - key: "Content-Type" - regex: "application/json.*" - regexType: "as_string" -response: - status: 200 - headers: - Content-Type: "application/json" - body: - data: - personToCheck: - name: "Old Enough" - age: "40" - matchers: - headers: - - key: "Content-Type" - regex: "application/json.*" - regexType: "as_string" -name: "shouldRetrieveOldEnoughPerson" -metadata: - verifier: - tool: "graphql" ----- -==== - -Adding the metadata section will change the way the default, WireMock stub is built. It will now use the Spring Cloud Contract request matcher, so that e.g. the `query` part of the GraphQL request gets compared against the real request by ignoring whitespaces. - -[[features-graphql-producer]] -== Producer Side Setup - -On the producer side your configuration can look as follows. - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - org.springframework.cloud - spring-cloud-contract-maven-plugin - ${spring-cloud-contract.version} - true - - EXPLICIT - com.example.BaseClass - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -contracts { - testMode = "EXPLICIT" - baseClassForTests = "com.example.BaseClass" -} ----- -==== - -The base class would set up the application running on a random port. - -==== -[source,java,indent=0,subs="verbatim,attributes"] -.Base Class ----- -@SpringBootTest(classes = ProducerApplication.class, - properties = "graphql.servlet.websocket.enabled=false", - webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) -public abstract class BaseClass { - - @LocalServerPort int port; - - @BeforeEach - public void setup() { - RestAssured.baseURI = "http://localhost:" + port; - } -} - ----- -==== - -[[features-graphql-consumer]] -== Consumer Side Setup - -Example of a consumer side test of the GraphQL API. - -==== -[source,java,indent=0,subs="verbatim,attributes"] -.Consumer Side Test ----- -@SpringBootTest(webEnvironment = WebEnvironment.NONE) -public class BeerControllerGraphQLTest { - - @RegisterExtension - static StubRunnerExtension rule = new StubRunnerExtension() - .downloadStub("com.example","beer-api-producer-graphql") - .stubsMode(StubRunnerProperties.StubsMode.LOCAL); - - private static final String REQUEST_BODY = "{\n" - + "\"query\":\"query queryName($personName: String!) {\\n personToCheck(name: $personName) {\\n name\\n age\\n }\\n}\"," - + "\"variables\":{\"personName\":\"Old Enough\"},\n" - + "\"operationName\":\"queryName\"\n" - + "}"; - - @Test - public void should_send_a_graphql_request() { - ResponseEntity responseEntity = new RestTemplate() - .exchange(RequestEntity - .post(URI.create("http://localhost:" + rule.findStubUrl("beer-api-producer-graphql").getPort() + "/graphql")) - .contentType(MediaType.APPLICATION_JSON) - .body(REQUEST_BODY), String.class); - - BDDAssertions.then(responseEntity.getStatusCodeValue()).isEqualTo(200); - - } -} - ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-flows/grpc.adoc b/docs/modules/ROOT/pages/_project-features-flows/grpc.adoc deleted file mode 100644 index d8c5d7d75b..0000000000 --- a/docs/modules/ROOT/pages/_project-features-flows/grpc.adoc +++ /dev/null @@ -1,277 +0,0 @@ -[[features-grpc]] -= GRPC - -https://grpc.io/[GRPC] is an RPC framework built on top of HTTP/2 for which Spring Cloud Contract has basic support. - -IMPORTANT: Spring Cloud Contract has an experimental support for basic use cases of GRPC. Unfortunately, due to GRPC's tweaking of the HTTP/2 Header frames, it's impossible to assert the `grpc-status` header. - -Let's look at the following contract. - -==== -[source,groovy,indent=0,subs="verbatim,attributes"] -.Groovy contract ----- -package contracts.beer.rest - - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.verifier.http.ContractVerifierHttpMetaData - -Contract.make { - description(""" -Represents a successful scenario of getting a beer - -``` -given: - client is old enough -when: - he applies for a beer -then: - we'll grant him the beer -``` - -""") - request { - method 'POST' - url '/beer.BeerService/check' - body(fileAsBytes("PersonToCheck_old_enough.bin")) - headers { - contentType("application/grpc") - header("te", "trailers") - } - } - response { - status 200 - body(fileAsBytes("Response_old_enough.bin")) - headers { - contentType("application/grpc") - header("grpc-encoding", "identity") - header("grpc-accept-encoding", "gzip") - } - } - metadata([ - "verifierHttp": [ - "protocol": ContractVerifierHttpMetaData.Protocol.H2_PRIOR_KNOWLEDGE.toString() - ] - ]) -} ----- -==== - -[[features-grpc-producer]] -== Producer Side Setup - -In order to leverage the HTTP/2 support you must set the `CUSTOM` test mode as follow. - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - org.springframework.cloud - spring-cloud-contract-maven-plugin - ${spring-cloud-contract.version} - true - - CUSTOM - com.example - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -contracts { - packageWithBaseClasses = 'com.example' - testMode = "CUSTOM" -} ----- -==== - -The base class would set up the application running on a random port. It will also set the `HttpVerifier` implementation to one that can use the HTTP/2 protocol. Spring Cloud Contract comes with the `OkHttpHttpVerifier` implementation. - -==== -[source,java,indent=0,subs="verbatim,attributes"] -.Base Class ----- -@SpringBootTest(classes = BeerRestBase.Config.class, - webEnvironment = SpringBootTest.WebEnvironment.NONE, - properties = { - "grpc.server.port=0" - }) -public abstract class BeerRestBase { - - @Autowired - GrpcServerProperties properties; - - @Configuration - @EnableAutoConfiguration - static class Config { - - @Bean - ProducerController producerController(PersonCheckingService personCheckingService) { - return new ProducerController(personCheckingService); - } - - @Bean - PersonCheckingService testPersonCheckingService() { - return argument -> argument.getAge() >= 20; - } - - @Bean - HttpVerifier httpOkVerifier(GrpcServerProperties properties) { - return new OkHttpHttpVerifier("localhost:" + properties.getPort()); - } - - } -} ----- -==== - -[[features-grpc-consumer]] -== Consumer Side Setup - -Example of GRPC consumer side test. Due to the unusual behaviour of the GRPC server side, the stub is unable to return the `grpc-status` header in the proper moment. This is why we need to manually set the return status. - -==== -[source,java,indent=0,subs="verbatim,attributes"] -.Consumer Side Test ----- -@SpringBootTest(webEnvironment = WebEnvironment.NONE, classes = GrpcTests.TestConfiguration.class, properties = { - "grpc.client.beerService.address=static://localhost:5432", "grpc.client.beerService.negotiationType=TLS" -}) -public class GrpcTests { - - @GrpcClient(value = "beerService", interceptorNames = "fixedStatusSendingClientInterceptor") - BeerServiceGrpc.BeerServiceBlockingStub beerServiceBlockingStub; - - int port; - - @RegisterExtension - static StubRunnerExtension rule = new StubRunnerExtension() - .downloadStub("com.example", "beer-api-producer-grpc") - // With WireMock PlainText mode you can just set an HTTP port -// .withPort(5432) - .stubsMode(StubRunnerProperties.StubsMode.LOCAL) - .withHttpServerStubConfigurer(MyWireMockConfigurer.class); - - @BeforeEach - public void setupPort() { - this.port = rule.findStubUrl("beer-api-producer-grpc").getPort(); - } - - @Test - public void should_give_me_a_beer_when_im_old_enough() throws Exception { - Response response = beerServiceBlockingStub.check(PersonToCheck.newBuilder().setAge(23).build()); - - BDDAssertions.then(response.getStatus()).isEqualTo(Response.BeerCheckStatus.OK); - } - - @Test - public void should_reject_a_beer_when_im_too_young() throws Exception { - Response response = beerServiceBlockingStub.check(PersonToCheck.newBuilder().setAge(17).build()); - response = response == null ? Response.newBuilder().build() : response; - - BDDAssertions.then(response.getStatus()).isEqualTo(Response.BeerCheckStatus.NOT_OK); - } - - // Not necessary with WireMock PlainText mode - static class MyWireMockConfigurer extends WireMockHttpServerStubConfigurer { - @Override - public WireMockConfiguration configure(WireMockConfiguration httpStubConfiguration, HttpServerStubConfiguration httpServerStubConfiguration) { - return httpStubConfiguration - .httpsPort(5432); - } - } - - @Configuration - @ImportAutoConfiguration(GrpcClientAutoConfiguration.class) - static class TestConfiguration { - - // Not necessary with WireMock PlainText mode - @Bean - public GrpcChannelConfigurer keepAliveClientConfigurer() { - return (channelBuilder, name) -> { - if (channelBuilder instanceof NettyChannelBuilder) { - try { - ((NettyChannelBuilder) channelBuilder) - .sslContext(GrpcSslContexts.forClient() - .trustManager(InsecureTrustManagerFactory.INSTANCE) - .build()); - } - catch (SSLException e) { - throw new IllegalStateException(e); - } - } - }; - } - - /** - * GRPC client interceptor that sets the returned status always to OK. - * You might want to change the return status depending on the received stub payload. - * - * Hopefully in the future this will be unnecessary and will be removed. - */ - @Bean - ClientInterceptor fixedStatusSendingClientInterceptor() { - return new ClientInterceptor() { - @Override - public ClientCall interceptCall(MethodDescriptor method, CallOptions callOptions, Channel next) { - ClientCall call = next.newCall(method, callOptions); - return new ClientCall() { - @Override - public void start(Listener responseListener, Metadata headers) { - Listener listener = new Listener() { - @Override - public void onHeaders(Metadata headers) { - responseListener.onHeaders(headers); - } - - @Override - public void onMessage(RespT message) { - responseListener.onMessage(message); - } - - @Override - public void onClose(Status status, Metadata trailers) { - // TODO: This must be fixed somehow either in Jetty (WireMock) or somewhere else - responseListener.onClose(Status.OK, trailers); - } - - @Override - public void onReady() { - responseListener.onReady(); - } - }; - call.start(listener, headers); - } - - @Override - public void request(int numMessages) { - call.request(numMessages); - } - - @Override - public void cancel(@Nullable String message, @Nullable Throwable cause) { - call.cancel(message, cause); - } - - @Override - public void halfClose() { - call.halfClose(); - } - - @Override - public void sendMessage(ReqT message) { - call.sendMessage(message); - } - }; - } - }; - } - } -} - ----- -==== diff --git a/docs/modules/ROOT/pages/_project-features-flows/jax-rs.adoc b/docs/modules/ROOT/pages/_project-features-flows/jax-rs.adoc deleted file mode 100644 index 9f951c19fb..0000000000 --- a/docs/modules/ROOT/pages/_project-features-flows/jax-rs.adoc +++ /dev/null @@ -1,26 +0,0 @@ -[[features-jax-rs]] -= JAX-RS - -The Spring Cloud Contract supports the JAX-RS 2 Client API. The base class needs -to define `protected WebTarget webTarget` and server initialization. The only option for -testing JAX-RS API is to start a web server. Also, a request with a body needs to have a -content type be set. Otherwise, the default of `application/octet-stream` gets used. - -To use JAX-RS mode, use the following setting: - -==== -[source,groovy,indent=0] ----- -testMode = 'JAXRSCLIENT' ----- -==== - -The following example shows a generated test API: - -==== -[source,groovy,indent=0] ----- -include:../:{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy[tags=jaxrs,indent=0] ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-flows/rest-docs.adoc b/docs/modules/ROOT/pages/_project-features-flows/rest-docs.adoc deleted file mode 100644 index b9b540717a..0000000000 --- a/docs/modules/ROOT/pages/_project-features-flows/rest-docs.adoc +++ /dev/null @@ -1,307 +0,0 @@ -[[features-rest-docs]] -= Working with REST Docs - -You can use https://projects.spring.io/spring-restdocs[Spring REST Docs] to generate -documentation (for example, in Asciidoc format) for an HTTP API with Spring MockMvc, -WebTestClient, or RestAssured. At the same time that you generate documentation for your API, you can also -generate WireMock stubs by using Spring Cloud Contract WireMock. To do so, write your -normal REST Docs test cases and use `@AutoConfigureRestDocs` to have stubs be -automatically generated in the REST Docs output directory. The following UML diagram shows -the REST Docs flow: - -[plantuml, rest-docs, png] ----- -"API Producer"->"API Producer": Add Spring Cloud Contract (SCC) \nStub Runner dependency -"API Producer"->"API Producer": Set up stub jar assembly -"API Producer"->"API Producer": Write and set up REST Docs tests -"API Producer"->"Build": Run build -"Build"->"REST Docs": Generate API \ndocumentation -"REST Docs"->"SCC": Generate stubs from the \nREST Docs tests -"REST Docs"->"SCC": Generate contracts from the \nREST Docs tests -"Build"->"Build": Assemble stubs jar with \nstubs and contracts -"Build"->"Nexus / Artifactory": Upload contracts \nand stubs and the project arifact -"Build"->"API Producer": Build successful -"API Consumer"->"API Consumer": Add SCC Stub Runner \ndependency -"API Consumer"->"API Consumer": Write a SCC Stub Runner \nbased contract test -"SCC Stub Runner"->"Nexus / Artifactory": Test asks for [API Producer] stubs -"Nexus / Artifactory"->"SCC Stub Runner": Fetch the [API Producer] stubs -"SCC Stub Runner"->"SCC Stub Runner": Run in memory\n HTTP server stubs -"API Consumer"->"SCC Stub Runner": Send a request \nto the HTTP server stub -"SCC Stub Runner"->"API Consumer": Communication is correct ----- - -The following example uses `MockMvc`: - -==== -[source,java,indent=0] ----- -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureRestDocs(outputDir = "target/snippets") -@AutoConfigureMockMvc -public class ApplicationTests { - - @Autowired - private MockMvc mockMvc; - - @Test - public void contextLoads() throws Exception { - mockMvc.perform(get("/resource")) - .andExpect(content().string("Hello World")) - .andDo(document("resource")); - } -} ----- -==== - -This test generates a WireMock stub at `target/snippets/stubs/resource.json`. It matches -all `GET` requests to the `/resource` path. The same example with WebTestClient (used -for testing Spring WebFlux applications) would be as follows: - -==== -[source,java,indent=0] ----- -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureRestDocs(outputDir = "target/snippets") -@AutoConfigureWebTestClient -public class ApplicationTests { - - @Autowired - private WebTestClient client; - - @Test - public void contextLoads() throws Exception { - client.get().uri("/resource").exchange() - .expectBody(String.class).isEqualTo("Hello World") - .consumeWith(document("resource")); - } -} ----- -==== - -Without any additional configuration, these tests create a stub with a request matcher -for the HTTP method and all headers except `host` and `content-length`. To match the -request more precisely (for example, to match the body of a POST or PUT), we need to -explicitly create a request matcher. Doing so has two effects: - -* Creating a stub that matches only in the way you specify. -* Asserting that the request in the test case also matches the same conditions. - -The main entry point for this feature is `WireMockRestDocs.verify()`, which can be used -as a substitute for the `document()` convenience method, as the following -example shows: - -==== -[source,java,indent=0] ----- -import static org.springframework.cloud.contract.wiremock.restdocs.WireMockRestDocs.verify; - -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureRestDocs(outputDir = "target/snippets") -@AutoConfigureMockMvc -public class ApplicationTests { - - @Autowired - private MockMvc mockMvc; - - @Test - public void contextLoads() throws Exception { - mockMvc.perform(post("/resource") - .content("{\"id\":\"123456\",\"message\":\"Hello World\"}")) - .andExpect(status().isOk()) - .andDo(verify().jsonPath("$.id")) - .andDo(document("resource")); - } -} ----- -==== - -The preceding contract specifies that any valid POST with an `id` field receives the response -defined in this test. You can chain together calls to `.jsonPath()` to add additional -matchers. If JSON Path is unfamiliar, the https://github.com/jayway/JsonPath[JayWay -documentation] can help you get up to speed. The WebTestClient version of this test -has a similar `verify()` static helper that you insert in the same place. - -Instead of the `jsonPath` and `contentType` convenience methods, you can also use the -WireMock APIs to verify that the request matches the created stub, as the -following example shows: - -==== -[source,java,indent=0] ----- - @Test - public void contextLoads() throws Exception { - mockMvc.perform(post("/resource") - .content("{\"id\":\"123456\",\"message\":\"Hello World\"}")) - .andExpect(status().isOk()) - .andDo(verify() - .wiremock(WireMock.post(urlPathEquals("/resource")) - .withRequestBody(matchingJsonPath("$.id")) - .andDo(document("post-resource")))); - } ----- -==== - -The WireMock API is rich. You can match headers, query parameters, and the request body by -regex as well as by JSON path. You can use these features to create stubs with a wider -range of parameters. The preceding example generates a stub resembling the following example: - -==== -.post-resource.json -[source,json] ----- -{ - "request" : { - "url" : "/resource", - "method" : "POST", - "bodyPatterns" : [ { - "matchesJsonPath" : "$.id" - }] - }, - "response" : { - "status" : 200, - "body" : "Hello World", - "headers" : { - "X-Application-Context" : "application:-1", - "Content-Type" : "text/plain" - } - } -} ----- -==== - -NOTE: You can use either the `wiremock()` method or the `jsonPath()` and `contentType()` -methods to create request matchers, but you cannot use both approaches. - -On the consumer side, you can make the `resource.json` generated earlier in this section -available on the classpath (by -xref:_project-features-stubrunner/stub-runner-publishing-stubs-as-jars.adoc[Publishing Stubs as JARs], for example). After that, you can create a stub that uses WireMock in a -number of different ways, including by using -`@AutoConfigureWireMock(stubs="classpath:resource.json")`, as described earlier in this -document. - -[[features-rest-docs-contracts]] -== Generating Contracts with REST Docs - -You can also generate Spring Cloud Contract DSL files and documentation with Spring REST -Docs. If you do so in combination with Spring Cloud WireMock, you get both the contracts -and the stubs. - -Why would you want to use this feature? Some people in the community asked questions -about a situation in which they would like to move to DSL-based contract definition, -but they already have a lot of Spring MVC tests. Using this feature lets you generate -the contract files that you can later modify and move to folders (defined in your -configuration) so that the plugin finds them. - -NOTE: You might wonder why this functionality is in the WireMock module. The functionality -is there because it makes sense to generate both the contracts and the stubs. - -Consider the following test: - -==== -[source,java] ----- -include:../:{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java[tags=contract_snippet] ----- -==== - -The preceding test creates the stub presented in the previous section, generating both -the contract and a documentation file. - -The contract is called `index.groovy` and might resemble the following example: - -==== -[source,groovy] ----- -import org.springframework.cloud.contract.spec.Contract - -Contract.make { - request { - method 'POST' - url '/foo' - body(''' - {"foo": 23 } - ''') - headers { - header('''Accept''', '''application/json''') - header('''Content-Type''', '''application/json''') - } - } - response { - status OK() - body(''' - bar - ''') - headers { - header('''Content-Type''', '''application/json;charset=UTF-8''') - header('''Content-Length''', '''3''') - } - bodyMatchers { - jsonPath('$[?(@.foo >= 20)]', byType()) - } - } -} ----- -==== - -The generated document (formatted in Asciidoc in this case) contains a formatted -contract. The location of this file would be `index/dsl-contract.adoc`. - -[[features-restdocs-priority-attribute]] -== Specifying the priority attribute - -The method `SpringCloudContractRestDocs.dslContract()` takes an optional Map parameter that allows you to specify additional attributes in the template. - -One of these attributes is the xref:_project-features-contract/dsl-http-top-level-elements.adoc[priority] field that you may specify as follows: - -[source,java,indent=0] ----- -SpringCloudContractRestDocs.dslContract(Map.of("priority", 1)) ----- - -[[features-restdocs-override]] -== Overriding the DSL contract template - -By default, the output of the contract is based on a file named `default-dsl-contract-only.snippet`. - -You may provide a custom template file instead by overriding the getTemplate() method as follows: - -[source,java,indent=0] ----- -new ContractDslSnippet(){ - @Override - protected String getTemplate() { - return "custom-dsl-contract"; - } -})); ----- - -so the example above showing this line -[source,java,indent=0] ----- -.andDo(document("index", SpringCloudContractRestDocs.dslContract())); ----- - -should be changed to: -[source,java,indent=0] ----- -.andDo(document("index", new ContractDslSnippet(){ - @Override - protected String getTemplate() { - return "custom-dsl-template"; - } - })); ----- - -Templates are resolved by looking for resources on the classpath. The following locations are checked in order: - -* `org/springframework/restdocs/templates/${templateFormatId}/${name}.snippet` -* `org/springframework/restdocs/templates/${name}.snippet` -* `org/springframework/restdocs/templates/${templateFormatId}/default-${name}.snippet` - -Therefore in the example above you should place a file named custom-dsl-template.snippet in `src/test/resources/org/springframework/restdocs/templates/custom-dsl-template.snippet` - - - diff --git a/docs/modules/ROOT/pages/_project-features-messaging.adoc b/docs/modules/ROOT/pages/_project-features-messaging.adoc deleted file mode 100644 index a51d0b6b8b..0000000000 --- a/docs/modules/ROOT/pages/_project-features-messaging.adoc +++ /dev/null @@ -1,621 +0,0 @@ -[[features-messaging]] -= Messaging - - -Spring Cloud Contract lets you verify applications that use messaging as a -means of communication. All of the integrations shown in this document work with Spring, -but you can also create one of your own and use that. - -[[contract-dsl-messaging-top-level]] -== Messaging DSL Top-level Elements - -The DSL for messaging looks a little bit different than the one that focuses on HTTP. The -following sections explain the differences: - -* xref:_project-features-messaging.adoc#contract-dsl-output-triggered-method[Output Triggered by a Method] -* xref:_project-features-messaging.adoc#contract-dsl-consumer-producer[Consumer/Producer] -* xref:_project-features-messaging.adoc#contract-dsl-messaging-common[Common] - -[[contract-dsl-output-triggered-method]] -=== Output Triggered by a Method - -The output message can be triggered by calling a method (such as a `Scheduler` when a contract was -started and when a message was sent), as shown in the following example: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include::{tests_path}/samples-messaging-integration/src/test/groovy/com/example/IntegrationMessagingApplicationSpec.groovy[tags=method_trigger,indent=0] ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -include::{verifier_core_path}/src/test/resources/yml/contract_message_method.yml[indent=0] ----- -==== - -In the previous example case, the output message is sent to `output` if a method called -`bookReturnedTriggered` is invoked. On the message publisher's side, we generate a -test that calls that method to trigger the message. On the consumer side, you can use -`some_label` to trigger the message. - - -[[contract-dsl-consumer-producer]] -=== Consumer/Producer - -IMPORTANT: This section is valid only for the Groovy DSL. - -In HTTP, you have a notion of `client`/`stub and `server`/`test` notation. You can also -use those paradigms in messaging. In addition, Spring Cloud Contract Verifier also -provides the `consumer` and `producer` methods -(note that you can use either `$` or `value` methods to provide `consumer` and `producer` -parts). - -[[contract-dsl-messaging-common]] -=== Common - -In the `input` or `outputMessage` section, you can call `assertThat` with the name -of a `method` (for example, `assertThatMessageIsOnTheQueue()`) that you have defined in the -base class or in a static import. Spring Cloud Contract runs that method -in the generated test. - -[[features-messaging-integrations]] -== Integrations - -You can use one of the following integration configurations: - -* Apache Camel -* Spring Integration -* Spring Cloud Stream -* Spring JMS - -Since we use Spring Boot, if you have added one of these libraries to the classpath, all -the messaging configuration is automatically set up. - -IMPORTANT: Remember to put `@AutoConfigureMessageVerifier` on the base class of your -generated tests. Otherwise, the messaging part of Spring Cloud Contract does not -work. - -[IMPORTANT] -===== -If you want to use Spring Cloud Stream, remember to add a test dependency on -`org.springframework.cloud:spring-cloud-stream`, as follows: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - org.springframework.cloud - spring-cloud-stream - test-jar - test - test-binder - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -testImplementation(group: 'org.springframework.cloud', name: 'spring-cloud-stream', classifier: 'test-binder') ----- -==== -===== - -[[features-messaging-manual]] -=== Manual Integration Testing - -The main interface used by the tests is -`org.springframework.cloud.contract.verifier.messaging.MessageVerifierSender` and `org.springframework.cloud.contract.verifier.messaging.MessageVerifierReceiver`. -It defines how to send and receive messages. - -In a test, you can inject a `ContractVerifierMessageExchange` to send and receive -messages that follow the contract. Then add `@AutoConfigureMessageVerifier` to your test. -The following example shows how to do so: - -==== -[source,java,indent=0] ----- -@RunWith(SpringTestRunner.class) -@SpringBootTest -@AutoConfigureMessageVerifier -public static class MessagingContractTests { - - @Autowired - private MessageVerifier verifier; - ... -} ----- -==== - -NOTE: If your tests require stubs as well, then `@AutoConfigureStubRunner` includes the -messaging configuration, so you only need the one annotation. - -[[features-messaging-test-generation]] -== Producer Side Messaging Test Generation - -Having the `input` or `outputMessage` sections in your DSL results in creation of tests -on the publisher's side. By default, JUnit 4 tests are created. However, there is also a -possibility to create JUnit 5, TestNG, or Spock tests. - -IMPORTANT: The destination passed to `messageFrom` or `sentTo` can have different -meanings for different messaging implementations. For Stream and Integration, it is -first resolved as a `destination` of a channel. Then, if there is no such `destination`, -it is resolved as a channel name. For Camel, that's a certain component (for example, -`jms`). - -Consider the following contract: - -===== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_method_dsl] ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML -[source,yml,indent=0] ----- -include::{verifier_core_path}/src/test/resources/yml/contract_message_scenario1.yml[indent=0] ----- -===== - -For the preceding example, the following test would be created: - -==== -[source,java,indent=0,subs="verbatim,attributes",role="primary"] -.JUnit ----- -include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_method_junit_test] ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Spock ----- -include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=trigger_method_test] ----- -==== - -[[features-messaging-consumer]] -== Consumer Stub Generation - -Unlike in the HTTP part, in messaging, we need to publish the contract definition inside the JAR with -a stub. Then it is parsed on the consumer side, and proper stubbed routes are created. - -IMPORTANT: If you have multiple frameworks on the classpath, Stub Runner needs to -define which one should be used. Assume that you have AMQP, Spring Cloud Stream, and Spring Integration -on the classpath and that you want to use Spring AMQP. Then you need to set -`stubrunner.stream.enabled=false` and `stubrunner.integration.enabled=false`. -That way, the only remaining framework is Spring AMQP. - -[[features-messaging-stub-triggering]] -=== Stub triggering - -To trigger a message, use the `StubTrigger` interface, as the following example shows: - -==== -[source,groovy] ----- -include::{stubrunner_core_path}/src/main/java/org/springframework/cloud/contract/stubrunner/StubTrigger.java[lines=16..-1] ----- -==== - -For convenience, the `StubFinder` interface extends `StubTrigger`, so you need only one -or the other in your tests. - -`StubTrigger` gives you the following options to trigger a message: - -* xref:_project-features-messaging.adoc#features-messaging-trigger-label[Trigger by Label] -* xref:_project-features-messaging.adoc#features-messaging-trigger-group-artifact-ids[Trigger by Group and Artifact IDs] -* xref:_project-features-messaging.adoc#features-messaging-trigger-artifact-ids[Trigger by Artifact IDs] -* xref:_project-features-messaging.adoc#features-messaging-trigger-all-messages[Trigger All Messages] - -[[features-messaging-trigger-label]] -=== Trigger by Label - -The following example shows how to trigger a message with a label: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[tags=client_trigger,indent=0] ----- -==== - -[[features-messaging-trigger-group-artifact-ids]] -=== Trigger by Group and Artifact IDs - -The following example shows how to trigger a message by group and artifact IDs: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[tags=trigger_group_artifact,indent=0] ----- -==== - -[[features-messaging-trigger-artifact-ids]] -=== Trigger by Artifact IDs - -The following example shows how to trigger a message from artifact IDs: - -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[tags=trigger_artifact,indent=0] ----- - -[[features-messaging-trigger-all-messages]] -=== Trigger All Messages - -The following example shows how to trigger all messages: - -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[tags=trigger_all,indent=0] ----- - -:input_name: jms:input -:output_name: jms:output - -[[features-messaging-stub-runner-camel]] -== Consumer Side Messaging With Apache Camel - -Spring Cloud Contract Stub Runner's messaging module gives you an easy way to integrate with Apache Camel. -For the provided artifacts, it automatically downloads the stubs and registers the required -routes. - -[[features-messaging-stub-runner-camel-adding]] -=== Adding Apache Camel to the Project - -You can have both Apache Camel and Spring Cloud Contract Stub Runner on the classpath. -Remember to annotate your test class with `@AutoConfigureStubRunner`. - -[[features-messaging-stub-runner-camel-disabling]] -=== Disabling the Functionality - -If you need to disable this functionality, set the `stubrunner.camel.enabled=false` property. - -[[features-messaging-stub-runner-camel-example]] -=== Examples - -Assume that we have the following Maven repository with deployed stubs for the -`camelService` application: - -==== -[source,bash,indent=0] ----- -└── .m2 - └── repository - └── io - └── codearte - └── accurest - └── stubs - └── camelService - ├── 0.0.1-SNAPSHOT - │   ├── camelService-0.0.1-SNAPSHOT.pom - │   ├── camelService-0.0.1-SNAPSHOT-stubs.jar - │   └── maven-metadata-local.xml - └── maven-metadata-local.xml ----- -==== - -Further, assume that the stubs contain the following structure: - -==== -[source,bash,indent=0] ----- -├── META-INF -│   └── MANIFEST.MF -└── repository - ├── accurest - │   └── bookReturned1.groovy - └── mappings ----- -==== - -Now consider the following contract: - -==== -[source,groovy] ----- -include::{tests_path}/samples-messaging-camel/src/test/groovy/com/example/CamelMessagingApplicationSpec.groovy[tags=sample_dsl,indent=0] ----- -==== - -To trigger a message from the `return_book_1` label, we use the `StubTrigger` interface, as follows: - -==== -[source,groovy] ----- -stubFinder.trigger("return_book_1") ----- -==== - -That will send out a message to the destination described in the output message of the contract. - -:input_name: input -:output_name: output - -[[features-messaging-stub-runner-integration]] -== Consumer Side Messaging with Spring Integration - -Spring Cloud Contract Stub Runner's messaging module gives you an easy way to -integrate with Spring Integration. For the provided artifacts, it automatically downloads -the stubs and registers the required routes. - -[[features-messaging-stub-runner-integration-adding]] -=== Adding the Runner to the Project - -You can have both Spring Integration and Spring Cloud Contract Stub Runner on the -classpath. Remember to annotate your test class with `@AutoConfigureStubRunner`. - -[[features-messaging-stub-runner-integration-disabling]] -=== Disabling the Functionality - -If you need to disable this functionality, set the -`stubrunner.integration.enabled=false` property. - -[[features-messaging-stub-runner-integration-example]] -=== Examples - -Assume that you have the following Maven repository with deployed stubs for the -`integrationService` application: - -==== -[source,bash,indent=0] ----- -└── .m2 - └── repository - └── io - └── codearte - └── accurest - └── stubs - └── integrationService - ├── 0.0.1-SNAPSHOT - │   ├── integrationService-0.0.1-SNAPSHOT.pom - │   ├── integrationService-0.0.1-SNAPSHOT-stubs.jar - │   └── maven-metadata-local.xml - └── maven-metadata-local.xml ----- -==== - -Further assume the stubs contain the following structure: - -==== -[source,bash,indent=0] ----- -├── META-INF -│   └── MANIFEST.MF -└── repository - ├── accurest - │   └── bookReturned1.groovy - └── mappings ----- -==== - -Consider the following contract: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-integration/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/integration/IntegrationStubRunnerSpec.groovy[tags=sample_dsl,indent=0] ----- -==== - -Now consider the following Spring Integration Route: - -==== -[source,xml] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-integration/src/test/resources/integration-context.xml[lines=1;18..-1] ----- -==== - -To trigger a message from the `return_book_1` label, use the `StubTrigger` interface, as -follows: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-integration/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/integration/IntegrationStubRunnerSpec.groovy[tags=client_trigger,indent=0] ----- -==== - -That will send out a message to the destination described in the output message of the contract. - -[[features-messaging-stub-runner-stream]] -== Consumer Side Messaging With Spring Cloud Stream - -Spring Cloud Contract Stub Runner's messaging module gives you an easy way to -integrate with Spring Stream. For the provided artifacts, it automatically downloads the -stubs and registers the required routes. - -CAUTION: If Stub Runner's integration with the Stream `messageFrom` or `sentTo` strings -are resolved first as the `destination` of a channel and no such `destination` exists, the -destination is resolved as a channel name. - -[IMPORTANT] -===== -If you want to use Spring Cloud Stream, remember to add a dependency on -`org.springframework.cloud:spring-cloud-stream` test support, as follows: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - org.springframework.cloud - spring-cloud-stream-test-binder - test - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -testImplementation('org.springframework.cloud:spring-cloud-stream-test-binder') ----- -==== -===== - -[[features-messaging-stub-runner-stream-adding]] -=== Adding the Runner to the Project - -You can have both Spring Cloud Stream and Spring Cloud Contract Stub Runner on the -classpath. Remember to annotate your test class with `@AutoConfigureStubRunner`. - -[[features-messaging-stub-runner-stream-disabling]] -=== Disabling the Functionality - -If you need to disable this functionality, set the `stubrunner.stream.enabled=false` -property. - -[[features-messaging-stub-runner-stream-example]] -=== Examples - -Assume that you have the following Maven repository with deployed stubs for the -`streamService` application: - -==== -[source,bash,indent=0] ----- -└── .m2 - └── repository - └── io - └── codearte - └── accurest - └── stubs - └── streamService - ├── 0.0.1-SNAPSHOT - │   ├── streamService-0.0.1-SNAPSHOT.pom - │   ├── streamService-0.0.1-SNAPSHOT-stubs.jar - │   └── maven-metadata-local.xml - └── maven-metadata-local.xml ----- -==== - -Further assume the stubs contain the following structure: - -==== -[source,bash,indent=0] ----- -├── META-INF -│   └── MANIFEST.MF -└── repository - ├── accurest - │   └── bookReturned1.groovy - └── mappings ----- -==== - -Consider the following contract: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[tags=sample_dsl,indent=0] ----- -==== - -Now consider the following Spring Cloud Stream function configuration: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[tags=setup,indent=0] ----- -==== - -Now consider the following Spring configuration: - -==== -[source,yaml] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/resources/application.yml[] ----- -==== - -To trigger a message from the `return_book_1` label, use the `StubTrigger` interface as -follows: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-stream/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/stream/StreamStubRunnerSpec.groovy[tags=client_trigger,indent=0] ----- -==== - - -That will send out a message to the destination described in the output message of the contract. - -[[features-messaging-stub-runner-jms]] -== Consumer Side Messaging With Spring JMS - -Spring Cloud Contract Stub Runner's messaging module provides an easy way to -integrate with Spring JMS. - -The integration assumes that you have a running instance of a JMS broker. - -[[features-messaging-stub-runner-jms-adding]] -=== Adding the Runner to the Project - -You need to have both Spring JMS and Spring Cloud Contract Stub Runner on the classpath. Remember to annotate your test class -with `@AutoConfigureStubRunner`. - -:input_name: input -:output_name: output - -[[features-messaging-stub-runner-jms-example]] -=== Examples - -Assume that the stub structure looks as follows: - -==== -[source,bash,indent=0] ----- -├── stubs - └── bookReturned1.groovy - ----- -==== - -Further assume the following test configuration: - -==== -[source,yml,indent=0] ----- -stubrunner: - repository-root: stubs:classpath:/stubs/ - ids: my:stubs - stubs-mode: remote -spring: - activemq: - send-timeout: 1000 - jms: - template: - receive-timeout: 1000 ----- -==== - -Now consider the following contract: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-jms/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/jms/JmsStubRunnerSpec.groovy[tags=sample_dsl,indent=0] ----- -==== - -To trigger a message from the `return_book_1` label, we use the `StubTrigger` interface, as follows: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-jms/src/test/groovy/org/springframework/cloud/contract/stubrunner/messaging/jms/JmsStubRunnerSpec.groovy[tags=client_trigger,indent=0] ----- -==== - -That will send out a message to the destination described in the output message of the contract. diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner.adoc deleted file mode 100644 index 2e77df4347..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner.adoc +++ /dev/null @@ -1,12 +0,0 @@ -[[features-stub-runner]] -= Spring Cloud Contract Stub Runner -:page-section-summary-toc: 1 - -One of the issues that you might encounter while using Spring Cloud Contract Verifier is -passing the generated WireMock JSON stubs from the server side to the client side (or to -various clients). The same takes place in terms of client-side generation for messaging. - -Copying the JSON files and setting the client side for messaging manually is out of the -question. That is why we introduced Spring Cloud Contract Stub Runner. It can -automatically download and run the stubs for you. - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-boot.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-boot.adoc deleted file mode 100644 index e63a0b3512..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-boot.adoc +++ /dev/null @@ -1,131 +0,0 @@ -[[features-stub-runner-boot]] -= Using the Stub Runner Boot Application - -Spring Cloud Contract Stub Runner Boot is a Spring Boot application that exposes REST endpoints to -trigger the messaging labels and to access WireMock servers. - -[[features-stub-runner-boot-security]] -== Stub Runner Boot Security - -The Stub Runner Boot application is not secured by design - securing it would require to add security to all -stubs even if they don't actually require it. Since this is a testing utility - the server is **not intended** -to be used in production environments. - -IMPORTANT: It is expected that **only a trusted client** has access to the Stub Runner Boot server. You should not -run this application as a Fat Jar or a link:docker-project.html#docker-stubrunner[Docker Image] in untrusted locations. - -[[features-stub-runner-boot-server]] -== Stub Runner Server - -To use the Stub Runner Server, add the following dependency: - -==== -[source,groovy,indent=0] ----- -compile "org.springframework.cloud:spring-cloud-starter-stub-runner" ----- -==== - -Then annotate a class with `@EnableStubRunnerServer`, build a fat jar, and it is ready to work. - -For the properties, see the xref:_project-features-stubrunner/stub-runner-junit.adoc#features-stub-runner-rule-spring[Stub Runner Spring] section. - -[[features-stub-runner-boot-how-fat-jar]] -== Stub Runner Server Fat Jar - -You can download a standalone JAR from Maven (for example, for version 2.0.1.RELEASE) -by running the following commands: - -==== -[source,bash,indent=0] ----- -$ wget -O stub-runner.jar 'https://search.maven.org/remotecontent?filepath=org/springframework/cloud/spring-cloud-contract-stub-runner-boot/2.0.1.RELEASE/spring-cloud-contract-stub-runner-boot-2.0.1.RELEASE.jar' -$ java -jar stub-runner.jar --stubrunner.ids=... --stubrunner.repositoryRoot=... ----- -==== - -[[features-stub-runner-boot-how-cli]] -== Spring Cloud CLI - -Starting from the `1.4.0.RELEASE` version of the https://cloud.spring.io/spring-cloud-cli[Spring Cloud CLI] -project, you can start Stub Runner Boot by running `spring cloud stubrunner`. - -To pass the configuration, you can create a `stubrunner.yml` file in the current working directory, -in a subdirectory called `config`, or in `~/.spring-cloud`. The file could resemble the following -example for running stubs installed locally: - - -.stubrunner.yml -==== -[source,yml,indent=0] ----- -stubrunner: - stubsMode: LOCAL - ids: - - com.example:beer-api-producer:+:9876 ----- -==== - -Then you can call `spring cloud stubrunner` from your terminal window to start -the Stub Runner server. It is available at port `8750`. - -[[features-stub-runner-boot-endpoints]] -== Endpoints - -Stub Runner Boot offers two endpoints: - -* xref:_project-features-stubrunner/stub-runner-boot.adoc#features-stub-runner-boot-endpoints-http[HTTP] -* xref:_project-features-stubrunner/stub-runner-boot.adoc#features-stub-runner-boot-endpoints-messaging[Messaging] - -[[features-stub-runner-boot-endpoints-http]] -=== HTTP - -For HTTP, Stub Runner Boot makes the following endpoints available: - -- GET `/stubs`: Returns a list of all running stubs in `ivy:integer` notation -- GET `/stubs/{ivy}`: Returns a port for the given `ivy` notation (when calling the endpoint `ivy` can also be `artifactId` only) - -[[features-stub-runner-boot-endpoints-messaging]] -=== Messaging - -For Messaging, Stub Runner Boot makes the following endpoints available: - -- GET `/triggers`: Returns a list of all running labels in `ivy : [ label1, label2 ...]` notation -- POST `/triggers/{label}`: Runs a trigger with `label` -- POST `/triggers/{ivy}/{label}`: Runs a trigger with a `label` for the given `ivy` notation -(when calling the endpoint, `ivy` can also be `artifactId` only) - -[[features-stub-runner-boot-endpoints-example]] -== Example - -The following example shows typical usage of Stub Runner Boot: - -[source,groovy,indent=0] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/server/StubRunnerBootSpec.groovy[tags=boot_usage] ----- - -[[features-stub-runner-boot-service-discovery]] -== Stub Runner Boot with Service Discovery - -One way to use Stub Runner Boot is to use it as a feed of stubs for "`smoke tests`". What does that mean? -Assume that you do not want to deploy 50 microservices to a test environment in order -to see whether your application works. You have already run a suite of tests during the build process, -but you would also like to ensure that the packaging of your application works. You can -deploy your application to an environment, start it, and run a couple of tests on it to see whether -it works. We can call those tests "`smoke tests`", because their purpose is to check only a handful -of testing scenarios. - -The problem with this approach is that, if you use microservices, you most likely also -use a service discovery tool. Stub Runner Boot lets you solve this issue by starting the -required stubs and registering them in a service discovery tool. - -Now assume that we want to start this application so that the stubs get automatically registered. -We can do so by running the application with `java -jar ${SYSTEM_PROPS} stub-runner-boot-eureka-example.jar`, where -`${SYSTEM_PROPS}`. - -That way, your deployed application can send requests to started WireMock servers through service -discovery. Most likely, points 1 through 3 could be set by default in `application.yml`, because they are not -likely to change. That way, you can provide only the list of stubs to download whenever you start -the Stub Runner Boot. - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-cloud.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-cloud.adoc deleted file mode 100644 index 70be63c9a6..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-cloud.adoc +++ /dev/null @@ -1,63 +0,0 @@ -[[features-stub-runner-cloud]] -= Stub Runner Spring Cloud - -Stub Runner can integrate with Spring Cloud. - -For real life examples, see: - -- https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/{samples_branch}/producer[The producer application sample] -- https://github.com/spring-cloud-samples/spring-cloud-contract-samples/tree/{samples_branch}/consumer_with_discovery[The consumer application sample] - -[[features-stub-runner-cloud-stubbing-discovery]] -== Stubbing Service Discovery - -The most important feature of `Stub Runner Spring Cloud` is the fact that it stubs: - -- `DiscoveryClient` -- `ReactorServiceInstanceLoadBalancer` - -That means that, regardless of whether you use Zookeeper, Consul, Eureka, or anything -else, you do not need that in your tests. We are starting WireMock instances of your -dependencies and we are telling your application, whenever you use `Feign`, to load a -balanced `RestTemplate` or `DiscoveryClient` directly, to call those stubbed servers -instead of calling the real Service Discovery tool. - -[[features-stub-runner-cloud-stubbing-profiles]] -=== Test Profiles and Service Discovery - -In your integration tests, you typically do not want to call either a discovery service (such as Eureka) -or Config Server. That is why you create an additional test configuration in which you want to disable -these features. - -Due to certain limitations of https://github.com/spring-cloud/spring-cloud-commons/issues/156[`spring-cloud-commons`], -to achieve this, you have to disable these properties -in a static block such as the following example (for Eureka): - -==== -[source,java] ----- - //Hack to work around https://github.com/spring-cloud/spring-cloud-commons/issues/156 - static { - System.setProperty("eureka.client.enabled", "false"); - System.setProperty("spring.cloud.config.failFast", "false"); - } ----- -==== - -[[features-stub-runner-additional-config]] -== Additional Configuration - -You can match the `artifactId` of the stub with the name of your application by using the `stubrunner.idsToServiceIds:` map. - -TIP: By default, all service discovery is stubbed. This means that, regardless of whether you have -an existing `DiscoveryClient`, its results are ignored. However, if you want to reuse it, you can set - `stubrunner.cloud.delegate.enabled` to `true`, and then your existing `DiscoveryClient` results are - merged with the stubbed ones. - -The default Maven configuration used by Stub Runner can be tweaked either -by setting the following system properties or by setting the corresponding environment variables: - -- `maven.repo.local`: Path to the custom maven local repository location -- `org.apache.maven.user-settings`: Path to custom maven user settings location -- `org.apache.maven.global-settings`: Path to maven global settings location - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-common.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-common.adoc deleted file mode 100644 index 487058628c..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-common.adoc +++ /dev/null @@ -1,60 +0,0 @@ -[[features-stub-runner-common]] -= Common Properties - -This section briefly describes common properties, including: - -* xref:_project-features-stubrunner/stub-runner-common.adoc#features-stub-runner-common-properties-junit-spring[Common Properties for JUnit and Spring] -* xref:_project-features-stubrunner/stub-runner-common.adoc#features-stub-runner-stub-runner-stub-ids[Stub Runner Stubs IDs] - -[[features-stub-runner-common-properties-junit-spring]] -== Common Properties for JUnit and Spring - -You can set repetitive properties by using system properties or Spring configuration -properties. The following table shows their names with their default values: - -[frame="topbot",options="header"] -|=============== -| Property name | Default value | Description -|`stubrunner.minPort`|`10000`| Minimum value of a port for a started WireMock with stubs. -|`stubrunner.maxPort`|`15000`| Maximum value of a port for a started WireMock with stubs. -|`stubrunner.repositoryRoot`|| Maven repository URL. If blank, then call the local Maven repo. -|`stubrunner.classifier`|`stubs`| Default classifier for the stub artifacts. -|`stubrunner.stubsMode`|`CLASSPATH`| The way you want to fetch and register the stubs. -|`stubrunner.ids`|| Array of Ivy notation stubs to download. -|`stubrunner.username`|| Optional username to access the tool that stores the JARs with -stubs. -|`stubrunner.password`|| Optional password to access the tool that stores the JARs with -stubs. -|`stubrunner.stubsPerConsumer`|`false`| Set to `true` if you want to use different stubs for -each consumer instead of registering all stubs for every consumer. -|`stubrunner.consumerName`|| If you want to use a stub for each consumer and want to -override the consumer name, change this value. -|=============== - -[[features-stub-runner-stub-runner-stub-ids]] -== Stub Runner Stubs IDs - -You can set the stubs to download in the `stubrunner.ids` system property. They -use the following pattern: - -==== -[source,java,indent=0] ----- -groupId:artifactId:version:classifier:port ----- -==== - -Note that `version`, `classifier`, and `port` are optional. - -* If you do not provide the `port`, a random one is picked. -* If you do not provide the `classifier`, the default is used. (Note that you can -pass an empty classifier this way: `groupId:artifactId:version:`). -* If you do not provide the `version`, then `+` is passed, and the latest one is -downloaded. - -`port` means the port of the WireMock server. - -IMPORTANT: Starting with version 1.0.4, you can provide a range of versions that you -would like the Stub Runner to take into consideration. You can read more about the -Aether versioning ranges -https://wiki.eclipse.org/Aether/New_and_Noteworthy#Version_Ranges[here]. diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-core.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-core.adoc deleted file mode 100644 index d9b97944d7..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-core.adoc +++ /dev/null @@ -1,304 +0,0 @@ -[[features-stub-runner-core]] -= Stub Runner Core - -The stub runner core runs stubs for service collaborators. Treating stubs as contracts of -services lets you use stub-runner as an implementation of -https://martinfowler.com/articles/consumerDrivenContracts.html[Consumer-driven Contracts]. - -Stub Runner lets you automatically download the stubs of the provided dependencies (or -pick those from the classpath), start WireMock servers for them, and feed them with proper -stub definitions. For messaging, special stub routes are defined. - -[[features-stub-runner-retrieving]] -== Retrieving stubs - -You can pick from the following options of acquiring stubs: - -- Aether-based solution that downloads JARs with stubs from Artifactory or Nexus -- Classpath-scanning solution that searches the classpath with a pattern to retrieve stubs -- Writing your own implementation of the `org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder` for full customization - -The latter example is described in the xref:advanced.adoc#customization-custom-stub-runner[Custom Stub Runner] section. - -[[features-stub-runner-downloading-stub]] -=== Downloading Stubs - -You can control the downloading of stubs with the `stubsMode` switch. It picks value from the -`StubRunnerProperties.StubsMode` enumeration. You can use the following options: - -- `StubRunnerProperties.StubsMode.CLASSPATH` (default value): Picks stubs from the classpath -- `StubRunnerProperties.StubsMode.LOCAL`: Picks stubs from a local storage (for example, `.m2`) -- `StubRunnerProperties.StubsMode.REMOTE`: Picks stubs from a remote location - -The following example picks stubs from a local location: - -==== -[source,java] ----- -@AutoConfigureStubRunner(repositoryRoot="https://foo.bar", ids = "com.example:beer-api-producer:+:stubs:8095", stubsMode = StubRunnerProperties.StubsMode.LOCAL) ----- -==== - -[[features-stub-runner-classpath-scanning]] -=== Classpath scanning - -If you set the `stubsMode` property to `StubRunnerProperties.StubsMode.CLASSPATH` -(or set nothing since `CLASSPATH` is the default value), the classpath is scanned. -Consider the following example: - -==== -[source,java] ----- -@AutoConfigureStubRunner(ids = { - "com.example:beer-api-producer:+:stubs:8095", - "com.example.foo:bar:1.0.0:superstubs:8096" -}) ----- -==== - -You can add the dependencies to your classpath, as follows: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - - com.example - beer-api-producer-restdocs - stubs - 0.0.1-SNAPSHOT - test - - - * - * - - - - - com.example.thing1 - thing2 - superstubs - 1.0.0 - test - - - * - * - - - ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -testCompile("com.example:beer-api-producer-restdocs:0.0.1-SNAPSHOT:stubs") { - transitive = false -} -testCompile("com.example.thing1:thing2:1.0.0:superstubs") { - transitive = false -} ----- -==== - -Then the specified locations on your classpath get scanned. For `com.example:beer-api-producer-restdocs`, -the following locations are scanned: - -- /META-INF/com.example/beer-api-producer-restdocs/**/*.* -- /contracts/com.example/beer-api-producer-restdocs/**/*.* -- /mappings/com.example/beer-api-producer-restdocs/**/*.* - -For `com.example.thing1:thing2`, the following locations are scanned: - -- /META-INF/com.example.thing1/thing2/**/*.* -- /contracts/com.example.thing1/thing2/**/*.* -- /mappings/com.example.thing1/thing2/**/*.* - -TIP: You have to explicitly provide the group and artifact IDs when you package the -producer stubs. - -To achieve proper stub packaging, the producer would set up the contracts as follows: - -==== -[source,bash] ----- -└── src - └── test - └── resources - └── contracts -    └── com.example -       └── beer-api-producer-restdocs -       └── nested -       └── contract3.groovy - ----- -==== - -By using the https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/{samples_branch}/producer_with_restdocs/pom.xml[Maven `assembly` plugin] or the -https://github.com/spring-cloud-samples/spring-cloud-contract-samples/blob/{samples_branch}/producer_with_restdocs/build.gradle[Gradle Jar] task, you have to create the following -structure in your stubs jar: - -==== -[source,bash] ----- -└── META-INF - └── com.example - └── beer-api-producer-restdocs - └── 2.0.0 - ├── contracts - │   └── nested -    │ └── contract2.groovy -    └── mappings -    └── mapping.json - ----- -==== - -By maintaining this structure, the classpath gets scanned and you can profit from the messaging or -HTTP stubs without the need to download artifacts. - -[[features-stub-runner-configuring-http-server-stubs]] -=== Configuring HTTP Server Stubs - -Stub Runner has a notion of a `HttpServerStub` that abstracts the underlying -concrete implementation of the HTTP server (for example, WireMock is one of the implementations). -Sometimes, you need to perform some additional tuning (which is concrete for the given implementation) of the stub servers. -To do that, Stub Runner gives you -the `httpServerStubConfigurer` property that is available in the annotation and the -JUnit rule and is accessible through system properties, where you can provide -your implementation of the `org.springframework.cloud.contract.stubrunner.HttpServerStubConfigurer` -interface. The implementations can alter -the configuration files for the given HTTP server stub. - -Spring Cloud Contract Stub Runner comes with an implementation that you -can extend for WireMock: -`org.springframework.cloud.contract.stubrunner.provider.wiremock.WireMockHttpServerStubConfigurer`. -In the `configure` method, -you can provide your own custom configuration for the given stub. The use -case might be starting WireMock for the given artifact ID, on an HTTPS port. The following -example shows how to do so: - -.WireMockHttpServerStubConfigurer implementation -==== -[source,groovy,indent=0] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfigurationSpec.groovy[tags=wireMockHttpServerStubConfigurer] ----- -==== - -You can then reuse it with the `@AutoConfigureStubRunner` annotation, as follows: - -==== -[source,groovy,indent=0] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfigurationSpec.groovy[tags=annotation] ----- -==== - -Whenever an HTTPS port is found, it takes precedence over the HTTP port. - -[[features-stub-runner-running-stubs]] -== Running stubs - -This section describes how to run stubs. It contains the following topics: - -* xref:_project-features-stubrunner/stub-runner-core.adoc#features-stub-runner-http-stubs[HTTP Stubs] -* xref:_project-features-stubrunner/stub-runner-core.adoc#features-stub-runner-viewing[Viewing Registered Mappings] -* xref:_project-features-stubrunner/stub-runner-core.adoc#features-stub-runner-messaging[Messaging Stubs] - -[[features-stub-runner-http-stubs]] -=== HTTP Stubs - -Stubs are defined in JSON documents, whose syntax is defined in the http://wiremock.org/stubbing.html[WireMock documentation]. - -The following example defines a stub in JSON: - -==== -[source,javascript,indent=0] ----- -{ - "request": { - "method": "GET", - "url": "/ping" - }, - "response": { - "status": 200, - "body": "pong", - "headers": { - "Content-Type": "text/plain" - } - } -} ----- -==== - -[[features-stub-runner-viewing]] -=== Viewing Registered Mappings - -Every stubbed collaborator exposes a list of defined mappings under the `__/admin/` endpoint. - -You can also use the `mappingsOutputFolder` property to dump the mappings to files. -For the annotation-based approach, it would resembling the following example: - -==== -[source,java] ----- -@AutoConfigureStubRunner(ids="a.b.c:loanIssuance,a.b.c:fraudDetectionServer", -mappingsOutputFolder = "target/outputmappings/") ----- -==== - -For the JUnit approach, it resembles the following example: - -==== -[source,java] ----- -@ClassRule @Shared StubRunnerRule rule = new StubRunnerRule() - .repoRoot("https://some_url") - .downloadStub("a.b.c", "loanIssuance") - .downloadStub("a.b.c:fraudDetectionServer") - .withMappingsOutputFolder("target/outputmappings") ----- -==== - -Then, if you check out the `target/outputmappings` folder, you would see the following structure; - -==== -[source,bash] ----- -. -├── fraudDetectionServer_13705 -└── loanIssuance_12255 ----- -==== - -That means that there were two stubs registered. `fraudDetectionServer` was registered at port `13705` -and `loanIssuance` at port `12255`. If we take a look at one of the files, we would see (for WireMock) -the mappings available for the given server: - -==== -[source,json] ----- -[{ - "id" : "f9152eb9-bf77-4c38-8289-90be7d10d0d7", - "request" : { - "url" : "/name", - "method" : "GET" - }, - "response" : { - "status" : 200, - "body" : "fraudDetectionServer" - }, - "uuid" : "f9152eb9-bf77-4c38-8289-90be7d10d0d7" -}, -... -] ----- -==== - -[[features-stub-runner-messaging]] -=== Messaging Stubs - -Depending on the provided Stub Runner dependency and the DSL, the messaging routes are automatically set up. - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-fail-on-no-stubs.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-fail-on-no-stubs.adoc deleted file mode 100644 index 3480c144f3..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-fail-on-no-stubs.adoc +++ /dev/null @@ -1,39 +0,0 @@ -[[features-stub-runner-fail-on-no-stubs]] -= Fail On No Stubs - -By default, Stub Runner will fail if no stubs are found. In order to change that behavior, set the `failOnNoStubs` property to `false` in the annotation or call the `withFailOnNoStubs(false)` method on a JUnit Rule or Extension. The following example shows how to do so: - -==== -[source,java,indent=0,subs="verbatim,attributes",role="primary"] -.Annotation ----- -@AutoConfigureStubRunner( -stubsMode = StubRunnerProperties.StubsMode.REMOTE, - repositoryRoot = "stubs://file://location/to/the/contracts", - ids = "com.example:some-producer", - failOnNoStubs = false) ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.JUnit 4 Rule ----- -@Rule - public StubRunnerRule rule = new StubRunnerRule() - .downloadStub("com.example:some-producer") - .repoRoot("stubs://file://location/to/the/contracts") - .stubsMode(StubRunnerProperties.StubsMode.REMOTE) - .withFailOnNoStubs(false); ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.JUnit 5 Extension ----- -@RegisterExtension - public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension() - .downloadStub("com.example:some-producer") - .repoRoot("stubs://file://location/to/the/contracts") - .stubsMode(StubRunnerProperties.StubsMode.REMOTE) - .withFailOnNoStubs(false); ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-generate-stubs-at-runtime.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-generate-stubs-at-runtime.adoc deleted file mode 100644 index 66b064fd5f..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-generate-stubs-at-runtime.adoc +++ /dev/null @@ -1,43 +0,0 @@ -[[features-stub-runner-generate-stubs-at-runtime]] -= Generating Stubs at Runtime - -As a consumer, you might not want to wait for the producer to finish its implementation and then publish their stubs. A solution to this problem can be generation of stubs at runtime. - -As a producer, when a contract is defined, you are required to make the generated tests pass in order for the stubs to be published. There are cases where you would like to unblock the consumers so that they can fetch the stubs before your tests actually pass. In this case, you should set such contracts as in-progress. You can read more about this under the xref:_project-features-contract/common-top-elements.adoc#contract-dsl-in-progress[Contracts in Progress] section. That way, your tests are not generated, but the stubs are generated. - -As a consumer, you can toggle a switch to generate stubs at runtime. Stub Runner ignores all the existing stub mappings and generates new ones for all the contract definitions. Another option is to pass the `stubrunner.generate-stubs` system property. The following example shows such a setup: - -==== -[source,java,indent=0,subs="verbatim,attributes",role="primary"] -.Annotation ----- -@AutoConfigureStubRunner( -stubsMode = StubRunnerProperties.StubsMode.REMOTE, - repositoryRoot = "stubs://file://location/to/the/contracts", - ids = "com.example:some-producer", - generateStubs = true) ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.JUnit 4 Rule ----- -@Rule - public StubRunnerRule rule = new StubRunnerRule() - .downloadStub("com.example:some-producer") - .repoRoot("stubs://file://location/to/the/contracts") - .stubsMode(StubRunnerProperties.StubsMode.REMOTE) - .withGenerateStubs(true); ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.JUnit 5 Extension ----- -@RegisterExtension - public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension() - .downloadStub("com.example:some-producer") - .repoRoot("stubs://file://location/to/the/contracts") - .stubsMode(StubRunnerProperties.StubsMode.REMOTE) - .withGenerateStubs(true); ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-junit.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-junit.adoc deleted file mode 100644 index 5c7ad331af..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-junit.adoc +++ /dev/null @@ -1,167 +0,0 @@ -[[features-stub-runner-junit]] -= Stub Runner JUnit Rule and Stub Runner JUnit5 Extension - -Stub Runner comes with a JUnit rule that lets you can download and run stubs for a given -group and artifact ID, as the following example shows: - -==== -[source,java,indent=0] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/junit4/StubRunnerRuleJUnitTest.java[tags=classrule] ----- -==== - -A `StubRunnerExtension` is also available for JUnit 5. `StubRunnerRule` and -`StubRunnerExtension` work in a very similar fashion. After the rule or extension is -called, Stub Runner connects to your Maven repository and, for the given list of -dependencies, tries to: - -- Download them -- Cache them locally -- Unzip them to a temporary folder -- Start a WireMock server for each Maven dependency on a random port from the provided -range of ports or the provided port -- Feed the WireMock server with all JSON files that are valid WireMock definitions -- Send messages (remember to pass an implementation of `MessageVerifierSender` interface) - -Stub Runner uses the https://wiki.eclipse.org/Aether[Eclipse Aether] mechanism to download the Maven dependencies. -Check their https://wiki.eclipse.org/Aether[docs] for more information. - -Since the `StubRunnerRule` and `StubRunnerExtension` implement the `StubFinder`, they let -you find the started stubs, as the following example shows: - -==== -[source,groovy,indent=0] ----- -include:../:{stubrunner_core_path}/src/main/java/org/springframework/cloud/contract/stubrunner/StubFinder.java[lines=16..-1] ----- -==== - -The following examples provide more detail about using Stub Runner: - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Spock ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/junit4/StubRunnerRuleSpec.groovy[tags=classrule] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Junit 4 ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/junit4/StubRunnerRuleJUnitTest.java[tags=test] ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.Junit 5 ----- -include:../:{stubrunner_core_path}/src/test/java/org/springframework/cloud/contract/stubrunner/junit/StubRunnerJUnit5ExtensionTests.java[tags=extension] ----- -==== - -See the xref:_project-features-stubrunner/stub-runner-common.adoc#features-stub-runner-common-properties-junit-spring[Common Properties for JUnit and Spring] for more information on -how to apply global configuration of Stub Runner. - -IMPORTANT: To use the JUnit rule or JUnit 5 extension together with messaging, you have to provide an implementation of the -`MessageVerifierSender` and `MessageVerifierReceiver` interface to the rule builder (for example, `rule.messageVerifierSender(new MyMessageVerifierSender())`). -If you do not do this, then, whenever you try to send a message, an exception is thrown. - -[[features-stub-runner-rule-maven-settings]] -== Maven Settings - -The stub downloader honors Maven settings for a different local repository folder. -Authentication details for repositories and profiles are currently not taken into account, -so you need to specify it by using the properties mentioned above. - -[[features-stub-runner-rule-fixed-ports]] -== Providing Fixed Ports - -You can also run your stubs on fixed ports. You can do it in two different ways. -One is to pass it in the properties, and the other is to use the fluent API of -JUnit rule. - -[[features-stub-runner-rule-fluent-api]] -== Fluent API - -When using the `StubRunnerRule` or `StubRunnerExtension`, you can add a stub to download -and then pass the port for the last downloaded stub. The following example shows how to do so: - -==== -[source,java,indent=0] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/junit4/StubRunnerRuleCustomPortJUnitTest.java[tags=classrule_with_port] ----- -==== - -For the preceding example, the following test is valid: - -==== -[source,java,indent=0] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/junit4/StubRunnerRuleCustomPortJUnitTest.java[tags=test_with_port] ----- -==== - -[[features-stub-runner-rule-spring]] -== Stub Runner with Spring - -Stub Runner with Spring sets up Spring configuration of the Stub Runner project. - -By providing a list of stubs inside your configuration file, Stub Runner automatically downloads -and registers in WireMock the selected stubs. - -If you want to find the URL of your stubbed dependency, you can autowire the `StubFinder` interface and use -its methods, as follows: - -==== -[source,groovy,indent=0] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfigurationSpec.groovy[tags=test] ----- -==== - -Doing so depends on the following configuration file: - -==== -[source,yml,indent=0] ----- -include:../:{stubrunner_core_path}/src/test/resources/application-test.yml[tags=test] ----- -==== - -Instead of using the properties, you can also use the properties inside the `@AutoConfigureStubRunner`. -The following example achieves the same result by setting values on the annotation: - -==== -[source,groovy,indent=0] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/consul/StubRunnerSpringCloudConsulAutoConfigurationSpec.groovy[tags=autoconfigure] ----- -==== - -Stub Runner Spring registers environment variables in the following manner -for every registered WireMock server. The following example shows Stub Runner IDs for -`com.example:thing1` and `com.example:thing2`: - -- `stubrunner.runningstubs.thing1.port` -- `stubrunner.runningstubs.com.example.thing1.port` -- `stubrunner.runningstubs.thing2.port` -- `stubrunner.runningstubs.com.example.thing2.port` - -You can reference these values in your code. - -You can also use the `@StubRunnerPort` annotation to inject the port of a running stub. -The value of the annotation can be the `groupid:artifactid` or only the `artifactid`. -The following example works shows Stub Runner IDs for -`com.example:thing1` and `com.example:thing2`. - -==== -[source,java,indent=0] ----- -@StubRunnerPort("thing1") -int thing1Port; -@StubRunnerPort("com.example:thing2") -int thing2Port; ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-publishing-stubs-as-jars.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-publishing-stubs-as-jars.adoc deleted file mode 100644 index 3e12070ae2..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-publishing-stubs-as-jars.adoc +++ /dev/null @@ -1,32 +0,0 @@ -[[features-stub-runner-publishing-stubs-as-jars]] -= Publishing Stubs as JARs - -The easiest approach to publishing stubs as jars is to centralize the way stubs are kept. -For example, you can keep them as jars in a Maven repository. - -TIP: For both Maven and Gradle, the setup comes ready to work. However, you can customize -it if you want to. - -The following example shows how to publish stubs as jars: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- - -include:../:{samples_url}/producer_with_restdocs/pom.xml[tags=skip_jar,indent=0] - - -include:../:{samples_url}/producer_with_restdocs/pom.xml[tags=assembly,indent=0] - - -include:../:{samples_url}/producer_with_restdocs/src/assembly/stub.xml[indent=0] ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -include:../:{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/functionalTest/scenarioProject/build.gradle[tags=jar_setup,indent=0] ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-snapshot-versions.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-snapshot-versions.adoc deleted file mode 100644 index f1b2725e86..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-snapshot-versions.adoc +++ /dev/null @@ -1,21 +0,0 @@ -[[features-stub-runner-snapshot-versions]] -= Snapshot Versions -:page-section-summary-toc: 1 - -You can add the additional snapshot repository to your build file to use snapshot -versions, which are automatically uploaded after every successful build, as follows: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- -include:../:{standalone_samples_path}/http-server/pom.xml[tags=repos,indent=0] ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle (`settings.xml`) ----- -include:../:{standalone_samples_path}/http-server/settings.gradle[tags=repos,indent=0] ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-stubs-per-consumer.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-stubs-per-consumer.adoc deleted file mode 100644 index 9b2cf5cc1e..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-stubs-per-consumer.adoc +++ /dev/null @@ -1,98 +0,0 @@ -[[features-stub-runner-stubs-per-consumer]] -= Consumer-Driven Contracts: Stubs Per Consumer - -There are cases in which two consumers of the same endpoint want to have two different responses. - -TIP: This approach also lets you immediately know which consumer uses which part of your API. -You can remove part of a response that your API produces and see which of your autogenerated tests -fails. If none fails, you can safely delete that part of the response, because nobody uses it. - -Consider the following example of a contract defined for the producer called `producer`, -which has two consumers (`foo-consumer` and `bar-consumer`): - -==== -.Consumer `foo-service` -[source,groovy] ----- -request { - url '/foo' - method GET() -} -response { - status OK() - body( - foo: "foo" - } -} ----- - -.Consumer `bar-service` -[source,groovy] ----- -request { - url '/bar' - method GET() -} -response { - status OK() - body( - bar: "bar" - } -} ----- -==== - -You cannot produce two different responses for the same request. That is why you can properly package the -contracts and then profit from the `stubsPerConsumer` feature. - -On the producer side, the consumers can have a folder that contains contracts related only to them. -By setting the `stubrunner.stubs-per-consumer` flag to `true`, we no longer register all stubs but only those that -correspond to the consumer application's name. In other words, we scan the path of every stub and, -if it contains a subfolder with name of the consumer in the path, only then is it registered. - -On the `foo` producer side the contracts would look like this - -[source,bash] ----- -. -└── contracts - ├── bar-consumer - │   ├── bookReturnedForBar.groovy - │   └── shouldCallBar.groovy - └── foo-consumer - ├── bookReturnedForFoo.groovy - └── shouldCallFoo.groovy ----- - -The `bar-consumer` consumer can either set the `spring.application.name` or the `stubrunner.consumer-name` to `bar-consumer` -Alternatively, you can set the test as follows: - -==== -[source,groovy] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerSpec.groovy[tags=test] -... -} ----- -==== - -Then only the stubs registered under a path that contains `bar-consumer` in its name (that is, those from the -`src/test/resources/contracts/bar-consumer/some/contracts/...` folder) are allowed to be referenced. - -You can also set the consumer name explicitly, as follows: - -==== -[source,groovy] ----- -include:../:{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/cloud/StubRunnerStubsPerConsumerWithConsumerNameSpec.groovy[tags=test] -... -} ----- -==== - -Then only the stubs registered under a path that contains the `foo-consumer` in its name (that is, those from the -`src/test/resources/contracts/foo-consumer/some/contracts/...` folder) are allowed to be referenced. - -For more information about the reasons behind this change, -see https://github.com/spring-cloud/spring-cloud-contract/issues/224[issue 224]. - diff --git a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-stubs-protocol.adoc b/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-stubs-protocol.adoc deleted file mode 100644 index c4085957a7..0000000000 --- a/docs/modules/ROOT/pages/_project-features-stubrunner/stub-runner-stubs-protocol.adoc +++ /dev/null @@ -1,121 +0,0 @@ -[[features-stub-runner-stubs-protocol]] -= Fetching Stubs or Contract Definitions From A Location - -Instead of picking the stubs or contract definitions from -Artifactory, Nexus, or Git, you can point to -a location on a drive or the classpath. Doing so can be especially useful in a multi-module project, where one module wants -to reuse stubs or contracts from another module without -the need to actually install those in a local maven -repository to commit those changes to Git. - -In order to achieve this, you can use the `stubs://` -protocol when the repository root parameter is set either -in Stub Runner or in a Spring Cloud Contract plugin. - -In this example, the `producer` project has been successfully -built and stubs were generated under the `target/stubs` folder. As a consumer, one can set up the Stub Runner to pick the stubs from that location by using the `stubs://` protocol. - -==== -[source,java,indent=0,subs="verbatim,attributes",role="primary"] -.Annotation ----- -@AutoConfigureStubRunner( -stubsMode = StubRunnerProperties.StubsMode.REMOTE, - repositoryRoot = "stubs://file://location/to/the/producer/target/stubs/", - ids = "com.example:some-producer") ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.JUnit 4 Rule ----- -@Rule - public StubRunnerRule rule = new StubRunnerRule() - .downloadStub("com.example:some-producer") - .repoRoot("stubs://file://location/to/the/producer/target/stubs/") - .stubsMode(StubRunnerProperties.StubsMode.REMOTE); ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.JUnit 5 Extension ----- -@RegisterExtension - public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension() - .downloadStub("com.example:some-producer") - .repoRoot("stubs://file://location/to/the/producer/target/stubs/") - .stubsMode(StubRunnerProperties.StubsMode.REMOTE); ----- -==== - -Contracts and stubs may be stored in a location, where each producer has its own, dedicated folder for contracts and stub mappings. Under that folder, each consumer can have its own setup. To make Stub Runner find the dedicated folder from the provided IDs, you can pass the `stubs.find-producer=true` property or the `stubrunner.stubs.find-producer=true` system property. -The following listing shows an arrangement of contracts and stubs: - -==== -[source,bash,indent=0] ----- -└── com.example <1> - ├── some-artifact-id <2> - │   └── 0.0.1 - │   ├── contracts <3> - │   │   └── shouldReturnStuffForArtifactId.groovy - │   └── mappings <4> - │   └── shouldReturnStuffForArtifactId.json - └── some-other-artifact-id <5> - ├── contracts - │   └── shouldReturnStuffForOtherArtifactId.groovy - └── mappings - └── shouldReturnStuffForOtherArtifactId.json - ----- -<1> group ID of the consumers -<2> consumer with artifact id [some-artifact-id] -<3> contracts for the consumer with artifact id [some-artifact-id] -<4> mappings for the consumer with artifact id [some-artifact-id] -<5> consumer with artifact id [some-other-artifact-id] -==== - -==== -[source,java,indent=0,subs="verbatim,attributes",role="primary"] -.Annotation ----- -@AutoConfigureStubRunner( -stubsMode = StubRunnerProperties.StubsMode.REMOTE, - repositoryRoot = "stubs://file://location/to/the/contracts/directory", - ids = "com.example:some-producer", - properties="stubs.find-producer=true") ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.JUnit 4 Rule ----- - static Map contractProperties() { - Map map = new HashMap<>(); - map.put("stubs.find-producer", "true"); - return map; - } - -@Rule - public StubRunnerRule rule = new StubRunnerRule() - .downloadStub("com.example:some-producer") - .repoRoot("stubs://file://location/to/the/contracts/directory") - .stubsMode(StubRunnerProperties.StubsMode.REMOTE) - .properties(contractProperties()); ----- - -[source,java,indent=0,subs="verbatim,attributes",role="secondary"] -.JUnit 5 Extension ----- - static Map contractProperties() { - Map map = new HashMap<>(); - map.put("stubs.find-producer", "true"); - return map; - } - -@RegisterExtension - public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension() - .downloadStub("com.example:some-producer") - .repoRoot("stubs://file://location/to/the/contracts/directory") - .stubsMode(StubRunnerProperties.StubsMode.REMOTE) - .properties(contractProperties()); ----- -==== - diff --git a/docs/modules/ROOT/pages/_project-features-wiremock.adoc b/docs/modules/ROOT/pages/_project-features-wiremock.adoc deleted file mode 100644 index fb4bfe4d0e..0000000000 --- a/docs/modules/ROOT/pages/_project-features-wiremock.adoc +++ /dev/null @@ -1,201 +0,0 @@ -[[features-wiremock]] -= Spring Cloud Contract WireMock - - -The Spring Cloud Contract WireMock modules let you use https://github.com/tomakehurst/wiremock[WireMock] in a -Spring Boot application. For more detail, check out the -https://github.com/spring-cloud/spring-cloud-contract/tree/{github-tag}/samples[samples]. - -If you have a Spring Boot application that uses Tomcat as an embedded server (which is -the default with `spring-boot-starter-web`), you can add -`spring-cloud-starter-contract-stub-runner` to your classpath and add `@AutoConfigureWireMock` -to use Wiremock in your tests. Wiremock runs as a stub server, and you -can register stub behavior by using a Java API or by using static JSON declarations as part of -your test. The following code shows an example: - -==== -[source,java,indent=0] ----- -include::{doc_samples_url}/src/test/java/com/example/WiremockForDocsTests.java[tags=wiremock_test1] -include::{doc_samples_url}/src/test/java/com/example/WiremockForDocsTests.java[tags=wiremock_test2] ----- -==== - -To start the stub server on a different port, use (for example), -`@AutoConfigureWireMock(port=9999)`. For a random port, use a value of `0`. The stub -server port can be bound in the test application context with the `wiremock.server.port` -property. Using `@AutoConfigureWireMock` adds a bean of type `WiremockConfiguration` to -your test application context, where it is cached between methods and classes -that have the same context. The same is true for Spring integration tests. Also, you can -inject a bean of type `WireMockServer` into your test. -The registered WireMock server is reset after each test class. -However, if you need to reset it after each test method, set the `wiremock.reset-mappings-after-each-test` property to `true`. - -[[features-wiremock-registering-stubs]] -== Registering Stubs Automatically - -If you use `@AutoConfigureWireMock`, it registers WireMock JSON stubs from the file -system or classpath (by default, from `file:src/test/resources/mappings`). You can -customize the locations by using the `stubs` attribute in the annotation, which can be an -Ant-style resource pattern or a directory. In the case of a directory, `**/*.json` is -appended. The following code shows an example: - -==== ----- -@RunWith(SpringRunner.class) -@SpringBootTest -@AutoConfigureWireMock(stubs="classpath:/stubs") -public class WiremockImportApplicationTests { - - @Autowired - private Service service; - - @Test - public void contextLoads() throws Exception { - assertThat(this.service.go()).isEqualTo("Hello World!"); - } - -} ----- -==== - -NOTE: Actually, WireMock always loads mappings from `src/test/resources/mappings` *as -well as* the custom locations in the `stubs` attribute. To change this behavior, you can -also specify a file root, as described in the xref:_project-features-wiremock.adoc#features-wiremock-using-files[next section of this document]. - -NOTE: Also, the mappings in the `stubs` location are not considered part of Wiremock's "default mappings" and calls -to `com.github.tomakehurst.wiremock.client.WireMock.resetToDefaultMappings` during a test do not result in the mappings -in the `stubs` location being included. However, the `org.springframework.cloud.contract.wiremock.WireMockTestExecutionListener` -does reset the mappings (including adding the ones from the stubs location) after every test class and, optionally, -after every test method (guarded by the `wiremock.reset-mappings-after-each-test` property). - -If you use Spring Cloud Contract's default stub jars, your -stubs are stored in the `/META-INF/group-id/artifact-id/versions/mappings/` folder. -If you want to register all stubs from that location, from all embedded JARs, you can use -the following syntax: - -==== -[source,java,indent=0] ----- -include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockFilesApplicationWithUrlResourceTests.java[tags=load_all_stubs] ----- -==== - -[[features-wiremock-using-files]] -== Using Files to Specify the Stub Bodies - -WireMock can read response bodies from files on the classpath or the file system. In the -case of the file system, you can see in the JSON DSL that the response has a `bodyFileName` instead of a -(literal) `body`. The files are resolved relative to a root directory (by default, -`src/test/resources/\__files`). To customize this location, you can set the `files` -attribute in the `@AutoConfigureWireMock` annotation to the location of the parent -directory (in other words, `__files` is a subdirectory). You can use a Spring resource -notation to refer to `file:...` or `classpath:...` locations. Generic URLs are not -supported. A list of values can be given -- in which case, WireMock resolves the first file -that exists when it needs to find a response body. - -NOTE: When you configure the `files` root, it also affects the -automatic loading of stubs, because they come from the root location -in a subdirectory called `mappings`. - -NOTE: The value of `files` has no -effect on the stubs loaded explicitly from the `stubs` attribute. - -[[features-wiremock-junit-rule]] -== Alternative: Using JUnit Rules - -For a more conventional WireMock experience, you can use JUnit `@Rules` to start and stop -the server. To do so, use the `WireMockSpring` convenience class to obtain an `Options` -instance, as the following example shows: - -==== -[source,java,indent=0] ----- -include::{doc_samples_url}/src/test/java/com/example/WiremockForDocsClassRuleTests.java[tags=wiremock_test1] -include::{doc_samples_url}/src/test/java/com/example/WiremockForDocsClassRuleTests.java[tags=wiremock_test2] ----- -==== - -The `@ClassRule` means that the server shuts down after all the methods in this class -have been run. - -[[features-wiremock-relaxed-ssl]] -== Relaxed SSL Validation for Rest Template - -WireMock lets you stub a "`secure`" server with an `https` URL protocol. If your -application wants to contact that stub server in an integration test, it finds that -the SSL certificates are not valid (the usual problem with self-installed certificates). -The best option is often to re-configure the client to use `http`. If that is not an -option, you can ask Spring to configure an HTTP client that ignores SSL validation errors -(do so only for tests, of course). - -To make this work with minimum fuss, you need to use the Spring Boot -`RestTemplateBuilder` in your application, as the following example shows: - -==== -[source,java,indent=0] ----- - @Bean - public RestTemplate restTemplate(RestTemplateBuilder builder) { - return builder.build(); - } ----- -==== - -You need `RestTemplateBuilder` because the builder is passed through callbacks to -initialize it, so the SSL validation can be set up in the client at that point. This -happens automatically in your test if you use the `@AutoConfigureWireMock` -annotation or the stub runner. If you use the JUnit `@Rule` approach, you need to add the -`@AutoConfigureHttpClient` annotation as well, as the following example shows: - -==== -[source,java,indent=0] ----- -@RunWith(SpringRunner.class) -@SpringBootTest("app.baseUrl=https://localhost:6443") -@AutoConfigureHttpClient -public class WiremockHttpsServerApplicationTests { - - @ClassRule - public static WireMockClassRule wiremock = new WireMockClassRule( - WireMockSpring.options().httpsPort(6443)); -... -} ----- -==== - -If you use `spring-boot-starter-test`, you have the Apache HTTP client on the -classpath, and it is selected by the `RestTemplateBuilder` and configured to ignore SSL -errors. If you use the default `java.net` client, you do not need the annotation (but it -does no harm). There is currently no support for other clients, but it may be added -in future releases. - -To disable the custom `RestTemplateBuilder`, set the `wiremock.rest-template-ssl-enabled` -property to `false`. - -[[features-wiremock-spring-mvc-mocks]] -== WireMock and Spring MVC Mocks - -Spring Cloud Contract provides a convenience class that can load JSON WireMock stubs into -a Spring `MockRestServiceServer`. The following code shows an example: - -==== -[source,java,indent=0] ----- -include::{doc_samples_url}/src/test/java/com/example/WiremockForDocsMockServerApplicationTests.java[tags=wiremock_test] ----- -==== - -The `baseUrl` value is prepended to all mock calls, and the `stubs()` method takes a stub -path resource pattern as an argument. In the preceding example, the stub defined at -`/stubs/resource.json` is loaded into the mock server. If the `RestTemplate` is asked to -visit `https://example.org/`, it gets the responses as being declared at that URL. More -than one stub pattern can be specified, and each one can be a directory (for a recursive -list of all `.json`), a fixed filename (as in the preceding example), or an Ant-style -pattern. The JSON format is the normal WireMock format, which you can read about at the -https://wiremock.org/docs/stubbing/[WireMock website]. - -Currently, the Spring Cloud Contract Verifier supports Tomcat, Jetty, and Undertow as -Spring Boot embedded servers, and Wiremock itself has "`native`" support for a particular -version of Jetty (currently 9.2). To use the native Jetty, you need to add the native -Wiremock dependencies and exclude the Spring Boot container (if there is one). diff --git a/docs/modules/ROOT/pages/advanced.adoc b/docs/modules/ROOT/pages/advanced.adoc deleted file mode 100644 index b1b48e2166..0000000000 --- a/docs/modules/ROOT/pages/advanced.adoc +++ /dev/null @@ -1,462 +0,0 @@ -[[contract-customization]] -= Spring Cloud Contract customization - -In this section, we describe how to customize various parts of Spring Cloud Contract. - -[[customization-customization]] -== DSL Customization - -IMPORTANT: This section is valid only for the Groovy DSL - -You can customize the Spring Cloud Contract Verifier by extending the DSL, as shown in -the remainder of this section. - -[[customization-extending]] -=== Extending the DSL - -You can provide your own functions to the DSL. The key requirement for this feature is to -maintain the static compatibility. Later in this chapter, you can see examples of: - -* Creating a JAR with reusable classes. -* Referencing of these classes in the DSLs. - -You can find the full example -https://github.com/spring-cloud-samples/spring-cloud-contract-samples[here]. - -[[customization-extending-common-jar]] -=== Common JAR - -The following examples show three classes that can be reused in the DSLs. - -`PatternUtils` contains functions used by both the consumer and the producer. -The following listing shows the `PatternUtils` class: - -==== -[source,java] ----- -include::{samples_url}/common/src/main/java/com/example/PatternUtils.java[] ----- -==== - -`ConsumerUtils` contains functions used by the consumer. -The following listing shows the `ConsumerUtils` class: - -==== -[source,java] ----- -include::{samples_url}/common/src/main/java/com/example/ConsumerUtils.java[] ----- -==== - -`ProducerUtils` contains functions used by the producer. -The following listing shows the `ProducerUtils` class: - -==== -[source,java] ----- -include::{samples_url}/common/src/main/java/com/example/ProducerUtils.java[] ----- -==== - -[[customization-test-dep]] -=== Adding a Test Dependency in the Project's Dependencies - -To add a test dependency in the project's dependencies, you must first add the common jar -dependency as a test dependency. Because your contracts files -are available on the test resources path, the common jar classes automatically become -visible in your Groovy files. The following examples show how to test the dependency: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- -include::{samples_url}/producer/pom.xml[tags=test_dep,indent=0] ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -include::{samples_url}/producer/build.gradle[tags=test_dep,indent=0] ----- -==== - -[[customization-plugin-dep]] -=== Adding a Test Dependency in the Plugin's Dependencies - -Now, you must add the dependency for the plugin to reuse at runtime, as the -following example shows: - -==== -[source,xml,indent=0,subs="verbatim,attributes",role="primary"] -.Maven ----- -include::{samples_url}/producer/pom.xml[tags=test_dep_in_plugin,indent=0] ----- - -[source,groovy,indent=0,subs="verbatim,attributes",role="secondary"] -.Gradle ----- -include::{samples_url}/producer/build.gradle[tags=test_dep_in_plugin,indent=0] ----- -==== - -[[customization-referencing]] -=== Referencing Classes in DSLs - -You can now reference your classes in your DSL, as the following example shows: - -==== -[source,groovy] ----- -include::{samples_url}/producer/src/test/resources/contracts/beer/rest/shouldGrantABeerIfOldEnough.groovy[indent=0] ----- -==== - -IMPORTANT: You can set the Spring Cloud Contract plugin up by setting `convertToYaml` to -`true`. That way, you do NOT have to add the dependency with the extended functionality -to the consumer side, since the consumer side uses YAML contracts instead of Groovy contracts. - -[[customization-wiremock]] -== WireMock Customization - -In this section, we show how to customize the way you work with https://wiremock.org[WireMock]. - -[[customization-wiremock-extension]] -=== Registering Your Own WireMock Extension - -WireMock lets you register custom extensions. By default, Spring Cloud Contract registers -the transformer, which lets you reference a request from a response. If you want to -provide your own extensions, you can register an implementation of the -`org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockExtensions` interface. -Since we use the `spring.factories` extension approach, you can create an entry similar to -the following in the `META-INF/spring.factories` file: - -==== -[source,groovy,indent=0] ----- -include::{stubrunner_core_path}/src/test/resources/META-INF/spring.factories[indent=0] ----- -==== - -The following example shows a custom extension: - -.TestWireMockExtensions.groovy -==== -[source,groovy,indent=0] ----- -include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/TestWireMockExtensions.groovy[indent=0] ----- -==== - -IMPORTANT: If you want the transformation to be applied only for a mapping that explicitly -requires it, override the `applyGlobally()` method and set it to `false` . - -[[customization-wiremock-configuration]] -=== Customization of WireMock Configuration - -You can register a bean of type `org.springframework.cloud.contract.wiremock.WireMockConfigurationCustomizer` -to customize the WireMock configuration (for example, to add custom transformers). -The following example shows how to do so: - -==== -[source,java,indent=0] ----- -include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockConfigurationCustomizerTests.java[tags=customizer_1] -// perform your customization here -include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/AutoConfigureWireMockConfigurationCustomizerTests.java[tags=customizer_2] ----- -==== - -[[customization-wiremock-from-metadata]] -=== Customization of WireMock via Metadata - -With version 3.0.0 you're able to set `metadata` in your contracts. If you set an entry with key equal to `wiremock` and the value -will be a valid WireMock's `StubMapping` JSON / map or an actual `StubMapping` object, Spring Cloud Contract will patch the generated -stub with part of your customization. Let's look at the following example - -[source,yaml,indent=0] ----- -include::{standalone_samples_path}/http-server/src/test/resources/contracts/yml/fraud/shouldReturnFraudStats.yml[tags=metadata,indent=0] ----- - -In the `metadata` section we've set an entry with key `wiremock` and its value is a JSON `StubMapping` that sets a delay in the generated stub. Such code allowed us to get the following merged WireMock JSON stub. - -[source,json,indent=0] ----- -{ - "id" : "ebae49e2-a2a3-490c-a57f-ba28e26b81ea", - "request" : { - "url" : "/yamlfrauds", - "method" : "GET" - }, - "response" : { - "status" : 200, - "body" : "{\"count\":200}", - "headers" : { - "Content-Type" : "application/json" - }, - "fixedDelayMilliseconds" : 2000, - "transformers" : [ "response-template" ] - }, - "uuid" : "ebae49e2-a2a3-490c-a57f-ba28e26b81ea" -} ----- - -The current implementation allows to manipulate only the stub side (we don't change the generated test). Also, what does not get changed -are the whole request and body and headers of the response. - -[[customization-wiremock-from-metadata-custom-processor]] -==== Customization of WireMock via Metadata and a Custom Processor - -If you want to apply a custom WireMock `StubMapping` post processing, you can under `META-INF/spring.factories` under the -`org.springframework.cloud.contract.verifier.converter.StubProcessor` key register your own implementation of a stub processor. For your convenience we've created an interface called `org.springframework.cloud.contract.verifier.wiremock.WireMockStubPostProcessor` that is dedicated to WireMock. - -You'll have to implement methods to inform Spring Cloud Contract whether the post processor is applicable for a given contract and how should the post processing look like. - -IMPORTANT: On the consumer side, when using Stub Runner, remember to pass the custom `HttpServerStubConfigurer` implementation (e.g. the one that extends `WireMockHttpServerStubConfigurer`) where you'll register a custom extension of your choosing. If you don't do so, even you have a custom WireMock extension on the classpath, WireMock will not notice it, won't apply it and will print out a warning statement that the given extension was not found. - -[[customization-pluggable-architecture]] -== Using the Pluggable Architecture - -You may encounter cases where your contracts have been defined in other formats, -such as YAML, RAML, or PACT. In those cases, you still want to benefit from the automatic -generation of tests and stubs. You can add your own implementation for generating both -tests and stubs. Also, you can customize the way tests are generated (for example, you -can generate tests for other languages) and the way stubs are generated (for example, you -can generate stubs for other HTTP server implementations). - -[[customization-custom-contract-converter]] -=== Custom Contract Converter - -The `ContractConverter` interface lets you register your own implementation of a contract -structure converter. The following code listing shows the `ContractConverter` interface: - -==== -[source,java] ----- -include::{contract_spec_path}/src/main/java/org/springframework/cloud/contract/spec/ContractConverter.java[indent=0,lines=17..-1] ----- -==== - -Your implementation must define the condition on which it should start the -conversion. Also, you must define how to perform that conversion in both directions. - -IMPORTANT: Once you create your implementation, you must create a -`/META-INF/spring.factories` file in which you provide the fully qualified name of your -implementation. - -The following example shows a typical `spring.factories` file: - -==== -[source] ----- -org.springframework.cloud.contract.spec.ContractConverter=\ -org.springframework.cloud.contract.verifier.converter.YamlContractConverter ----- -==== - -[[customization-custom-test-generator]] -=== Using the Custom Test Generator - -If you want to generate tests for languages other than Java or you are not happy with the -way the verifier builds Java tests, you can register your own implementation. - -The `SingleTestGenerator` interface lets you register your own implementation. The -following code listing shows the `SingleTestGenerator` interface: - -==== -[source,groovy] ----- -include::{verifier_core_path}/src/main/java/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.java[indent=0,lines=17..-1] ----- -==== - -Again, you must provide a `spring.factories` file, such as the one shown in the following -example: - -==== -[source] ----- -org.springframework.cloud.contract.verifier.builder.SingleTestGenerator=/ -com.example.MyGenerator ----- -==== - -[[customization-custom-stub-generator]] -=== Using the Custom Stub Generator - -If you want to generate stubs for stub servers other than WireMock, you can plug in your -own implementation of the `StubGenerator` interface. The following code listing shows the -`StubGenerator` interface: - -==== -[source,groovy] ----- -include::{converters_path}/src/main/java/org/springframework/cloud/contract/verifier/converter/StubGenerator.java[indent=0,lines=16..-1] ----- -==== - -Again, you must provide a `spring.factories` file, such as the one shown in the following -example: - -==== -[source] ----- -include::{converters_path}/src/main/resources/META-INF/spring.factories[indent=0] ----- -==== - -The default implementation is the WireMock stub generation. - -TIP: You can provide multiple stub generator implementations. For example, from a single -DSL, you can produce both WireMock stubs and Pact files. - -[[customization-custom-stub-runner]] -=== Using the Custom Stub Runner - -If you decide to use custom stub generation, you also need a custom way of running -stubs with your different stub provider. - -Assume that you use https://github.com/dreamhead/moco[Moco] to build your stubs and that -you have written a stub generator and placed your stubs in a JAR file. - -In order for Stub Runner to know how to run your stubs, you have to define a custom -HTTP Stub server implementation, which might resemble the following example: - -==== -[source,groovy] ----- -include::{tests_path}/spring-cloud-contract-stub-runner-moco/src/test/groovy/org/springframework/cloud/contract/stubrunner/provider/moco/MocoHttpServerStub.groovy[indent=0,lines=16..-1] ----- -==== - -Then you can register it in your `spring.factories` file, as the following -example shows: - -==== -[source] ----- -org.springframework.cloud.contract.stubrunner.HttpServerStub=\ -org.springframework.cloud.contract.stubrunner.provider.moco.MocoHttpServerStub ----- -==== - -Now you can run stubs with Moco. - -IMPORTANT: If you do not provide any implementation, the default (WireMock) -implementation is used. If you provide more than one, the first one on the list is used. - -[[customization-custom-stub-downloader]] -=== Using the Custom Stub Downloader - -You can customize the way your stubs are downloaded by creating an implementation of the -`StubDownloaderBuilder` interface, as the following example shows: - -==== -[source,java] ----- -package com.example; - -class CustomStubDownloaderBuilder implements StubDownloaderBuilder { - - @Override - public StubDownloader build(final StubRunnerOptions stubRunnerOptions) { - return new StubDownloader() { - @Override - public Map.Entry downloadAndUnpackStubJar( - StubConfiguration config) { - File unpackedStubs = retrieveStubs(); - return new AbstractMap.SimpleEntry<>( - new StubConfiguration(config.getGroupId(), config.getArtifactId(), version, - config.getClassifier()), unpackedStubs); - } - - File retrieveStubs() { - // here goes your custom logic to provide a folder where all the stubs reside - } - } - } -} ----- -==== - -Then you can register it in your `spring.factories` file, as the following -example shows: - -==== -[source] ----- -# Example of a custom Stub Downloader Provider -org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder=\ -com.example.CustomStubDownloaderBuilder ----- -==== - -Now you can pick a folder with the source of your stubs. - -IMPORTANT: If you do not provide any implementation, the default (scanning the classpath) is used. -If you provide the `stubsMode = StubRunnerProperties.StubsMode.LOCAL` or -`stubsMode = StubRunnerProperties.StubsMode.REMOTE`, the Aether implementation is used -If you provide more than one, the first one on the list is used. - -[[scm-stub-downloader]] -=== Using the SCM Stub Downloader - -Whenever the `repositoryRoot` starts with a SCM protocol -(currently, we support only `git://`), the stub downloader tries -to clone the repository and use it as a source of contracts -to generate tests or stubs. - -Through environment variables, system properties, or properties set -inside the plugin or the contracts repository configuration, you can -tweak the downloader's behavior. The following table describes the available -properties: - -.SCM Stub Downloader properties -|==== -|Type of a property |Name of the property | Description -| -* `git.branch` (plugin prop) - -* `stubrunner.properties.git.branch` (system prop) - -* `STUBRUNNER_PROPERTIES_GIT_BRANCH` (env prop) -|master -|Which branch to checkout - -| -* `git.username` (plugin prop) - -* `stubrunner.properties.git.username` (system prop) - -* `STUBRUNNER_PROPERTIES_GIT_USERNAME` (env prop) -| -|Git clone username - -| -* `git.password` (plugin prop) - -* `stubrunner.properties.git.password` (system prop) - -* `STUBRUNNER_PROPERTIES_GIT_PASSWORD` (env prop) -| -|Git clone password - -| -* `git.no-of-attempts` (plugin prop) - -* `stubrunner.properties.git.no-of-attempts` (system prop) - -* `STUBRUNNER_PROPERTIES_GIT_NO_OF_ATTEMPTS` (env prop) -|10 -|Number of attempts to push the commits to `origin` - -| -* `git.wait-between-attempts` (Plugin prop) - -* `stubrunner.properties.git.wait-between-attempts` (system prop) - -* `STUBRUNNER_PROPERTIES_GIT_WAIT_BETWEEN_ATTEMPTS` (env prop) -|1000 -|Number of milliseconds to wait between attempts to push the commits to `origin` -|==== diff --git a/docs/modules/ROOT/pages/appendix.adoc b/docs/modules/ROOT/pages/appendix.adoc deleted file mode 100644 index e88632a567..0000000000 --- a/docs/modules/ROOT/pages/appendix.adoc +++ /dev/null @@ -1,20 +0,0 @@ -:numbered!: -[appendix] -[[common-application-properties]] -= Common application properties -:page-section-summary-toc: 1 - - -Various properties can be specified inside your `application.properties` file, inside your `application.yml` file, or as command line switches. -This appendix provides a list of common {project-full-name} properties and references to the underlying classes that consume them. - -NOTE: Property contributions can come from additional jar files on your classpath, so you should not consider this an exhaustive list. -Also, you can define your own properties. - -[[default-application-properties]] -== Default application properties - - -[[additional-application-properties]] -== Additional application properties - diff --git a/docs/modules/ROOT/pages/docker-project.adoc b/docs/modules/ROOT/pages/docker-project.adoc deleted file mode 100644 index fce6ad412c..0000000000 --- a/docs/modules/ROOT/pages/docker-project.adoc +++ /dev/null @@ -1,627 +0,0 @@ -[[docker]] -= Docker Project - -In this section, we publish a `springcloud/spring-cloud-contract` Docker image -that contains a project that generates tests and runs them in `EXPLICIT` mode -against a running application. - -TIP: The `EXPLICIT` mode means that the tests generated from contracts send -real requests and not mocked ones. - -We also publish a `spring-cloud/spring-cloud-contract-stub-runner` Docker image -that starts the standalone version of Stub Runner. - -[[docker-intro]] -== A Short Introduction to Maven, JARs, and Binary Storage - -Since non-JVM projects can use the Docker image, it is good to -explain the basic terms behind Spring Cloud Contract packaging defaults. - -Parts of the following definitions were taken from the https://maven.apache.org/glossary.html[Maven Glossary]: - -- `Project`: Maven thinks in terms of projects. Projects -are all you build. Those projects follow a well defined -"`Project Object Model`". Projects can depend on other projects -- -in that case, the latter are called "`dependencies`". A project may -consistent of several subprojects. However, these subprojects are still -treated equally as projects. -- `Artifact`: An artifact is something that is either produced or used -by a project. Examples of artifacts produced by Maven for a project -include JAR files and source and binary distributions. Each artifact -is uniquely identified by a group ID and an artifact ID that is -unique within a group. -- `JAR`: JAR stands for Java ARchive. Its format is based on -the ZIP file format. Spring Cloud Contract packages the contracts and generated -stubs in a JAR file. -- `GroupId`: A group ID is a universally unique identifier for a project. -While this is often just the project name (for example, `commons-collections`), -it is helpful to use a fully-qualified package name to distinguish it -from other projects with a similar name (for example, `org.apache.maven`). -Typically, when published to the Artifact Manager, the `GroupId` gets -slash separated and forms part of the URL. For example, for a group ID of `com.example` -and an artifact ID of `application`, the result would be `/com/example/application/`. -- `Classifier`: The Maven dependency notation looks as follows: -`groupId:artifactId:version:classifier`. The classifier is an additional suffix -passed to the dependency -- for example, `stubs` or `sources`. The same dependency -(for example, `com.example:application`) can produce multiple artifacts that -differ from each other with the classifier. -- `Artifact manager`: When you generate binaries, sources, or packages, you would -like them to be available for others to download, reference, or reuse. In the case -of the JVM world, those artifacts are generally JARs. For Ruby, those artifacts are gems. -For Docker, those artifacts are Docker images. You can store those artifacts -in a manager. Examples of such managers include https://jfrog.com/artifactory/[Artifactory] -and https://www.sonatype.org/nexus/[Nexus]. - -[[docker-how-it-works]] -== Generating Tests on the Producer Side - -The image searches for contracts under the `/contracts` folder. -The output from running the tests is available in the -`/spring-cloud-contract/build` folder (useful for debugging -purposes). - -You can mount your contracts and pass the environment variables. -The image then: - -- Generates the contract tests -- Runs the tests against the provided URL -- Generates the https://github.com/tomakehurst/wiremock[WireMock] stubs -- Publishes the stubs to a Artifact Manager (optional -- turned on by default) - -[[docker-env-vars]] -=== Environment Variables - -The Docker image requires some environment variables to point to -your running application, to the Artifact manager instance, and so on. -The following list describes the environment variables: - -// TODO: reenable -//include::{project-root}/docker/spring-cloud-contract-docker/target/adoc/props.adoc[indent=0] - -The following environment variables are used when tests are run: - -// TODO: reenable -//include::{project-root}/docker/spring-cloud-contract-docker/target/adoc/appProps.adoc[indent=0] - -### Customizing the gradle build - -You can provide a customized `gradle.build` to be run in the container by mounting your customized build file as a volume when running the container: - -==== -[source,bash] ----- -$ docker run -v :/spring-cloud-contract/build.gradle springcloud/spring-cloud-contract: ----- -==== - -[[docker-example-of-usage]] -=== Example of Usage via HTTP - -In this section, we explore a simple MVC application. To get started, clone the following -git repository and cd to the resulting directory, by running the following commands: - -==== -[source,bash] ----- -$ git clone https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs -$ cd bookstore ----- -==== - -The contracts are available in the `/contracts` folder. - -Since we want to run tests, we can run the following command: - -==== -[source,bash] ----- -$ npm test ----- -==== - -However, for learning purposes, we split it into pieces, as follows: - -==== -[source,bash] ----- -# Stop docker infra (nodejs, artifactory) -$ ./stop_infra.sh -# Start docker infra (nodejs, artifactory) -$ ./setup_infra.sh - -# Kill & Run app -$ pkill -f "node app" -$ nohup node app & - -# Prepare environment variables -$ SC_CONTRACT_DOCKER_VERSION="..." -$ APP_IP="192.168.0.100" -$ APP_PORT="3000" -$ ARTIFACTORY_PORT="8081" -$ APPLICATION_BASE_URL="http://${APP_IP}:${APP_PORT}" -$ ARTIFACTORY_URL="http://${APP_IP}:${ARTIFACTORY_PORT}/artifactory/libs-release-local" -$ CURRENT_DIR="$( pwd )" -$ CURRENT_FOLDER_NAME=${PWD##*/} -$ PROJECT_VERSION="0.0.1.RELEASE" - -# Run contract tests -$ docker run --rm -e "APPLICATION_BASE_URL=${APPLICATION_BASE_URL}" -e "PUBLISH_ARTIFACTS=true" -e "PROJECT_NAME=${CURRENT_FOLDER_NAME}" -e "REPO_WITH_BINARIES_URL=${ARTIFACTORY_URL}" -e "PROJECT_VERSION=${PROJECT_VERSION}" -v "${CURRENT_DIR}/contracts/:/contracts:ro" -v "${CURRENT_DIR}/node_modules/spring-cloud-contract/output:/spring-cloud-contract-output/" springcloud/spring-cloud-contract:"${SC_CONTRACT_DOCKER_VERSION}" - -# Kill app -$ pkill -f "node app" ----- -==== - -Through bash scripts, the following happens: - -- The infrastructure (MongoDb and Artifactory) is set up. -In a real-life scenario, you would run the NodeJS application -with a mocked database. In this example, we want to show how we can -benefit from Spring Cloud Contract in very little time. -- Due to those constraints, the contracts also represent the -stateful situation. -** The first request is a `POST` that causes data to get inserted into the database. -** The second request is a `GET` that returns a list of data with 1 previously inserted element. -- The NodeJS application is started (on port `3000`). -- The contract tests are generated through Docker, and tests -are run against the running application. -** The contracts are taken from `/contracts` folder. -** The output of the test is available under -`node_modules/spring-cloud-contract/output`. -- The stubs are uploaded to Artifactory. You can find them in -http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/. -The stubs are at http://localhost:8081/artifactory/libs-release-local/com/example/bookstore/0.0.1.RELEASE/bookstore-0.0.1.RELEASE-stubs.jar. - -[[docker-example-of-usage-messaging]] -=== Example of Usage via Messaging - -If you want to use Spring Cloud Contract with messaging via the Docker images (e.g. -in case of polyglot applications) then you'll have to have the following prerequisites met: - -* Middleware (e.g. RabbitMQ or Kafka) must be running before generating tests -* Your contract needs to call a method `triggerMessage(...)` with a `String` parameter that is equal to the contract's `label`. -* Your application needs to have a HTTP endpoint via which we can trigger a message -** That endpoint should not be available on production (could be enabled via an environment variable) - -[[docker-example-of-usage-messaging-contract]] -==== Example of a Messaging Contract - -The contract needs to call a `triggerMessage(...)` method. That method is already provided in the base class for all tests in the docker image and will send out a request to the HTTP endpoint on the producer side. Below you can find examples of such contracts. - -==== -[source,groovy,indent=0,subs="verbatim,attributes",role="primary"] -.Groovy ----- -import org.springframework.cloud.contract.spec.Contract - -Contract.make { - description 'Send a pong message in response to a ping message' - label 'ping_pong' - input { - // You have to provide the `triggerMessage` method with the `label` - // as a String parameter of the method - triggeredBy('triggerMessage("ping_pong")') - } - outputMessage { - sentTo('output') - body([ - message: 'pong' - ]) - } - metadata( - [amqp: - [ - outputMessage: [ - connectToBroker: [ - declareQueueWithName: "queue" - ], - messageProperties: [ - receivedRoutingKey: '#' - ] - ] - ] - ]) -} ----- - -[source,yml,indent=0,subs="verbatim,attributes",role="secondary"] -.YAML ----- -description: 'Send a pong message in response to a ping message' -label: 'ping_pong' -input: - # You have to provide the `triggerMessage` method with the `label` - # as a String parameter of the method - triggeredBy: 'triggerMessage("ping_pong")' -outputMessage: - sentTo: 'output' - body: - message: 'pong' -metadata: - amqp: - outputMessage: - connectToBroker: - declareQueueWithName: "queue" - messageProperties: - receivedRoutingKey: '#' ----- -==== - -[[docker-example-of-usage-messaging-endpoint]] -==== HTTP Endpoint to Trigger a Message - -Why is there need to develop such an endpoint? Spring Cloud Contract -would have to generate code in various languages (as it does in Java) to make it possible to trigger production -code that sends a message to a broker. If such code is not generated then we need to be able to trigger the message anyways, and the way to do it is to provide an HTTP endpoint that the user will prepare in the language of their choosing. - -The endpoint must have the following configuration: - -- URL: `/springcloudcontract/{label}` where `label` can be any text -- Method: `POST` -- Basing on the `label` will generate a message that will be sent to a given destination according to the contract definition - -Below you have an example of such an endpoint. If you're interested in -providing an example in your language don't hesitate to file an issue in -the https://github.com/spring-cloud/spring-cloud-contract/issues/new?assignees=&labels=&template=feature_request.md&title=New+Polyglot+Sample+of+a+HTTP+controller[Spring Cloud Contract repository at Github]. - -==== -[source,python,indent=0,subs="verbatim,attributes"] -.Python ----- -#!/usr/bin/env python - -from flask import Flask -from flask import jsonify -import pika -import os - -app = Flask(__name__) - -# Production code that sends a message to RabbitMQ -def send_message(cmd): - connection = pika.BlockingConnection(pika.ConnectionParameters(host='localhost')) - channel = connection.channel() - channel.basic_publish( - exchange='output', - routing_key='#', - body=cmd, - properties=pika.BasicProperties( - delivery_mode=2, # make message persistent - )) - connection.close() - return " [x] Sent via Rabbit: %s" % cmd - -# This should be ran in tests (shouldn't be publicly available) -if 'CONTRACT_TEST' in os.environ: - @app.route('/springcloudcontract/