Skip to content

Commit

Permalink
feat: use new 'pacts for verification' endpoint when PACT_BROKER_PACT…
Browse files Browse the repository at this point in the history
…S_FOR_VERIFICATION_ENABLED is set to 'true'
  • Loading branch information
bethesque committed Sep 26, 2019
1 parent bf4bc93 commit 6e6f45b
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 76 deletions.
39 changes: 22 additions & 17 deletions lib/pact/provider_verifier/aggregate_pact_configs.rb
Original file line number Diff line number Diff line change
@@ -1,53 +1,58 @@
require 'pact/pact_broker'
require 'ostruct'
require 'pact/provider/pact_uri'

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
def self.call(pact_urls, provider_name, consumer_version_tags, provider_version_tags, pact_broker_base_url, http_client_options)
new(pact_urls, provider_name, consumer_version_tags, provider_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)
def initialize(pact_urls, provider_name, consumer_version_tags, provider_version_tags, pact_broker_base_url, http_client_options)
@pact_urls = pact_urls
@provider_name = provider_name
@consumer_version_tags = consumer_version_tags
@provider_version_tags = provider_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) }
if ENV['PACT_BROKER_PACTS_FOR_VERIFICATION_ENABLED'] == 'true' && pacts_for_verification_uris.any?
pacts_for_verification_uris + specified_pact_uris
else
pacts_urls_from_broker + specified_pact_uris
end
end

private

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

def specified_pact_uris
pact_urls.collect{ | url | Pact::PactBroker.build_pact_uri(url) }
end

def pacts_urls_from_broker
if pact_broker_base_url && provider_name
net_pending_pact_uris.collect{ | uri| OpenStruct.new(uri: uri, pending: true) } +
non_pending_pact_uris.collect{ | uri| OpenStruct.new(uri: uri) }
old_pact_uris
else
[]
end
end

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

def pending_pact_uris
@pending_pact_uris ||= Pact::PactBroker.fetch_pending_pact_uris(provider_name, pact_broker_base_url, http_client_options)
def pacts_for_verification_uris
@pacts_for_verification ||= Pact::PactBroker.fetch_pacts_for_verification(provider_name, consumer_version_selectors, provider_version_tags, pact_broker_base_url, http_client_options)
end

def net_pending_pact_uris
if ENV['PACT_INCLUDE_PENDING'] == 'true'
pending_pact_uris - non_pending_pact_uris
else
[]
end
def consumer_version_selectors
consumer_version_tags.collect{ |tag| { tag: tag, latest: true } }
end
end
end
Expand Down
28 changes: 13 additions & 15 deletions lib/pact/provider_verifier/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ class App
include Pact::WaitUntilServerAvailable

PROXY_PACT_HELPER = File.expand_path(File.join(File.dirname(__FILE__), "pact_helper.rb"))
attr_reader :pact_urls, :options, :consumer_version_tags, :provider_version_tags

def initialize pact_urls, options = {}
@pact_urls = pact_urls
@options = options
@consumer_version_tags = options[:consumer_version_tag] || []
@provider_version_tags = options[:provider_version_tag] || []
end

def self.call pact_urls, options
Expand All @@ -33,16 +35,15 @@ def call

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

exit_statuses.all?{ | status | status == 0 }
end

private

attr_reader :pact_urls, :options, :consumer_version_tags

def setup
print_deprecation_note
Expand All @@ -66,24 +67,22 @@ def configure_service_provider
application = configure_custom_middleware(application)
application = configure_custom_header_middleware(application)

provider_version_tag = options.provider_version_tag || [] # array
provider_application_version = options.provider_app_version
publish_results = options.publish_verification_results
this = self

Pact.service_provider "Running Provider Application" do
app do
application
end

if provider_application_version
app_version provider_application_version
if this.options.provider_app_version
app_version this.options.provider_app_version
end

if provider_version_tag.any?
app_version_tags provider_version_tag
if this.provider_version_tags.any?
app_version_tags this.provider_version_tags
end

publish_verification_results publish_results
publish_verification_results this.options.publish_verification_results
end
end

Expand Down Expand Up @@ -139,18 +138,17 @@ def apply_custom_middleware app
end
end

def verify_pact(config)
def verify_pact(pact_uri)
begin
verify_options = {
pact_helper: PROXY_PACT_HELPER,
pact_uri: config.uri,
pact_uri: pact_uri,
backtrace: ENV['BACKTRACE'] == 'true',
pact_broker_username: options.broker_username,
pact_broker_password: options.broker_password,
pact_broker_token: options.broker_token,
format: options.format,
out: options.out,
ignore_failures: config.pending,
request_customizer: ProviderStates::AddProviderStatesHeader
}
verify_options[:description] = ENV['PACT_DESCRIPTION'] if ENV['PACT_DESCRIPTION']
Expand All @@ -176,7 +174,7 @@ def reset_pact_configuration

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

def require_pact_project_pact_helper
Expand Down
6 changes: 6 additions & 0 deletions script/dev/bar_provider_config.ru
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

app = ->(env) {
[201, [], ["something"]]
}

run app
13 changes: 11 additions & 2 deletions script/dev/broker.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
bundle exec rackup -p 4567 spec/support/config.ru 2> /dev/null &
bundle exec rackup -p 4567 script/dev/bar_provider_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
export PACT_BROKER_PACTS_FOR_VERIFICATION_ENABLED=true
# 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
# --consumer-version-tag dev \
bundle exec bin/pact-provider-verifier --broker-token localhost \
--provider Bar \
--provider-version-tag pdev \
--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 \
--publish-verification-results

kill -2 $pid
wait $pid
15 changes: 3 additions & 12 deletions spec/integration_with_pact_broker_config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
before do
allow(pact_broker_api).to receive(:fetch_pact_uris).and_return(pact_uris)
allow(pact_broker_api).to receive(:fetch_pending_pact_uris).and_return(pending_pact_uris)
allow(pact_broker_api).to receive(:build_pact_uri) { | url | OpenStruct.new(uri: url) }
allow(Pact::Cli::RunPactVerification).to receive(:call)
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with('PACT_INCLUDE_PENDING').and_return('true')
Expand All @@ -27,18 +28,8 @@
subject
end

it "fetches the pending pacts URIs from the broker" do
expect(pact_broker_api).to receive(:fetch_pending_pact_uris).with("Foo", "http://localhost:5738", { username: "username", password: "password", token: "token", verbose: nil })
subject
end

it "verifies the non-pending pact" do
expect(Pact::Cli::RunPactVerification).to receive(:call).with(hash_including(pact_uri: "http://non-pending-pact", ignore_failures: nil))
subject
end

it "verifies the pending pact" do
expect(Pact::Cli::RunPactVerification).to receive(:call).with(hash_including(pact_uri: "http://pending-pact", ignore_failures: true))
it "verifies the pact" do
expect(Pact::Cli::RunPactVerification).to receive(:call).with(hash_including(pact_uri: "http://non-pending-pact"))
subject
end
end
64 changes: 34 additions & 30 deletions spec/lib/pact/provider_verifier/aggregate_pact_configs_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,23 @@ module ProviderVerifier
let(:pact_urls) { ["http://pact-1"] }
let(:provider_name) { "Foo" }
let(:consumer_version_tags) { ["master", "prod"] }
let(:provider_version_tags) { ["dev"] }
let(:pact_broker_base_url) { "http://broker" }
let(:http_client_options) { { "foo" => "bar"} }

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

let(:pending_pact_uris) { ["http://pact-2", "http://pact-3"] }
let(:pact_uris) { [double('PactURI', uri: "http://pact-2")] }
let(:pending_pact_2) { double('PactURI', uri: "http://pact-2") }
let(:pending_pact_3) { double('PactURI', uri: "http://pact-3") }
let(:pending_pact_uris) { [pending_pact_2, pending_pact_3] }
let(:pact_broker_api) { class_double(Pact::PactBroker).as_stubbed_const }

subject { AggregatePactConfigs.call(pact_urls, provider_name, consumer_version_tags, pact_broker_base_url, http_client_options) }
before do
# Trying to expose as little as possible of the class structure in the pact gem to pact-provider-verifier
# This whole thing is a mess really!
allow(pact_broker_api).to receive(:build_pact_uri) { | url | OpenStruct.new(uri: url) }
end

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

context "with no broker config" do
let(:pact_broker_base_url) { nil }
Expand All @@ -37,47 +45,43 @@ module ProviderVerifier
allow(pact_broker_api).to receive(:fetch_pending_pact_uris).and_return(pending_pact_uris)
end

it "fetches the non pending pacts" do
it "fetches the pacts using the old Pact Broker API" do
expect(pact_broker_api).to receive(:fetch_pact_uris).with(provider_name, consumer_version_tags, pact_broker_base_url, http_client_options)
subject
end

context "when env var PACT_INCLUDE_PENDING is not 'true'" do
it "does not fetch the pending pacts" do
expect(pact_broker_api).to_not receive(:fetch_pending_pact_uris)
subject
end

it "returns the non pending urls first" do
expect(subject.first).to eq OpenStruct.new(uri: "http://pact-2")
context "when env var PACTS_FOR_VERIFICATION_ENABLED" do
before do
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with('PACT_BROKER_PACTS_FOR_VERIFICATION_ENABLED').and_return('true')
allow(pact_broker_api).to receive(:fetch_pacts_for_verification).and_return(pact_uris)
end

it "returns the hardcoded urls last" do
expect(subject.last).to eq OpenStruct.new(uri: "http://pact-1")
end
end
let(:metadata) { { some: 'metadata'} }
let(:pact_uris) { [double('PactURI', uri: "http://pact-1", metadata: metadata)] }

context "when env var PACT_INCLUDE_PENDING is 'true'" do
before do
allow(ENV).to receive(:[]).and_call_original
allow(ENV).to receive(:[]).with('PACT_INCLUDE_PENDING').and_return('true')
let(:consumer_version_selectors) do
[{ tag: "master", latest: true }, { tag: "prod", latest: true }]
end

it "fetches the pending pacts" do
expect(pact_broker_api).to receive(:fetch_pending_pact_uris).with(provider_name, pact_broker_base_url, http_client_options)
it "fetches the pacts for verification" do
expect(pact_broker_api).to receive(:fetch_pacts_for_verification).with(provider_name, consumer_version_selectors, provider_version_tags, pact_broker_base_url, http_client_options)
subject
end

it "returns the pending urls first, with the non-pending pact URLs removed" do
expect(subject.first).to eq OpenStruct.new(uri: "http://pact-3", pending: true)
it "returns a list of verification configs" do
expect(subject.last).to eq OpenStruct.new(uri: "http://pact-1")
end

it "returns the non pending urls next" do
expect(subject[1]).to eq OpenStruct.new(uri: "http://pact-2")
end
context "when there are no pacts returned" do
before do
allow(pact_broker_api).to receive(:fetch_pacts_for_verification).and_return([])
end

it "returns the hardcoded urls last" do
expect(subject.last).to eq OpenStruct.new(uri: "http://pact-1")
it "fetches pacts the old way" do
expect(pact_broker_api).to receive(:fetch_pact_uris)
subject
end
end
end
end
Expand Down

0 comments on commit 6e6f45b

Please sign in to comment.