diff --git a/lib/pact_broker/api/contracts/dry_validation_predicates.rb b/lib/pact_broker/api/contracts/dry_validation_predicates.rb index a9904a2c9..953db32d1 100644 --- a/lib/pact_broker/api/contracts/dry_validation_predicates.rb +++ b/lib/pact_broker/api/contracts/dry_validation_predicates.rb @@ -9,6 +9,10 @@ module DryValidationPredicates predicate(:date?) do |value| DateTime.parse(value) rescue false end + + predicate(:not_blank?) do | value | + value && value.is_a?(String) && value.strip.size > 0 + end end end end diff --git a/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema.rb b/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema.rb index d12041e80..773044088 100644 --- a/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema.rb +++ b/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema.rb @@ -13,6 +13,7 @@ class VerifiablePactsJSONQuerySchema SCHEMA = Dry::Validation.Schema do configure do predicates(DryValidationPredicates) + config.messages_file = File.expand_path("../../../locale/en.yml", __FILE__) end optional(:providerVersionTags).maybe(:array?) optional(:consumerVersionSelectors).each do @@ -26,6 +27,7 @@ class VerifiablePactsJSONQuerySchema required(:tag).filled(:str?) optional(:latest).filled(included_in?: [true, false]) optional(:fallbackTag).filled(:str?) + optional(:consumer).filled(:str?, :not_blank?) # rule(fallbackTagMustBeForLatest: [:fallbackTag, :latest]) do | fallback_tag, latest | # fallback_tag.filled?.then(latest.eql?(true)) diff --git a/lib/pact_broker/api/contracts/verifiable_pacts_query_schema.rb b/lib/pact_broker/api/contracts/verifiable_pacts_query_schema.rb index 797e50827..62b9a9720 100644 --- a/lib/pact_broker/api/contracts/verifiable_pacts_query_schema.rb +++ b/lib/pact_broker/api/contracts/verifiable_pacts_query_schema.rb @@ -12,6 +12,7 @@ class VerifiablePactsQuerySchema SCHEMA = Dry::Validation.Schema do configure do predicates(DryValidationPredicates) + config.messages_file = File.expand_path("../../../locale/en.yml", __FILE__) end optional(:provider_version_tags).maybe(:array?) optional(:consumer_version_selectors).each do @@ -19,6 +20,7 @@ class VerifiablePactsQuerySchema required(:tag).filled(:str?) optional(:latest).filled(included_in?: ["true", "false"]) optional(:fallback_tag).filled(:str?) + optional(:consumer).filled(:str?, :not_blank?) end end optional(:include_pending_status).filled(included_in?: ["true", "false"]) diff --git a/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb b/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb index a9ad1aca3..5b617cdef 100644 --- a/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +++ b/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb @@ -20,6 +20,7 @@ class VerifiablePactsQueryDecorator < BaseDecorator represented.latest = (fragment == 'true' || fragment == true) } property :fallback_tag + property :consumer end property :include_pending_status, default: false, diff --git a/lib/pact_broker/pacts/pact_publication.rb b/lib/pact_broker/pacts/pact_publication.rb index f09a5da5f..b444b5c5d 100644 --- a/lib/pact_broker/pacts/pact_publication.rb +++ b/lib/pact_broker/pacts/pact_publication.rb @@ -82,6 +82,14 @@ def order_by_consumer_name def order_by_consumer_version_order order_append(Sequel[:cv][:order]) end + + def where_consumer_if_set(consumer) + if consumer + where(consumer: consumer) + else + self + end + end end def before_create diff --git a/lib/pact_broker/pacts/repository.rb b/lib/pact_broker/pacts/repository.rb index 3a2e70741..bb2ce5172 100644 --- a/lib/pact_broker/pacts/repository.rb +++ b/lib/pact_broker/pacts/repository.rb @@ -130,17 +130,18 @@ def find_latest_pact_versions_for_provider provider_name, tag = nil end end - def find_all_pact_versions_for_provider_with_consumer_version_tags provider_name, consumer_version_tag_names + def find_all_pact_versions_for_provider_with_consumer_version_tags provider_name, consumer_version_tag_name, consumer_name = nil provider = pacticipant_repository.find_by_name(provider_name) - + consumer = consumer_name ? pacticipant_repository.find_by_name(consumer_name) : nil PactPublication .select_all_qualified .select_append(Sequel[:cv][:order].as(:consumer_version_order)) .select_append(Sequel[:ct][:name].as(:consumer_version_tag_name)) .remove_overridden_revisions .join_consumer_versions(:cv) - .join_consumer_version_tags_with_names(consumer_version_tag_names) + .join_consumer_version_tags_with_names(consumer_version_tag_name) .where(provider: provider) + .where_consumer_if_set(consumer) .eager(:consumer) .eager(:consumer_version) .eager(:provider) @@ -457,12 +458,10 @@ def find_pacts_for_which_the_latest_version_for_the_fallback_tag_is_required(pro def find_pacts_for_which_all_versions_for_the_tag_are_required(provider_name, consumer_version_selectors) # The tags for which all versions are specified - tag_names = consumer_version_selectors.tag_names_of_selectors_for_all_pacts + selectors = consumer_version_selectors.select(&:all_for_tag?) - if tag_names.any? - find_all_pact_versions_for_provider_with_consumer_version_tags(provider_name, tag_names) - else - [] + selectors.flat_map do | selector | + find_all_pact_versions_for_provider_with_consumer_version_tags(provider_name, selector.tag, selector.consumer) end end diff --git a/lib/pact_broker/pacts/selector.rb b/lib/pact_broker/pacts/selector.rb index 3a22f89b9..3ad385edc 100644 --- a/lib/pact_broker/pacts/selector.rb +++ b/lib/pact_broker/pacts/selector.rb @@ -25,6 +25,14 @@ def fallback_tag self[:fallback_tag] end + def consumer= consumer + self[:consumer] = consumer + end + + def consumer + self[:consumer] + end + def self.overall_latest Selector.new(latest: true) end @@ -41,6 +49,9 @@ def self.all_for_tag(tag) Selector.new(tag: tag) end + def self.all_for_tag_and_consumer(tag, consumer) + Selector.new(tag: tag, consumer: consumer) + end def self.from_hash hash Selector.new(hash) diff --git a/spec/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema_spec.rb b/spec/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema_spec.rb index 5adb93346..d07fb3b77 100644 --- a/spec/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema_spec.rb +++ b/spec/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema_spec.rb @@ -113,6 +113,19 @@ module Contracts it { is_expected.to_not have_key(:includeWipPactsSince) } end end + + context "when a blank consumer name is specified" do + let(:consumer_version_selectors) do + [{ + tag: "feat-x", + consumer: "" + }] + end + + it "has an error" do + expect(subject[:consumerVersionSelectors].first).to include "blank" + end + end end end end diff --git a/spec/lib/pact_broker/api/contracts/verifiable_pacts_query_schema_spec.rb b/spec/lib/pact_broker/api/contracts/verifiable_pacts_query_schema_spec.rb index 4847d5fbb..5f7022117 100644 --- a/spec/lib/pact_broker/api/contracts/verifiable_pacts_query_schema_spec.rb +++ b/spec/lib/pact_broker/api/contracts/verifiable_pacts_query_schema_spec.rb @@ -78,6 +78,19 @@ module Contracts it { is_expected.to_not have_key(:include_wip_pacts_since) } end end + + context "when a blank consumer name is specified" do + let(:consumer_version_selectors) do + [{ + tag: "feat-x", + consumer: "" + }] + end + + it "has an error" do + expect(subject[:consumer_version_selectors].first).to include "blank" + end + end end end end diff --git a/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb b/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb index 4eb51edda..abb222d71 100644 --- a/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +++ b/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb @@ -103,6 +103,32 @@ def find_by_consumer_name_and_consumer_version_number(consumer_name, consumer_ve end end + context "when all versions with a given tag for a given consumer are requested" do + before do + td.create_pact_with_hierarchy("Foo2", "prod-version-1", "Bar2") + .create_consumer_version_tag("prod") + .create_consumer_version("not-prod-version", tag_names: %w[master]) + .create_pact + .create_consumer_version("prod-version-2", tag_names: %w[prod]) + .create_pact + .create_consumer("Foo3") + .create_consumer_version("prod-version-3", tag_names: %w[prod]) + .create_pact + end + + let(:consumer_version_selectors) { Selectors.new(pact_selector_1) } + let(:pact_selector_1) { Selector.all_for_tag_and_consumer('prod', "Foo2") } + + subject { Repository.new.find_for_verification("Bar2", consumer_version_selectors) } + + it "returns all the versions with the specified tag and consumer" do + expect(subject.size).to be 2 + expect(find_by_consumer_version_number("prod-version-1")).to_not be nil + expect(find_by_consumer_version_number("prod-version-2")).to_not be nil + expect(find_by_consumer_version_number("prod-version-3")).to be nil + end + end + context "when a pact version has been selected by two different selectors" do before do td.create_pact_with_hierarchy("Foo", "1", "Bar")