How Can I Use Git as the Storage for Contracts and Stubs?
在多语言世界中,有一些语言不使用二进制存储,就像 Artifactory 和 Nexus 所做的那样。从 Spring Cloud Contract 版本 2.0.0 开始,我们提供了一种机制,用于在 SCM(源代码管理)存储库中存储合同和存根。目前,唯一受支持的 SCM 是 Git。 存储库必须具有以下设置(你可以从 here 中检出):
.
└── META-INF
└── com.example
└── beer-api-producer-git
└── 0.0.1-SNAPSHOT
├── contracts
│ └── beer-api-consumer
│ ├── messaging
│ │ ├── shouldSendAcceptedVerification.groovy
│ │ └── shouldSendRejectedVerification.groovy
│ └── rest
│ ├── shouldGrantABeerIfOldEnough.groovy
│ └── shouldRejectABeerIfTooYoung.groovy
└── mappings
└── beer-api-consumer
└── rest
├── shouldGrantABeerIfOldEnough.json
└── shouldRejectABeerIfTooYoung.json
在 META-INF
文件夹下:
-
我们按
groupId
(例如com.example
)对应用程序进行分组。 -
每个应用程序由其
artifactId
(例如beer-api-producer-git
)表示。 -
接下来,每个应用程序按其版本(例如
0.0.1-SNAPSHOT
)进行组织。从 Spring Cloud Contract 版本2.1.0
开始,你可以如下指定版本(假设你的版本遵循语义版本控制):-
+
或latest
:查找存根的最新版本(假设快照始终是给定修订号的最新构件)。这意味着:-
如果你有
1.0.0.RELEASE
、2.0.0.BUILD-SNAPSHOT
和2.0.0.RELEASE
,我们假设最新的是2.0.0.BUILD-SNAPSHOT
。 -
如果你有
1.0.0.RELEASE
和2.0.0.RELEASE
,我们假设最新的是2.0.0.RELEASE
。 -
如果你有称为
latest
或+
的版本,我们将选择该文件夹。
-
-
release
: 查找 Stub 的最新版本。这意味着:-
如果您有
1.0.0.RELEASE
、2.0.0.BUILD-SNAPSHOT
、和2.0.0.RELEASE
,我们假设最新版本是2.0.0.RELEASE
。 -
如果有一个名为
release
的版本,我们将选择该文件夹。
-
-
最后,有两个文件夹:
-
contracts
: 一个好做法是将每个使用者所需的合同存储在带有使用者名称的文件夹中(例如beer-api-consumer
)。这样,您可以使用stubs-per-consumer
功能。其他目录结构是任意的。 -
mappings
: Maven 或 Gradle Spring Cloud Contract 插件将 Stub Server 映射推送到该文件夹中。在使用者侧,Stub Runner 将扫描此文件夹,使用 Stub 定义启动 Stub Server。此文件夹结构是contracts
子文件夹中所创建的结构的副本。
Protocol Convention
为了控制合同来源的类型和位置(无论是个二进制存储还是一个 SCM 资源库),你可以在资源库的 URL 中使用协议。Spring Cloud Contract 会重复使用已注册协议解析器并尝试提取合同(使用插件)或存根(从存根运行器)。
对于 SCM 功能,我们目前支持 Git 资源库。要使用它,在需要放置资源库 URL 的属性中,你必须在连接 URL 前加上 git://
。下列清单显示了一些示例:
git://file:///foo/bar
git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git
git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git
Producer
对于生产者来说,要使用 SCM(源代码管理)方法,我们可以重复使用我们用于外部合同的相同机制。我们将 Spring Cloud Contract 路由到使用以 git://
协议开头的 URL 的 SCM 实现。
您必须在 Maven 中手动添加`pushStubsToScm`目标或使用 Gradle(绑定)pushStubsToScm`任务。我们不会将存根推送到您的 Git 存储库的`origin
。
下列清单包含相关的 Maven 和 Gradle 构建文件:
-
Maven
-
Gradle
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<!-- Base class mappings etc. -->
<!-- We want to pick contracts from a Git repository -->
<contractsRepositoryUrl>git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git</contractsRepositoryUrl>
<!-- We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts -->
<contractDependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</contractDependency>
<!-- The contracts mode can't be classpath -->
<contractsMode>REMOTE</contractsMode>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<!-- By default we will not push the stubs back to SCM,
you have to explicitly add it as a goal -->
<goal>pushStubsToScm</goal>
</goals>
</execution>
</executions>
</plugin>
contracts {
// We want to pick contracts from a Git repository
contractDependency {
stringNotation = "${project.group}:${project.name}:${project.version}"
}
/*
We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts
*/
contractRepository {
repositoryUrl = "git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git"
}
// The mode can't be classpath
contractsMode = "REMOTE"
// Base class mappings etc.
}
/*
In this scenario we want to publish stubs to SCM whenever
the `publish` task is invoked
*/
publish.dependsOn("publishStubsToScm")
你还可以进一步自定义 publishStubsToScm
Gradle 任务。在下面的示例中,此任务已自定义为从本地 git 资源库中提取合同:
publishStubsToScm {
// We want to modify the default set up of the plugin when publish stubs to scm is called
// We want to pick contracts from a Git repository
contractDependency {
stringNotation = "${project.group}:${project.name}:${project.version}"
}
/*
We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts
*/
contractRepository {
repositoryUrl = "git://file://${new File(project.rootDir, "../target")}/contract_empty_git/"
}
// We set the contracts mode to `LOCAL`
contractsMode = "LOCAL"
}
- IMPORTANT
-
Starting with the
2.3.0.RELEASE
, thecustomize{}
closure previously used for thepublishStubsToScm
customization is no longer available. The settings should be applied directly within thepublishStubsToScm
closure, as in the preceding example.
使用此设置:
-
一个 git 项目会被克隆到一个临时目录
-
SCM Stub 下载程序会转到
META-INF/groupId/artifactId/version/contracts
文件夹以查找合同。例如,对于com.example:foo:1.0.0
,路径将为META-INF/com.example/foo/1.0.0/contracts
。 -
测试从合同生成。
-
Stubs 从合同生成。
-
一旦测试通过,Stub 会提交到所克隆的代码库。
-
最后,会向该代码库的
origin
发送一个 push。
Producer with Contracts Stored Locally
Другой возможностью использования SCM в качестве назначения для заглушек и контрактов является локальное хранение контрактов у изготовителя и отправка только контрактов и заглушек в SCM. В следующем [проекте] {samples_url}/producer_with_empty_git/ показана настройка, необходимая для этого с помощью Maven и Gradle.
使用此设置:
-
会选择默认
src/test/resources/contracts
目录的合同。 -
测试从合同生成。
-
Stubs 从合同生成。
-
Once the tests pass:
-
Git 项目会被克隆到一个临时目录。
-
Stubs 和合同会被提交到所克隆的代码库中。
-
-
最后,会向该代码库的
origin
执行一个 push。
Keeping Contracts with the Producer and Stubs in an External Repository
你还可以将合同保存在生产者资源库中,但将存根保存在外部 git 资源库中。当你想要使用基础消费者-生产者协作流程但不能使用工件资源库存储存根时,此操作最有用。
要做到这一点,请使用常规生产者设置,然后添加 pushStubsToScm
目标并设置 contractsRepositoryUrl
到你想为存根保留的资源库中。
Consumer
在消费者方面,当你从 @AutoConfigureStubRunner
注释、JUnit 4 规则、JUnit 5 扩展或属性传递 repositoryRoot
参数时,你可以传递 SCM 资源库的 URL,该 URL 以 git://
协议为前缀。以下示例展示如何做到这一点:
@AutoConfigureStubRunner(
stubsMode="REMOTE",
repositoryRoot="git://https://github.com/spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git",
ids="com.example:bookstore:0.0.1.RELEASE"
)
使用此设置:
-
Git 项目会被克隆到一个临时目录。
-
SCM Stub 下载程序会转到
META-INF/groupId/artifactId/version/
文件夹以查找 Stub 定义和合同。例如,对于com.example:foo:1.0.0
,路径将为META-INF/com.example/foo/1.0.0/
。 -
Stub Server 会启动并使用映射进行填充。
-
消息定义会读取,并用于消息测试中。