Skip to content

Commit

Permalink
feat: allow pact equality to be based only on the content that affect…
Browse files Browse the repository at this point in the history
…s verification results
  • Loading branch information
bethesque committed May 20, 2018
1 parent e982d49 commit bf8130f
Show file tree
Hide file tree
Showing 19 changed files with 585 additions and 81 deletions.
7 changes: 6 additions & 1 deletion lib/pact_broker/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ class Configuration
]

attr_accessor :log_dir, :database_connection, :auto_migrate_db, :use_hal_browser, :html_pact_renderer
attr_accessor :validate_database_connection_config, :enable_diagnostic_endpoints, :version_parser
attr_accessor :validate_database_connection_config, :enable_diagnostic_endpoints, :version_parser, :sha_generator
attr_accessor :use_case_sensitive_resource_names, :order_versions_by_date
attr_accessor :check_for_potential_duplicate_pacticipant_names
attr_accessor :semver_formats
attr_accessor :enable_public_badge_access, :shields_io_base_url
attr_accessor :webhook_retry_schedule
attr_accessor :disable_ssl_verification
attr_accessor :base_equality_only_on_content_that_affects_verification_results
attr_reader :api_error_reporters
attr_writer :logger

Expand All @@ -51,6 +52,8 @@ def logger

def self.default_configuration
require 'pact_broker/versions/parse_semantic_version'
require 'pact_broker/pacts/generate_sha'

config = Configuration.new
config.log_dir = File.expand_path("./log")
config.auto_migrate_db = true
Expand All @@ -62,6 +65,8 @@ def self.default_configuration
config.use_case_sensitive_resource_names = true
config.html_pact_renderer = default_html_pact_render
config.version_parser = PactBroker::Versions::ParseSemanticVersion
config.sha_generator = PactBroker::Pacts::GenerateSha
config.base_equality_only_on_content_that_affects_verification_results = false
# Not recommended to set this to true unless there is no way to
# consistently extract an orderable object from the consumer application version number.
config.order_versions_by_date = false
Expand Down
66 changes: 66 additions & 0 deletions lib/pact_broker/pacts/content.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
require 'pact_broker/pacts/parse'
require 'pact_broker/pacts/sort_content'

module PactBroker
module Pacts
class Content

def initialize pact_hash
@pact_hash = pact_hash
end

def self.from_json json_content
new(Parse.call(json_content))
end

def self.from_hash pact_hash
new(pact_hash)
end

def to_hash
pact_hash
end

def to_json
pact_hash.to_json
end

def sort
Content.from_hash(SortContent.call(pact_hash))
end

# Half thinking this belongs in GenerateSha
def content_that_affects_verification_results
if interactions || messages
cont = {}
cont['interactions'] = interactions if interactions
cont['messages'] = messages if messages
cont['pact_specification_version'] = pact_specification_version if pact_specification_version
cont
else
pact_hash
end
end

def messages
pact_hash.is_a?(Hash) ? pact_hash['messages'] : nil
end

def interactions
pact_hash.is_a?(Hash) ? pact_hash['interactions'] : nil
end

def pact_specification_version
maybe_pact_specification_version_1 = pact_hash['metadata']['pactSpecification']['version'] rescue nil
maybe_pact_specification_version_2 = pact_hash['metadata']['pact-specification']['version'] rescue nil
maybe_pact_specification_version_3 = pact_hash['metadata'] && pact_hash['metadata']['pactSpecificationVersion'] rescue nil
maybe_pact_specification_version_1 || maybe_pact_specification_version_2 || maybe_pact_specification_version_3
end

private

attr_reader :pact_hash

end
end
end
1 change: 0 additions & 1 deletion lib/pact_broker/pacts/create_formatted_diff.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ def self.call pact_json_content, previous_pact_json_content
difference = diff(previous_pact_hash, pact_hash)
Pact::Matchers::UnixDiffFormatter.call(difference, colour: false, include_explanation: false)
end

end
end
end
5 changes: 3 additions & 2 deletions lib/pact_broker/pacts/diff.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
require 'pact_broker/api/pact_broker_urls'
require 'pact_broker/date_helper'
require 'pact_broker/pacts/create_formatted_diff'
require 'pact_broker/pacts/sort_verifiable_content'
require 'pact_broker/pacts/sort_content'
require 'pact_broker/pacts/parse'
require 'pact_broker/repositories'
require 'yaml'

Expand Down Expand Up @@ -110,7 +111,7 @@ def prepare_content json_content
if options[:raw]
json_content
else
PactBroker::Pacts::SortVerifiableContent.call(json_content)
SortContent.call(Parse.call(json_content)).to_json
end
end
end
Expand Down
24 changes: 24 additions & 0 deletions lib/pact_broker/pacts/generate_sha.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'digest/sha1'
require 'pact_broker/configuration'
require 'pact_broker/pacts/sort_content'
require 'pact_broker/pacts/parse'
require 'pact_broker/pacts/content'

module PactBroker
module Pacts
class GenerateSha
def self.call json_content, options = {}
content_for_sha = if PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results
extract_verifiable_content_for_sha(json_content)
else
json_content
end
Digest::SHA1.hexdigest(content_for_sha)
end

def self.extract_verifiable_content_for_sha json_content
Content.from_json(json_content).sort.content_that_affects_verification_results.to_json
end
end
end
end
11 changes: 11 additions & 0 deletions lib/pact_broker/pacts/parse.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
require 'pact_broker/json'

module PactBroker
module Pacts
class Parse
def self.call(json)
JSON.parse(json, PACT_PARSING_OPTIONS)
end
end
end
end
6 changes: 3 additions & 3 deletions lib/pact_broker/pacts/repository.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
require 'digest/sha1'
require 'sequel'
require 'ostruct'
require 'pact_broker/logging'
require 'pact_broker/pacts/generate_sha'
require 'pact_broker/pacts/pact_publication'
require 'pact_broker/pacts/all_pact_publications'
require 'pact_broker/pacts/latest_pact_publications_by_consumer_version'
require 'pact_broker/pacts/latest_pact_publications'
require 'pact_broker/pacts/latest_tagged_pact_publications'
require 'pact/shared/json_differ'
require 'pact_broker/domain'
require 'pact_broker/pacts/parse'

module PactBroker
module Pacts
Expand Down Expand Up @@ -197,7 +198,7 @@ def different? pact, other_pact
end

def find_or_create_pact_version consumer_id, provider_id, json_content
sha = Digest::SHA1.hexdigest(json_content)
sha = PactBroker.configuration.sha_generator.call(json_content)
PactVersion.find(sha: sha, consumer_id: consumer_id, provider_id: provider_id) || create_pact_version(consumer_id, provider_id, sha, json_content)
end

Expand All @@ -206,7 +207,6 @@ def create_pact_version consumer_id, provider_id, sha, json_content
pact_version = PactVersion.new(consumer_id: consumer_id, provider_id: provider_id, sha: sha, content: json_content)
pact_version.save
end

end
end
end
54 changes: 54 additions & 0 deletions lib/pact_broker/pacts/sort_content.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
require 'pact_broker/json'

module PactBroker
module Pacts
class SortContent
def self.call pact_hash
key = verifiable_content_key_for(pact_hash)

if key
content = pact_hash[key]
sorted_pact_hash = order_object(pact_hash)
sorted_pact_hash[key] = order_verifiable_content(content)
sorted_pact_hash
else
pact_hash
end
end

def self.verifiable_content_key_for pact_hash
if pact_hash['interactions']
'interactions'
elsif pact_hash['messages']
'messages'
else
nil
end
end


def self.order_verifiable_content array
array_with_ordered_hashes = order_object(array)
array_with_ordered_hashes.sort{|a, b| a.to_json <=> b.to_json }
end

def self.order_object thing
case thing
when Hash then order_hash(thing)
when Array then order_child_array(thing)
else thing
end
end

def self.order_child_array array
array.collect{|thing| order_object(thing) }
end

def self.order_hash hash
hash.keys.sort.each_with_object({}) do | key, new_hash |
new_hash[key] = order_object(hash[key])
end
end
end
end
end
41 changes: 0 additions & 41 deletions lib/pact_broker/pacts/sort_verifiable_content.rb

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
RSpec.describe "base_equality_only_on_content_that_affects_verification_results" do
let(:td) { TestDataBuilder.new }
let(:json_content_1) { load_fixture('foo-bar.json') }
let(:json_content_2) do
pact_hash = load_json_fixture('foo-bar.json')
pact_hash['interactions'] = pact_hash['interactions'].reverse
pact_hash.to_json
end
let(:base_equality_only_on_content_that_affects_verification_results) { true }

before do
PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results = base_equality_only_on_content_that_affects_verification_results
td.create_pact_with_hierarchy("Foo", "1", "Bar", json_content_1)
.create_verification(provider_version: "5")
.create_consumer_version("2")
.create_pact(json_content: json_content_2)
end

context "when a pact is published with a different order of interactions to a previous version, but which is otherwise the same" do
context "when base_equality_only_on_content_that_affects_verification_results is true" do
it "applies the verifications from the previous version" do
expect(PactBroker::Matrix::Row.all).to contain_hash(consumer_version_number: "2", provider_version_number: "5")
end
end

context "when base_equality_only_on_content_that_affects_verification_results is false" do
let(:base_equality_only_on_content_that_affects_verification_results) { false }

it "does not apply the verifications from the previous version" do
expect(PactBroker::Matrix::Row.all).to_not contain_hash(consumer_version_number: "2", provider_version_number: "5")
end
end
end
end
Loading

0 comments on commit bf8130f

Please sign in to comment.