Skip to content

Commit

Permalink
chore: expand the verified pacts for saving, rather than just for the…
Browse files Browse the repository at this point in the history
… webhooks
  • Loading branch information
bethesque committed Aug 18, 2021
1 parent 28a5dc2 commit 09c11d3
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 49 deletions.
3 changes: 2 additions & 1 deletion lib/pact_broker/api/resources/verifications.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ def create_path

def from_json
handle_webhook_events do
verification = verification_service.create(next_verification_number, verification_params, pact, event_context)
verified_pacts = pact_service.find_for_verification_publication(pact_params, event_context[:consumer_version_selectors])
verification = verification_service.create(next_verification_number, verification_params, verified_pacts, event_context)
response.body = decorator_for(verification).to_json(decorator_options)
end
true
Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/pacts/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,10 @@ def find_previous_pacts pact
end
end

def find_pact_version(consumer, provider, pact_version_sha)
PactBroker::Pacts::PactVersion.where(consumer_id: consumer.id, provider_id: provider.id, sha: pact_version_sha).single_record
end

private

def find_previous_distinct_pact_by_sha pact
Expand Down
10 changes: 10 additions & 0 deletions lib/pact_broker/pacts/selected_pact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,16 @@ def self.merge_by_pact_version_sha(selected_pacts)
.sort
end

def self.merge_by_consumer_version_number(selected_pacts)
selected_pacts
.group_by{ |p| [p.consumer_name, p.consumer_version_number] }
.values
.collect do | selected_pacts_for_consumer_version_number |
SelectedPact.merge(selected_pacts_for_consumer_version_number)
end
.sort
end

def self.merge(selected_pacts)
latest_selected_pact = selected_pacts.sort_by(&:consumer_version_order).last
selectors = selected_pacts.collect(&:selectors).reduce(&:+).sort
Expand Down
21 changes: 21 additions & 0 deletions lib/pact_broker/pacts/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
require "pact_broker/pacts/squash_pacts_for_verification"
require "pact_broker/events/publisher"
require "pact_broker/messages"
require "pact_broker/hash_refinements"

module PactBroker
module Pacts
module Service
using PactBroker::HashRefinements

extend self
extend PactBroker::Events::Publisher
Expand Down Expand Up @@ -133,6 +135,25 @@ def find_for_verification(provider_name, provider_version_branch, provider_versi
explicitly_specified_verifiable_pacts + verifiable_wip_pacts
end

def find_for_verification_publication(pact_params, consumer_version_selector_hashes)
if consumer_version_selector_hashes&.any?
selected_pacts = consumer_version_selector_hashes.collect do | consumer_version_selector_hash |
find_pact_params = {
consumer_name: pact_params.consumer_name,
provider_name: pact_params.provider_name,
pact_version_sha: pact_params.pact_version_sha,
consumer_version_number: consumer_version_selector_hash[:consumer_version_number]
}
pact = find_pact(find_pact_params)
resolved_selector = Selector.new(consumer_version_selector_hash.without(:consumer_version_number)).resolve(pact.consumer_version)
SelectedPact.new(pact, Selectors.new(resolved_selector))
end
SelectedPact.merge_by_consumer_version_number(selected_pacts)
else
[SelectedPact.new(find_pact(pact_params), Selectors.new)]
end
end

# Overwriting an existing pact with the same consumer/provider/consumer version number
def update_pact params, existing_pact
logger.info "Updating existing pact publication with params #{params.reject{ |k, _v| k == :json_content}}"
Expand Down
3 changes: 2 additions & 1 deletion lib/pact_broker/test/test_data_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,8 @@ def create_verification parameters = {}
parameters = default_parameters.merge(parameters)
parameters.delete(:provider_version)
verification = PactBroker::Domain::Verification.new(parameters)
@verification = PactBroker::Verifications::Repository.new.create(verification, provider_version_number, @pact)
pact_version = PactBroker::Pacts::Repository.new.find_pact_version(@consumer, @provider, pact.pact_version_sha)
@verification = PactBroker::Verifications::Repository.new.create(verification, provider_version_number, pact_version)
@provider_version = PactBroker::Domain::Version.where(pacticipant_id: @provider.id, number: provider_version_number).single_record
@provider_version.update(branch: branch) if branch

Expand Down
16 changes: 5 additions & 11 deletions lib/pact_broker/verifications/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@ def next_number
Sequence.next_val
end

def create verification, provider_version_number, pact
provider = pacticipant_repository.find_by_name(pact.provider_name)
consumer = pacticipant_repository.find_by_name(pact.consumer_name)
version = version_repository.find_by_pacticipant_id_and_number_or_create(provider.id, provider_version_number)
verification.pact_version_id = pact_version_id_for(pact)
def create verification, provider_version_number, pact_version
version = version_repository.find_by_pacticipant_id_and_number_or_create(pact_version.provider_id, provider_version_number)
verification.pact_version_id = pact_version.id
verification.provider_version = version
verification.provider_id = provider.id
verification.consumer_id = consumer.id
verification.provider_id = pact_version.provider_id
verification.consumer_id = pact_version.consumer_id
verification.tag_names = version.tag_names # TODO pass this in from contracts service
verification.save
update_latest_verification_id(verification)
Expand Down Expand Up @@ -151,10 +149,6 @@ def delete_all_verifications_between(consumer_name, options)
provider = pacticipant_repository.find_by_name!(options.fetch(:and))
PactBroker::Domain::Verification.where(provider: provider, consumer: consumer).delete
end

def pact_version_id_for pact
PactBroker::Pacts::PactPublication.select(:pact_version_id).where(id: pact.id)
end
end
end
end
14 changes: 9 additions & 5 deletions lib/pact_broker/verifications/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,21 @@ def next_number
verification_repository.next_number
end

def create next_verification_number, params, pact, event_context
logger.info "Creating verification #{next_verification_number} for pact_id=#{pact.id}", payload: params.reject{ |k,_| k == "testResults"}
# verified_pacts is an array of SelectedPact objects
def create next_verification_number, params, verified_pacts, event_context
first_verified_pact = verified_pacts.first
logger.info "Creating verification #{next_verification_number} for pact_version_sha=#{first_verified_pact.pact_version_sha}", payload: params.reject{ |k,_| k == "testResults"}
verification = PactBroker::Domain::Verification.new
provider_version_number = params.fetch("providerApplicationVersion")
PactBroker::Api::Decorators::VerificationDecorator.new(verification).from_hash(params)
verification.wip = params.fetch("wip")
verification.number = next_verification_number
verification = verification_repository.create(verification, provider_version_number, pact)
verification.consumer_version_selector_hashes = event_context[:consumer_version_selectors]

broadcast_events(verification, pact, event_context)
pact_version = pact_repository.find_pact_version(first_verified_pact.consumer, first_verified_pact.provider, first_verified_pact.pact_version_sha)
verification = verification_repository.create(verification, provider_version_number, pact_version)
# TODO set the latest_verification_id on each PactPublication
# TODO broadcast the verified_pacts for the webhooks
broadcast_events(verification, first_verified_pact.pact, event_context)

verification
end
Expand Down
5 changes: 4 additions & 1 deletion spec/lib/pact_broker/api/resources/verifications_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,14 @@ module Resources

before do
allow(Pacts::Service).to receive(:find_pact).and_return(pact)
allow(Pacts::Service).to receive(:find_for_verification_publication).and_return(verified_pacts)
allow(PactBroker::Verifications::Service).to receive(:next_number).and_return(next_verification_number)
allow(PactBroker::Api::Decorators::VerificationDecorator).to receive(:new).and_return(decorator)
allow(PactBroker.configuration).to receive(:show_webhook_response?).and_return("some-boolean")
end

let(:verified_pacts) { double("verified pacts") }

it "parses the webhook metadata" do
expect(PactBrokerUrls).to receive(:decode_pact_metadata).with("abcd")
subject
Expand All @@ -84,7 +87,7 @@ module Resources
expect(PactBroker::Verifications::Service).to receive(:create).with(
next_verification_number,
hash_including("some" => "params", "wip" => false),
pact,
verified_pacts,
parsed_metadata
)
subject
Expand Down
61 changes: 61 additions & 0 deletions spec/lib/pact_broker/pacts/service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,67 @@ module Pacts
end
end
end

describe "find_for_verification_publication integration test" do
before do
json_content = { interactions: [] }.to_json
td.create_pact_with_hierarchy("Foo", "1", "Bar", json_content)
.create_pact_with_hierarchy("Foo", "2", "Bar", json_content)
end

let(:consumer_version_selector_hashes) do
[
{ tag: "foo", latest: true, consumer_version_number: "1"},
{ tag: "bar", latest: true, consumer_version_number: "1"},
{ branch: "beep", latest: true, consumer_version_number: "2"}
]
end

let(:pact_params) do
PactParams.new(
consumer_name: "Foo",
provider_name: "Bar",
pact_version_sha: td.and_return(:pact).pact_version_sha
)
end

subject { Service.find_for_verification_publication(pact_params, consumer_version_selector_hashes) }

it "deduplicates the pacts by consumer version number" do
expect(subject.size).to eq 2
end

it "sets the selectors" do
expect(subject.first.selectors.size).to eq 2
expect(subject.first.selectors.first).to have_attributes(latest: true, tag: "bar")
expect(subject.first.selectors.first.consumer_version).to have_attributes(number: "1")

expect(subject.first.selectors.last).to have_attributes(latest: true, tag: "foo")
expect(subject.first.selectors.last.consumer_version).to have_attributes(number: "1")

expect(subject.last.selectors.size).to eq 1
expect(subject.last.selectors.first).to have_attributes(latest: true, branch: "beep")
expect(subject.last.selectors.last.consumer_version).to have_attributes(number: "2")
end

context "when there are no consumer version selectors" do
let(:consumer_version_selector_hashes) { nil }

it "returns the latest pact for the sha" do
expect(subject.size).to eq 1
expect(subject.first.consumer_version_number).to eq "2"
end
end

context "when the consumer version selectors is empty" do
let(:consumer_version_selector_hashes) { [] }

it "returns the latest pact for the sha" do
expect(subject.size).to eq 1
expect(subject.first.consumer_version_number).to eq "2"
end
end
end
end
end
end
46 changes: 17 additions & 29 deletions spec/lib/pact_broker/verifications/repository_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ module Verifications
end

let(:provider_version_number) { "2" }
let(:pact) do
td.create_pact_with_hierarchy("Foo", "1", "Bar").and_return(:pact)
let(:pact_version) do
PactBroker::Pacts::PactVersion.first
end

subject { Repository.new.create verification, provider_version_number, pact}
subject { Repository.new.create(verification, provider_version_number, pact_version) }

it "creates a LatestVerificationIdForPactVersionAndProviderVersion" do
expect { subject }.to change { LatestVerificationIdForPactVersionAndProviderVersion.count }.by(1)
Expand All @@ -47,23 +47,21 @@ module Verifications

describe "#find" do
let!(:pact) do
builder = TestDataBuilder.new
pact = builder

pact = td
.create_provider("Provider1")
.create_consumer("Consumer1")
.create_consumer_version("1.0.0")
.create_pact
.and_return(:pact)

builder
.create_verification(number: 1)
td.create_verification(number: 1)
.create_verification(number: 2, provider_version: "3.7.4")
.create_consumer_version("1.2.3")
.create_pact
.create_verification(number: 1)

TestDataBuilder.new
.create_provider("Provider3")
td.create_provider("Provider3")
.create_consumer("Consumer2")
.create_consumer_version("1.2.3")
.create_pact
Expand All @@ -83,8 +81,7 @@ module Verifications

describe "#find_latest_verifications_for_consumer_version" do
before do
TestDataBuilder.new
.create_provider("Provider1")
td.create_provider("Provider1")
.create_consumer("Consumer1")
.create_consumer_version("1.0.0")
.create_pact
Expand All @@ -97,8 +94,7 @@ module Verifications
.create_pact
.create_verification(number: 1, provider_version: "6.5.4")

TestDataBuilder.new
.create_provider("Provider3")
td.create_provider("Provider3")
.create_consumer("Consumer2")
.create_consumer_version("1.2.3")
.create_pact
Expand All @@ -115,8 +111,7 @@ module Verifications

describe "#search_for_latest" do
before do
TestDataBuilder.new
.create_pact_with_hierarchy("Foo", "1", "Bar")
td.create_pact_with_hierarchy("Foo", "1", "Bar")
.create_verification(provider_version: "2")
.create_verification(provider_version: "3", number: 2)
.create_provider("Wiffle")
Expand Down Expand Up @@ -152,8 +147,7 @@ module Verifications
describe "#find_latest_verification_for" do
context "when there is a revision" do
before do
TestDataBuilder.new
.create_provider("Provider1")
td.create_provider("Provider1")
.create_consumer("Consumer1")
.create_consumer_version("1.2.3")
.create_pact
Expand All @@ -172,8 +166,7 @@ module Verifications
context "when no tag is specified" do
before do
PactBroker.configuration.order_versions_by_date = false
TestDataBuilder.new
.create_provider("Provider1")
td.create_provider("Provider1")
.create_consumer("Consumer1")
.create_consumer_version("1.2.3")
.create_pact
Expand All @@ -198,8 +191,7 @@ module Verifications

context "when a tag is specified" do
before do
TestDataBuilder.new
.create_provider("Provider1")
td.create_provider("Provider1")
.create_consumer("Consumer1")
.create_consumer_version("1.0.0")
.create_consumer_version_tag("prod")
Expand Down Expand Up @@ -237,8 +229,7 @@ module Verifications

context "when the latest untagged verification is required" do
before do
TestDataBuilder.new
.create_provider("Provider1")
td.create_provider("Provider1")
.create_consumer("Consumer1")
.create_consumer_version("1.0.0")
.create_pact
Expand Down Expand Up @@ -270,8 +261,7 @@ module Verifications
describe "find_latest_verification_for_tags" do
context "with no revisions" do
before do
TestDataBuilder.new
.create_pact_with_hierarchy("Foo", "1", "Bar")
td.create_pact_with_hierarchy("Foo", "1", "Bar")
.create_consumer_version_tag("feat-x")
.create_verification(provider_version: "5")
.use_provider_version("5")
Expand All @@ -297,8 +287,7 @@ module Verifications
let(:content_2) { { content: 2 }.to_json }

before do
TestDataBuilder.new
.create_pact_with_hierarchy("Foo", "1", "Bar", content_1)
td.create_pact_with_hierarchy("Foo", "1", "Bar", content_1)
.create_consumer_version_tag("develop")
.create_verification(provider_version: "5", number: 1, tag_name: "develop", comment: "not this because pact revised")
.create_verification(provider_version: "6", number: 2, tag_name: "develop", comment: "not this because pact revised")
Expand Down Expand Up @@ -340,8 +329,7 @@ module Verifications

describe "delete_by_provider_version_id" do
let!(:provider_version) do
TestDataBuilder.new
.create_consumer
td.create_consumer
.create_provider
.create_consumer_version
.create_pact
Expand Down
3 changes: 2 additions & 1 deletion spec/lib/pact_broker/verifications/service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ module Verifications
.create_provider_version_tag("dev")
.and_return(:pact)
end
let(:create_verification) { subject.create 3, params, pact, event_context }
let(:selected_pacts) { [PactBroker::Pacts::SelectedPact.new(pact, PactBroker::Pacts::Selectors.new)]}
let(:create_verification) { subject.create 3, params, selected_pacts, event_context }

it "logs the creation" do
expect(logger).to receive(:info).with(/.*verification.*3/, payload: {"providerApplicationVersion"=>"4.5.6", "success"=>true, "wip"=>true})
Expand Down

0 comments on commit 09c11d3

Please sign in to comment.