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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1bc95def65b82d8d938fa3b245bb6f306092d8d00572778f8b3f8ae377479fd0
4
- data.tar.gz: 2790ca52a1db8ba01ca02ef24b6816482a4fdf38a925e8eb737d998ff2ff1213
3
+ metadata.gz: 4a3779dfce4701e31c25e10a37154785df8745aa022869f70bcdd3c080066169
4
+ data.tar.gz: d9c48a07a42949aea37a84ca43930a53d6403abe02a96d1c1de2d58a27d763bc
5
5
  SHA512:
6
- metadata.gz: 9d2740784d48edea10528d9b3a1db0ec6f89d5474c2b7b3c4c4077a7b1d57c714f7f902066e7e76cf921ab5b51e8cc58b6d3146a2a752c3535394c87e7457831
7
- data.tar.gz: 5fb6688a830ecd05bf7eb8985d651f0a406a5bfe348e29287b93328bb2cf9f36013fda31394e3499ee058c10e54c326366f59567dc3d5eadf02507d9512787f6
6
+ metadata.gz: 2a4a61fe0838766004ab06723b406d51149d748ec449c81139ada966a223b5491d4728fa0cdd52d6e369081af490eb03b4b7036c12c6f2a6b014bf20608c9d68
7
+ data.tar.gz: 569774601622663f53d824d40b0013afd6728f0c603fb9f2f8d66f759603daf7d361d6481003dc83a2a844415d93eae78694a076be1172eb45728d678cd672a2
@@ -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.wip ? { wip: true } : nil
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)).each_with_object({}) do | (k, v), new_hash |
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
- join(:pacticipants) do | p |
52
- Sequel.&(
53
- { Sequel[first_source_alias][:pacticipant_id] => Sequel[p][:id] },
54
- name_like(Sequel[p][:name], pacticipant_name)
55
- )
56
- end
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
- consumer_version_tags: [selection_parameters[:tag]],
15
- consumer_version_number: pact.consumer_version_number
23
+ "cvt" => [selection_parameters[:tag]],
24
+ "cvn" => pact.consumer_version_number
16
25
  }
17
26
  else
18
27
  {
19
- consumer_version_number: pact.consumer_version_number
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
- consumer_version_number: pact.consumer_version_number,
32
- consumer_version_tags: pact.consumer_version_tag_names
40
+ "cvn" => pact.consumer_version_number,
41
+ "cvt" => pact.consumer_version_tag_names
33
42
  }
34
- metadata[:wip] = "true"
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
- resolved_pact = selector.consumer ? Selector.latest_for_tag_and_consumer(selector.tag, selector.consumer) : Selector.latest_for_tag(selector.tag)
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(resolved_pact)
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,6 +19,10 @@ module PactBroker
19
19
  Selectors.new([Selector.overall_latest])
20
20
  end
21
21
 
22
+ def resolve(consumer_version)
23
+ Selectors.new(collect{ |selector| selector.resolve(consumer_version) })
24
+ end
25
+
22
26
  def + other
23
27
  Selectors.new(super)
24
28
  end
@@ -19,13 +19,13 @@ module PactBroker
19
19
  logger.filter(/(Authorization: ).*/,'\1[REMOVED]')
20
20
  end
21
21
  end
22
- # faraday.headers['Authorization'] = "Bearer #{pactflow_api_token}"
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 1
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["_embedded"]["pacts"]
92
- puts "Pacts for verification (#{pacts.count}):"
93
- pacts.each do | pact |
94
- puts({
95
- "url" => pact["_links"]["self"]["href"],
96
- "wip" => pact["verificationProperties"]["wip"],
97
- "pending" => pact["verificationProperties"]["pending"]
98
- }.to_yaml)
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
- pact_response = client.get(url_of_pact_to_verify)
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 "\nPublishing verification"
116
- response = client.post(verification_results_url, results.to_json)
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
- client.delete("/integrations/provider/#{encode(provider)}/consumer/#{encode(consumer)}")
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
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '2.73.0'
2
+ VERSION = '2.74.0'
3
3
  end
@@ -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
@@ -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, nil, 'http://example.org')
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(PactBrokerUrls.build_metadata_for_webhook_triggered_by_pact_publication(pact))
116
- expect(PactBrokerUrls.decode_pact_metadata(encoded_metadata)).to eq (expected_metadata)
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
- expect(find_by_consumer_name_and_consumer_version_number("Foo1", "1").selectors).to eq [pact_selector_1]
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 [{ tag: 'dev', latest: true }, { tag: 'prod', latest: true }]
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", pending: "not yet implemented, but will do" do
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 "only returns the pacts for that consumer" do
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.73.0
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: 2020-12-16 00:00:00.000000000 Z
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.1
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