Skip to content

Commit

Permalink
feat: use the consumer version number in the metadata to select the c…
Browse files Browse the repository at this point in the history
…orrect consumer version for a pact version resource

Fixes: pact-foundation/pact-jvm#1249
  • Loading branch information
bethesque committed Dec 2, 2020
1 parent 8a0faac commit 422c87f
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 29 deletions.
2 changes: 1 addition & 1 deletion lib/pact_broker/api/pact_broker_urls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def encode_metadata(metadata)
end

def decode_pact_metadata(metadata)
if metadata
if metadata && metadata != ''
begin
Rack::Utils.parse_nested_query(Base64.strict_decode64(metadata)).each_with_object({}) do | (k, v), new_hash |
new_hash[k.to_sym] = v
Expand Down
23 changes: 23 additions & 0 deletions lib/pact_broker/api/resources/metadata_resource_methods.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
require 'pact_broker/hash_refinements'

module PactBroker
module Api
module Resources
module MetadataResourceMethods
using PactBroker::HashRefinements

def pact_params
@pact_params ||= PactBroker::Pacts::PactParams.from_request(request, maybe_params_with_consumer_version_number.merge(path_info))
end

def maybe_params_with_consumer_version_number
metadata.slice(:consumer_version_number)
end

def metadata
@metadata ||= PactBrokerUrls.decode_pact_metadata(identifier_from_path[:metadata])
end
end
end
end
end
3 changes: 3 additions & 0 deletions lib/pact_broker/api/resources/pact_version.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
require 'pact_broker/api/resources/pact'
require 'pact_broker/api/resources/metadata_resource_methods'

module PactBroker
module Api
module Resources
class PactVersion < Pact
include MetadataResourceMethods

def allowed_methods
["GET", "OPTIONS"]
end
Expand Down
6 changes: 2 additions & 4 deletions lib/pact_broker/api/resources/verifications.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
require 'pact_broker/api/contracts/verification_contract'
require 'pact_broker/api/decorators/verification_decorator'
require 'pact_broker/api/resources/webhook_execution_methods'
require 'pact_broker/api/resources/metadata_resource_methods'

module PactBroker
module Api
module Resources
class Verifications < BaseResource
include WebhookExecutionMethods
include MetadataResourceMethods

def content_types_accepted
[["application/json", :from_json]]
Expand Down Expand Up @@ -75,10 +77,6 @@ def decorator_for model
PactBroker::Api::Decorators::VerificationDecorator.new(model)
end

def metadata
PactBrokerUrls.decode_pact_metadata(identifier_from_path[:metadata])
end

def wip?
metadata[:wip] == 'true'
end
Expand Down
43 changes: 31 additions & 12 deletions lib/pact_broker/pacts/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require 'pact_broker/logging'
require 'pact_broker/pacts/generate_sha'
require 'pact_broker/pacts/pact_publication'
require 'pact_broker/pacts/pact_version'
require 'pact_broker/pacts/all_pact_publications'
require 'pact_broker/pacts/latest_pact_publications_by_consumer_version'
require 'pact_broker/pacts/latest_pact_publications'
Expand Down Expand Up @@ -295,20 +296,38 @@ def search_for_latest_pact(consumer_name, provider_name, tag = nil)
end

def find_pact consumer_name, consumer_version, provider_name, pact_version_sha = nil
query = if pact_version_sha
scope_for(AllPactPublications)
pact_publication_by_consumer_version = scope_for(LatestPactPublicationsByConsumerVersion)
.consumer(consumer_name)
.provider(provider_name)
.consumer_version_number(consumer_version)
.limit(1)

latest_pact_publication_by_sha = scope_for(AllPactPublications)
.consumer(consumer_name)
.provider(provider_name)
.pact_version_sha(pact_version_sha)
.reverse_order(:consumer_version_order)
.reverse_order(:consumer_version_order, :revision_number)
.limit(1)
else
scope_for(LatestPactPublicationsByConsumerVersion)

query = if consumer_version && !pact_version_sha
pact_publication_by_consumer_version
.eager(:tags)
.collect(&:to_domain_with_content).first
elsif pact_version_sha && !consumer_version
latest_pact_publication_by_sha
.eager(:tags)
.collect(&:to_domain_with_content).first
elsif consumer_version && pact_version_sha
pact_publication = pact_publication_by_consumer_version.all.first
if pact_publication && pact_publication.pact_version.sha == pact_version_sha
pact_publication.tags
pact_publication.to_domain_with_content
else
latest_pact_publication_by_sha
.eager(:tags)
.collect(&:to_domain_with_content).first
end
end
query = query
.eager(:tags)
.consumer(consumer_name)
.provider(provider_name)
query = query.consumer_version_number(consumer_version) if consumer_version
query.collect(&:to_domain_with_content)[0]
end

def find_all_revisions consumer_name, consumer_version, provider_name
Expand Down Expand Up @@ -502,7 +521,7 @@ def find_or_create_pact_version consumer_id, provider_id, pact_version_sha, json
end

def create_pact_version consumer_id, provider_id, sha, json_content
PactVersion.new(
PactBroker::Pacts::PactVersion.new(
consumer_id: consumer_id,
provider_id: provider_id,
sha: sha,
Expand Down
15 changes: 15 additions & 0 deletions lib/pact_broker/test/test_data_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class TestDataBuilder
attr_reader :provider_version
attr_reader :version
attr_reader :pact
attr_reader :pact_version
attr_reader :verification
attr_reader :webhook
attr_reader :webhook_execution
Expand Down Expand Up @@ -246,6 +247,20 @@ def revise_pact json_content = nil
self
end

def create_pact_version_without_publication(json_content = nil )
json_content = json_content ? json_content : {random: rand}.to_json
pact_version_sha = generate_pact_version_sha(json_content)

@pact_version = PactBroker::Pacts::PactVersion.new(
consumer_id: consumer.id,
provider_id: provider.id,
sha: pact_version_sha,
content: json_content,
created_at: Sequel.datetime_class.now
).save
self
end

def create_webhook parameters = {}
params = parameters.dup
consumer = params.key?(:consumer) ? params.delete(:consumer) : @consumer
Expand Down
4 changes: 2 additions & 2 deletions spec/features/get_pact_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
describe "retrieving a pact" do

subject { get path; last_response }
subject { get(path) }

context "when differing case is used in the consumer and provider names" do

Expand Down Expand Up @@ -30,6 +29,7 @@
end
end
end

context "when differing case is used in the tag name" do

let(:path) { "/pacts/provider/a%20provider/consumer/a%20consumer/latest/PROD" }
Expand Down
29 changes: 26 additions & 3 deletions spec/features/get_pact_version.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,36 @@
describe "retrieving a pact" do
subject { get path; last_response }
RSpec.describe "retrieving a pact" do
subject { get(path) }

context "when differing case is used in the consumer and provider names" do
let(:td) { TestDataBuilder.new }
let(:pact) { td.create_pact_with_hierarchy("Foo", "1", "Bar").and_return(:pact) }
let!(:path) { "/pacts/provider/Bar/consumer/Foo/pact-version/#{pact.pact_version_sha}" }

it "returns a 200 Success" do
expect(subject.status).to be 200
end
end

context "when there are multiple consumer versions for the same sha" do
before do
td.create_pact_with_hierarchy("Foo", "1", "Bar")
.create_consumer_version("2")
.republish_same_pact
end

let(:pact) { PactBroker::Pacts::PactPublication.order(:id).first.to_domain }
let(:path) { PactBroker::Api::PactBrokerUrls.pact_version_url(pact) }

it "returns the latest" do
expect(JSON.parse(subject.body)['_links']['pb:consumer-version']['name']).to eq "2"
end

context "when there is metadata specifying the consumer version number" do
let(:pact) { PactBroker::Pacts::PactPublication.order(:id).first.to_domain }
let(:path) { PactBroker::Api::PactBrokerUrls.pact_version_url_with_webhook_metadata(pact) }

it "returns the pact with the matching consumer version number" do
expect(JSON.parse(subject.body)['_links']['pb:consumer-version']['name']).to eq "1"
end
end
end
end
6 changes: 6 additions & 0 deletions spec/lib/pact_broker/api/pact_broker_urls_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ module Api
end
end

context "when the metadata is empty" do
it "returns an empty hash" do
expect(PactBrokerUrls.decode_pact_metadata("")).to eq({})
end
end

context "when the metadata is not valid base64" do
it "returns an empty hash" do
expect(PactBrokerUrls.decode_pact_metadata("foo==,")).to eq({})
Expand Down
10 changes: 7 additions & 3 deletions spec/lib/pact_broker/api/resources/verifications_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ module Resources
let(:database_connector) { double('database_connector' )}
let(:verification) { double(PactBroker::Domain::Verification) }
let(:errors_empty) { true }
let(:parsed_metadata) { { the: 'metadata' } }
let(:parsed_metadata) { { the: 'metadata', consumer_version_number: "2"} }
let(:base_url) { "http://example.org" }
let(:webhook_execution_configuration) { instance_double(PactBroker::Webhooks::ExecutionConfiguration) }

Expand All @@ -29,10 +29,14 @@ module Resources
allow(webhook_execution_configuration).to receive(:with_webhook_context).and_return(webhook_execution_configuration)
end

subject { post url, request_body, rack_env; last_response }
subject { post(url, request_body, rack_env) }

it "looks up the specified pact" do
allow(Pacts::Service).to receive(:find_pact).with(instance_of(PactBroker::Pacts::PactParams))
expect(Pacts::Service).to receive(:find_pact) do | arg |
expect(arg).to be_a(PactBroker::Pacts::PactParams)
expect(arg[:consumer_version_number]).to eq "2"
end
subject
end

context "when the pact does not exist" do
Expand Down
48 changes: 44 additions & 4 deletions spec/lib/pact_broker/pacts/repository_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -609,26 +609,66 @@ module Pacts
expect(subject.provider.name).to eq "Provider"
expect(subject.consumer_version_number).to eq "1.2.4"
expect(subject.revision_number).to eq 2

end

context "when there are multiple pact publications for the pact version" do
before do
# Double check the data is set up correctly...
expect(pact_1.pact_version_sha).to eq(pact_2.pact_version_sha)
end

let(:td) { TestDataBuilder.new }
let!(:pact_1) { td.create_pact_with_hierarchy("Foo", "1", "Bar").and_return(:pact) }
let!(:pact_2) { td.create_consumer_version("2").create_pact(json_content: pact_1.json_content).and_return(:pact) }

subject { Repository.new.find_pact "Foo", nil, "Bar", pact_1.pact_version_sha }
let(:consumer_version_number) { nil }

subject { Repository.new.find_pact "Foo", consumer_version_number, "Bar", pact_1.pact_version_sha }

it "returns the latest pact, ordered by consumer version order" do
expect(subject.consumer_version_number).to eq "2"
end

context "when the consumer_version_number is specified too (from the URL metadata)" do
let(:consumer_version_number) { "1" }

it "returns the publication with the consumer version specified" do
expect(subject.consumer_version_number).to eq "1"
end
end

context "when the consumer_version_number is specified too (from the URL metadata) but it doesn't exist (anymore)" do
let(:consumer_version_number) { "9" }

it "returns the pact matching the sha with the latest consumer version" do
expect(subject.consumer_version_number).to eq "2"
end
end

# Not sure when this would happen
context "when the consumer_version_number is specified too (from the URL metadata) and it exists but it doesn't match the sha" do
before do
td.create_pact_with_hierarchy("Foo", "8", "Bar")
end

let(:consumer_version_number) { "8" }

it "returns the pact matching the sha with the latest consumer version" do
expect(subject.consumer_version_number).to eq "2"
end
end

context "when the pact has multiple revisions and goes back to a previous revision" do
before do
td.revise_pact
.revise_pact(pact_1.json_content)
end

it "returns the latest revision" do
expect(subject.revision_number).to eq 3
end
end
end
end

end

describe "find_all_revisions" do
Expand Down

0 comments on commit 422c87f

Please sign in to comment.