Skip to main content

· 4 min read

When following the "consumer driven" workflow, often the contract will change to express the desired functionality before the implementation exists in the provider. This means that when the changed pact is verified against the provider, the verification step fails, and until recently, this meant that the provider's build would also fail. (This has been fixed with the release of the pending pacts feature.) The recommended approach to avoid breaking the provider's build is to use "tags" to distinguish between the "safe" contracts and the changed contracts (tags are metadata that get applied to the application version resource in the Pact Broker that can be used to identify which branch or stage the version belongs to eg. master, feat/foo or prod). By making changes to the pact on a branch of the consumer (eg feat/foo) and publishing it with a matching tag, a provider that was configured to verify master pacts would not have its build broken.

For the consumer to get a verification result for the feat/foo pact, however, manual action was required from the provider team. They would need to add the feat/foo pact to the list of pacts to verify, generally on a feature branch of their own to avoid breaking the master build. There was no automated workflow to include the newly changed pacts in the provider's list of pacts to verify.

The solution

To solve this problem, we've introduced the concept of "WIP" (work in progress) pacts. "WIP pacts" is built on top of the recently released pending pacts feature which allows changed pacts to be verified without failing the build. Previously, during a verification step, only the pacts for the configured tags (eg master and prod) would be verified. With the WIP pacts feature enabled, all pacts that are the latest for their tag that have not yet been successfully verified will now also be automatically verified - in pending mode. This allows consumers to get feedback on whether or not their changed pacts are valid, without the provider team having to take action, and without breaking the provider build.

Let's walk through an example. Imagine FooApp and BarAPI have a pact. BarAPI is configured to verify the master and prod pacts for FooApp during its verification step. When it publishes the verification results, its own application version is tagged with the branch name. We'll just consider the builds that run on the BarAPI master branch for now.

FooApp creates a branch called feat/x, makes a change to the contract, and then publishes it with the feat/x tag. When the BarAPI build executes, it runs the verification task for the configured master and prod pacts as normal, but it also now verifies the feat/x pact in pending mode, and publishes the results back to the broker. Publishing the failed results allows the consumer team gets the feedback for feat/x pact, and the fact that it runs in pending mode means that even though the feat/x pact fails verification, the BarAPI build remains green.

A few days later, the BarAPI team implements the changes required for the feat/x pact. During the BarAPI CI build, master, prod and feat/x pacts are verified and the results published, but this time, the verification of the feat/x pact passes. The Pact Broker now knows that the master branch of the provider supports the feat/x contract, and from then on it ceases to be a WIP pact for master BarAPI versions. The next time the BarAPI build runs, it will not include the feat/x pact.

Now the action is on the consumer team to merge the feat/x branch into their own master branch. Using webhooks that update the Git commit status or posting to a Slack channel is a good way to notify the consumer team that their pact is now green.

A note for advanced Pact Broker users

As noted in the blog on the pending pacts feature, the pending status is calculated based on the tags that will be applied to the provider version when the verification results are published. This means that a pact that has been successfully verified by the feat/bar branch of your provider, but not master, will still be included in the "work in progress" pacts for master builds, but not for feat/bar builds.

How do I start using WIP pacts?

Head to https://docs.pact.io/wip for information on how to setup your Pact Broker (it is enabled by default on https://pactflow.io)

To start getting the benefit of this new and improved workflow, you will need to upgrade to the latest version of the Pact Broker and your Pact testing libraries. Consult the documentation for your language to find out how to enable the WIP pacts feature.

· One min read

If you use Pact and would like to support us in realising our vision of transforming the way teams test and release distributed systems, we have recently released Pactflow - our fully managed Pact Broker with additional features to simplify teams getting started and scaling with Pact and contract testing.

Read our launch announcement for more background as to why and how this all came about. It's just the start, but we're really excited about the future.

If you're hosting your own broker, or are looking to set one up, you can get started quickly and for free on our Developer Plan.

We hope to see you soon!

· 3 min read

REST is dead, long live REST

GraphQL is being hailed by many as the new REST - it has type safety, a neat DSL and a great ecosystem. Perhaps best of all, it focuses on the needs of the client; consumers get the data they want, in the shape they want it - nothing more and nothing less.

I can now fetch data from my BFF via my React Component with caching, error handling and state management all taken care of for me, just like so:

import { Query } from "react-apollo";
import gql from "graphql-tag";

const ExchangeRates = () => (
<Query
query={gql`
{
rates(currency: "USD") {
currency
rate
}
}
`}
>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;

return data.rates.map(({ currency, rate }) => (
<div key={currency}>
<p>{`${currency}: ${rate}`}</p>
</div>
));
}}
</Query>
);

For some, however, this ability to define a schema and even generate client code, harkens back to the brittle and dark ages of WSDL, whereby clients are tightly coupled to their API implementation.

Can we have our cake and it it too?

 

If you look under the covers, it turns out GraphQL is actually just a simple abstraction over REST, which means we can still test GraphQL as we do with regular RESTful APIs - including using contract testing! 🙌

GraphQL (mostly) follows just a few simple rules:

  1. Requests are made via an HTTP POST
  2. GraphQL queries are sent as stringified JSON contained within a query property of the request
  3. The response body is wrapped in the data sub-property, namespaced by the operation (Query or Mutation) that is being called, alongside any errors for the operation.

Read more about the GraphQL specification here

Constructing a basic cURL for a simplistic hello operation looks something like this:

curl -X POST \
-H 'content-type: application/json' \
-d '{ "query": "{ hello }" }' \
http://someapi/api

Whilst you can create this request using the usual Pact DSL, in our latest version of Pact JS (6.x.x or @prerelease) we have even created a GraphQLInteraction interface to simplify creating the expectations - including variables support and matching rules:

  const graphqlQuery = new GraphQLInteraction()
.uponReceiving("a hello request")
.withQuery(`{ hello(person: $person }`)
.withRequest({
path: "/graphql",
method: "POST",
})
.withVariables({
person: "Sally",
})
.willRespondWith({
status: 200,
headers: {
"Content-Type": "application/json; charset=utf-8",
},
body: {
data: {
hello: like("Hello Sally"),
},
},
});

So there it is, Pact + GraphQL: a match made in heaven.

· 2 min read

If you're using Travis CI, Code Climate, or one of many other CI tools with Github, you've probably noticed the little checklist of items that shows just above the "merge" button when you open a pull request.

commit-statuses

These are called commit "statuses", and there is a Github API for reporting these (Gitlab also has a similar API). If you are using a git sha for the consumer version number when you publish your pacts, you can now use Pact Broker webhooks to report the verification statuses of your pacts back to Github.

To do this, open up your Pact Broker API Browser, and click on the NON-GET button next to the pb:webhooks relation. Modify the JSON below to match your consumer, repository and Github auth details (we recommend you make a separate token for this purpose with the repo:status grant), and click Make Request.

{
"consumer": {
"name": "<consumer name>"
},
"events": [
{
"name": "contract_published"
},
{
"name": "provider_verification_published"
}
],
"request": {
"method": "POST",
"url": "https://api.github.com/repos/<organization>/<project>/statuses/${pactbroker.consumerVersionNumber}",
"headers": {
"Content-Type": "application/json"
},
"body": {
"state": "${pactbroker.githubVerificationStatus}",
"description": "Pact Verification Tests ${pactbroker.providerVersionTags}",
"context": "${pactbroker.providerName}",
"target_url": "${pactbroker.verificationResultUrl}"
},
"username": "USERNAME",
"password": "PASSWORD"
}
}

If all your consumer names match their repository names in Github, you can make this a global webhook by removing the consumer node, and replacing the hardcoded <project> name in the URL with the parameter ${pactbroker.consumerName}.

Want to use this cool feature? You'll need version 2.47.1 or later of the Pact Broker.

Check out the webhook template library for more handy webhooks.

· 2 min read

The can-i-deploy tool is a CLI that ensures you are safe to deploy a consumer or provider into a given environment. To do this, it queries the Pact Broker to ensure that there is a successful verification result between the existing application versions and the application version you're about to deploy.

If you deploy to a test environment as part of your build pipeline, you may find yourself in the situation where the verification result is unknown because the provider build is still running. What typically would happen is that a changed pact would trigger a provider build via a webhook in the Pact Broker, and the provider may not have finished before can-i-deploy is invoked.

To help out in this scenario, you can now use the following two options to let the can-i-deploy command poll until all the verification results arrive.

[--retry-while-unknown=TIMES] 
# The number of times to retry while there is an unknown
# verification result
# (ie. the provider verification is likely still running)
# Default: 0
[--retry-interval=SECONDS]
# The time between retries in seconds.
# Use in conjuction with --retry-while-unknown
# Default: 10

Remember, however, that changes to pacts are best introduced on feature branches of your consumer. This allows your pact to be "pre-verified" by the time the branch is merged into master, which will mean can-i-deploy should never block your master build.

You can read about how to do this in The steps to reaching Pact Nirvana.

Want to use this new feature? You'll need version 1.48.0 or later of the Pact CLI, and version 2.23.4 or later of the Pact Broker

· One min read

Pact is a tool for implementing "consumer driven contracts" - a technique for testing integrations without using traditional integration tests. It was first written at realestate.com.au to help a team of developers escape the integration test hell of a rapidly expanding HTTP microservices network, and has since grown to become an open source project for contract testing in multiple languages and protocols.

Since its creation in 2013, Pact has come a long way. We're always adding new features in response to the feedback we get from our users and our own experience, but recently we've realised that we've done a poor job of letting everyone know about the awesome new things we've added along the way.

So, we've started docs.pact.io/blog as a place to let everyone know about new features in Pact, to share people's Pact experiences (good and bad!), and to help build a community of Pact users who can help each other. If you haven't already, please join us at slack.pact.io, and if you'd like to contribute a post to our blog, chat to us on the #blog channel.