Skip to content

Commit

Permalink
feat: allow matrix to be queried for _all_ versions with a given tag
Browse files Browse the repository at this point in the history
Previously, only querying for the _latest_ version with a given tag was supported.
  • Loading branch information
bethesque committed Apr 19, 2018
1 parent 7a81292 commit cac3023
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 55 deletions.
2 changes: 1 addition & 1 deletion lib/pact_broker/api/resources/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def delete_resource

def version
if path_info[:tag]
@version ||= version_service.find_by_pacticpant_name_and_latest_tag(path_info[:pacticipant_name], path_info[:tag])
@version ||= version_service.find_by_pacticipant_name_and_latest_tag(path_info[:pacticipant_name], path_info[:tag])
elsif path_info[:pacticipant_version_number]
@version ||= version_service.find_by_pacticipant_name_and_number path_info
else
Expand Down
65 changes: 39 additions & 26 deletions lib/pact_broker/matrix/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,21 +134,19 @@ def view_for(options)
end

def resolve_selectors(selectors, options)
selectors = look_up_versions_for_latest_and_tag(selectors, options)

if options[:latest]
apply_latest_and_tag_to_inferred_selectors(selectors, options)
resolved_selectors = look_up_version_numbers(selectors, options)
if options[:latest] || options[:tag]
apply_latest_and_tag_to_inferred_selectors(resolved_selectors, options)
else
selectors
resolved_selectors
end
end

# Find the version number for selectors with the latest (tagged) version specified
def look_up_versions_for_latest_and_tag(selectors, options)
# Find the version number for selectors with the latest and/or tag specified
def look_up_version_numbers(selectors, options)
selectors.collect do | selector |
# resource validation currently stops tag being specified without latest=true
if selector[:tag] && selector[:latest]
version = version_repository.find_by_pacticpant_name_and_latest_tag(selector[:pacticipant_name], selector[:tag])
version = version_repository.find_by_pacticipant_name_and_latest_tag(selector[:pacticipant_name], selector[:tag])
raise Error.new("Could not find version with tag #{selector[:tag].inspect} for #{selector[:pacticipant_name]}") unless version
# validation in resource should ensure we always have a version
{
Expand All @@ -161,25 +159,38 @@ def look_up_versions_for_latest_and_tag(selectors, options)
pacticipant_name: selector[:pacticipant_name],
pacticipant_version_number: version.number
}
elsif selector[:tag]
# validation in resource should ensure we always have at least one version
versions = version_repository.find_by_pacticipant_name_and_tag(selector[:pacticipant_name], selector[:tag])
versions.collect do | version |
{
pacticipant_name: selector[:pacticipant_name],
pacticipant_version_number: version.number
}
end
else
selector.dup
end
end.collect do | selector |
if selector[:pacticipant_name]
pacticipant = PactBroker::Domain::Pacticipant.find(name: selector[:pacticipant_name])
selector[:pacticipant_id] = pacticipant ? pacticipant.id : nil
end
end.flatten.compact.collect do | selector |
add_ids(selector)
end
end

if selector[:pacticipant_name] && selector[:pacticipant_version_number]
version = version_repository.find_by_pacticipant_name_and_number(selector[:pacticipant_name], selector[:pacticipant_version_number])
selector[:pacticipant_version_id] = version ? version.id : nil
end
def add_ids(selector)
if selector[:pacticipant_name]
pacticipant = PactBroker::Domain::Pacticipant.find(name: selector[:pacticipant_name])
selector[:pacticipant_id] = pacticipant ? pacticipant.id : nil
end

if selector[:pacticipant_version_number].nil?
selector[:pacticipant_version_id] = nil
end
selector
if selector[:pacticipant_name] && selector[:pacticipant_version_number]
version = version_repository.find_by_pacticipant_name_and_number(selector[:pacticipant_name], selector[:pacticipant_version_number])
selector[:pacticipant_version_id] = version ? version.id : nil
end

if selector[:pacticipant_version_number].nil?
selector[:pacticipant_version_id] = nil
end
selector
end

# eg. when checking to see if Foo version 2 can be deployed to prod,
Expand All @@ -190,13 +201,15 @@ def apply_latest_and_tag_to_inferred_selectors(selectors, options)
inferred_names = all_pacticipant_names - specified_names

inferred_selectors = inferred_names.collect do | pacticipant_name |
{
selector = {
pacticipant_name: pacticipant_name,
latest: options[:latest]
}.tap { |it| it[:tag] = options[:tag] if options[:tag] }
}
selector[:tag] = options[:tag] if options[:tag]
selector[:latest] = options[:latest] if options[:latest]
selector
end

selectors + look_up_versions_for_latest_and_tag(inferred_selectors, options)
selectors + look_up_version_numbers(inferred_selectors, options)
end

def all_pacticipant_names_in_specified_matrix(selectors, options)
Expand Down
8 changes: 2 additions & 6 deletions lib/pact_broker/matrix/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@ def validate_selectors selectors
error_messages << "Please specify the pacticipant name"
else
if s.key?(:pacticipant_version_number) && s.key?(:latest)
error_messages << "A version and latest flag cannot both be specified for #{s[:pacticipant_name]}"
end

if s.key?(:tag) && !s.key?(:latest)
error_messages << "Querying for all versions with a tag is not currently supported. The latest=true flag must be specified when a tag is given."
error_messages << "A version number and latest flag cannot both be specified for #{s[:pacticipant_name]}"
end
end
end
Expand All @@ -78,7 +74,7 @@ def validate_selectors selectors
version = version_service.find_by_pacticipant_name_and_number(pacticipant_name: s[:pacticipant_name], pacticipant_version_number: s[:pacticipant_version_number])
error_messages << "No pact or verification found for #{s[:pacticipant_name]} version #{s[:pacticipant_version_number]}" if version.nil?
elsif s[:tag]
version = version_service.find_by_pacticpant_name_and_latest_tag(s[:pacticipant_name], s[:tag])
version = version_service.find_by_pacticipant_name_and_latest_tag(s[:pacticipant_name], s[:tag])
error_messages << "No version of #{s[:pacticipant_name]} found with tag #{s[:tag]}" if version.nil?
end
end
Expand Down
12 changes: 11 additions & 1 deletion lib/pact_broker/versions/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def find_by_pacticipant_id_and_number pacticipant_id, number
PactBroker::Domain::Version.where(number: number, pacticipant_id: pacticipant_id).single_record
end

def find_by_pacticpant_name_and_latest_tag pacticipant_name, tag
def find_by_pacticipant_name_and_latest_tag pacticipant_name, tag
PactBroker::Domain::Version
.select_all_qualified
.join(:pacticipants, {id: :pacticipant_id}, {implicit_qualifier: :versions})
Expand All @@ -23,6 +23,16 @@ def find_by_pacticpant_name_and_latest_tag pacticipant_name, tag
.first
end

def find_by_pacticipant_name_and_tag pacticipant_name, tag
PactBroker::Domain::Version
.select_all_qualified
.join(:pacticipants, {id: :pacticipant_id}, {implicit_qualifier: :versions})
.join(:tags, {version_id: :id}, {implicit_qualifier: :versions})
.where(name_like(Sequel[:tags][:name], tag))
.where(name_like(Sequel[:pacticipants][:name], pacticipant_name))
.all
end

def find_latest_by_pacticpant_name pacticipant_name
PactBroker::Domain::Version
.select_all_qualified
Expand Down
4 changes: 2 additions & 2 deletions lib/pact_broker/versions/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ def self.find_by_pacticipant_name_and_number params
version_repository.find_by_pacticipant_name_and_number params.fetch(:pacticipant_name), params.fetch(:pacticipant_version_number)
end

def self.find_by_pacticpant_name_and_latest_tag(pacticipant_name, tag)
version_repository.find_by_pacticpant_name_and_latest_tag(pacticipant_name, tag)
def self.find_by_pacticipant_name_and_latest_tag(pacticipant_name, tag)
version_repository.find_by_pacticipant_name_and_latest_tag(pacticipant_name, tag)
end

def self.delete version
Expand Down
52 changes: 52 additions & 0 deletions spec/lib/pact_broker/matrix/repository_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,58 @@ def shorten_rows rows
end
end

context "when compability is required with all versions with a given tag" do
before do
td.create_pact_with_hierarchy("android app", "1", "BFF")
.create_consumer_version_tag("prod")
.create_verification(provider_version: "5", comment: "included")
.create_consumer_version("2", tag_name: "prod")
.create_pact
.create_verification(provider_version: "5", comment: "included")
.create_consumer_version("3")
.create_pact
.create_verification(provider_version: "5", comment: "not included")
.create_consumer("ios app")
.create_consumer_version("20", tag_name: "prod")
.create_pact
.create_verification(provider_version: "5", comment: "not included")
end

context "when the other service is specifically named" do
let(:selectors) do
[
{ pacticipant_name: "android app", tag: "prod" },
{ pacticipant_name: "BFF", pacticipant_version_number: "5" }
]
end

let(:options) { {} }

it "returns the matrix for all of the versions for the specified pacticipants with the given tag" do
expect(subject).to include_hash_matching(consumer_version_number: "1")
expect(subject).to include_hash_matching(consumer_version_number: "2")
expect(subject).to_not include_hash_matching(consumer_version_number: "3")
expect(subject).to_not include_hash_matching(consumer_name: "ios app")
end
end

context "when the other service is not specifically named" do
let(:selectors) do
[
{ pacticipant_name: "BFF", pacticipant_version_number: "5" }
]
end

let(:options) { { tag: "prod" } }

it "returns the matrix for all of the versions with the given tag" do
expect(subject).to include_hash_matching(consumer_name: "android app", consumer_version_number: "1")
expect(subject).to include_hash_matching(consumer_name: "android app", consumer_version_number: "2")
expect(subject).to include_hash_matching(consumer_name: "ios app", consumer_version_number: "20")
end
end
end

context "using the success option" do
before do
td.create_pact_with_hierarchy("A", "1.2.3", "B")
Expand Down
18 changes: 1 addition & 17 deletions spec/lib/pact_broker/matrix/service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,23 +102,7 @@ module Matrix
let(:selectors) { [{ pacticipant_name: "Foo", pacticipant_version_number: "1", latest: true }, { pacticipant_name: "Bar", pacticipant_version_number: "2" }] }

it "returns an error message" do
expect(subject).to eq ["A version and latest flag cannot both be specified for Foo"]
end
end

context "when a tag is specified without latest=true" do
before do
td.create_pacticipant("Foo")
.create_version("1")
.create_tag("prod")
.create_pacticipant("Bar")
.create_version("2")
end

let(:selectors) { [{ pacticipant_name: "Foo", tag: "1"}] }

it "returns an error message" do
expect(subject).to eq ["Querying for all versions with a tag is not currently supported. The latest=true flag must be specified when a tag is given."]
expect(subject).to eq ["A version number and latest flag cannot both be specified for Foo"]
end
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/lib/pact_broker/versions/repository_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module Versions
let(:version_number) { "1.2.3" }


describe "#find_by_pacticpant_name_and_latest_tag" do
describe "#find_by_pacticipant_name_and_latest_tag" do
before do
td.create_consumer("Bar")
.create_consumer_version("2.3.4")
Expand All @@ -23,7 +23,7 @@ module Versions
.create_consumer_version("5.6.7")
end

subject { Repository.new.find_by_pacticpant_name_and_latest_tag("Foo", "prod") }
subject { Repository.new.find_by_pacticipant_name_and_latest_tag("Foo", "prod") }

it "returns the most recent version that has the specified tag" do

Expand Down
4 changes: 4 additions & 0 deletions spec/support/test_data_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,11 @@ def create_version version_number = "1.0.#{model_counter}", params = {}

def create_consumer_version version_number = "1.0.#{model_counter}", params = {}
params.delete(:comment)
tag_names = [params.delete(:tag_names), params.delete(:tag_name)].flatten.compact
@consumer_version = PactBroker::Domain::Version.create(:number => version_number, :pacticipant => @consumer)
tag_names.each do | tag_name |
PactBroker::Domain::Tag.create(name: tag_name, version: @consumer_version)
end
self
end

Expand Down

0 comments on commit cac3023

Please sign in to comment.