pact_broker 2.19.1 → 2.19.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +20 -0
- data/README.md +0 -1
- data/db/migrations/000002_create_versions_table.rb +1 -1
- data/db/migrations/20180311_optimise_head_matrix.rb +1 -0
- data/db/migrations/20180523_create_latest_verifications_for_consumer_version_tags.rb +50 -0
- data/db/migrations/20180524_create_latest_verifications_for_consumer_and_provider.rb +46 -0
- data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +7 -3
- data/lib/pact_broker/configuration.rb +6 -1
- data/lib/pact_broker/domain/webhook_request.rb +12 -11
- data/lib/pact_broker/index/service.rb +14 -84
- data/lib/pact_broker/matrix/aggregated_row.rb +71 -0
- data/lib/pact_broker/matrix/head_row.rb +23 -0
- data/lib/pact_broker/matrix/repository.rb +0 -1
- data/lib/pact_broker/matrix/row.rb +15 -20
- data/lib/pact_broker/pacts/content.rb +66 -0
- data/lib/pact_broker/pacts/create_formatted_diff.rb +0 -1
- data/lib/pact_broker/pacts/diff.rb +3 -2
- data/lib/pact_broker/pacts/generate_sha.rb +24 -0
- data/lib/pact_broker/pacts/parse.rb +11 -0
- data/lib/pact_broker/pacts/repository.rb +4 -4
- data/lib/pact_broker/pacts/service.rb +4 -2
- data/lib/pact_broker/pacts/sort_content.rb +54 -0
- data/lib/pact_broker/verifications/latest_verification_for_consumer_and_provider.rb +26 -0
- data/lib/pact_broker/verifications/latest_verification_for_consumer_version_tag.rb +23 -0
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/repository.rb +12 -3
- data/script/run-with-ssl.rb +44 -0
- data/spec/features/base_equality_only_on_content_that_affects_verification_results_spec.rb +34 -0
- data/spec/lib/pact_broker/api/decorators/webhook_execution_result_decorator_spec.rb +6 -2
- data/spec/lib/pact_broker/domain/{index_items_spec.rb → index_item_spec.rb} +0 -0
- data/spec/lib/pact_broker/domain/webhook_request_spec.rb +16 -5
- data/spec/lib/pact_broker/matrix/aggregated_row_spec.rb +79 -0
- data/spec/lib/pact_broker/matrix/head_row_spec.rb +55 -0
- data/spec/lib/pact_broker/matrix/row_spec.rb +22 -2
- data/spec/lib/pact_broker/pacts/content_spec.rb +166 -0
- data/spec/lib/pact_broker/pacts/create_formatted_diff_spec.rb +0 -3
- data/spec/lib/pact_broker/pacts/generate_sha_spec.rb +92 -0
- data/spec/lib/pact_broker/pacts/repository_spec.rb +47 -4
- data/spec/lib/pact_broker/pacts/sort_content_spec.rb +44 -0
- data/spec/lib/pact_broker/versions/repository_spec.rb +13 -5
- data/spec/spec_helper.rb +1 -0
- data/spec/support/foo-bar.json +34 -0
- data/spec/support/rspec_match_hash.rb +14 -17
- data/spec/support/test_data_builder.rb +5 -4
- metadata +26 -8
- data/lib/pact_broker/matrix/latest_row.rb +0 -10
- data/lib/pact_broker/pacts/sort_verifiable_content.rb +0 -41
- data/spec/lib/pact_broker/pacts/sort_verifiable_content_spec.rb +0 -25
@@ -7,6 +7,29 @@ module PactBroker
|
|
7
7
|
class HeadRow < Row
|
8
8
|
set_dataset(:materialized_head_matrix)
|
9
9
|
|
10
|
+
# one_to_one :latest_verification_for_consumer_version_tag,
|
11
|
+
# :class => "PactBroker::Verifications::LatestVerificationForConsumerVersionTag",
|
12
|
+
# primary_key: [:provider_id, :consumer_id, :consumer_version_tag_name], key: [:provider_id, :consumer_id, :consumer_version_tag_name]
|
13
|
+
|
14
|
+
# Loading the latest_verification_for_consumer_version_tag objects this way is quicker than
|
15
|
+
# doing it using an inbult relation with primary_key/key, if we are loading the relation for
|
16
|
+
# the entire HeadRow table
|
17
|
+
# Using the inbuilt relation puts constraints on the columns that are not necessary and slow
|
18
|
+
# the query down.
|
19
|
+
# This relation relies on consumer_version_tags already being loaded
|
20
|
+
one_to_one :latest_verification_for_consumer_version_tag, :class => "PactBroker::Verifications::LatestVerificationForConsumerVersionTag", primary_keys: [], key: [], :eager_loader=>(proc do |eo_opts|
|
21
|
+
tag_to_row = eo_opts[:rows].each_with_object({}) { | row, map | map[[row.provider_id, row.consumer_id, row.consumer_version_tag_name]] = row }
|
22
|
+
eo_opts[:rows].each{|row| row.associations[:latest_verification_for_consumer_version_tag] = nil}
|
23
|
+
|
24
|
+
# Need the all then the each to ensure the eager loading works
|
25
|
+
PactBroker::Verifications::LatestVerificationForConsumerVersionTag.each do | verification |
|
26
|
+
key = [verification.provider_id, verification.consumer_id, verification.consumer_version_tag_name]
|
27
|
+
if tag_to_row[key]
|
28
|
+
tag_to_row[key].associations[:latest_verification_for_consumer_version_tag] = verification
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end)
|
32
|
+
|
10
33
|
dataset_module do
|
11
34
|
include PactBroker::Repositories::Helpers
|
12
35
|
include PactBroker::Logging
|
@@ -2,9 +2,12 @@ require 'pact_broker/repositories/helpers'
|
|
2
2
|
require 'pact_broker/webhooks/latest_triggered_webhook'
|
3
3
|
require 'pact_broker/tags/tag_with_latest_flag'
|
4
4
|
require 'pact_broker/logging'
|
5
|
+
require 'pact_broker/verifications/latest_verification_for_consumer_version_tag'
|
6
|
+
require 'pact_broker/verifications/latest_verification_for_consumer_and_provider'
|
5
7
|
|
6
8
|
module PactBroker
|
7
9
|
module Matrix
|
10
|
+
|
8
11
|
class Row < Sequel::Model(:materialized_matrix)
|
9
12
|
|
10
13
|
# Used when using table_print to output query results
|
@@ -15,6 +18,10 @@ module PactBroker
|
|
15
18
|
associate(:one_to_many, :consumer_version_tags, :class => "PactBroker::Tags::TagWithLatestFlag", primary_key: :consumer_version_id, key: :version_id)
|
16
19
|
associate(:one_to_many, :provider_version_tags, :class => "PactBroker::Tags::TagWithLatestFlag", primary_key: :provider_version_id, key: :version_id)
|
17
20
|
|
21
|
+
many_to_one :latest_verification_for_consumer_and_provider,
|
22
|
+
:class => "PactBroker::Verifications::LatestVerificationForConsumerAndProvider",
|
23
|
+
primary_key: [:provider_id, :consumer_id], key: [:provider_id, :consumer_id]
|
24
|
+
|
18
25
|
dataset_module do
|
19
26
|
include PactBroker::Repositories::Helpers
|
20
27
|
include PactBroker::Logging
|
@@ -111,20 +118,6 @@ module PactBroker
|
|
111
118
|
end
|
112
119
|
end
|
113
120
|
|
114
|
-
# tags for which this pact publication is the latest of that tag
|
115
|
-
# this is set in the code rather than the database
|
116
|
-
def consumer_head_tag_names
|
117
|
-
@consumer_head_tag_names ||= []
|
118
|
-
end
|
119
|
-
|
120
|
-
def consumer_head_tag_names= consumer_head_tag_names
|
121
|
-
@consumer_head_tag_names = consumer_head_tag_names
|
122
|
-
end
|
123
|
-
|
124
|
-
# def latest_triggered_webhooks
|
125
|
-
# @latest_triggered_webhooks ||= []
|
126
|
-
# end
|
127
|
-
|
128
121
|
def summary
|
129
122
|
"#{consumer_name}#{consumer_version_number} #{provider_name}#{provider_version_number || '?'} (r#{pact_revision_number}n#{verification_number || '?'})"
|
130
123
|
end
|
@@ -138,17 +131,18 @@ module PactBroker
|
|
138
131
|
end
|
139
132
|
|
140
133
|
def consumer_version
|
141
|
-
@consumer_version ||= OpenStruct.new(number: consumer_version_number, id: consumer_version_id, pacticipant: consumer)
|
134
|
+
@consumer_version ||= OpenStruct.new(number: consumer_version_number, order: consumer_version_order, id: consumer_version_id, pacticipant: consumer)
|
142
135
|
end
|
143
136
|
|
144
137
|
def provider_version
|
145
138
|
if provider_version_number
|
146
|
-
@provider_version ||= OpenStruct.new(number: provider_version_number, id: provider_version_id, pacticipant: provider)
|
139
|
+
@provider_version ||= OpenStruct.new(number: provider_version_number, order: provider_version_order, id: provider_version_id, pacticipant: provider)
|
147
140
|
end
|
148
141
|
end
|
149
142
|
|
150
143
|
def pact
|
151
|
-
@pact ||= OpenStruct.new(
|
144
|
+
@pact ||= OpenStruct.new(
|
145
|
+
consumer: consumer,
|
152
146
|
provider: provider,
|
153
147
|
consumer_version: consumer_version,
|
154
148
|
consumer_version_number: consumer_version_number,
|
@@ -158,7 +152,7 @@ module PactBroker
|
|
158
152
|
)
|
159
153
|
end
|
160
154
|
|
161
|
-
def
|
155
|
+
def verification
|
162
156
|
if verification_executed_at
|
163
157
|
@latest_verification ||= OpenStruct.new(
|
164
158
|
id: verification_id,
|
@@ -167,10 +161,12 @@ module PactBroker
|
|
167
161
|
execution_date: verification_executed_at,
|
168
162
|
created_at: verification_executed_at,
|
169
163
|
provider_version_number: provider_version_number,
|
164
|
+
provider_version_order: provider_version_order,
|
170
165
|
build_url: verification_build_url,
|
171
166
|
provider_version: provider_version,
|
172
167
|
consumer_name: consumer_name,
|
173
|
-
provider_name: provider_name
|
168
|
+
provider_name: provider_name,
|
169
|
+
pact_version_sha: pact_version_sha
|
174
170
|
)
|
175
171
|
end
|
176
172
|
end
|
@@ -187,7 +183,6 @@ module PactBroker
|
|
187
183
|
]
|
188
184
|
|
189
185
|
comparisons.find{|c| c != 0 } || 0
|
190
|
-
|
191
186
|
end
|
192
187
|
|
193
188
|
def compare_name_asc name1, name2
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'pact_broker/pacts/parse'
|
2
|
+
require 'pact_broker/pacts/sort_content'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Pacts
|
6
|
+
class Content
|
7
|
+
|
8
|
+
def initialize pact_hash
|
9
|
+
@pact_hash = pact_hash
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.from_json json_content
|
13
|
+
new(Parse.call(json_content))
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.from_hash pact_hash
|
17
|
+
new(pact_hash)
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_hash
|
21
|
+
pact_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_json
|
25
|
+
pact_hash.to_json
|
26
|
+
end
|
27
|
+
|
28
|
+
def sort
|
29
|
+
Content.from_hash(SortContent.call(pact_hash))
|
30
|
+
end
|
31
|
+
|
32
|
+
# Half thinking this belongs in GenerateSha
|
33
|
+
def content_that_affects_verification_results
|
34
|
+
if interactions || messages
|
35
|
+
cont = {}
|
36
|
+
cont['interactions'] = interactions if interactions
|
37
|
+
cont['messages'] = messages if messages
|
38
|
+
cont['pact_specification_version'] = pact_specification_version if pact_specification_version
|
39
|
+
cont
|
40
|
+
else
|
41
|
+
pact_hash
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def messages
|
46
|
+
pact_hash.is_a?(Hash) ? pact_hash['messages'] : nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def interactions
|
50
|
+
pact_hash.is_a?(Hash) ? pact_hash['interactions'] : nil
|
51
|
+
end
|
52
|
+
|
53
|
+
def pact_specification_version
|
54
|
+
maybe_pact_specification_version_1 = pact_hash['metadata']['pactSpecification']['version'] rescue nil
|
55
|
+
maybe_pact_specification_version_2 = pact_hash['metadata']['pact-specification']['version'] rescue nil
|
56
|
+
maybe_pact_specification_version_3 = pact_hash['metadata'] && pact_hash['metadata']['pactSpecificationVersion'] rescue nil
|
57
|
+
maybe_pact_specification_version_1 || maybe_pact_specification_version_2 || maybe_pact_specification_version_3
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
attr_reader :pact_hash
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
require 'pact_broker/api/pact_broker_urls'
|
2
2
|
require 'pact_broker/date_helper'
|
3
3
|
require 'pact_broker/pacts/create_formatted_diff'
|
4
|
-
require 'pact_broker/pacts/
|
4
|
+
require 'pact_broker/pacts/sort_content'
|
5
|
+
require 'pact_broker/pacts/parse'
|
5
6
|
require 'pact_broker/repositories'
|
6
7
|
require 'yaml'
|
7
8
|
|
@@ -110,7 +111,7 @@ module PactBroker
|
|
110
111
|
if options[:raw]
|
111
112
|
json_content
|
112
113
|
else
|
113
|
-
|
114
|
+
SortContent.call(Parse.call(json_content)).to_json
|
114
115
|
end
|
115
116
|
end
|
116
117
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'digest/sha1'
|
2
|
+
require 'pact_broker/configuration'
|
3
|
+
require 'pact_broker/pacts/sort_content'
|
4
|
+
require 'pact_broker/pacts/parse'
|
5
|
+
require 'pact_broker/pacts/content'
|
6
|
+
|
7
|
+
module PactBroker
|
8
|
+
module Pacts
|
9
|
+
class GenerateSha
|
10
|
+
def self.call json_content, options = {}
|
11
|
+
content_for_sha = if PactBroker.configuration.base_equality_only_on_content_that_affects_verification_results
|
12
|
+
extract_verifiable_content_for_sha(json_content)
|
13
|
+
else
|
14
|
+
json_content
|
15
|
+
end
|
16
|
+
Digest::SHA1.hexdigest(content_for_sha)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.extract_verifiable_content_for_sha json_content
|
20
|
+
Content.from_json(json_content).sort.content_that_affects_verification_results.to_json
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
|
-
require 'digest/sha1'
|
2
1
|
require 'sequel'
|
3
2
|
require 'ostruct'
|
4
3
|
require 'pact_broker/logging'
|
4
|
+
require 'pact_broker/pacts/generate_sha'
|
5
5
|
require 'pact_broker/pacts/pact_publication'
|
6
6
|
require 'pact_broker/pacts/all_pact_publications'
|
7
7
|
require 'pact_broker/pacts/latest_pact_publications_by_consumer_version'
|
@@ -9,6 +9,7 @@ require 'pact_broker/pacts/latest_pact_publications'
|
|
9
9
|
require 'pact_broker/pacts/latest_tagged_pact_publications'
|
10
10
|
require 'pact/shared/json_differ'
|
11
11
|
require 'pact_broker/domain'
|
12
|
+
require 'pact_broker/pacts/parse'
|
12
13
|
|
13
14
|
module PactBroker
|
14
15
|
module Pacts
|
@@ -197,16 +198,15 @@ module PactBroker
|
|
197
198
|
end
|
198
199
|
|
199
200
|
def find_or_create_pact_version consumer_id, provider_id, json_content
|
200
|
-
sha =
|
201
|
+
sha = PactBroker.configuration.sha_generator.call(json_content)
|
201
202
|
PactVersion.find(sha: sha, consumer_id: consumer_id, provider_id: provider_id) || create_pact_version(consumer_id, provider_id, sha, json_content)
|
202
203
|
end
|
203
204
|
|
204
205
|
def create_pact_version consumer_id, provider_id, sha, json_content
|
205
|
-
|
206
|
+
logger.debug("Creating new pact version for sha #{sha}")
|
206
207
|
pact_version = PactVersion.new(consumer_id: consumer_id, provider_id: provider_id, sha: sha, content: json_content)
|
207
208
|
pact_version.save
|
208
209
|
end
|
209
|
-
|
210
210
|
end
|
211
211
|
end
|
212
212
|
end
|
@@ -102,7 +102,8 @@ module PactBroker
|
|
102
102
|
private
|
103
103
|
|
104
104
|
def update_pact params, existing_pact
|
105
|
-
logger.info "Updating existing pact
|
105
|
+
logger.info "Updating existing pact publication with params #{params.reject{ |k, v| k == :json_content}}"
|
106
|
+
logger.debug "Content #{params[:json_content]}"
|
106
107
|
updated_pact = pact_repository.update existing_pact.id, params
|
107
108
|
|
108
109
|
if existing_pact.json_content != updated_pact.json_content
|
@@ -113,7 +114,8 @@ module PactBroker
|
|
113
114
|
end
|
114
115
|
|
115
116
|
def create_pact params, version, provider
|
116
|
-
logger.info "Creating new pact
|
117
|
+
logger.info "Creating new pact publication with params #{params.reject{ |k, v| k == :json_content}}"
|
118
|
+
logger.debug "Content #{params[:json_content]}"
|
117
119
|
pact = pact_repository.create json_content: params[:json_content], version_id: version.id, provider_id: provider.id, consumer_id: version.pacticipant_id
|
118
120
|
trigger_webhooks pact
|
119
121
|
pact
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'pact_broker/json'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Pacts
|
5
|
+
class SortContent
|
6
|
+
def self.call pact_hash
|
7
|
+
key = verifiable_content_key_for(pact_hash)
|
8
|
+
|
9
|
+
if key
|
10
|
+
content = pact_hash[key]
|
11
|
+
sorted_pact_hash = order_object(pact_hash)
|
12
|
+
sorted_pact_hash[key] = order_verifiable_content(content)
|
13
|
+
sorted_pact_hash
|
14
|
+
else
|
15
|
+
pact_hash
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.verifiable_content_key_for pact_hash
|
20
|
+
if pact_hash['interactions']
|
21
|
+
'interactions'
|
22
|
+
elsif pact_hash['messages']
|
23
|
+
'messages'
|
24
|
+
else
|
25
|
+
nil
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
def self.order_verifiable_content array
|
31
|
+
array_with_ordered_hashes = order_object(array)
|
32
|
+
array_with_ordered_hashes.sort{|a, b| a.to_json <=> b.to_json }
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.order_object thing
|
36
|
+
case thing
|
37
|
+
when Hash then order_hash(thing)
|
38
|
+
when Array then order_child_array(thing)
|
39
|
+
else thing
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.order_child_array array
|
44
|
+
array.collect{|thing| order_object(thing) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.order_hash hash
|
48
|
+
hash.keys.sort.each_with_object({}) do | key, new_hash |
|
49
|
+
new_hash[key] = order_object(hash[key])
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'pact_broker/domain/verification'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Verifications
|
5
|
+
|
6
|
+
include PactBroker::Repositories::Helpers
|
7
|
+
|
8
|
+
class LatestVerificationForConsumerAndProvider < PactBroker::Domain::Verification
|
9
|
+
set_dataset(:latest_verifications_for_consumer_and_provider)
|
10
|
+
|
11
|
+
# Don't need to load the pact_version as we do in the superclass,
|
12
|
+
# as pact_version_sha is included in the view for convenience
|
13
|
+
def pact_version_sha
|
14
|
+
values[:pact_version_sha]
|
15
|
+
end
|
16
|
+
|
17
|
+
def provider_version_number
|
18
|
+
values[:provider_version_number]
|
19
|
+
end
|
20
|
+
|
21
|
+
def provider_version_order
|
22
|
+
values[:provider_version_order]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'pact_broker/domain/verification'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Verifications
|
5
|
+
class LatestVerificationForConsumerVersionTag < PactBroker::Domain::Verification
|
6
|
+
set_dataset(:latest_verifications_for_consumer_version_tags)
|
7
|
+
|
8
|
+
# Don't need to load the pact_version as we do in the superclass,
|
9
|
+
# as pact_version_sha is included in the view for convenience
|
10
|
+
def pact_version_sha
|
11
|
+
values[:pact_version_sha]
|
12
|
+
end
|
13
|
+
|
14
|
+
def provider_version_number
|
15
|
+
values[:provider_version_number]
|
16
|
+
end
|
17
|
+
|
18
|
+
def provider_version_order
|
19
|
+
values[:provider_version_order]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/pact_broker/version.rb
CHANGED
@@ -51,10 +51,19 @@ module PactBroker
|
|
51
51
|
.single_record
|
52
52
|
end
|
53
53
|
|
54
|
+
# There may be a race condition if two simultaneous requests come in to create the same version
|
54
55
|
def create args
|
55
|
-
PactBroker.logger.info "
|
56
|
-
|
57
|
-
|
56
|
+
PactBroker.logger.info "Upserting version #{args[:number]} for pacticipant_id=#{args[:pacticipant_id]}"
|
57
|
+
version_params = {
|
58
|
+
number: args[:number],
|
59
|
+
pacticipant_id: args[:pacticipant_id],
|
60
|
+
created_at: Sequel.datetime_class.now,
|
61
|
+
updated_at: Sequel.datetime_class.now
|
62
|
+
}
|
63
|
+
id = PactBroker::Domain::Version.db[:versions].insert_ignore.insert(version_params)
|
64
|
+
version = PactBroker::Domain::Version.find(number: args[:number], pacticipant_id: args[:pacticipant_id])
|
65
|
+
PactBroker::Domain::OrderVersions.(version)
|
66
|
+
version.refresh # reload with the populated order
|
58
67
|
end
|
59
68
|
|
60
69
|
def find_by_pacticipant_id_and_number_or_create pacticipant_id, number
|