pact_broker 2.73.0 → 2.74.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +3 -1
- data/lib/pact_broker/api/pact_broker_urls.rb +3 -3
- data/lib/pact_broker/api/resources/metadata_resource_methods.rb +2 -1
- data/lib/pact_broker/domain/version.rb +13 -6
- data/lib/pact_broker/pacts/metadata.rb +53 -6
- data/lib/pact_broker/pacts/repository.rb +10 -17
- data/lib/pact_broker/pacts/selector.rb +22 -0
- data/lib/pact_broker/pacts/selectors.rb +4 -0
- data/lib/pact_broker/test/http_test_data_builder.rb +45 -18
- data/lib/pact_broker/version.rb +1 -1
- data/pact_broker.gemspec +1 -0
- data/script/reproduce-issue.rb +6 -1
- data/spec/lib/pact_broker/api/decorators/verifiable_pact_decorator_spec.rb +5 -7
- data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +2 -6
- data/spec/lib/pact_broker/pacts/metadata_spec.rb +73 -0
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +2 -2
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +33 -13
- metadata +25 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4a3779dfce4701e31c25e10a37154785df8745aa022869f70bcdd3c080066169
|
4
|
+
data.tar.gz: d9c48a07a42949aea37a84ca43930a53d6403abe02a96d1c1de2d58a27d763bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a4a61fe0838766004ab06723b406d51149d748ec449c81139ada966a223b5491d4728fa0cdd52d6e369081af490eb03b4b7036c12c6f2a6b014bf20608c9d68
|
7
|
+
data.tar.gz: 569774601622663f53d824d40b0013afd6728f0c603fb9f2f8d66f759603daf7d361d6481003dc83a2a844415d93eae78694a076be1172eb45728d678cd672a2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
<a name="v2.74.0"></a>
|
2
|
+
### v2.74.0 (2021-01-04)
|
3
|
+
|
4
|
+
#### Features
|
5
|
+
|
6
|
+
* include the consumer version selectors in the metadata of the 'pact for verification' URL ([32bbe1c3](/../../commit/32bbe1c3))
|
7
|
+
|
8
|
+
#### Bug Fixes
|
9
|
+
|
10
|
+
* **deps**
|
11
|
+
* update nokogiri for CVE-2020-26247 ([336ec897](/../../commit/336ec897))
|
12
|
+
|
1
13
|
<a name="v2.73.0"></a>
|
2
14
|
### v2.73.0 (2020-12-16)
|
3
15
|
|
@@ -1,11 +1,13 @@
|
|
1
1
|
require_relative 'base_decorator'
|
2
2
|
require 'pact_broker/api/pact_broker_urls'
|
3
3
|
require 'pact_broker/pacts/build_verifiable_pact_notices'
|
4
|
+
require 'pact_broker/pacts/metadata'
|
4
5
|
|
5
6
|
module PactBroker
|
6
7
|
module Api
|
7
8
|
module Decorators
|
8
9
|
class VerifiablePactDecorator < BaseDecorator
|
10
|
+
include PactBroker::Pacts::Metadata
|
9
11
|
|
10
12
|
property :shortDescription, getter: -> (context) { PactBroker::Pacts::VerifiablePactMessages.new(context[:represented], nil).pact_version_short_description }
|
11
13
|
|
@@ -27,7 +29,7 @@ module PactBroker
|
|
27
29
|
end
|
28
30
|
|
29
31
|
link :self do | user_options |
|
30
|
-
metadata = represented
|
32
|
+
metadata = build_metadata_for_pact_for_verification(represented)
|
31
33
|
{
|
32
34
|
href: pact_version_url_with_metadata(represented, metadata, user_options[:base_url]),
|
33
35
|
name: represented.name
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'erb'
|
2
2
|
require 'pact_broker/pacts/metadata'
|
3
3
|
require 'pact_broker/logging'
|
4
|
+
require 'base64'
|
5
|
+
require 'rack'
|
4
6
|
|
5
7
|
module PactBroker
|
6
8
|
module Api
|
@@ -77,9 +79,7 @@ module PactBroker
|
|
77
79
|
def decode_pact_metadata(metadata)
|
78
80
|
if metadata && metadata != ''
|
79
81
|
begin
|
80
|
-
Rack::Utils.parse_nested_query(Base64.strict_decode64(metadata))
|
81
|
-
new_hash[k.to_sym] = v
|
82
|
-
end
|
82
|
+
Rack::Utils.parse_nested_query(Base64.strict_decode64(metadata))
|
83
83
|
rescue StandardError => e
|
84
84
|
logger.warn("Exception parsing webhook metadata: #{metadata}", e)
|
85
85
|
{}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'pact_broker/hash_refinements'
|
2
|
+
require 'pact_broker/pacts/metadata'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Api
|
@@ -15,7 +16,7 @@ module PactBroker
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def metadata
|
18
|
-
@metadata ||= PactBrokerUrls.decode_pact_metadata(identifier_from_path[:metadata])
|
19
|
+
@metadata ||= PactBroker::Pacts::Metadata.parse_metadata(PactBrokerUrls.decode_pact_metadata(identifier_from_path[:metadata]))
|
19
20
|
end
|
20
21
|
end
|
21
22
|
end
|
@@ -47,13 +47,20 @@ module PactBroker
|
|
47
47
|
dataset_module do
|
48
48
|
include PactBroker::Repositories::Helpers
|
49
49
|
|
50
|
+
def for(pacticipant_name, version_number)
|
51
|
+
where_pacticipant_name(pacticipant_name).where_number(version_number).single_record
|
52
|
+
end
|
53
|
+
|
50
54
|
def where_pacticipant_name(pacticipant_name)
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
where(pacticipant_id: db[:pacticipants].select(:id).where(name_like(:name, pacticipant_name)))
|
56
|
+
# If we do a join, we get the extra columns from the pacticipant table that then
|
57
|
+
# make == not work
|
58
|
+
# join(:pacticipants) do | p |
|
59
|
+
# Sequel.&(
|
60
|
+
# { Sequel[first_source_alias][:pacticipant_id] => Sequel[p][:id] },
|
61
|
+
# name_like(Sequel[p][:name], pacticipant_name)
|
62
|
+
# )
|
63
|
+
# end
|
57
64
|
end
|
58
65
|
|
59
66
|
def where_tag(tag)
|
@@ -3,6 +3,15 @@ module PactBroker
|
|
3
3
|
module Metadata
|
4
4
|
extend self
|
5
5
|
|
6
|
+
MAPPINGS = [
|
7
|
+
[:consumer_version_tags, "cvt"],
|
8
|
+
[:consumer_version_number, "cvn"],
|
9
|
+
[:wip, "w"],
|
10
|
+
[:consumer_version_selectors, "s"],
|
11
|
+
[:tag, "t"],
|
12
|
+
[:latest, "l"]
|
13
|
+
]
|
14
|
+
|
6
15
|
# When verifying a pact at /.../latest/TAG, this stores the
|
7
16
|
# tag and the current consumer version number in the
|
8
17
|
# metadata parameter of the URL for publishing the verification results.
|
@@ -11,12 +20,12 @@ module PactBroker
|
|
11
20
|
def build_metadata_for_latest_pact(pact, selection_parameters)
|
12
21
|
if selection_parameters[:tag]
|
13
22
|
{
|
14
|
-
|
15
|
-
|
23
|
+
"cvt" => [selection_parameters[:tag]],
|
24
|
+
"cvn" => pact.consumer_version_number
|
16
25
|
}
|
17
26
|
else
|
18
27
|
{
|
19
|
-
|
28
|
+
"cvn" => pact.consumer_version_number
|
20
29
|
}
|
21
30
|
end
|
22
31
|
end
|
@@ -28,12 +37,50 @@ module PactBroker
|
|
28
37
|
# go back to the correct consumer version number (eg for git statuses)
|
29
38
|
def build_metadata_for_webhook_triggered_by_pact_publication(pact)
|
30
39
|
metadata = {
|
31
|
-
|
32
|
-
|
40
|
+
"cvn" => pact.consumer_version_number,
|
41
|
+
"cvt" => pact.consumer_version_tag_names
|
33
42
|
}
|
34
|
-
metadata[
|
43
|
+
metadata["w"] = "true"
|
35
44
|
metadata
|
36
45
|
end
|
46
|
+
|
47
|
+
def build_metadata_for_pact_for_verification(verifiable_pact)
|
48
|
+
# todo put in tags
|
49
|
+
if verifiable_pact.wip
|
50
|
+
{
|
51
|
+
"w" => true
|
52
|
+
}
|
53
|
+
else
|
54
|
+
{
|
55
|
+
"s" => verifiable_pact.selectors.collect do | selector |
|
56
|
+
{
|
57
|
+
"t" => selector.tag,
|
58
|
+
"l" => selector.latest,
|
59
|
+
"cvn" => selector.consumer_version.number
|
60
|
+
}.compact
|
61
|
+
end
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def parse_metadata(metadata)
|
67
|
+
parse_object(metadata)
|
68
|
+
end
|
69
|
+
|
70
|
+
def parse_object(object)
|
71
|
+
case object
|
72
|
+
when Hash then parse_hash(object)
|
73
|
+
when Array then object.collect{|i| parse_object(i) }
|
74
|
+
else object
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def parse_hash(hash)
|
79
|
+
hash.each_with_object({}) do | (key, value), new_hash |
|
80
|
+
long_key = MAPPINGS.find{ |mapping| mapping.last == key }&.first
|
81
|
+
new_hash[long_key || key] = parse_object(value)
|
82
|
+
end
|
83
|
+
end
|
37
84
|
end
|
38
85
|
end
|
39
86
|
end
|
@@ -168,7 +168,7 @@ module PactBroker
|
|
168
168
|
.values
|
169
169
|
.collect do | pact_publications |
|
170
170
|
latest_pact_publication = pact_publications.sort_by{ |p| p.values.fetch(:consumer_version_order) }.last
|
171
|
-
SelectedPact.new(latest_pact_publication.to_domain, Selectors.new(selector))
|
171
|
+
SelectedPact.new(latest_pact_publication.to_domain, Selectors.new(selector).resolve(latest_pact_publication.consumer_version))
|
172
172
|
end
|
173
173
|
end
|
174
174
|
|
@@ -428,7 +428,7 @@ module PactBroker
|
|
428
428
|
.order_ignore_case(:consumer_name)
|
429
429
|
.collect do | latest_pact_publication |
|
430
430
|
pact_publication = PactPublication.find(id: latest_pact_publication.id)
|
431
|
-
SelectedPact.new(pact_publication.to_domain, Selectors.create_for_overall_latest)
|
431
|
+
SelectedPact.new(pact_publication.to_domain, Selectors.create_for_overall_latest.resolve(pact_publication.consumer_version))
|
432
432
|
end
|
433
433
|
else
|
434
434
|
selectors_for_overall_latest = consumer_version_selectors.select(&:overall_latest?)
|
@@ -438,7 +438,7 @@ module PactBroker
|
|
438
438
|
query.collect do | latest_pact_publication |
|
439
439
|
pact_publication = PactPublication.find(id: latest_pact_publication.id)
|
440
440
|
resolved_selector = selector.consumer ? Selector.latest_for_consumer(selector.consumer) : Selector.overall_latest
|
441
|
-
SelectedPact.new(pact_publication.to_domain, Selectors.new(resolved_selector))
|
441
|
+
SelectedPact.new(pact_publication.to_domain, Selectors.new(resolved_selector).resolve(pact_publication.consumer_version))
|
442
442
|
end
|
443
443
|
end
|
444
444
|
end
|
@@ -453,26 +453,19 @@ module PactBroker
|
|
453
453
|
query = query.consumer(selector.consumer) if selector.consumer
|
454
454
|
query.all.collect do | latest_tagged_pact_publication |
|
455
455
|
pact_publication = PactPublication.find(id: latest_tagged_pact_publication.id)
|
456
|
-
|
456
|
+
resolved_selector = if selector.consumer
|
457
|
+
Selector.latest_for_tag_and_consumer(selector.tag, selector.consumer).resolve(pact_publication.consumer_version)
|
458
|
+
else
|
459
|
+
Selector.latest_for_tag(selector.tag).resolve(pact_publication.consumer_version)
|
460
|
+
end
|
457
461
|
SelectedPact.new(
|
458
462
|
pact_publication.to_domain,
|
459
|
-
Selectors.new(
|
463
|
+
Selectors.new(resolved_selector)
|
460
464
|
)
|
461
465
|
end
|
462
466
|
end
|
463
467
|
end
|
464
468
|
|
465
|
-
def create_fallback_selected_pact(pact_publications, consumer_version_selectors)
|
466
|
-
selector_tag_names = pact_publications.collect(&:tag_name)
|
467
|
-
selectors = Selectors.create_for_latest_fallback_of_each_tag(selector_tag_names)
|
468
|
-
last_pact_publication = pact_publications.sort_by(&:consumer_version_order).last
|
469
|
-
pact_publication = unscoped(PactPublication).find(id: last_pact_publication.id)
|
470
|
-
SelectedPact.new(
|
471
|
-
pact_publication.to_domain,
|
472
|
-
selectors
|
473
|
-
)
|
474
|
-
end
|
475
|
-
|
476
469
|
def find_pacts_for_which_the_latest_version_for_the_fallback_tag_is_required(provider_name, selectors)
|
477
470
|
selectors.collect do | selector |
|
478
471
|
query = scope_for(LatestTaggedPactPublications).provider(provider_name).where(tag_name: selector.fallback_tag)
|
@@ -482,7 +475,7 @@ module PactBroker
|
|
482
475
|
pact_publication = unscoped(PactPublication).find(id: latest_tagged_pact_publication.id)
|
483
476
|
SelectedPact.new(
|
484
477
|
pact_publication.to_domain,
|
485
|
-
Selectors.new(selector)
|
478
|
+
Selectors.new(selector.resolve(pact_publication.consumer_version))
|
486
479
|
)
|
487
480
|
end
|
488
481
|
end.flatten
|
@@ -5,6 +5,10 @@ module PactBroker
|
|
5
5
|
merge!(options)
|
6
6
|
end
|
7
7
|
|
8
|
+
def resolve(consumer_version)
|
9
|
+
ResolvedSelector.new(self.to_h, consumer_version)
|
10
|
+
end
|
11
|
+
|
8
12
|
def tag= tag
|
9
13
|
self[:tag] = tag
|
10
14
|
end
|
@@ -94,6 +98,10 @@ module PactBroker
|
|
94
98
|
!!(tag && !latest?)
|
95
99
|
end
|
96
100
|
|
101
|
+
def == other
|
102
|
+
other.class == self.class && super
|
103
|
+
end
|
104
|
+
|
97
105
|
def <=> other
|
98
106
|
if overall_latest? || other.overall_latest?
|
99
107
|
if overall_latest? == other.overall_latest?
|
@@ -124,5 +132,19 @@ module PactBroker
|
|
124
132
|
!!self[:latest]
|
125
133
|
end
|
126
134
|
end
|
135
|
+
|
136
|
+
class ResolvedSelector < Selector
|
137
|
+
def initialize(options = {}, consumer_version)
|
138
|
+
super(options.merge(consumer_version: consumer_version))
|
139
|
+
end
|
140
|
+
|
141
|
+
def consumer_version
|
142
|
+
self[:consumer_version]
|
143
|
+
end
|
144
|
+
|
145
|
+
def == other
|
146
|
+
super && consumer_version == other.consumer_version
|
147
|
+
end
|
148
|
+
end
|
127
149
|
end
|
128
150
|
end
|
@@ -19,13 +19,13 @@ module PactBroker
|
|
19
19
|
logger.filter(/(Authorization: ).*/,'\1[REMOVED]')
|
20
20
|
end
|
21
21
|
end
|
22
|
-
|
22
|
+
faraday.headers['Authorization'] = "Bearer #{auth[:token]}" if auth[:token]
|
23
23
|
faraday.adapter Faraday.default_adapter
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
def sleep
|
28
|
-
Kernel.sleep
|
28
|
+
Kernel.sleep 0.5
|
29
29
|
self
|
30
30
|
end
|
31
31
|
|
@@ -42,7 +42,7 @@ module PactBroker
|
|
42
42
|
|
43
43
|
def create_tag(pacticipant:, version:, tag:)
|
44
44
|
puts "Creating tag '#{tag}' for #{pacticipant} version #{version}"
|
45
|
-
client.put("/pacticipants/#{encode(pacticipant)}/versions/#{encode(version)}/tags/#{encode(tag)}", {})
|
45
|
+
client.put("/pacticipants/#{encode(pacticipant)}/versions/#{encode(version)}/tags/#{encode(tag)}", {}).tap { |response| check_for_error(response) }
|
46
46
|
self
|
47
47
|
end
|
48
48
|
|
@@ -53,6 +53,13 @@ module PactBroker
|
|
53
53
|
self
|
54
54
|
end
|
55
55
|
|
56
|
+
def create_pacticipant(name)
|
57
|
+
puts "Creating pacticipant with name #{name}"
|
58
|
+
client.post("/pacticipants", { name: name}).tap { |response| check_for_error(response) }
|
59
|
+
separate
|
60
|
+
self
|
61
|
+
end
|
62
|
+
|
56
63
|
def publish_pact(consumer: last_consumer_name, consumer_version:, provider: last_provider_name, content_id:, tag:)
|
57
64
|
@last_consumer_name = consumer
|
58
65
|
@last_provider_name = provider
|
@@ -61,16 +68,18 @@ module PactBroker
|
|
61
68
|
[*tag].each do | tag |
|
62
69
|
create_tag(pacticipant: consumer, version: consumer_version, tag: tag)
|
63
70
|
end
|
71
|
+
puts "" if [*tag].any?
|
64
72
|
|
65
73
|
content = generate_content(consumer, provider, content_id)
|
66
74
|
puts "Publishing pact for consumer #{consumer} version #{consumer_version} and provider #{provider}"
|
67
75
|
pact_path = "/pacts/provider/#{encode(provider)}/consumer/#{encode(consumer)}/version/#{encode(consumer_version)}"
|
68
|
-
@publish_pact_response = client.put(pact_path, content)
|
76
|
+
@publish_pact_response = client.put(pact_path, content).tap { |response| check_for_error(response) }
|
69
77
|
separate
|
70
78
|
self
|
71
79
|
end
|
72
80
|
|
73
81
|
def get_pacts_for_verification(provider: last_provider_name, provider_version_tag: , consumer_version_selectors:, enable_pending: false, include_wip_pacts_since: nil)
|
82
|
+
@last_provider_name = provider
|
74
83
|
puts "Fetching pacts for verification for #{provider}"
|
75
84
|
body = {
|
76
85
|
providerVersionTags: [*provider_version_tag],
|
@@ -80,7 +89,7 @@ module PactBroker
|
|
80
89
|
}.compact
|
81
90
|
puts body.to_yaml
|
82
91
|
puts ""
|
83
|
-
@pacts_for_verification_response = client.post("/pacts/provider/#{encode(provider)}/for-verification", body)
|
92
|
+
@pacts_for_verification_response = client.post("/pacts/provider/#{encode(provider)}/for-verification", body).tap { |response| check_for_error(response) }
|
84
93
|
|
85
94
|
print_pacts_for_verification
|
86
95
|
separate
|
@@ -88,23 +97,32 @@ module PactBroker
|
|
88
97
|
end
|
89
98
|
|
90
99
|
def print_pacts_for_verification
|
91
|
-
pacts = @pacts_for_verification_response.body
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
100
|
+
pacts = @pacts_for_verification_response.body&.dig("_embedded", "pacts")
|
101
|
+
if pacts
|
102
|
+
puts "Pacts for verification (#{pacts.count}):"
|
103
|
+
pacts.each do | pact |
|
104
|
+
puts({
|
105
|
+
"url" => pact["_links"]["self"]["href"],
|
106
|
+
"wip" => pact["verificationProperties"]["wip"],
|
107
|
+
"pending" => pact["verificationProperties"]["pending"]
|
108
|
+
}.to_yaml)
|
109
|
+
end
|
99
110
|
end
|
100
111
|
self
|
101
112
|
end
|
102
113
|
|
103
114
|
def verify_pact(index: 0, success:, provider: last_provider_name, provider_version_tag: , provider_version: )
|
115
|
+
@last_provider_name = provider
|
104
116
|
pact_to_verify = @pacts_for_verification_response.body["_embedded"]["pacts"][index]
|
105
117
|
raise "No pact found to verify at index #{index}" unless pact_to_verify
|
106
118
|
url_of_pact_to_verify = pact_to_verify["_links"]["self"]["href"]
|
107
|
-
|
119
|
+
|
120
|
+
[*provider_version_tag].each do | tag |
|
121
|
+
create_tag(pacticipant: provider, version: provider_version, tag: tag)
|
122
|
+
end
|
123
|
+
puts "" if [*provider_version_tag].any?
|
124
|
+
|
125
|
+
pact_response = client.get(url_of_pact_to_verify).tap { |response| check_for_error(response) }
|
108
126
|
verification_results_url = pact_response.body["_links"]["pb:publish-verification-results"]["href"]
|
109
127
|
|
110
128
|
results = {
|
@@ -112,8 +130,9 @@ module PactBroker
|
|
112
130
|
testResults: [],
|
113
131
|
providerApplicationVersion: provider_version
|
114
132
|
}
|
115
|
-
puts "
|
116
|
-
|
133
|
+
puts "Publishing verification"
|
134
|
+
puts results.to_yaml
|
135
|
+
response = client.post(verification_results_url, results.to_json).tap { |response| check_for_error(response) }
|
117
136
|
separate
|
118
137
|
self
|
119
138
|
end
|
@@ -124,7 +143,7 @@ module PactBroker
|
|
124
143
|
end
|
125
144
|
|
126
145
|
def can_i_deploy(pacticipant:, version:, to:)
|
127
|
-
can_i_deploy_response = client.get("/can-i-deploy", { pacticipant: pacticipant, version: version, to: to} )
|
146
|
+
can_i_deploy_response = client.get("/can-i-deploy", { pacticipant: pacticipant, version: version, to: to} ).tap { |response| check_for_error(response) }
|
128
147
|
can = !!(can_i_deploy_response.body['summary'] || {})['deployable']
|
129
148
|
puts "can-i-deploy #{pacticipant} version #{version} to #{to}: #{can ? 'yes' : 'no'}"
|
130
149
|
puts (can_i_deploy_response.body['summary'] || can_i_deploy_response.body).to_yaml
|
@@ -133,7 +152,8 @@ module PactBroker
|
|
133
152
|
end
|
134
153
|
|
135
154
|
def delete_integration(consumer:, provider:)
|
136
|
-
|
155
|
+
puts "Deleting all data for the integration between #{consumer} and #{provider}"
|
156
|
+
client.delete("/integrations/provider/#{encode(provider)}/consumer/#{encode(consumer)}").tap { |response| check_for_error(response) }
|
137
157
|
separate
|
138
158
|
self
|
139
159
|
end
|
@@ -163,6 +183,13 @@ module PactBroker
|
|
163
183
|
def encode string
|
164
184
|
ERB::Util.url_encode(string)
|
165
185
|
end
|
186
|
+
|
187
|
+
def check_for_error(response)
|
188
|
+
if ! response.success?
|
189
|
+
puts response.status
|
190
|
+
puts response.body
|
191
|
+
end
|
192
|
+
end
|
166
193
|
end
|
167
194
|
end
|
168
195
|
end
|
data/lib/pact_broker/version.rb
CHANGED
data/pact_broker.gemspec
CHANGED
@@ -64,4 +64,5 @@ Gem::Specification.new do |gem|
|
|
64
64
|
gem.add_runtime_dependency 'table_print', '~> 1.5'
|
65
65
|
gem.add_runtime_dependency 'semantic_logger', '~> 4.3'
|
66
66
|
gem.add_runtime_dependency 'sanitize', '>= 5.2.1', '~> 5.2'
|
67
|
+
gem.add_runtime_dependency 'nokogiri', '< 2.0', '>= 1.11.0.rc4' # For CVE-2020-26247 Remove when 1.11 is released properly
|
67
68
|
end
|
data/script/reproduce-issue.rb
CHANGED
@@ -9,10 +9,15 @@ begin
|
|
9
9
|
|
10
10
|
td = PactBroker::Test::HttpTestDataBuilder.new(base_url, { })
|
11
11
|
td.delete_integration(consumer: "MyConsumer", provider: "MyProvider")
|
12
|
+
.create_pacticipant("MyConsumer")
|
13
|
+
.create_pacticipant("MyProvider")
|
12
14
|
.publish_pact(consumer: "MyConsumer", consumer_version: "1", provider: "MyProvider", content_id: "111", tag: "main")
|
15
|
+
.publish_pact(consumer: "MyConsumer", consumer_version: "2", provider: "MyProvider", content_id: "222", tag: "main")
|
16
|
+
.publish_pact(consumer: "MyConsumer", consumer_version: "3", provider: "MyProvider", content_id: "111", tag: "feat/a")
|
13
17
|
.get_pacts_for_verification(
|
14
18
|
provider_version_tag: "main",
|
15
|
-
consumer_version_selectors: [{ tag: "main", latest: true }])
|
19
|
+
consumer_version_selectors: [{ tag: "main" }, { tag: "feat/a", latest: true }])
|
20
|
+
.verify_pact(success: true, provider_version_tag: "main", provider_version: "2" )
|
16
21
|
|
17
22
|
|
18
23
|
rescue StandardError => e
|
@@ -8,6 +8,7 @@ module PactBroker
|
|
8
8
|
allow_any_instance_of(PactBroker::Api::PactBrokerUrls).to receive(:pact_version_url_with_metadata).and_return('http://pact')
|
9
9
|
allow(PactBroker::Pacts::BuildVerifiablePactNotices).to receive(:call).and_return(notices)
|
10
10
|
allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:pact_version_short_description).and_return('short desc')
|
11
|
+
allow_any_instance_of(VerifiablePactDecorator).to receive(:build_metadata_for_pact_for_verification).and_return(metadata)
|
11
12
|
end
|
12
13
|
|
13
14
|
let(:pending_reason) { "the pending reason" }
|
@@ -45,13 +46,15 @@ module PactBroker
|
|
45
46
|
name: "name",
|
46
47
|
provider_name: "Bar",
|
47
48
|
pending_provider_tags: pending_provider_tags,
|
48
|
-
consumer_tags: consumer_tags
|
49
|
+
consumer_tags: consumer_tags,
|
50
|
+
selectors: PactBroker::Pacts::Selectors.new([PactBroker::Pacts::ResolvedSelector.new({ latest: true }, double('version', number: "2", id: 1))]))
|
49
51
|
end
|
50
52
|
let(:pending_provider_tags) { %w[dev] }
|
51
53
|
let(:consumer_tags) { %w[dev] }
|
52
54
|
let(:options) { { user_options: { base_url: 'http://example.org', include_pending_status: include_pending_status } } }
|
53
55
|
let(:include_pending_status) { true }
|
54
56
|
let(:wip){ false }
|
57
|
+
let(:metadata) { double('metadata') }
|
55
58
|
let(:json) { decorator.to_json(options) }
|
56
59
|
|
57
60
|
subject { JSON.parse(json) }
|
@@ -61,7 +64,7 @@ module PactBroker
|
|
61
64
|
end
|
62
65
|
|
63
66
|
it "creates the pact version url" do
|
64
|
-
expect(decorator).to receive(:pact_version_url_with_metadata).with(pact,
|
67
|
+
expect(decorator).to receive(:pact_version_url_with_metadata).with(pact, metadata, 'http://example.org')
|
65
68
|
subject
|
66
69
|
end
|
67
70
|
|
@@ -84,11 +87,6 @@ module PactBroker
|
|
84
87
|
it "includes the wip flag" do
|
85
88
|
expect(subject['verificationProperties']['wip']).to be true
|
86
89
|
end
|
87
|
-
|
88
|
-
it "includes it in the metadata" do
|
89
|
-
expect(decorator).to receive(:pact_version_url_with_metadata).with(pact, { wip: true }, 'http://example.org')
|
90
|
-
subject
|
91
|
-
end
|
92
90
|
end
|
93
91
|
end
|
94
92
|
end
|
@@ -107,13 +107,9 @@ module PactBroker
|
|
107
107
|
end
|
108
108
|
|
109
109
|
describe "webhook metadata" do
|
110
|
-
let(:expected_metadata) do
|
111
|
-
{ consumer_version_number: "123/456", consumer_version_tags: %w[dev], wip: "true" }
|
112
|
-
end
|
113
|
-
|
114
110
|
it "builds the webhook metadata" do
|
115
|
-
encoded_metadata = PactBrokerUrls.encode_metadata(
|
116
|
-
expect(PactBrokerUrls.decode_pact_metadata(encoded_metadata)).to eq
|
111
|
+
encoded_metadata = PactBrokerUrls.encode_metadata("some" => "metadata")
|
112
|
+
expect(PactBrokerUrls.decode_pact_metadata(encoded_metadata)).to eq "some" => "metadata"
|
117
113
|
end
|
118
114
|
end
|
119
115
|
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'pact_broker/pacts/metadata'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Pacts
|
5
|
+
module Metadata
|
6
|
+
describe "#build_metadata_for_pact_for_verification" do
|
7
|
+
let(:selectors) do
|
8
|
+
Selectors.new([ResolvedSelector.new({ latest: true, consumer: "consumer", tag: "tag" }, consumer_version)])
|
9
|
+
end
|
10
|
+
let(:consumer_version) { double('version', number: "2") }
|
11
|
+
let(:verifiable_pact) { double('PactBroker::Pacts::VerifiablePact', wip: wip, selectors: selectors) }
|
12
|
+
let(:wip) { false }
|
13
|
+
|
14
|
+
subject { Metadata.build_metadata_for_pact_for_verification(verifiable_pact) }
|
15
|
+
|
16
|
+
it "builds the metadata with the resolved selectors" do
|
17
|
+
expect(subject).to eq({
|
18
|
+
"s" => [
|
19
|
+
{
|
20
|
+
"l" => true,
|
21
|
+
"t" => "tag",
|
22
|
+
"cvn" => "2"
|
23
|
+
}
|
24
|
+
]
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when wip is true" do
|
29
|
+
let(:wip) { true }
|
30
|
+
|
31
|
+
it { is_expected.to eq "w" => true }
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "parse_metadata" do
|
37
|
+
let(:incoming_metadata) do
|
38
|
+
{
|
39
|
+
"cvn" => "2",
|
40
|
+
"cvt" => ["tag"],
|
41
|
+
"w" => true,
|
42
|
+
"s" => [
|
43
|
+
{
|
44
|
+
"l" => true,
|
45
|
+
"t" => "tag",
|
46
|
+
"cvn" => "2"
|
47
|
+
}
|
48
|
+
]
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
let(:parsed_metadata) do
|
53
|
+
{
|
54
|
+
:consumer_version_number => "2",
|
55
|
+
:consumer_version_tags => ["tag"],
|
56
|
+
:wip => true,
|
57
|
+
:consumer_version_selectors => [
|
58
|
+
{
|
59
|
+
:latest => true,
|
60
|
+
:tag => "tag",
|
61
|
+
:consumer_version_number => "2"
|
62
|
+
}
|
63
|
+
]
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
it "expands the key names" do
|
68
|
+
expect(Metadata.parse_metadata(incoming_metadata)).to eq parsed_metadata
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -30,7 +30,7 @@ module PactBroker
|
|
30
30
|
context "when a pact exists for the main tag" do
|
31
31
|
it "returns the pact with the main tag" do
|
32
32
|
expect(find_by_consumer_version_number("2")).to_not be nil
|
33
|
-
expect(find_by_consumer_version_number("2").selectors.first).to eq Selector.latest_for_tag(tag)
|
33
|
+
expect(find_by_consumer_version_number("2").selectors.first).to eq Selector.latest_for_tag(tag).resolve(PactBroker::Domain::Version.for("Foo", "2"))
|
34
34
|
end
|
35
35
|
|
36
36
|
it "does not set the fallback_tag on the selector" do
|
@@ -67,7 +67,7 @@ module PactBroker
|
|
67
67
|
it "only returns the pacts for the consumer" do
|
68
68
|
expect(subject.size).to eq 1
|
69
69
|
expect(subject.first.consumer.name).to eq "Foo"
|
70
|
-
expect(subject.first.selectors.first).to eq selector
|
70
|
+
expect(subject.first.selectors.first).to eq selector.resolve(PactBroker::Domain::Version.for("Foo", "1"))
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
@@ -3,8 +3,6 @@ require 'pact_broker/pacts/repository'
|
|
3
3
|
module PactBroker
|
4
4
|
module Pacts
|
5
5
|
describe Repository do
|
6
|
-
let(:td) { TestDataBuilder.new }
|
7
|
-
|
8
6
|
describe "#find_for_verification" do
|
9
7
|
def find_by_consumer_version_number(consumer_version_number)
|
10
8
|
subject.find{ |pact| pact.consumer_version_number == consumer_version_number }
|
@@ -55,8 +53,8 @@ module PactBroker
|
|
55
53
|
|
56
54
|
it "returns the latest pact for each consumer" do
|
57
55
|
expect(subject.size).to eq 2
|
58
|
-
expect(find_by_consumer_name_and_consumer_version_number("Foo1", "2").selectors).to eq [Selector.overall_latest]
|
59
|
-
expect(find_by_consumer_name_and_consumer_version_number("Foo2", "3").selectors).to eq [Selector.overall_latest]
|
56
|
+
expect(find_by_consumer_name_and_consumer_version_number("Foo1", "2").selectors).to eq [Selector.overall_latest.resolve(PactBroker::Domain::Version.find(number: "2"))]
|
57
|
+
expect(find_by_consumer_name_and_consumer_version_number("Foo2", "3").selectors).to eq [Selector.overall_latest.resolve(PactBroker::Domain::Version.find(number: "3"))]
|
60
58
|
end
|
61
59
|
end
|
62
60
|
|
@@ -76,7 +74,7 @@ module PactBroker
|
|
76
74
|
|
77
75
|
it "returns the latest pact for each consumer" do
|
78
76
|
expect(subject.size).to eq 1
|
79
|
-
expect(find_by_consumer_name_and_consumer_version_number("Foo1", "2").selectors).to eq [pact_selector_1]
|
77
|
+
expect(find_by_consumer_name_and_consumer_version_number("Foo1", "2").selectors).to eq [pact_selector_1.resolve(PactBroker::Domain::Version.find(number: "2"))]
|
80
78
|
end
|
81
79
|
end
|
82
80
|
|
@@ -98,7 +96,8 @@ module PactBroker
|
|
98
96
|
|
99
97
|
it "returns the latest pact for each consumer" do
|
100
98
|
expect(subject.size).to eq 1
|
101
|
-
|
99
|
+
expected_consumer_version = PactBroker::Domain::Version.where_pacticipant_name("Foo1").where(number: "1").single_record
|
100
|
+
expect(find_by_consumer_name_and_consumer_version_number("Foo1", "1").selectors).to eq [pact_selector_1.resolve(expected_consumer_version)]
|
102
101
|
end
|
103
102
|
end
|
104
103
|
|
@@ -122,11 +121,17 @@ module PactBroker
|
|
122
121
|
let(:consumer_version_selectors) do
|
123
122
|
Selectors.new(pact_selector_1, pact_selector_2)
|
124
123
|
end
|
124
|
+
let(:expected_sorted_selectors) do
|
125
|
+
[
|
126
|
+
ResolvedSelector.new({ tag: 'dev', latest: true }, PactBroker::Domain::Version.for("Baz", "baz-latest-dev-version")),
|
127
|
+
ResolvedSelector.new({ tag: 'prod', latest: true }, PactBroker::Domain::Version.for("Baz", "baz-latest-dev-version"))
|
128
|
+
]
|
129
|
+
end
|
125
130
|
|
126
131
|
it "returns the latest pact with the specified tags for each consumer" do
|
127
|
-
expect(find_by_consumer_version_number("foo-latest-prod-version").selectors).to eq [Selector.latest_for_tag('prod')]
|
128
|
-
expect(find_by_consumer_version_number("foo-latest-dev-version").selectors).to eq [Selector.latest_for_tag('dev')]
|
129
|
-
expect(find_by_consumer_version_number("baz-latest-dev-version").selectors.sort_by{ |s| s[:tag] }).to eq
|
132
|
+
expect(find_by_consumer_version_number("foo-latest-prod-version").selectors).to eq [Selector.latest_for_tag('prod').resolve(PactBroker::Domain::Version.for("Foo", "foo-latest-prod-version"))]
|
133
|
+
expect(find_by_consumer_version_number("foo-latest-dev-version").selectors).to eq [Selector.latest_for_tag('dev').resolve(PactBroker::Domain::Version.for("Foo", "foo-latest-dev-version"))]
|
134
|
+
expect(find_by_consumer_version_number("baz-latest-dev-version").selectors.sort_by{ |s| s[:tag] }).to eq expected_sorted_selectors
|
130
135
|
expect(subject.size).to eq 3
|
131
136
|
end
|
132
137
|
|
@@ -134,14 +139,29 @@ module PactBroker
|
|
134
139
|
expect(find_by_consumer_version_number("foo-latest-prod-version").selectors.collect(&:tag)).to eq ['prod']
|
135
140
|
end
|
136
141
|
|
137
|
-
context "when a consumer name is specified"
|
142
|
+
context "when a consumer name is specified" do
|
143
|
+
before do
|
144
|
+
td.create_pact_with_hierarchy("Foo", "2", "Bar")
|
145
|
+
.create_consumer_version_tag("prod")
|
146
|
+
.create_pact_with_hierarchy("Foo", "3", "Bar")
|
147
|
+
.create_consumer_version_tag("prod")
|
148
|
+
.create_consumer_version("4")
|
149
|
+
.create_consumer_version_tag("prod")
|
150
|
+
.republish_same_pact
|
151
|
+
end
|
152
|
+
|
138
153
|
let(:consumer_version_selectors) do
|
139
154
|
Selectors.new(Selector.all_for_tag_and_consumer('prod', 'Foo'))
|
140
155
|
end
|
141
156
|
|
142
|
-
it "
|
157
|
+
it "returns all the pacts with that tag for that consumer" do
|
143
158
|
expect(subject.size).to eq 3
|
144
|
-
expect(find_by_consumer_version_number("foo-latest-prod-version").selectors).to eq [Selector.all_for_tag_and_consumer('prod', 'Foo')]
|
159
|
+
expect(find_by_consumer_version_number("foo-latest-prod-version").selectors).to eq [Selector.all_for_tag_and_consumer('prod', 'Foo').resolve(PactBroker::Domain::Version.for("Foo", "foo-latest-prod-version"))]
|
160
|
+
end
|
161
|
+
|
162
|
+
it "uses the latest consumer verison number as the resolved version when the same pact content is selected multiple times" do
|
163
|
+
expect(find_by_consumer_version_number("3")).to be nil
|
164
|
+
expect(find_by_consumer_version_number("4").selectors).to eq [Selector.all_for_tag_and_consumer('prod', 'Foo').resolve(PactBroker::Domain::Version.for("Foo", "4"))]
|
145
165
|
end
|
146
166
|
end
|
147
167
|
end
|
@@ -246,7 +266,7 @@ module PactBroker
|
|
246
266
|
end
|
247
267
|
|
248
268
|
it "does not set the tag name" do
|
249
|
-
expect(find_by_consumer_version_number("foo-latest-dev-version").selectors).to eq [{ latest: true }]
|
269
|
+
expect(find_by_consumer_version_number("foo-latest-dev-version").selectors).to eq [ResolvedSelector.new({ latest: true }, PactBroker::Domain::Version.find(number: "foo-latest-dev-version"))]
|
250
270
|
expect(find_by_consumer_version_number("foo-latest-dev-version").overall_latest?).to be true
|
251
271
|
end
|
252
272
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact_broker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.74.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bethany Skurrie
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date:
|
13
|
+
date: 2021-01-04 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: httparty
|
@@ -354,6 +354,26 @@ dependencies:
|
|
354
354
|
- - "~>"
|
355
355
|
- !ruby/object:Gem::Version
|
356
356
|
version: '5.2'
|
357
|
+
- !ruby/object:Gem::Dependency
|
358
|
+
name: nokogiri
|
359
|
+
requirement: !ruby/object:Gem::Requirement
|
360
|
+
requirements:
|
361
|
+
- - "<"
|
362
|
+
- !ruby/object:Gem::Version
|
363
|
+
version: '2.0'
|
364
|
+
- - ">="
|
365
|
+
- !ruby/object:Gem::Version
|
366
|
+
version: 1.11.0.rc4
|
367
|
+
type: :runtime
|
368
|
+
prerelease: false
|
369
|
+
version_requirements: !ruby/object:Gem::Requirement
|
370
|
+
requirements:
|
371
|
+
- - "<"
|
372
|
+
- !ruby/object:Gem::Version
|
373
|
+
version: '2.0'
|
374
|
+
- - ">="
|
375
|
+
- !ruby/object:Gem::Version
|
376
|
+
version: 1.11.0.rc4
|
357
377
|
description: A server that stores and returns pact files generated by the pact gem.
|
358
378
|
It enables head/prod cross testing of the consumer and provider projects.
|
359
379
|
email:
|
@@ -1294,6 +1314,7 @@ files:
|
|
1294
1314
|
- spec/lib/pact_broker/pacts/generate_sha_spec.rb
|
1295
1315
|
- spec/lib/pact_broker/pacts/latest_tagged_pact_publications_spec.rb
|
1296
1316
|
- spec/lib/pact_broker/pacts/merger_spec.rb
|
1317
|
+
- spec/lib/pact_broker/pacts/metadata_spec.rb
|
1297
1318
|
- spec/lib/pact_broker/pacts/pact_params_spec.rb
|
1298
1319
|
- spec/lib/pact_broker/pacts/pact_publication_spec.rb
|
1299
1320
|
- spec/lib/pact_broker/pacts/pact_version_spec.rb
|
@@ -1463,7 +1484,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
1463
1484
|
- !ruby/object:Gem::Version
|
1464
1485
|
version: '0'
|
1465
1486
|
requirements: []
|
1466
|
-
rubygems_version: 3.2.
|
1487
|
+
rubygems_version: 3.2.4
|
1467
1488
|
signing_key:
|
1468
1489
|
specification_version: 4
|
1469
1490
|
summary: See description
|
@@ -1693,6 +1714,7 @@ test_files:
|
|
1693
1714
|
- spec/lib/pact_broker/pacts/generate_sha_spec.rb
|
1694
1715
|
- spec/lib/pact_broker/pacts/latest_tagged_pact_publications_spec.rb
|
1695
1716
|
- spec/lib/pact_broker/pacts/merger_spec.rb
|
1717
|
+
- spec/lib/pact_broker/pacts/metadata_spec.rb
|
1696
1718
|
- spec/lib/pact_broker/pacts/pact_params_spec.rb
|
1697
1719
|
- spec/lib/pact_broker/pacts/pact_publication_spec.rb
|
1698
1720
|
- spec/lib/pact_broker/pacts/pact_version_spec.rb
|