Using Pact successfully requires you to understand how Pact works and the concepts and terminology behind Pact. If you try to build your CI/CD without this foundational understanding, you may find yourself getting confused or getting unexpected results.
Consumers and publishing pacts
Whenever a consumer runs a contract test for a particular provider and it succeeds, a file is generated that records all of the interactions between the consumer and the provider. This record is called a pact.
In your CI/CD environment, every time you run the contract tests, the resulting pact will be published to the Pact Broker. This is called a pact publication.
Whenever the consumer changes, this is called a consumer version. The version is often identified by its git hash. You may also want to add other distinguishing information, such as the feature toggle name if you are using feature toggles or feature branches, if you are using feature branches. In general, you want to uniquely identify each version of the consumer that may be deployed to an environment which may require a different contract.
A given pact published by the consumer may or may not change actual contents of the pact (e.g. by adding a request parameter, or changing the expected results). If it does change, then the pact gets a new pact version.
It's important to understand a few rules about how consumers relate to pacts:
- Multiple versions of the consumer can have the same pact version (if the changes to the consumer don't change the pact)
- A specific version of the consumer will always have exactly one pact version for each provider.
Branches & Environments
THE GOLDEN RULE FOR LABELLING
At any point you may want to label a particular version of the consumer with one or more identifiers. For example, you can identify the consumer with its current branch (e.g. a PR branch or the main branch), or you can identify it with the environment it has been deployed to.
Branches in the Pact Broker are designed to model repository (git, svn etc) branches. A branch in the Pact Broker belongs to an application. A branch may have many application versions, and an application version may belong to many branches (but typically, it will belong to just one).
note: if you are using feature toggles or other configuration systems that change the behavior depending on a configuration. The same commit in a repository may interact with different versions of a pact, and therefore require different pacticipant versions
We recommend that you set the branch property when you publish pacts and verification results, and use record-deployment or record-release when you deploy/release.
The general recommendation is to set the branch name when you publish a pact, and set with the environment when you deploy. I'll discuss later how we use labels to help answer the question: can I deploy?
For example, let's say you have a PetStoreConsumer application. Every time you change it that's a new version of the application. When you run contract tests for that version, you publish a new pact publication to the broker, which may or may not generate a new pact version.
|Date||Consumer Versions||branches||environment||Pact Version|
Here we see that:
- Version 63be8b is deployed to prod and is in the main branch.
- Version 9ecb61 is deployed to staging, and is also in the main branch. It has changed the pact, so it has a new pact version.
- Version 31696e is in a feature branch and has not been deployed anywhere. It did not change the pact, so the pact version remains the same
- Version 3b4de7 is in a different feature branch. It did change the pact, so we now have a new pact version
A caveat about Pact terminology
If you are not new to Pact, you may have heard of the terminology
tag, if so, please read this section, otherwise you can skip this note.
Tags that represent branches and environments, while still supported, have been superseded by first class support for branches and environments from version 2.82.0 onwards. Please read this post for more information. You'll find links at the bottom of this post to help you migrate from tags to branches and environments.
Verifying the pact
We need to know if a particular pact version will work with a particular version of the provider. This is done by running a verification, where Pact replays the interactions against the provider and ensures that the providers responses match the consumer's expectations recorded in the pact.
In our CI/CD environment, every time we run a verification, the results will be published to the Pact Broker. This is called a verification result.
Whenever the provider changes, this is called a provider version (usually identified by its git hash plus other identifying information like a toggle name).
Just as with a consumer, you may want to label a particular version of the provider with one or more branch label. For example, you can label the provider with its
current branch (e.g. a PR branch or the main branch), or you can label it with the environment it has been deployed to.
The general recommendation is to set a label of the branch name when a verification passes, and record a deployment to environment name (like "prod" or "staging") when the provider is deployed to that environment.
Let's expand the example from above to include the provider and its verifications.
|Date||Provider Version||branches||environment||Verified against pact versions|
Note that provider version 35a850 in the feat-X branch has not been verified against pact version 1. Because that's the version that the prod consumer is at, it is not safe to deploy this version of the provider to prod. You probably also don't want to merge it into main until this gets fixed. Similarly provider version 741a54 has only verified pact version 3. So it's not safe to deploy to either staging or prod, and should definitely not be merged to main.
Generalizing: the pacticipant
We have generalized the "consumer" and "provider" roles of a pact using the term pacticipant. A particular pact publication has two pacticipants: the consumer and the provider. A verification result also has two pacticipants: the consumer and the provider.
This generalized concept of a pacticipant can be useful because sometimes you can perform the same operations on a pacticipant regardless of whether it is a consumer or a provider.