Tags

The Golden Rule for tagging is:

Tag with the branch name when you publish pacts or verification results, and tag with the environment name when you deploy.

To find out what this means, read below!

Tags are simple String values that that belong to "pacticipant" version (that is, application version) resources in the Pact Broker. They are typically used to provide metadata about a version - the most common use cases being to indicate the git branch of a version (eg. master) or a stage (eg test, prod).

Pacticipant version tags can be used for multiple purposes.

  • Tags can be used to enable you to test consumer and provider head and prod versions against each other. This allows you to decouple the release cycles of your consumer and provider. Read more about this here.
  • Tags can be used to enable you to add new interactions without breaking all the builds. Read more about this here.

Note that the tag is actually placed on the pacticipant version resource, not the pact itself (conceptually, you are indicating that that particular version of the application is a "prod" version, or a "feature-x" version). The URL structures, however, then allow you to retrieve pacts by the tags on their associated versions.

As an example, to tag Foo application version b5236e772 as the production version, do a PUT to the resource /pacticipants/Foo/versions/b5236e772/tags/prod. All the pacts and verifications associated with Foo version b5236e772 are now considered to be the production pacts/verifications. The pact for provider Bar and the latest production version of consumer Foo can be retrieved from /pacts/provider/Bar/consumer/Foo/latest/prod.

You may have noticed that the URL for a pacticipant version tag starts with /pacticipants, not /consumers or /providers. That is because consumer and provider are roles that a pacticipant takes in a pact, not identities in themselves. An application may be both a consumer and a provider.

When you are using tags, you need to ensure that the version numbering scheme you use to identify a "version" cannot give you version that exists on more than one repository branch - don't hard code it. It should either be the git sha (or equivalent for your repository), or it should include the git sha as metadata if you are using semantic versioning eg. 1.2.456+405b31ec6. See Versioning in the Pact Broker for more information.

"Latest" pacts

Please note that in the Pact Broker (unlike Docker) the term "latest" is not a tag name itself - it's a dynamic reference to the most recently created resource, like "HEAD" in git. The URL /pacts/provider/{provider}/consumer/{consumer}/latest refers to pact for the most recently created pacticipant version. The same URL with /{tag} appended refers to the pact for the most recently created pacticipant version that has the specified tag. Some Pact-JVM implementations require you to put the key word "latest" in the list of tags for verification when you want the overall latest pact. This is just an implementation choice of that particular client, and does not mean that there is or should be a tag called "latest". Please do not use the tag "latest" or you will get very confused when talking about the "latest latest pact", which would have a URL of /pacts/provider/Bar/consumer/Foo/latest/latest!

When are tags created?

When publishing pacts

Your Pact consumer library will allow you to set the "consumer version tags" that will be set for the relevant consumer version when you publish your pacts. The recommended tag value to use is the name of your git branch, if applicable, or something like dev, if not.

When publishing verification results

Your Pact provider library will allow you to set the "provider version tags" that will be set for the relevant provider version when you publish your verification results. The recommended tag value to use is the name of your git branch, if applicable, or something like dev, if not.

After deploying to an environment

Note: this tag is required for the use of can-i-deploy, however, if you are just starting with Pact, you can skip it for now.

When you deploy an application that uses Pact to a given environment (eg test, prod) then you should tag the relevant pacticipant version with the name of the stage using the create version tag command from the Pact Broker client. This allows other applications to use can-i-deploy to ensure that they're compatible with the version you just deployed before they deploy their own version.

Remember the Golden Rule for tagging is:

Tag with the branch name when you publish pacts or verification results, and tag with the environment name when you deploy.

When are tags used?

When retrieving pacts to verify

Providers should be configured to retrieve pacts by tag name (usually the "latest pact" for a given tag eg. the latest master and latest prod pacts).

Before deploying to an environment

The can-i-deploy tool queries the Pact Broker to determine if the version of the application you are about to deploy is compatible with the versions of the other applications that are already in that environment, and it uses tags to determine this. For example can-i-deploy --pacticipant Foo --version ad72df2 --to prod will tell the Pact Broker to look up the latest version with the tag prod for each of Foo's integrations partners, and see if there is a successfully verified pact between that version and version ad72df2 of Foo.

Retrieving pacts

  • /pacts/provider/PROVIDER/consumer/CONSUMER/latest/TAG will return the pact associated with the latest pacticipant version that has the specified tag.
  • /pacts/provider/PROVIDER/consumer/CONSUMER/latest-untagged will return the pact for the latest pacticipant version that doesn't have any tags.
  • /pacts/provider/PROVIDER/consumer/CONSUMER/latest will return the pact for the latest pacticipant version, regardless of tags.

Creating tags

Most of the Pact libraries will provide configuration options to create tags automatically when publishing pacts or verification results.

If you need to create a tag manually, then you can use the Pact Broker Client CLI, or send a PUT request to the tag resource path.

When publishing pacts

This is a Javascript example, assuming that the build is running on Travis CI. Please consult the documentation for your chosen Pact language for the relevant syntax for your codebase.

const opts = {
pactFilesOrDirs: ['./pacts'],
pactBroker: '...',
consumerVersion: process.env.TRAVIS_COMMIT,
tags: [process.env.TRAVIS_BRANCH]
}
new Publisher(opts).publishPacts()

Once you have your Pact CI/CD implementation running properly, you would only publish your pacts and verification results from your CI, and not your local development machines. However, if you are in the experimentation stage and wish to publish from your local machine, you can set the version and tags from your local git repository like so:

const exec = command =>
childProcess
.execSync(command)
.toString()
.trim() //must trim to remove the new line on the end!
const opts = {
...,
consumerVersion: process.env.TRAVIS_COMMIT || exec('git rev-parse HEAD'),
tags: [process.env.TRAVIS_BRANCH || exec('git rev-parse --abbrev-ref HEAD')]
}
new Publisher(opts).publishPacts()

When publishing verification results

const opts = {
pactBrokerUrl: '...',
providerVersion: process.env.TRAVIS_COMMIT,
providerVersionTags: [process.env.TRAVIS_BRANCH],
publishVerificationResult: process.env.CI === 'true' // only publish from CI
}
return new Verifier(opts).verifyProvider()

Using tags

When verifying pacts

If you have reached the stage of Pact CI/CD maturity where you are tagging with the environment name and using can-i-deploy, then you should verify the pact from each environment to ensure that can-i-deploy returns a yes result when promoting a version through the environments.

If you are just starting out with Pact, then we recommend you just start by verifying the master pact (or whatever you have called the tag for your main line of development.)

const opts = {
...,
consumerVersionTags: ['master', 'test','production'],
}
return new Verifier(opts).verifyProvider()

When deploying

See the can-i-deploy documentation.

Deleting tags

At the moment, there is no CLI to delete a tag, but you can delete it via the API by sending a DELETE request to the tag resource URL. eg curl -X DELETE https://broker/pacticipants/PACTICIPANT/versions/VERSION/tags/TAG.

The most common reason for deleting tags is if you are rolling back to a previously deployed application version.

Adding new interactions

In summary: keep the CI running against a stable version of the pact, while simultaneously providing a new version for the provider team so they can update their code and provider states. Once both the stable and the new versions of the pact are green, the new version can be published as the stable version.

Remember: just because you're doing consumer driven contracts doesn't meant that the consumer team gets to tell the provider team what to do. Please remember that the best results will be achieved by a collaborative approach between the two teams. Communicate with your nice human words folks.

Ensuring backwards compatibility

If you want to ensure your provider is compatible with both the head version of your consumer, and the production version, you can use pact tagging to achieve this. To read more about this idea, check out this blog post on decoupling the release cycles of your services.

Step 1. Tag the production version of the pact

Use the create-version-tag command from the Pact Broker Client CLI.

Step 2. Configure the provider to verify the production pact

Add the production tag to the list of tags to verify in your provider's verification configuration.

Handling rollbacks

When the Pact Broker is determining "the latest production application version" or "the latest production pact" the logic it uses is "find all the pacticipant versions that have the production tag, and return the most recently created one", NOT "find the most recently created production tag, and then return the associated pacticipant version".

This means that if you are rolling back to a previously deployed (and hence, previously tagged) application version, you need to remove the production tag from the version you are undeploying. See the Deleting tags section.

Last updated on by Elliott Murray