Skip to content

Commit

Permalink
feat: allow pacts to be fetched from a Pact Broker by provider name, …
Browse files Browse the repository at this point in the history
…including WIP pacts.
  • Loading branch information
bethesque committed Jul 24, 2018
1 parent d134ba6 commit 0b80528
Show file tree
Hide file tree
Showing 7 changed files with 189 additions and 7 deletions.
50 changes: 50 additions & 0 deletions lib/pact/provider_verifier/aggregate_pact_configs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
require 'pact/pact_broker'
require 'ostruct'

module Pact
module ProviderVerifier
class AggregatePactConfigs

def self.call(pact_urls, provider_name, consumer_version_tags, pact_broker_base_url, http_client_options)
new(pact_urls, provider_name, consumer_version_tags, pact_broker_base_url, http_client_options).call
end

def initialize(pact_urls, provider_name, consumer_version_tags, pact_broker_base_url, http_client_options)
@pact_urls = pact_urls
@provider_name = provider_name
@consumer_version_tags = consumer_version_tags
@pact_broker_base_url = pact_broker_base_url
@http_client_options = http_client_options
end

def call
pacts_urls_from_broker + pact_urls.collect{ |uri| OpenStruct.new(uri: uri) }
end

private

attr_reader :pact_urls, :provider_name, :consumer_version_tags, :pact_broker_base_url, :http_client_options

def pacts_urls_from_broker
if pact_broker_base_url && provider_name
net_wip_pact_uris.collect{ | uri| OpenStruct.new(uri: uri, wip: true) } +
non_wip_pact_uris.collect{ | uri| OpenStruct.new(uri: uri) }
else
[]
end
end

def non_wip_pact_uris
@non_wip_pact_uris ||= Pact::PactBroker.fetch_pact_uris(provider_name, consumer_version_tags, pact_broker_base_url, http_client_options)
end

def wip_pact_uris
@wip_pact_uris ||= Pact::PactBroker.fetch_wip_pact_uris(provider_name, pact_broker_base_url, http_client_options)
end

def net_wip_pact_uris
wip_pact_uris - non_wip_pact_uris
end
end
end
end
18 changes: 13 additions & 5 deletions lib/pact/provider_verifier/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'pact/provider/rspec'
require 'pact/message'
require 'pact/cli/run_pact_verification'
require 'pact/provider_verifier/aggregate_pact_configs'
require 'rack/reverse_proxy'
require 'faraday_middleware'
require 'json'
Expand All @@ -16,6 +17,7 @@ class App
def initialize pact_urls, options = {}
@pact_urls = pact_urls
@options = options
@consumer_version_tags = options[:consumer_version_tag] || []
end

def self.call pact_urls, options
Expand All @@ -25,7 +27,7 @@ def self.call pact_urls, options
def call
setup

exit_statuses = pact_urls.collect do |pact_url|
exit_statuses = all_pact_urls.collect do |pact_url|
verify_pact pact_url
end

Expand All @@ -35,7 +37,7 @@ def call

private

attr_reader :pact_urls, :options
attr_reader :pact_urls, :options, :consumer_version_tags

def setup
print_deprecation_note
Expand Down Expand Up @@ -92,16 +94,17 @@ def configure_custom_header_middleware rack_reverse_proxy
end
end

def verify_pact pact_url
def verify_pact config
begin
verify_options = {
pact_helper: PROXY_PACT_HELPER,
pact_uri: pact_url,
pact_uri: config.uri,
backtrace: ENV['BACKTRACE'] == 'true',
pact_broker_username: options.broker_username,
pact_broker_password: options.broker_password,
format: options.format,
out: options.out
out: options.out,
wip: config.wip
}
verify_options[:description] = ENV['PACT_DESCRIPTION'] if ENV['PACT_DESCRIPTION']
verify_options[:provider_state] = ENV['PACT_PROVIDER_STATE'] if ENV['PACT_PROVIDER_STATE']
Expand All @@ -124,6 +127,11 @@ def reset_pact_configuration
configure_service_provider
end

def all_pact_urls
http_client_options = { username: options.broker_username, password: options.broker_password }
AggregatePactConfigs.call(pact_urls, options.provider, consumer_version_tags, options.pact_broker_base_url, http_client_options)
end

def require_pact_project_pact_helper
require ENV['PACT_PROJECT_PACT_HELPER'] if ENV.fetch('PACT_PROJECT_PACT_HELPER','') != ''
end
Expand Down
17 changes: 15 additions & 2 deletions lib/pact/provider_verifier/cli/verify.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,19 @@ module Pact
module ProviderVerifier
module CLI
class Verify < CustomThor

class InvalidArgumentsError < ::Thor::Error; end

desc 'PACT_URL ...', "Verify pact(s) against a provider. Supports local and networked (http-based) files."
method_option :provider_base_url, aliases: "-h", desc: "Provider host URL", :required => true
method_option :provider_states_setup_url, aliases: "-c", desc: "Base URL to setup the provider states at", :required => false
method_option :provider_app_version, aliases: "-a", desc: "Provider application version, required when publishing verification results", :required => false
method_option :publish_verification_results, aliases: "-r", desc: "Publish verification results to the broker", required: false
method_option :pact_broker_base_url, desc: "Base URL of the Pact Broker from which to retrieve the pacts.", :required => false
method_option :broker_username, aliases: "-n", desc: "Pact Broker basic auth username", :required => false
method_option :broker_password, aliases: "-p", desc: "Pact Broker basic auth password", :required => false
method_option :provider, required: false
method_option :consumer_version_tag, type: :array, desc: "Retrieve the latest pacts with this consumer version tag. Used in conjuction with --provider.", :required => false
method_option :provider_app_version, aliases: "-a", desc: "Provider application version, required when publishing verification results", :required => false
method_option :publish_verification_results, aliases: "-r", desc: "Publish verification results to the broker", required: false
method_option :custom_provider_header, type: :array, banner: 'CUSTOM_PROVIDER_HEADER', desc: "Header to add to provider state set up and pact verification requests. eg 'Authorization: Basic cGFjdDpwYWN0'. May be specified multiple times.", :required => false
method_option :monkeypatch, hide: true, type: :array, :required => false
method_option :verbose, aliases: "-v", desc: "Verbose output", :required => false
Expand All @@ -23,6 +29,7 @@ class Verify < CustomThor
method_option :pact_urls, aliases: "-u", hide: true, :required => false

def verify(*pact_urls)
validate_verify
print_deprecation_warnings
Pact::ProviderVerifier::App.call(merged_urls(pact_urls), options)
end
Expand All @@ -46,6 +53,12 @@ def print_deprecation_warnings
$stderr.puts "WARN: The --pact-urls option is deprecated. Please pass in a space separated list of URLs as the first arguments to the pact-provider-verifier command."
end
end

def validate_verify
if options.pact_broker_base_url && (options.provider.nil? || options.provider == "")
raise InvalidArgumentsError, "No value provided for required option '--provider'"
end
end
end
end
end
Expand Down
8 changes: 8 additions & 0 deletions script/dev/broker.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
bundle exec rackup -p 4567 spec/support/config.ru 2> /dev/null &
pid=$!
sleep 3

bundle exec bin/pact-provider-verifier --provider Bar --consumer-version-tag prod --pact-broker-base-url http://localhost:9292 -a 1.0.100 --provider-base-url http://localhost:4567 --provider-states-setup-url http://localhost:4567/provider-state

kill -2 $pid
wait $pid
63 changes: 63 additions & 0 deletions spec/lib/pact/provider_verifier/aggregate_pact_configs_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
require 'pact/provider_verifier/aggregate_pact_configs'

module Pact
module ProviderVerifier
describe AggregatePactConfigs do
describe ".call" do
let(:pact_urls) { ["http://pact-1"] }
let(:provider_name) { "Foo" }
let(:consumer_version_tags) { ["master", "prod"] }
let(:pact_broker_base_url) { "http://broker" }
let(:http_client_options) { { "foo" => "bar"} }

let(:pact_uris) { ["http://pact-2"] }

let(:wip_pact_uris) { ["http://pact-2", "http://pact-3"] }

subject { AggregatePactConfigs.call(pact_urls, provider_name, consumer_version_tags, pact_broker_base_url, http_client_options) }

context "with no broker config" do
let(:pact_broker_base_url) { nil }

it "does not make a call to a Pact Broker" do
expect(Pact::PactBroker).to_not receive(:fetch_pact_uris)
subject
end

it "returns the hardcoded urls" do
expect(subject).to eq [OpenStruct.new(uri: "http://pact-1")]
end
end

context "with broker config" do
before do
allow(Pact::PactBroker).to receive(:fetch_pact_uris).and_return(pact_uris)
allow(Pact::PactBroker).to receive(:fetch_wip_pact_uris).and_return(wip_pact_uris)
end

it "fetches the non wip pacts" do
expect(Pact::PactBroker).to receive(:fetch_pact_uris).with(provider_name, consumer_version_tags, pact_broker_base_url, http_client_options)
subject
end

it "fetches the wip pacts" do
expect(Pact::PactBroker).to receive(:fetch_wip_pact_uris).with(provider_name, pact_broker_base_url, http_client_options)
subject
end

it "returns the wip urls first, with the non-wip pact URLs removed" do
expect(subject.first).to eq OpenStruct.new(uri: "http://pact-3", wip: true)
end

it "returns the wip urls next" do
expect(subject[1]).to eq OpenStruct.new(uri: "http://pact-2")
end

it "returns the hardcoded urls last" do
expect(subject.last).to eq OpenStruct.new(uri: "http://pact-1")
end
end
end
end
end
end
36 changes: 36 additions & 0 deletions spec/lib/pact/provider_verifier/cli/verify_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,42 @@ module CLI
invoke_verify
end

context "with a pact broker config" do
before do
subject.options = OpenStruct.new(options)
end

let(:options) do
minimum_valid_options.merge(
pact_broker_base_url: "http://broker",
provider: "Foo",
consumer_version_tag: ["master", "prod"]
)
end

it "invokes the verifier app with the given options" do
expect(Pact::ProviderVerifier::App).to receive(:call).with(
pact_urls, OpenStruct.new(options))
invoke_verify
end
end

context "with a pact broker URL but no provider name" do
before do
subject.options = OpenStruct.new(options)
end

let(:options) do
minimum_valid_options.merge(
pact_broker_base_url: "http://broker"
)
end

it "raises an InvalidArgumentsError" do
expect { subject.verify }.to raise_error Verify::InvalidArgumentsError
end
end

context "when the deprecated pact-urls option is used" do
before do
allow($stderr).to receive(:puts)
Expand Down
4 changes: 4 additions & 0 deletions spec/support/provider.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ def initialize
@logger.info "#{response.status} #{response.body}"
end

not_found do
status 404
end

error do
e = env['sinatra.error']
@logger.error "#{e.class} #{e.message} #{e.backtrace.join("\n")}"
Expand Down

0 comments on commit 0b80528

Please sign in to comment.