pact_broker 2.73.0 → 2.74.0
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 +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
|