Step 12 - Using Webhooks
Move to step 12
git checkout step12
- Javascript
npm install
Learning Objectives
Step | Title | Concept Covered | Learning objectives | Further Reading |
---|---|---|---|---|
step 12 | Simulate Broker Webhooks | Automation |
|
honours course
When a consumer contract is published, we want to trigger a provider build, in order to verify the contract.
We can simulate this locally and explore the techniques involved.
Update your docker-compose file to support webhooks running from your local machine
- in
docker-compose.yaml
PACT_BROKER_WEBHOOK_SCHEME_WHITELIST: http
PACT_BROKER_WEBHOOK_HOST_WHITELIST: host.docker.internal
Recreate or Start the Pact Broker if its not already running
docker compose up -d
Start the fake broker webhook service
npm install
- we need to install the dependencies for a fake broker-webhook service.npm run start --prefix broker-webhook
> broker-webhook@1.0.0 start
> node server.js
## CI Simulator ## Broker webhook is listening on port 9090...
Publish a webhook to our Pact broker
npm run create-webhook --prefix broker-webhook
curl http://host.docker.internal:8000/webhooks \
-X POST --user pact_workshop:pact_workshop \
-H "Content-Type: application/json" -d @broker-create-body.json -v
This will send the following payload.
{
"events": [
{
"name": "contract_content_changed"
}
],
"request": {
"method": "POST",
"url": "http://host.docker.internal:9090",
"headers": {
"Content-Type": "application/json"
},
"body": {
"state": "${pactbroker.githubVerificationStatus}",
"description": "Pact Verification Tests ${pactbroker.providerVersionTags}",
"context": "${pactbroker.providerName}",
"target_url": "${pactbroker.verificationResultUrl}"
}
}
}
> broker-webhook@1.0.0 create-webhook
> ./create_webhook.sh
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
* Server auth using Basic with user 'pact_workshop'
> POST /webhooks HTTP/1.1
> Host: localhost:8000
> Authorization: Basic cGFjdF93b3Jrc2hvcDpwYWN0X3dvcmtzaG9w
> User-Agent: curl/8.1.2
> Accept: */*
> Content-Type: application/json
> Content-Length: 511
>
< HTTP/1.1 201 Created
< Vary: Accept
< Content-Type: application/hal+json;charset=utf-8
< Location: http://localhost:8000/webhooks/QxdSU5uCDllJTLDS_iLbNg
< Date: Fri, 29 Sep 2023 14:28:43 GMT
< Server: Webmachine-Ruby/2.0.0 Rack/1.3
< X-Pact-Broker-Version: 2.107.1
< X-Content-Type-Options: nosniff
< Content-Length: 926
<
* Connection #0 to host localhost left intact
{"uuid":"QxdSU5uCDllJTLDS_iLbNg","description":"POST host.docker.internal","enabled":true,"request":{"method":"POST","url":"http://host.docker.internal:9090","headers":{"Content-Type":"application/json"},"body":{"state":"${pactbroker.githubVerificationStatus}","description":"Pact Verification Tests ${pactbroker.providerVersionTags}","context":"${pactbroker.providerName}","target_url":"${pactbroker.verificationResultUrl}"}},"events":[{"name":"contract_content_changed"}],"createdAt":"2023-09-29T14:28:43+00:00","_links":{"self":{"title":"POST host.docker.internal","href":"http://localhost:8000/webhooks/QxdSU5uCDllJTLDS_iLbNg"},"pb:execute":{"title":"Test the execution of the webhook with the latest matching pact or verification by sending a POST request to this URL","href":"http://localhost:8000/webhooks/QxdSU5uCDllJTLDS_iLbNg/execute"},"pb:webhooks":{"title":"All webhooks","href":"http://localhost:8000/webhooks"}}}%
Run the consumer pact tests
npm run test:pact --prefix consumer
Publish the consumer pact tests
npm run pact:publish --prefix consumer
> consumer@0.1.0 pact:publish
> pact-broker publish ./pacts --consumer-app-version="1.0.1" --auto-detect-version-properties --broker-base-url=http://127.0.0.1:8000 --broker-username pact_workshop --broker-password pact_workshop
Created FrontendWebsite version 1.0.1 with branch all_steps
Pact successfully published for FrontendWebsite version 1.0.1 and provider ProductService.
View the published pact at http://127.0.0.1:8000/pacts/provider/ProductService/consumer/FrontendWebsite/version/1.0.1
Events detected: contract_published, contract_content_changed (first time untagged pact published)
Webhook QxdSU5uCDllJTLDS_iLbNg triggered for event contract_content_changed.
View logs at http://127.0.0.1:8000/triggered-webhooks/f8299b7a-53c4-4f5f-b4a8-7f87dbee1bdf/logs
Next steps:
* Add Pact verification tests to the ProductService build. See https://docs.pact.io/go/provider_verification
This will trigger the provider tests.
## CI Simulator ## Broker webhook is listening on port 9090...
Got webhook {"state":"pending","description":"Pact Verification Tests ","context":"ProductService","target_url":""}
Triggering provider tests...
provider-verification:
> product-service@1.0.0 test:pact
> jest --testTimeout 30000 --testMatch "**/*.pact.test.js"
Try publishing the contract again. You'll note the broker webhook does not trigger a 2nd time as the content has not changed.
> consumer@0.1.0 pact:publish
> pact-broker publish ./pacts --consumer-app-version="1.0.1" --auto-detect-version-properties --broker-base-url=http://127.0.0.1:8000 --broker-username pact_workshop --broker-password pact_workshop
Updated FrontendWebsite version 1.0.1 with branch step12
Pact successfully republished for FrontendWebsite version 1.0.1 and provider ProductService with no content changes.
View the published pact at http://127.0.0.1:8000/pacts/provider/ProductService/consumer/FrontendWebsite/version/1.0.1
Events detected: contract_published
No enabled webhooks found for the detected events
Try updating the version of the contract, in consumer/package.json
"pact:publish": "pact-broker publish ./pacts --consumer-app-version=\"1.0.2\" --auto-detect-version-properties --broker-base-url=http://127.0.0.1:8000 --broker-username pact_workshop --broker-password pact_workshop",
You'll again note, that as the contract version has changed, but the contents have not changed, since the last verification, the Pact Broker is aware of this, pre-verifying the Pact without needing to trigger the provider build.
> consumer@0.1.0 pact:publish
> pact-broker publish ./pacts --consumer-app-version="1.0.2" --auto-detect-version-properties --broker-base-url=http://127.0.0.1:8000 --broker-username pact_workshop --broker-password pact_workshop
Created FrontendWebsite version 1.0.2 with branch step12
Pact successfully published for FrontendWebsite version 1.0.2 and provider ProductService.
View the published pact at http://127.0.0.1:8000/pacts/provider/ProductService/consumer/FrontendWebsite/version/1.0.2
Events detected: contract_published (pact content is the same as previous versions with tags and no new tags were applied)
No enabled webhooks found for the detected events
If you update the Pact contracts and attempt to republish under an existing version number, you will be stopped by the Pact Broker.
This ensures contracts remain consistent once published.
> consumer@0.1.0 pact:publish
> pact-broker publish ./pacts --consumer-app-version="1.0.2" --auto-detect-version-properties --broker-base-url=http://127.0.0.1:8000 --broker-username pact_workshop --broker-password pact_workshop
Cannot change the content of the pact for ProductService version 1.0.2 and provider ProductService, as race conditions will cause unreliable results for can-i-deploy. Each pact must be published with a unique consumer version number. Some Pact libraries generate random data when a concrete value for a type matcher is not specified, and this can cause the contract to mutate - ensure you have given example values for all type matchers. For more information see https://docs.pact.io/go/versioning
... ,
{
"request": {
- "path": "/product/10"
+ "path": "/product/11"
}
},
... ,
Optional - Move on to step 13 for integrating with a PactFlow Broker