pact-foundation / pact_broker

Enables your consumer driven contracts workflow
http://pactflow.io
MIT License
701 stars 171 forks source link

Master issue for new 'pacts for verification' endpoint #307

Closed bethesque closed 3 years ago

bethesque commented 4 years ago

Audience

This issue is for Pact library maintainers, to document and discuss the adoption of the new 'pacts for verification' endpoint.

Summary

The new 'pacts for verification' endpoint allows you to specify the provider name, the consumer version 'selectors', (and later on, the provider version tags that will be published with the verification results), and the Pact Broker will return a list of pacts to verify. This will replace the current approach of making multiple individual calls to the latest provider pacts and latest provider pacts with tag endpoints.

Why make this change?

What changes need to be made to the code that uses this new API?

For implementations that wrap the ruby standalone

Note that the --consumer-version-selector argument is a json string, due to the complexity of the field. If your language allows it, please do not validate this hash - just pass it through. This will allow new features to be added to the selectors without having to make code updates to the wrapper implementations.

You can have a play around with an example CLI here https://github.com/pact-foundation/pact-provider-verifier/blob/master/script/dev/broker.sh

For native implementations

API documentation

URL

POST pacts/provider/{provider}/for-verification (but please, use the pb:provider-pacts-for-verification relation in the HAL index rather than hardcoding this, so that you can detect when this feature is available in the version of the Pact Broker that is being used. The request uses POST because the input parameters need to be structured data, and that just gets messy in GET query params.

Body

Example: This data structure represents the way a user might specify "I want to verify the latest 'master' pact, all 'prod' pacts, and when I publish the verification results, I'm going to tag the provider version with 'master'"

{
  "consumerVersionSelectors": [
    {
      "tag": "master",
      "latest": true
    },{
      "tag": "prod"
    }
  ],
  "providerVersionTags": ["master"]
}

consumerVersionSelectors.tag: the tag name(s) of the consumer versions to get the pacts for.

consumerVersionSelectors.fallbackTag: the name of the tag to fallback to if the specified tag does not exist. This is useful when the consumer and provider use matching branch names to coordinate the development of new features.

consumerVersionSelectors.latest: true. If the latest flag is omitted, all the pacts with the specified tag will be returned. (This might seem a bit weird, but it's done this way to match the syntax used for the matrix query params. See https://docs.pact.io/selectors)

consumerVersionSelectors.consumer: allows a selector to only be applied to a certain consumer. This is used when there is an API that has multiple consumers, one of which is a deployed service, and one of which is a mobile consumer. The deployed service only needs the latest production pact verified, where as the mobile consumer may want all the production pacts verified.

providerVersionTags: the tag name(s) for the provider application version that will be published with the verification results. This is used by the Broker to determine whether or not a particular pact is in pending state or not. This parameter can be specified multiple times.

Response body

pending flag and the "pending reason" notice will only be included if includePendingStatus is set to true.

{
  "_embedded": {
    "pacts": [
      {
        "verificationProperties": {
          "notices": [
            {
              "text": "This pact is being verified because it is the pact for the latest version of Foo tagged with 'dev'"
            }
          ],
        },
        "_links": {
          "self": {
            "href": "http://localhost:9292/pacts/provider/Bar/consumer/Foo/pact-version/0e3369199f4008231946e0245474537443ccda2a",
            "name": "Pact between Foo (v1.0.0) and Bar"
          }
        }
      }
    ]
  },
  "_links": {
    "self": {
      "href": "http://localhost:9292/pacts/provider/Bar/for-verification",
      "title": "Pacts to be verified"
    }
  }
}

Testing

This feature is only released in the Pactflow code, until we have tested and finalised the API. You can use this instance to test with.

Broker base URL: https://test.pact.dius.com.au
username: dXfltyFMgNOFZAxr8io9wJ37iUpY42M
password: O5AIZWxelWbLvqMd8PkAVycBJh2Psyg1

If you're writing a native implementation, please write me a pact and I'll add it to the verifications! Here's an example: https://github.com/pact-foundation/pact-ruby/blob/master/spec/service_providers/pact_ruby_fetch_pacts_for_verification_test.rb

Upcoming features

Just a heads up so that you can make informed decisions now about how to design the interface that your users see.

fallback: in the consumerVersionSelector, the user will be able to specify a "fallback" tag to use if the tag that they have specified does not exist. This will support "feature branch" development across projects where the branch names for a particular feature match for consumers and providers, to help them coordinate development.

includePendingStatus: true|false. This is to support the "pending pacts" feature. When true, a pending boolean will be added to the verificationProperties in the response, and an extra message will appear in the notices array to indicate why this pact is/is not in pending state.

includeWipPactsSince: Date. The "work in progress" pacts feature will allow newly changed pacts to be automatically included in the verification task without having to modify the list of consumer tags. More on this later.

excludeWipConsumerVersionTags: When the WIP feature is implemented, and the newly changed pacts are automatically included in this response, this will allow providers to skip specific verification for specific tags if they have decided that that pact will never be verified, and the consumer team has not removed that pact from the broker yet.

mefellows commented 4 years ago

@bethesque is this statement still true? My understanding is that by omitting latest now, it will indeed fetch all pacts with that tag, and eventually, scoped to a specific user if specified.

consumerVersionSelectors.latest: true. For now, this is mandatory, and must be set to true, as the other variations have not been implemented yet. When implemented, if the latest flag is omitted, all the pacts with the specified tag will be returned. (This might seem a bit weird, but it's done this way to match the syntax used for the matrix query params.) I suggest exposing a more intuitive interface to the users however.

bethesque commented 4 years ago

It's implemented now. I'll update that section. Thanks.