pact_broker-client 1.61.1 → 1.63.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 302e6410c4705e3215f63cd3cde0d0f776f2509e06f286fd7dfc3ae6f7762fef
4
- data.tar.gz: af9abb55766a45839a59bebfb2dd4eb93698a3f12f207a24e94c8e93219ecc57
3
+ metadata.gz: 1c364b3a4f6acc4007f18baf2812262423988555e78e03617641e557ebbb3402
4
+ data.tar.gz: f741a0a0ad6ad08e4b0ef9f80cc02b07f409b6eaf84fcf609419644d7f9c6255
5
5
  SHA512:
6
- metadata.gz: 7cdd9bffc84f8c5ff9a012732510dd9a5df4afe1d8c9bfe538b7173d1b92382982ce4ecde02a57b8fc2968ce83a7c4c6e882f882d9c872a48dcf329f97b059e0
7
- data.tar.gz: 3739ba7cd7295b088f5ff0b457c37f7eeb93ce4e03dc1e826b4f924e216d90ae00c04f8def2e32cf8a440f8ad3ea907da2e17908021b17d1b9231df736c6ae7d
6
+ metadata.gz: 14252b9713e0f0ab18a5f4418f697757acdd8cccb572658b5655a073105abd00996ba37d2b7c467135a906df1f9c10b8ebb25a2ecdafde2901e219bc521e5b16
7
+ data.tar.gz: fc6eb7836d4ba0f1016538fa03134e44b00679458f8d5a17a091779de8698e04de64497468ea335ca0fc5e74ed3080baf06ae766a8080381eaf492b01de0a78a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,28 @@
1
+ <a name="v1.63.0"></a>
2
+ ### v1.63.0 (2022-05-10)
3
+
4
+ #### Features
5
+
6
+ * add --verification-exit-code to publish-provider-contract command ([d35d908](/../../commit/d35d908))
7
+
8
+ <a name="v1.62.1"></a>
9
+ ### v1.62.1 (2022-05-10)
10
+
11
+ #### Bug Fixes
12
+
13
+ * set exit on failure to true for new pactflow command ([429dfbd](/../../commit/429dfbd))
14
+
15
+ <a name="v1.62.0"></a>
16
+ ### v1.62.0 (2022-05-10)
17
+
18
+ #### Features
19
+
20
+ * add command to publish provider contracts to pactflow (feature toggle required) (#107) ([80cc10e](/../../commit/80cc10e))
21
+
22
+ #### Bug Fixes
23
+
24
+ * use ruby < 2.3 syntax. (#108) ([20f1e01](/../../commit/20f1e01))
25
+
1
26
  <a name="v1.61.1"></a>
2
27
  ### v1.61.1 (2022-05-09)
3
28
 
data/bin/pactflow ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require "pactflow/client/cli/pactflow"
3
+
4
+ Pactflow::Client::CLI::Pactflow.start
@@ -4,6 +4,8 @@
4
4
 
5
5
  * [A request for the index resource](#a_request_for_the_index_resource)
6
6
 
7
+ * [A request to create a provider contract](#a_request_to_create_a_provider_contract)
8
+
7
9
  * [A request to create a webhook for a team](#a_request_to_create_a_webhook_for_a_team_given_a_team_with_UUID_2abbc12a-427d-432a-a521-c870af1739d9_exists) given a team with UUID 2abbc12a-427d-432a-a521-c870af1739d9 exists
8
10
 
9
11
  #### Interactions
@@ -41,6 +43,40 @@ Pactflow will respond with:
41
43
  }
42
44
  }
43
45
  ```
46
+ <a name="a_request_to_create_a_provider_contract"></a>
47
+ Upon receiving **a request to create a provider contract** from Pact Broker Client, with
48
+ ```json
49
+ {
50
+ "method": "put",
51
+ "path": "/contracts/provider/Bar/version/1",
52
+ "headers": {
53
+ "Content-Type": "application/json",
54
+ "Accept": "application/hal+json"
55
+ },
56
+ "body": {
57
+ "content": "LS0tCjpzb21lOiBjb250cmFjdAo=",
58
+ "contractType": "oas",
59
+ "contentType": "application/yaml",
60
+ "verificationResults": {
61
+ "success": true,
62
+ "content": "c29tZSByZXN1bHRz",
63
+ "contentType": "text/plain",
64
+ "format": "text",
65
+ "verifier": "my custom tool",
66
+ "verifierVersion": "1.0"
67
+ }
68
+ }
69
+ }
70
+ ```
71
+ Pactflow will respond with:
72
+ ```json
73
+ {
74
+ "status": 201,
75
+ "headers": {
76
+ "Content-Type": "application/hal+json;charset=utf-8"
77
+ }
78
+ }
79
+ ```
44
80
  <a name="a_request_to_create_a_webhook_for_a_team_given_a_team_with_UUID_2abbc12a-427d-432a-a521-c870af1739d9_exists"></a>
45
81
  Given **a team with UUID 2abbc12a-427d-432a-a521-c870af1739d9 exists**, upon receiving **a request to create a webhook for a team** from Pact Broker Client, with
46
82
  ```json
@@ -34,12 +34,6 @@ module PactBroker
34
34
  require "pact_broker/client/version"
35
35
  $stdout.puts PactBroker::Client::VERSION
36
36
  end
37
-
38
- no_commands do
39
- def self.exit_on_failure?
40
- true
41
- end
42
- end
43
37
  end
44
38
  end
45
39
  end
@@ -15,6 +15,10 @@ module PactBroker
15
15
  using PactBroker::Client::HashRefinements
16
16
 
17
17
  no_commands do
18
+ def self.exit_on_failure?
19
+ true
20
+ end
21
+
18
22
  def self.start given_args = ARGV, config = {}
19
23
  super(massage_args(given_args))
20
24
  end
@@ -8,6 +8,10 @@ module PactBroker
8
8
  PactBroker::Client::Hal::EntryPoint.new(pact_broker_base_url, create_http_client(pact_broker_client_options))
9
9
  end
10
10
 
11
+ def create_entry_point(entry_point, pact_broker_client_options)
12
+ PactBroker::Client::Hal::EntryPoint.new(entry_point, create_http_client(pact_broker_client_options))
13
+ end
14
+
11
15
  def create_http_client(pact_broker_client_options)
12
16
  PactBroker::Client::Hal::HttpClient.new(pact_broker_client_options.merge(pact_broker_client_options[:basic_auth] || {}))
13
17
  end
@@ -1,5 +1,5 @@
1
1
  module PactBroker
2
2
  module Client
3
- VERSION = '1.61.1'
3
+ VERSION = '1.63.0'
4
4
  end
5
5
  end
@@ -0,0 +1,12 @@
1
+ require "pactflow/client/cli/provider_contract_commands"
2
+ require "pact_broker/client/cli/custom_thor"
3
+
4
+ module Pactflow
5
+ module Client
6
+ module CLI
7
+ class Pactflow < PactBroker::Client::CLI::CustomThor
8
+ include ::Pactflow::Client::CLI::ProviderContractCommands
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,89 @@
1
+ require "pact_broker/client/hash_refinements"
2
+
3
+ module Pactflow
4
+ module Client
5
+ module CLI
6
+ module ProviderContractCommands
7
+ using PactBroker::Client::HashRefinements
8
+
9
+ def self.included(thor)
10
+ thor.class_eval do
11
+
12
+ if ENV.fetch("PACTFLOW_FEATURES", "").include?("publish-provider-contract")
13
+
14
+ desc 'publish-provider-contract CONTRACT_FILE ...', "Publish provider contract to Pactflow"
15
+ method_option :provider, required: true, desc: "The provider name"
16
+ method_option :provider_app_version, required: true, aliases: "-a", desc: "The provider application version"
17
+ method_option :branch, aliases: "-h", desc: "Repository branch of the provider version"
18
+ #method_option :auto_detect_version_properties, hidden: true, type: :boolean, default: false, desc: "Automatically detect the repository branch from known CI environment variables or git CLI."
19
+ method_option :tag, aliases: "-t", type: :array, banner: "TAG", desc: "Tag name for provider version. Can be specified multiple times."
20
+ #method_option :tag_with_git_branch, aliases: "-g", type: :boolean, default: false, required: false, desc: "Tag consumer version with the name of the current git branch. Default: false"
21
+ method_option :specification, default: "oas", desc: "The contract specification"
22
+ method_option :content_type, desc: "The content type. eg. application/yml"
23
+ method_option :verification_success, type: :boolean, desc: "Whether or not the self verification passed successfully."
24
+ method_option :verification_exit_code, type: :numeric, desc: "The exit code of the verification process. Can be used instead of --verificaiton-success|--no-verification-success for a simpler build script."
25
+ method_option :verification_results, desc: "The path to the file containing the output from the verification process"
26
+ method_option :verification_results_content_type, desc: "The content type of the verification output eg. text/plain, application/yaml"
27
+ method_option :verification_results_format, desc: "The format of the verification output eg. junit, text"
28
+ method_option :verifier, desc: "The tool used to verify the provider contract"
29
+ method_option :verifier_version, desc: "The version of the tool used to verify the provider contract"
30
+ #method_option :build_url, desc: "The build URL that created the pact"
31
+
32
+ output_option_json_or_text
33
+ shared_authentication_options
34
+
35
+ def publish_provider_contract(provider_contract_path)
36
+ require "pactflow/client/provider_contracts/publish"
37
+
38
+ validate_publish_provider_contract_options(provider_contract_path)
39
+ result = ::Pactflow::Client::ProviderContracts::Publish.call(
40
+ publish_provider_contract_command_params(provider_contract_path),
41
+ command_options,
42
+ pact_broker_client_options
43
+ )
44
+ $stdout.puts result.message
45
+ exit(1) unless result.success
46
+ end
47
+
48
+ no_commands do
49
+ def command_options
50
+ { verbose: options.verbose, output: options.output }
51
+ end
52
+
53
+ def validate_publish_provider_contract_options(provider_contract_path)
54
+ if !options.verification_success.nil? && options.verification_exit_code
55
+ raise Thor::Error, "Cannot use both --verification-success|--no-verification-success and --verification-exit-code"
56
+ end
57
+ end
58
+
59
+ def publish_provider_contract_command_params(provider_contract_path)
60
+ success = !options.verification_success.nil? ? options.verification_success : ( options.verification_exit_code && options.verification_exit_code == 0 )
61
+
62
+ {
63
+ provider_name: options.provider.strip,
64
+ provider_version_number: options.provider_app_version.strip,
65
+ branch_name: options.branch && options.branch.strip,
66
+ tags: (options.tag && options.tag.collect(&:strip)) || [],
67
+ contract: {
68
+ content: File.read(provider_contract_path),
69
+ content_type: options.content_type,
70
+ specification: options.specification
71
+ },
72
+ verification_results: {
73
+ success: success,
74
+ content: options.verification_results ? File.read(options.verification_results) : nil,
75
+ content_type: options.verification_results_content_type,
76
+ format: options.verification_results_format,
77
+ verifier: options.verifier,
78
+ verifier_version: options.verifier_version
79
+ }
80
+ }
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,79 @@
1
+ require "pact_broker/client/base_command"
2
+ require "pact_broker/client/versions/create"
3
+ require "base64"
4
+
5
+ module Pactflow
6
+ module Client
7
+ module ProviderContracts
8
+ class Publish < PactBroker::Client::BaseCommand
9
+ attr_reader :branch_name, :tags, :provider_name, :provider_version_number, :contract, :verification_results
10
+
11
+ def initialize(params, options, pact_broker_client_options)
12
+ super
13
+ @provider_name = params[:provider_name]
14
+ @provider_version_number = params[:provider_version_number]
15
+ @branch_name = params[:branch_name]
16
+ @tags = params[:tags] || []
17
+ @contract = params[:contract]
18
+ @verification_results = params[:verification_results]
19
+ end
20
+
21
+ private
22
+
23
+ def do_call
24
+ create_branch_version_and_tags
25
+ create_contract
26
+ PactBroker::Client::CommandResult.new(true, green("Successfully published provider contract for #{provider_name} version #{provider_version_number}"))
27
+ end
28
+
29
+ def create_branch_version_and_tags
30
+ if branch_name || tags.any?
31
+ pacticipant_version_params = {
32
+ pacticipant_name: provider_name,
33
+ version_number: provider_version_number,
34
+ branch_name: branch_name,
35
+ tags: tags
36
+ }
37
+ result = PactBroker::Client::Versions::Create.call(pacticipant_version_params, options, pact_broker_client_options)
38
+ if !result.success
39
+ raise PactBroker::Client::Error.new(result.message)
40
+ end
41
+ end
42
+ end
43
+
44
+ def create_contract
45
+ contract_path = "#{pact_broker_base_url}/contracts/provider/{provider}/version/{version}"
46
+ entrypoint = create_entry_point(contract_path, pact_broker_client_options)
47
+ entrypoint.expand(provider: provider_name, version: provider_version_number).put!(contract_params)
48
+ end
49
+
50
+ def contract_params
51
+ verification_results_params = {
52
+ success: verification_results[:success],
53
+ content: verification_results[:content] ? encode_content(verification_results[:content]) : nil,
54
+ contentType: verification_results[:content_type],
55
+ format: verification_results[:format],
56
+ verifier: verification_results[:verifier],
57
+ verifierVersion: verification_results[:verifier_version]
58
+ }.compact
59
+
60
+ body_params = {
61
+ content: encode_content(contract[:content]),
62
+ contractType: contract[:specification],
63
+ contentType: contract[:content_type],
64
+ }.compact
65
+
66
+ if verification_results_params.any?
67
+ body_params[:verificationResults] = verification_results_params
68
+ end
69
+
70
+ body_params
71
+ end
72
+
73
+ def encode_content oas
74
+ Base64.strict_encode64(oas)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
data/script/oas.yml ADDED
@@ -0,0 +1,49 @@
1
+ openapi: 3.0.0
2
+ info:
3
+ title: Sample API
4
+ description: Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML.
5
+ version: 0.1.9
6
+ servers:
7
+ - url: https://test.pactflow.io
8
+ description: Prod
9
+ - url: https://test.test.pactflow.io
10
+ description: Test
11
+ paths:
12
+ /admin/teams/{uuid}:
13
+ get:
14
+ summary: Returns a team
15
+ parameters:
16
+ - name: uuid
17
+ in: path
18
+ description: The UUID of the team to return
19
+ required: true
20
+ example: 85ad09f5-e014-4e0f-a146-4377fa64b5ef
21
+ schema:
22
+ type: string
23
+ responses:
24
+ '200':
25
+ description: A JSON team
26
+ content:
27
+ application/json:
28
+ schema:
29
+ type: object
30
+ additionalProperties: false
31
+ properties:
32
+ name:
33
+ type: string
34
+ example: Team Awesome
35
+ uuid:
36
+ type: string
37
+ example: 85ad09f5-e014-4e0f-a146-4377fa64b5ef
38
+ numberOfMembers:
39
+ type: integer
40
+ example: 4
41
+ _links:
42
+ type: object
43
+ properties:
44
+ self:
45
+ type: object
46
+ properties:
47
+ href:
48
+ type: string
49
+ example: http://test.pactflow.io/admin/teams/85ad09f5-e014-4e0f-a146-4377fa64b5ef
@@ -0,0 +1,28 @@
1
+ export PACT_BROKER_BASE_URL=${PACT_BROKER_BASE_URL:-"http://localhost:9292"}
2
+ export PACTFLOW_FEATURES=publish-provider-contract
3
+ bundle exec bin/pactflow publish-provider-contract \
4
+ script/oas.yml \
5
+ --provider Foo \
6
+ --provider-app-version 1013b5650d61214e19f10558f97fb5a3bb082d44 \
7
+ --branch main \
8
+ --tag dev \
9
+ --specification oas \
10
+ --content-type application/yml \
11
+ --verification-exit-code 0 \
12
+ --verification-results script/verification-results.txt \
13
+ --verification-results-content-type text/plain \
14
+ --verification-results-format text \
15
+ --verifier my-custom-tool \
16
+ --verifier-version "1.0" \
17
+ --verbose
18
+
19
+
20
+ # bundle exec bin/pactflow publish-provider-contract \
21
+ # script/oas.yml \
22
+ # --provider Foo \
23
+ # --provider-app-version 1013b5650d61214e19f10558f97fb5a3bb082d44 \
24
+ # --branch main \
25
+ # --tag dev \
26
+ # --specification oas \
27
+ # --content-type application/yml
28
+
@@ -0,0 +1 @@
1
+ These are some results.
@@ -6,6 +6,36 @@
6
6
  "name": "Pactflow"
7
7
  },
8
8
  "interactions": [
9
+ {
10
+ "description": "a request to create a provider contract",
11
+ "request": {
12
+ "method": "put",
13
+ "path": "/contracts/provider/Bar/version/1",
14
+ "headers": {
15
+ "Content-Type": "application/json",
16
+ "Accept": "application/hal+json"
17
+ },
18
+ "body": {
19
+ "content": "LS0tCjpzb21lOiBjb250cmFjdAo=",
20
+ "contractType": "oas",
21
+ "contentType": "application/yaml",
22
+ "verificationResults": {
23
+ "success": true,
24
+ "content": "c29tZSByZXN1bHRz",
25
+ "contentType": "text/plain",
26
+ "format": "text",
27
+ "verifier": "my custom tool",
28
+ "verifierVersion": "1.0"
29
+ }
30
+ }
31
+ },
32
+ "response": {
33
+ "status": 201,
34
+ "headers": {
35
+ "Content-Type": "application/hal+json;charset=utf-8"
36
+ }
37
+ }
38
+ },
9
39
  {
10
40
  "description": "a request for the index resource",
11
41
  "request": {
@@ -0,0 +1,92 @@
1
+ require_relative "pact_helper"
2
+ require "pactflow/client/provider_contracts/publish"
3
+ require "yaml"
4
+
5
+ RSpec.describe "publishing a provider contract to Pactflow", pact: true do
6
+ before do
7
+ # no point re-testing this
8
+ allow(PactBroker::Client::Versions::Create).to receive(:call).and_return(double("result", success: true))
9
+ end
10
+
11
+ include_context "pact broker"
12
+ include PactBrokerPactHelperMethods
13
+
14
+ let(:command_params) do
15
+ {
16
+ provider_name: "Bar",
17
+ provider_version_number: "1",
18
+ branch_name: "main",
19
+ tags: ["dev"],
20
+ contract: {
21
+ content: { some: "contract" }.to_yaml,
22
+ content_type: "application/yaml",
23
+ specification: "oas"
24
+ },
25
+ verification_results: {
26
+ success: true,
27
+ content: "some results",
28
+ content_type: "text/plain",
29
+ format: "text",
30
+ verifier: "my custom tool",
31
+ verifier_version: "1.0"
32
+ }
33
+ }
34
+ end
35
+
36
+ let(:body) { { some: "body" }.to_json }
37
+
38
+ let(:request_body) do
39
+ {
40
+ "content" => "LS0tCjpzb21lOiBjb250cmFjdAo=",
41
+ "contractType" => "oas",
42
+ "contentType" => "application/yaml",
43
+ "verificationResults" => {
44
+ "success" => true,
45
+ "content" => "c29tZSByZXN1bHRz",
46
+ "contentType" => "text/plain",
47
+ "format" => "text",
48
+ "verifier" => "my custom tool",
49
+ "verifierVersion" => "1.0"
50
+ }
51
+ }
52
+ end
53
+
54
+ let(:response_status) { 201 }
55
+ let(:success_response) do
56
+ {
57
+ status: response_status,
58
+ headers: pact_broker_response_headers
59
+ }
60
+ end
61
+
62
+ let(:options) do
63
+ {
64
+ verbose: false
65
+ }
66
+ end
67
+
68
+ let(:pact_broker_client_options) do
69
+ { pact_broker_base_url: pactflow.mock_service_base_url }
70
+ end
71
+
72
+ subject { Pactflow::Client::ProviderContracts::Publish.call(command_params, options, pact_broker_client_options) }
73
+
74
+ context "creating a provider contract with valid parameters" do
75
+ before do
76
+ pactflow
77
+ .upon_receiving("a request to create a provider contract")
78
+ .with(
79
+ method: :put,
80
+ path: "/contracts/provider/Bar/version/1",
81
+ headers: put_request_headers,
82
+ body: request_body)
83
+ .will_respond_with(success_response)
84
+ end
85
+
86
+ it "returns a CommandResult with success = true" do
87
+ expect(subject).to be_a PactBroker::Client::CommandResult
88
+ expect(subject.success).to be true
89
+ expect(subject.message).to include "Successfully published provider contract for Bar version 1"
90
+ end
91
+ end
92
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact_broker-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.61.1
4
+ version: 1.63.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Beth Skurrie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-09 00:00:00.000000000 Z
11
+ date: 2022-05-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -204,6 +204,7 @@ email:
204
204
  - beth@bethesque.com
205
205
  executables:
206
206
  - pact-broker
207
+ - pactflow
207
208
  extensions: []
208
209
  extra_rdoc_files: []
209
210
  files:
@@ -220,6 +221,7 @@ files:
220
221
  - Rakefile
221
222
  - appveyor.yml
222
223
  - bin/pact-broker
224
+ - bin/pactflow
223
225
  - ci.sh
224
226
  - doc/CAN_I_DEPLOY_USAGE_WITH_TAGS.md
225
227
  - doc/pacts/markdown/Pact Broker Client - Pact Broker.md
@@ -314,17 +316,23 @@ files:
314
316
  - lib/pact_broker/client/webhooks/create.rb
315
317
  - lib/pact_broker/client/webhooks/test.rb
316
318
  - lib/pact_broker_client.rb
319
+ - lib/pactflow/client/cli/pactflow.rb
320
+ - lib/pactflow/client/cli/provider_contract_commands.rb
321
+ - lib/pactflow/client/provider_contracts/publish.rb
317
322
  - pact-broker-client.gemspec
318
323
  - script/approve-all.sh
319
324
  - script/can-i-deploy.sh
320
325
  - script/create-pacticipant.sh
326
+ - script/oas.yml
321
327
  - script/publish-pact.sh
328
+ - script/publish-provider-contract.sh
322
329
  - script/record-deployment.sh
323
330
  - script/record-deployments-and-releases.sh
324
331
  - script/record-undeployment.sh
325
332
  - script/release.sh
326
333
  - script/trigger-release.sh
327
334
  - script/update-cli-usage-in-readme.rb
335
+ - script/verification-results.txt
328
336
  - script/webhook-commands.sh
329
337
  - spec/fixtures/approvals/can_i_deploy_failure_dry_run.approved.txt
330
338
  - spec/fixtures/approvals/can_i_deploy_ignore.approved.txt
@@ -389,6 +397,7 @@ files:
389
397
  - spec/service_providers/pact_broker_client_tags_spec.rb
390
398
  - spec/service_providers/pact_broker_client_versions_spec.rb
391
399
  - spec/service_providers/pact_helper.rb
400
+ - spec/service_providers/pactflow_publish_provider_contract_spec.rb
392
401
  - spec/service_providers/pactflow_webhooks_create_spec.rb
393
402
  - spec/service_providers/pacticipants_create_spec.rb
394
403
  - spec/service_providers/publish_pacts_spec.rb
@@ -497,6 +506,7 @@ test_files:
497
506
  - spec/service_providers/pact_broker_client_tags_spec.rb
498
507
  - spec/service_providers/pact_broker_client_versions_spec.rb
499
508
  - spec/service_providers/pact_helper.rb
509
+ - spec/service_providers/pactflow_publish_provider_contract_spec.rb
500
510
  - spec/service_providers/pactflow_webhooks_create_spec.rb
501
511
  - spec/service_providers/pacticipants_create_spec.rb
502
512
  - spec/service_providers/publish_pacts_spec.rb