From 59ec8c8a2995771ff86d90948acf312dc4874176 Mon Sep 17 00:00:00 2001 From: Beth Skurrie Date: Sun, 2 Feb 2020 14:29:27 +1100 Subject: [PATCH] feat(pacts for verification): update the inclusion notice text to handle 'all pacts for tag' --- lib/pact_broker/pacts/repository.rb | 1 + lib/pact_broker/pacts/selector.rb | 26 ++++++++++++-- lib/pact_broker/pacts/selectors.rb | 2 +- lib/pact_broker/pacts/service.rb | 4 +-- .../pacts/verifiable_pact_messages.rb | 35 +++++++++++++------ .../pacts/verifiable_pact_messages_spec.rb | 24 +++++++------ 6 files changed, 66 insertions(+), 26 deletions(-) diff --git a/lib/pact_broker/pacts/repository.rb b/lib/pact_broker/pacts/repository.rb index 92d9a17ca..43b51af35 100644 --- a/lib/pact_broker/pacts/repository.rb +++ b/lib/pact_broker/pacts/repository.rb @@ -16,6 +16,7 @@ require 'pact_broker/repositories/helpers' require 'pact_broker/pacts/selected_pact' require 'pact_broker/pacts/selector' +require 'pact_broker/pacts/selectors' module PactBroker module Pacts diff --git a/lib/pact_broker/pacts/selector.rb b/lib/pact_broker/pacts/selector.rb index 461135616..867665036 100644 --- a/lib/pact_broker/pacts/selector.rb +++ b/lib/pact_broker/pacts/selector.rb @@ -13,22 +13,44 @@ def self.latest_for_tag(tag) Selector.new(latest: true, tag: tag) end - def self.one_of_tag(tag) + def self.all_for_tag(tag) Selector.new(tag: tag) end + def self.from_hash hash + Selector.new(hash) + end + def tag self[:tag] end def overall_latest? - !!(latest && !tag) + !!(latest? && !tag) end def latest_for_tag? !!(latest && tag) end + def <=> other + if overall_latest? || other.overall_latest? + if overall_latest? == other.overall_latest? + 0 + else + overall_latest? ? -1 : 1 + end + elsif latest_for_tag? || other.latest_for_tag? + if latest_for_tag? == other.latest_for_tag? + tag <=> other.tag + else + latest_for_tag? ? -1 : 1 + end + else + tag <=> other.tag + end + end + private def latest? diff --git a/lib/pact_broker/pacts/selectors.rb b/lib/pact_broker/pacts/selectors.rb index 2c65d68b5..c434ea15a 100644 --- a/lib/pact_broker/pacts/selectors.rb +++ b/lib/pact_broker/pacts/selectors.rb @@ -8,7 +8,7 @@ def initialize selectors end def self.create_for_all_of_each_tag(tag_names) - Selectors.new(tag_names.collect{ | tag_name | Selector.one_of_tag(tag_name) }) + Selectors.new(tag_names.collect{ | tag_name | Selector.all_for_tag(tag_name) }) end def self.create_for_overall_latest_of_each_tag(tag_names) diff --git a/lib/pact_broker/pacts/service.rb b/lib/pact_broker/pacts/service.rb index a426c7912..df980858b 100644 --- a/lib/pact_broker/pacts/service.rb +++ b/lib/pact_broker/pacts/service.rb @@ -136,8 +136,8 @@ def find_for_verification(provider_name, provider_version_tags, consumer_version private def exclude_specified_pacts(wip_pacts, specified_pacts) - wip_pacts.select do | wip_pact | - !specified_pacts.any? do | specified_pacts | + wip_pacts.reject do | wip_pact | + specified_pacts.any? do | specified_pacts | wip_pact.pact_version_sha == specified_pacts.pact_version_sha end end diff --git a/lib/pact_broker/pacts/verifiable_pact_messages.rb b/lib/pact_broker/pacts/verifiable_pact_messages.rb index fae56dd67..5b90f373c 100644 --- a/lib/pact_broker/pacts/verifiable_pact_messages.rb +++ b/lib/pact_broker/pacts/verifiable_pact_messages.rb @@ -29,17 +29,14 @@ def inclusion_reason # WIP pacts will always have tags, because it is part of the definition of being a WIP pact "The pact at #{pact_version_url} is being verified because it is a 'work in progress' pact (ie. it is the pact for the latest #{version_text} of Foo tagged with #{joined_head_consumer_tags} and is still in pending state). #{READ_MORE_WIP}" else - if selectors.overall_latest? - "The pact at #{pact_version_url} is being verified because it is the latest pact between #{consumer_name} and #{provider_name}." - else - "The pact at #{pact_version_url} is being verified because it is the pact for the latest #{version_text} of Foo tagged with #{joined_head_consumer_tags}" - end + criteria_or_criterion = selectors.size > 1 ? "criteria" : "criterion" + "The pact at #{pact_version_url} is being verified because it matches the following configured selection #{criteria_or_criterion}: #{selector_descriptions}#{same_content_note}" end end def pending_reason if pending? - "This pact is in pending state because it has not yet been successfully verified by #{pending_provider_tags_description}. If this verification fails, it will not cause the overall build to fail. #{READ_MORE_PENDING}" + "This pact is in pending state for this version of #{provider_name} because a successful verification result for #{pending_provider_tags_description("a")} has not yet been published. If this verification fails, it will not cause the overall build to fail. #{READ_MORE_PENDING}" else "This pact has previously been successfully verified by #{non_pending_provider_tags_description}. If this verification fails, it will fail the build. #{READ_MORE_PENDING}" end @@ -87,18 +84,18 @@ def joined_head_consumer_tags end def same_content_note - case head_consumer_tags.size + case selectors.size when 1 then "" when 2 then " (both have the same content)" else " (all have the same content)" end end - def pending_provider_tags_description + def pending_provider_tags_description(any_or_a = "any") case pending_provider_tags.size when 0 then provider_name - when 1 then "any version of #{provider_name} with tag '#{pending_provider_tags.first}'" - else "any versions of #{provider_name} with tag #{join(pending_provider_tags)}" + when 1 then "#{any_or_a} version of #{provider_name} with tag '#{pending_provider_tags.first}'" + else "#{any_or_a} versions of #{provider_name} with tag #{join(pending_provider_tags)}" end end @@ -122,6 +119,24 @@ def head_consumer_tags selectors.tag_names_for_selectors_for_latest_pacts end + def selector_descriptions + selectors.sort.collect do | selector | + selector_description(selector) + end.join(", ") + end + + def selector_description selector + if selector.overall_latest? + "latest pact between a consumer and #{provider_name}" + elsif selector.latest_for_tag? + "latest pact for a consumer version tagged '#{selector.tag}'" + elsif selector.tag + "pacts for all consumer versions tagged '#{selector.tag}'" + else + selector.to_json + end + end + def selectors verifiable_pact.selectors end diff --git a/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb b/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb index 92fc3a82b..171f763ee 100644 --- a/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +++ b/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb @@ -29,29 +29,25 @@ module Pacts describe "#inclusion_reason" do context "when there are no head consumer tags" do let(:selectors) { Selectors.create_for_overall_latest } - its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it is the latest pact between Foo and Bar." } + its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criterion: latest pact between a consumer and Bar" } end context "when there is 1 head consumer tags" do let(:selectors) { Selectors.create_for_overall_latest_of_each_tag(%w[dev]) } - its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it is the pact for the latest version of Foo tagged with 'dev'" } + its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criterion: latest pact for a consumer version tagged 'dev'" } its(:pact_description) { is_expected.to eq "Pact between Foo and Bar, consumer version 123, latest dev"} end context "when there are 2 head consumer tags" do let(:selectors) { Selectors.create_for_overall_latest_of_each_tag(%w[dev prod]) } - its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it is the pact for the latest versions of Foo tagged with 'dev' and 'prod' (both have the same content)" } + its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criteria: latest pact for a consumer version tagged 'dev', latest pact for a consumer version tagged 'prod' (both have the same content)" } end context "when there are 3 head consumer tags" do let(:selectors) { Selectors.create_for_overall_latest_of_each_tag(%w[dev prod feat-x]) } - its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it is the pact for the latest versions of Foo tagged with 'dev', 'prod' and 'feat-x' (all have the same content)" } + its(:inclusion_reason) { is_expected.to include " (all have the same content)" } end - context "when there are 4 head consumer tags" do - let(:selectors) { Selectors.create_for_overall_latest_of_each_tag(%w[dev prod feat-x feat-y]) } - its(:inclusion_reason) { is_expected.to include "'dev', 'prod', 'feat-x' and 'feat-y'" } - end context "when the pact is a WIP pact" do let(:selectors) { Selectors.create_for_overall_latest_of_each_tag(%w[feat-x]) } @@ -61,6 +57,12 @@ module Pacts its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it is a 'work in progress' pact (ie. it is the pact for the latest version of Foo tagged with 'feat-x' and is still in pending state)."} end + + context "when the pact is one of all versions for a tag" do + let(:selectors) { Selectors.create_for_all_of_each_tag(%w[prod]) } + + its(:inclusion_reason) { is_expected.to include "The pact at http://pact is being verified because it matches the following configured selection criterion: pacts for all consumer versions tagged 'prod'"} + end end describe "#pending_reason" do @@ -81,20 +83,20 @@ module Pacts context "when there are no pending_provider_tags" do context "when there are no non_pending_provider_tags" do - its(:pending_reason) { is_expected.to include "This pact is in pending state because it has not yet been successfully verified by Bar. If this verification fails, it will not cause the overall build to fail." } + its(:pending_reason) { is_expected.to include "This pact is in pending state for this version of Bar because a successful verification result for Bar has not yet been published. If this verification fails, it will not cause the overall build to fail." } end end context "when there is 1 pending_provider_tag" do let(:pending_provider_tags) { %w[dev] } - its(:pending_reason) { is_expected.to include "This pact is in pending state because it has not yet been successfully verified by any version of Bar with tag 'dev'. If this verification fails, it will not cause the overall build to fail." } + its(:pending_reason) { is_expected.to include "This pact is in pending state for this version of Bar because a successful verification result for a version of Bar with tag 'dev' has not yet been published. If this verification fails, it will not cause the overall build to fail." } end context "when there are 2 pending_provider_tags" do let(:pending_provider_tags) { %w[dev feat-x] } - its(:pending_reason) { is_expected.to include "This pact is in pending state because it has not yet been successfully verified by any versions of Bar with tag 'dev' and 'feat-x'." } + its(:pending_reason) { is_expected.to include "This pact is in pending state for this version of Bar because a successful verification result for a versions of Bar with tag 'dev' and 'feat-x' has not yet been published. If this verification fails, it will not cause the overall build to fail." } end context "when there are 3 pending_provider_tags" do