pact_broker 2.8.0.beta.5 → 2.9.0.beta.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cebfc643458ec866835a2820e3dcbc3f214266ae
4
- data.tar.gz: 85ab89a5a77b328efe497d9846110a5291de65c1
3
+ metadata.gz: bf490a74cabeccee8ad6973db3e32c96a0ff2f6b
4
+ data.tar.gz: a4983395d117314b3c7da784a7855a20d5483147
5
5
  SHA512:
6
- metadata.gz: 76afaaa40c825514aeeae6e334274caf8d52b850b41126ae68163214810bd0d5bf9244b9e737135f0baf82339f43a48d07d5ce0df2c6372d3705a86dfaa2d71d
7
- data.tar.gz: 4f35850adae4e26e3ed41c83e71c0509b05f5ba7af7dacb30ca37bb059abe6c62c2eba346fc0b790ec6ca6f6a0f3e7c19b1e47818b3d93939e796ae1cea2010a
6
+ metadata.gz: 9720bb92c02c741b93c63b127c4c53fab0bbf980fc7af1842fce100186fc78edfd8936ef2c535dc6c51c1d2aeff4057b48c4a2c3f4e568243456e285a6604476
7
+ data.tar.gz: 67f17b7730351717e5c47b87b7813065c1eac0d02750c9908fbe5264acb75ddc38e659197766b5de85599949805e324924a0467e427fd4f60f99ce654d3d8498
data/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ <a name="v2.9.0.beta.5"></a>
2
+ ### v2.9.0.beta.5 (2017-11-09)
3
+
4
+
5
+ #### Features
6
+
7
+ * **webhook templating**
8
+ * add support for ${pactbroker.pactUrl} in query and body ([0eed596](/../../commit/0eed596))
9
+
10
+ * **matrix**
11
+ * allow query to determine if a particular pacticipant version is compatible with the latest tagged versions of all its dependencies ([ba4a1cc](/../../commit/ba4a1cc))
12
+
13
+
1
14
  <a name="v2.8.0.beta.5"></a>
2
15
  ### v2.8.0.beta.5 (2017-11-06)
3
16
 
@@ -3,6 +3,7 @@ require 'pact_broker/db'
3
3
  require 'pact_broker/project_root'
4
4
  require 'rack-protection'
5
5
  require 'rack/hal_browser'
6
+ require 'rack/pact_broker/store_base_url'
6
7
  require 'rack/pact_broker/add_pact_broker_version_header'
7
8
  require 'rack/pact_broker/convert_file_extension_to_accept_header'
8
9
  require 'rack/pact_broker/database_transaction'
@@ -106,6 +107,7 @@ module PactBroker
106
107
  # NOTE THAT NONE OF THIS IS PROTECTED BY AUTH - is that ok?
107
108
  @app_builder.use Rack::Protection, except: [:path_traversal, :remote_token, :session_hijacking, :http_origin]
108
109
  @app_builder.use Rack::PactBroker::InvalidUriProtection
110
+ @app_builder.use Rack::PactBroker::StoreBaseURL
109
111
  @app_builder.use Rack::PactBroker::AddPactBrokerVersionHeader
110
112
  @app_builder.use Rack::Static, :urls => ["/stylesheets", "/css", "/fonts", "/js", "/javascripts", "/images"], :root => PactBroker.project_root.join("public")
111
113
  @app_builder.use Rack::Static, :urls => ["/favicon.ico"], :root => PactBroker.project_root.join("public/images"), header_rules: [[:all, {'Content-Type' => 'image/x-icon'}]]
@@ -123,6 +123,10 @@ module PactBroker
123
123
  self.enable_public_badge_access = enable_badge_resources
124
124
  end
125
125
 
126
+ def base_url
127
+ ENV['PACT_BROKER_BASE_URL']
128
+ end
129
+
126
130
  def save_to_database
127
131
  # Can't require a Sequel::Model class before the connection has been set
128
132
  require 'pact_broker/config/save'
@@ -31,9 +31,9 @@ module PactBroker
31
31
  request && request.description
32
32
  end
33
33
 
34
- def execute options
34
+ def execute pact, options
35
35
  logger.info "Executing #{self}"
36
- request.execute options
36
+ request.execute pact, options
37
37
  end
38
38
 
39
39
  def to_s
@@ -4,6 +4,7 @@ require 'pact_broker/logging'
4
4
  require 'pact_broker/messages'
5
5
  require 'net/http'
6
6
  require 'pact_broker/webhooks/redact_logs'
7
+ require 'pact_broker/api/pact_broker_urls'
7
8
 
8
9
  module PactBroker
9
10
 
@@ -47,11 +48,11 @@ module PactBroker
47
48
  password.nil? ? nil : "**********"
48
49
  end
49
50
 
50
- def execute options = {}
51
+ def execute pact, options = {}
51
52
  logs = StringIO.new
52
53
  execution_logger = Logger.new(logs)
53
54
  begin
54
- execute_and_build_result(options, logs, execution_logger)
55
+ execute_and_build_result(pact, options, logs, execution_logger)
55
56
  rescue StandardError => e
56
57
  handle_error_and_build_result(e, options, logs, execution_logger)
57
58
  end
@@ -59,9 +60,10 @@ module PactBroker
59
60
 
60
61
  private
61
62
 
62
- def execute_and_build_result options, logs, execution_logger
63
- req = build_request(execution_logger)
64
- response = do_request(req)
63
+ def execute_and_build_result pact, options, logs, execution_logger
64
+ uri = build_uri(pact)
65
+ req = build_request(uri, pact, execution_logger)
66
+ response = do_request(uri, req)
65
67
  log_response(response, execution_logger)
66
68
  result = WebhookExecutionResult.new(response, logs.string)
67
69
  log_completion_message(options, execution_logger, result.success?)
@@ -75,9 +77,9 @@ module PactBroker
75
77
  WebhookExecutionResult.new(nil, logs.string, e)
76
78
  end
77
79
 
78
- def build_request execution_logger
79
- req = http_request
80
- execution_logger.info "HTTP/1.1 #{method.upcase} #{url_with_credentials}"
80
+ def build_request uri, pact, execution_logger
81
+ req = http_request(uri)
82
+ execution_logger.info "HTTP/1.1 #{method.upcase} #{url_with_credentials(pact)}"
81
83
 
82
84
  headers.each_pair do | name, value |
83
85
  execution_logger.info Webhooks::RedactLogs.call("#{name}: #{value}")
@@ -88,9 +90,9 @@ module PactBroker
88
90
 
89
91
  unless body.nil?
90
92
  if String === body
91
- req.body = body
93
+ req.body = gsub_body(pact, body)
92
94
  else
93
- req.body = body.to_json
95
+ req.body = gsub_body(pact, body.to_json)
94
96
  end
95
97
  end
96
98
 
@@ -98,7 +100,7 @@ module PactBroker
98
100
  req
99
101
  end
100
102
 
101
- def do_request req
103
+ def do_request uri, req
102
104
  logger.info "Making webhook #{uuid} request #{to_s}"
103
105
  Net::HTTP.start(uri.hostname, uri.port,
104
106
  :use_ssl => uri.scheme == 'https') do |http|
@@ -126,19 +128,31 @@ module PactBroker
126
128
  "#{method.upcase} #{url}, username=#{username}, password=#{display_password}, headers=#{headers}, body=#{body}"
127
129
  end
128
130
 
129
- def http_request
130
- Net::HTTP.const_get(method.capitalize).new(url)
131
+ def http_request(uri)
132
+ Net::HTTP.const_get(method.capitalize).new(uri)
131
133
  end
132
134
 
133
- def uri
134
- URI(url)
135
+ def build_uri pact
136
+ URI(gsub_url(pact, url))
135
137
  end
136
138
 
137
- def url_with_credentials
138
- u = URI(url)
139
+ def url_with_credentials pact
140
+ u = build_uri(pact)
139
141
  u.userinfo = "#{username}:#{display_password}" if username
140
142
  u
141
143
  end
144
+
145
+ def gsub_body pact, body
146
+ base_url = PactBroker.configuration.base_url
147
+ body.gsub('${pactbroker.pactUrl}', PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact))
148
+ end
149
+
150
+ def gsub_url pact, url
151
+ base_url = PactBroker.configuration.base_url
152
+ pact_url = PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact)
153
+ escaped_pact_url = CGI::escape(pact_url)
154
+ url.gsub('${pactbroker.pactUrl}', escaped_pact_url)
155
+ end
142
156
  end
143
157
  end
144
158
  end
@@ -31,6 +31,12 @@ module PactBroker
31
31
  if params.key?('limit')
32
32
  options[:limit] = params['limit']
33
33
  end
34
+ if params.key?('latest')
35
+ options[:latest] = params['latest']
36
+ end
37
+ if params.key?('tag')
38
+ options[:tag] = params['tag']
39
+ end
34
40
  return selectors, options
35
41
  end
36
42
  end
@@ -18,8 +18,8 @@ module PactBroker
18
18
  def find selectors, options = {}
19
19
  # The group with the nil provider_version_numbers will be the results of the left outer join
20
20
  # that don't have verifications, so we need to include them all.
21
- lines = find_all(selectors, options)
22
- lines = apply_scope(options, selectors, lines)
21
+ lines = query_matrix(resolve_selectors(selectors, options), options)
22
+ lines = apply_latestby(options, selectors, lines)
23
23
 
24
24
  if options.key?(:success)
25
25
  lines = lines.select{ |l| options[:success].include?(l.success) }
@@ -28,11 +28,7 @@ module PactBroker
28
28
  lines.sort.collect(&:values)
29
29
  end
30
30
 
31
- def all_versions_specified? selectors
32
- selectors.all?{ |s| s[:pacticipant_version_number] }
33
- end
34
-
35
- def apply_scope options, selectors, lines
31
+ def apply_latestby options, selectors, lines
36
32
  return lines unless options[:latestby] == 'cvp' || options[:latestby] == 'cp'
37
33
 
38
34
  group_by_columns = case options[:latestby]
@@ -48,46 +44,41 @@ module PactBroker
48
44
 
49
45
  def find_for_consumer_and_provider pacticipant_1_name, pacticipant_2_name
50
46
  selectors = [{ pacticipant_name: pacticipant_1_name }, { pacticipant_name: pacticipant_2_name }]
51
- find_all(selectors, {latestby: 'cvpv'}).sort.collect(&:values)
47
+ options = { latestby: 'cvpv' }
48
+ query_matrix(resolve_selectors(selectors, options), options).sort.collect(&:values)
52
49
  end
53
50
 
54
51
  def find_compatible_pacticipant_versions selectors
55
52
  find(selectors, latestby: 'cvpv').select{|line| line[:success] }
56
53
  end
57
54
 
58
- ##
59
- # If the version is nil, it means all versions for that pacticipant are to be included
60
- #
61
- def find_all selectors, options
62
- selectors = look_up_versions_for_tags(selectors)
63
- query = base_table(options).select_all
64
-
65
- if selectors.size == 1
66
- query = where_consumer_or_provider_is(selectors.first, query)
67
- else
68
- query = where_consumer_and_provider_in(selectors, query)
69
- end
70
-
55
+ def query_matrix selectors, options
56
+ query = view_for(options).select_all.matching_selectors(selectors)
71
57
  query = query.limit(options[:limit]) if options[:limit]
72
- query.order(
73
- Sequel.asc(:consumer_name),
74
- Sequel.desc(:consumer_version_order),
75
- Sequel.desc(:pact_revision_number),
76
- Sequel.asc(:provider_name),
77
- Sequel.desc(:provider_version_order),
78
- Sequel.desc(:verification_id)).all
58
+ query.order_by_names_ascending_most_recent_first.all
79
59
  end
80
60
 
81
- def base_table(options)
82
- return Row unless options[:latestby]
83
- return LatestRow
61
+ def view_for(options)
62
+ options[:latestby] ? LatestRow : Row
84
63
  end
85
64
 
86
- def look_up_versions_for_tags(selectors)
65
+ def resolve_selectors(selectors, options)
66
+ selectors = look_up_versions_for_latest_and_tag(selectors, options)
67
+
68
+ if options[:latest]
69
+ apply_latest_and_tag_to_inferred_selectors(selectors, options)
70
+ else
71
+ selectors
72
+ end
73
+ end
74
+
75
+ # Find the version number for selectors with the latest (tagged) version specified
76
+ def look_up_versions_for_latest_and_tag(selectors, options)
87
77
  selectors.collect do | selector |
88
78
  # resource validation currently stops tag being specified without latest=true
89
79
  if selector[:tag] && selector[:latest]
90
80
  version = version_repository.find_by_pacticpant_name_and_latest_tag(selector[:pacticipant_name], selector[:tag])
81
+ raise "Could not find version with tag #{selector[:tag].inspect} for #{selector[:pacticipant_name]}" unless version
91
82
  # validation in resource should ensure we always have a version
92
83
  {
93
84
  pacticipant_name: selector[:pacticipant_name],
@@ -105,28 +96,63 @@ module PactBroker
105
96
  end
106
97
  end
107
98
 
108
- def where_consumer_and_provider_in selectors, query
109
- query.where{
110
- Sequel.&(
111
- Sequel.|(
112
- *selectors.collect{ |s| s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]) }
113
- ),
114
- Sequel.|(
115
- *(selectors.collect{ |s| s[:pacticipant_version_number] ? Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: s[:pacticipant_version_number]) : Sequel.&(provider_name: s[:pacticipant_name]) } +
116
- selectors.collect{ |s| Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: nil) })
117
- )
118
- )
119
- }
99
+ # eg. when checking to see if Foo version 2 can be deployed to prod,
100
+ # need to look up all the 'partner' pacticipants, and determine their latest prod versions
101
+ def apply_latest_and_tag_to_inferred_selectors(selectors, options)
102
+ all_pacticipant_names = all_pacticipant_names_in_specified_matrix(selectors, options)
103
+ specified_names = selectors.collect{ |s| s[:pacticipant_name] }
104
+ inferred_names = all_pacticipant_names - specified_names
105
+
106
+ inferred_selectors = inferred_names.collect do | pacticipant_name |
107
+ {
108
+ pacticipant_name: pacticipant_name,
109
+ latest: options[:latest]
110
+ }.tap { |it| it[:tag] = options[:tag] if options[:tag] }
111
+ end
112
+
113
+ selectors + look_up_versions_for_latest_and_tag(inferred_selectors, options)
120
114
  end
121
115
 
122
- def where_consumer_or_provider_is s, query
123
- query.where{
124
- Sequel.|(
125
- s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]),
126
- s[:pacticipant_version_number] ? Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: s[:pacticipant_version_number]) : Sequel.&(provider_name: s[:pacticipant_name])
127
- )
128
- }
116
+ def all_pacticipant_names_in_specified_matrix(selectors, options)
117
+ query = view_for(options).select(:consumer_name, :provider_name)
118
+ query = query.matching_selectors(selectors)
119
+ query
120
+ .all
121
+ .collect{ | row | [row.consumer_name, row.provider_name] }
122
+ .flatten
123
+ .uniq
129
124
  end
125
+
126
+ # def where_row_matches_selectors selectors, query
127
+ # if selectors.size == 1
128
+ # where_consumer_or_provider_is(selectors.first, query)
129
+ # else
130
+ # where_consumer_and_provider_in(selectors, query)
131
+ # end
132
+ # end
133
+
134
+ # def where_consumer_and_provider_in selectors, query
135
+ # query.where{
136
+ # Sequel.&(
137
+ # Sequel.|(
138
+ # *selectors.collect{ |s| s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]) }
139
+ # ),
140
+ # Sequel.|(
141
+ # *(selectors.collect{ |s| s[:pacticipant_version_number] ? Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: s[:pacticipant_version_number]) : Sequel.&(provider_name: s[:pacticipant_name]) } +
142
+ # selectors.collect{ |s| Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: nil) })
143
+ # )
144
+ # )
145
+ # }
146
+ # end
147
+
148
+ # def where_consumer_or_provider_is s, query
149
+ # query.where{
150
+ # Sequel.|(
151
+ # s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]),
152
+ # s[:pacticipant_version_number] ? Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: s[:pacticipant_version_number]) : Sequel.&(provider_name: s[:pacticipant_name])
153
+ # )
154
+ # }
155
+ # end
130
156
  end
131
157
  end
132
158
  end
@@ -6,6 +6,47 @@ module PactBroker
6
6
 
7
7
  dataset_module do
8
8
  include PactBroker::Repositories::Helpers
9
+
10
+ def matching_selectors selectors
11
+ if selectors.size == 1
12
+ where_consumer_or_provider_is(selectors.first)
13
+ else
14
+ where_consumer_and_provider_in(selectors)
15
+ end
16
+ end
17
+
18
+ def where_consumer_and_provider_in selectors
19
+ where{
20
+ Sequel.&(
21
+ Sequel.|(
22
+ *selectors.collect{ |s| s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]) }
23
+ ),
24
+ Sequel.|(
25
+ *(selectors.collect{ |s| s[:pacticipant_version_number] ? Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: s[:pacticipant_version_number]) : Sequel.&(provider_name: s[:pacticipant_name]) } +
26
+ selectors.collect{ |s| Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: nil) })
27
+ )
28
+ )
29
+ }
30
+ end
31
+
32
+ def where_consumer_or_provider_is s
33
+ where{
34
+ Sequel.|(
35
+ s[:pacticipant_version_number] ? Sequel.&(consumer_name: s[:pacticipant_name], consumer_version_number: s[:pacticipant_version_number]) : Sequel.&(consumer_name: s[:pacticipant_name]),
36
+ s[:pacticipant_version_number] ? Sequel.&(provider_name: s[:pacticipant_name], provider_version_number: s[:pacticipant_version_number]) : Sequel.&(provider_name: s[:pacticipant_name])
37
+ )
38
+ }
39
+ end
40
+
41
+ def order_by_names_ascending_most_recent_first
42
+ order(
43
+ Sequel.asc(:consumer_name),
44
+ Sequel.desc(:consumer_version_order),
45
+ Sequel.desc(:pact_revision_number),
46
+ Sequel.asc(:provider_name),
47
+ Sequel.desc(:provider_version_order),
48
+ Sequel.desc(:verification_id))
49
+ end
9
50
  end
10
51
 
11
52
  def summary
@@ -14,7 +55,6 @@ module PactBroker
14
55
 
15
56
  # Add logic for ignoring case
16
57
  def <=> other
17
-
18
58
  comparisons = [
19
59
  compare_name_asc(consumer_name, other.consumer_name),
20
60
  compare_number_desc(consumer_version_order, other.consumer_version_order),
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = '2.8.0.beta.5'
2
+ VERSION = '2.9.0.beta.5'
3
3
  end
@@ -46,7 +46,7 @@ module PactBroker
46
46
  end
47
47
 
48
48
  def execute options
49
- webhook.to_domain.execute options
49
+ webhook.to_domain.execute pact_publication.to_domain, options
50
50
  end
51
51
 
52
52
  def consumer_name
@@ -0,0 +1,14 @@
1
+ module Rack
2
+ module PactBroker
3
+ class StoreBaseURL
4
+ def initialize app
5
+ @app = app
6
+ end
7
+
8
+ def call(env)
9
+ ENV['PACT_BROKER_BASE_URL'] ||= ::Rack::Request.new(env).base_url
10
+ @app.call(env)
11
+ end
12
+ end
13
+ end
14
+ end
data/script/seed.rb CHANGED
@@ -53,7 +53,7 @@ TestDataBuilder.new
53
53
  .create_label("microservice")
54
54
  .create_provider("Bar")
55
55
  .create_label("microservice")
56
- .create_webhook(method: 'GET', url: 'http://localhost:9393/')
56
+ .create_webhook(method: 'GET', url: 'http://localhost:9393?url=${pactbroker.pactUrl}', body: '${pactbroker.pactUrl}')
57
57
  .create_consumer_version("1.2.100")
58
58
  .publish_pact
59
59
  .create_verification(provider_version: "1.4.234", success: true, execution_date: DateTime.now - 15)
@@ -1,6 +1,10 @@
1
+ require 'rack/utils'
2
+
1
3
  count = 0
2
4
  run -> (env) {
3
5
  count += 1
4
6
  status = (count % 3 == 0) ? 200 : 500
5
- puts "Received request"; [status, {}, ["Hello. This might be an error.\n"]]
7
+ puts Rack::Utils.parse_nested_query(env['QUERY_STRING'])
8
+ puts env['rack.input'].read
9
+ [status, {}, ["Hello. This might be an error.\n"]]
6
10
  }
@@ -7,8 +7,13 @@ describe "Execute a webhook" do
7
7
  let(:td) { TestDataBuilder.new }
8
8
 
9
9
  before do
10
- td.create_pact_with_hierarchy("Some Consumer", "1", "Some Provider")
11
- .create_webhook(method: 'POST')
10
+ ENV['PACT_BROKER_BASE_URL'] = 'http://example.org'
11
+ td.create_pact_with_hierarchy("Foo", "1", "Bar")
12
+ .create_webhook(method: 'POST', body: '${pactbroker.pactUrl}')
13
+ end
14
+
15
+ after do
16
+ ENV.delete('PACT_BROKER_BASE_URL')
12
17
  end
13
18
 
14
19
  let(:path) { "/webhooks/#{td.webhook.uuid}/execute" }
@@ -18,7 +23,7 @@ describe "Execute a webhook" do
18
23
 
19
24
  context "when the execution is successful" do
20
25
  let!(:request) do
21
- stub_request(:post, /http/).to_return(:status => 200)
26
+ stub_request(:post, /http/).with(body: 'http://example.org/pacts/provider/Bar/consumer/Foo/version/1').to_return(:status => 200)
22
27
  end
23
28
 
24
29
  it "performs the HTTP request" do
@@ -7,6 +7,10 @@ module PactBroker
7
7
  module Domain
8
8
 
9
9
  describe WebhookRequest do
10
+ before do
11
+ allow(PactBroker::Api::PactBrokerUrls).to receive(:pact_url).and_return('http://example.org/pact-url')
12
+ allow(PactBroker.configuration).to receive(:base_url).and_return('http://example.org')
13
+ end
10
14
 
11
15
  let(:username) { nil }
12
16
  let(:password) { nil }
@@ -15,6 +19,7 @@ module PactBroker
15
19
  let(:logs) { StringIO.new }
16
20
  let(:execution_logger) { Logger.new(logs) }
17
21
  let(:options) { {failure_log_message: 'oops'}}
22
+ let(:pact) { instance_double('PactBroker::Domain::Pact') }
18
23
 
19
24
  subject do
20
25
  WebhookRequest.new(
@@ -26,7 +31,8 @@ module PactBroker
26
31
  body: body)
27
32
  end
28
33
 
29
- let(:logs) { subject.execute(options).logs }
34
+ let(:logs) { subject.execute(pact, options).logs }
35
+
30
36
 
31
37
  describe "description" do
32
38
  it "returns a brief description of the HTTP request" do
@@ -56,15 +62,59 @@ module PactBroker
56
62
  to_return(:status => 200, :body => "respbod", :headers => {'Content-Type' => 'text/foo, blah'})
57
63
  end
58
64
 
65
+ describe "when the String body contains a ${pactbroker.pactUrl} parameter" do
66
+ let!(:http_request) do
67
+ stub_request(:post, "http://example.org/hook").
68
+ with(:headers => {'Content-Type'=>'text/plain'}, :body => "<xml><url>http://example.org/pact-url</url></xml>").
69
+ to_return(:status => 200)
70
+ end
71
+
72
+ let(:body) { "<xml><url>${pactbroker.pactUrl}</url></xml>" }
73
+
74
+ it "replaces the token with the live value" do
75
+ subject.execute(pact, options)
76
+ expect(http_request).to have_been_made
77
+ end
78
+ end
79
+
80
+ describe "when the JSON body contains a ${pactbroker.pactUrl} parameter" do
81
+ let!(:http_request) do
82
+ stub_request(:post, "http://example.org/hook").
83
+ with(:headers => {'Content-Type'=>'text/plain'}, :body => '{"url":"http://example.org/pact-url"}').
84
+ to_return(:status => 200)
85
+ end
86
+
87
+ let(:body) { { url: '${pactbroker.pactUrl}' } }
88
+
89
+ it "replaces the token with the live value" do
90
+ subject.execute(pact, options)
91
+ expect(http_request).to have_been_made
92
+ end
93
+ end
94
+
95
+ describe "when the URL contains a ${pactbroker.pactUrl} parameter" do
96
+ let!(:http_request) do
97
+ stub_request(:post, "http://example.org/hook?url=http%3A%2F%2Fexample.org%2Fpact-url").
98
+ to_return(:status => 200)
99
+ end
100
+
101
+ let(:url) { 'http://example.org/hook?url=${pactbroker.pactUrl}' }
102
+
103
+ it "replaces the token with the live value" do
104
+ subject.execute(pact, options)
105
+ expect(http_request).to have_been_made
106
+ end
107
+ end
108
+
59
109
  it "executes the configured request" do
60
- subject.execute(options)
110
+ subject.execute(pact, options)
61
111
  expect(http_request).to have_been_made
62
112
  end
63
113
 
64
114
  it "logs the request" do
65
115
  allow(PactBroker.logger).to receive(:info)
66
116
  expect(PactBroker.logger).to receive(:info).with(/POST.*example.*text.*body/)
67
- subject.execute(options)
117
+ subject.execute(pact, options)
68
118
  end
69
119
 
70
120
  it "logs the response" do
@@ -72,7 +122,7 @@ module PactBroker
72
122
  allow(PactBroker.logger).to receive(:debug)
73
123
  expect(PactBroker.logger).to receive(:info).with(/response.*200/)
74
124
  expect(PactBroker.logger).to receive(:debug).with(/respbod/)
75
- subject.execute(options)
125
+ subject.execute(pact, options)
76
126
  end
77
127
 
78
128
  describe "execution logs" do
@@ -144,7 +194,7 @@ module PactBroker
144
194
  end
145
195
 
146
196
  it "uses the credentials" do
147
- subject.execute(options)
197
+ subject.execute(pact, options)
148
198
  expect(http_request_with_basic_auth).to have_been_made
149
199
  end
150
200
  end
@@ -160,7 +210,7 @@ module PactBroker
160
210
  end
161
211
 
162
212
  it "uses SSL" do
163
- subject.execute(options)
213
+ subject.execute(pact, options)
164
214
  expect(https_request).to have_been_made
165
215
  end
166
216
  end
@@ -175,7 +225,7 @@ module PactBroker
175
225
  end
176
226
 
177
227
  it "converts the body to JSON before submitting the request" do
178
- subject.execute(options)
228
+ subject.execute(pact, options)
179
229
  expect(http_request).to have_been_made
180
230
  end
181
231
  end
@@ -190,18 +240,18 @@ module PactBroker
190
240
  end
191
241
 
192
242
  it "executes the request without a body" do
193
- subject.execute(options)
243
+ subject.execute(pact, options)
194
244
  expect(http_request).to have_been_made
195
245
  end
196
246
  end
197
247
 
198
248
  context "when the request is successful" do
199
249
  it "returns a WebhookExecutionResult with success=true" do
200
- expect(subject.execute(options).success?).to be true
250
+ expect(subject.execute(pact, options).success?).to be true
201
251
  end
202
252
 
203
253
  it "sets the response on the result" do
204
- expect(subject.execute(options).response).to be_instance_of(Net::HTTPOK)
254
+ expect(subject.execute(pact, options).response).to be_instance_of(Net::HTTPOK)
205
255
  end
206
256
  end
207
257
 
@@ -214,11 +264,11 @@ module PactBroker
214
264
  end
215
265
 
216
266
  it "returns a WebhookExecutionResult with success=false" do
217
- expect(subject.execute(options).success?).to be false
267
+ expect(subject.execute(pact, options).success?).to be false
218
268
  end
219
269
 
220
270
  it "sets the response on the result" do
221
- expect(subject.execute(options).response).to be_instance_of(Net::HTTPInternalServerError)
271
+ expect(subject.execute(pact, options).response).to be_instance_of(Net::HTTPInternalServerError)
222
272
  end
223
273
  end
224
274
 
@@ -233,15 +283,15 @@ module PactBroker
233
283
  it "logs the error" do
234
284
  allow(PactBroker.logger).to receive(:error)
235
285
  expect(PactBroker.logger).to receive(:error).with(/Error.*WebhookTestError.*blah/)
236
- subject.execute(options)
286
+ subject.execute(pact, options)
237
287
  end
238
288
 
239
289
  it "returns a WebhookExecutionResult with success=false" do
240
- expect(subject.execute(options).success?).to be false
290
+ expect(subject.execute(pact, options).success?).to be false
241
291
  end
242
292
 
243
293
  it "returns a WebhookExecutionResult with an error" do
244
- expect(subject.execute(options).error).to be_instance_of WebhookTestError
294
+ expect(subject.execute(pact, options).error).to be_instance_of WebhookTestError
245
295
  end
246
296
 
247
297
  it "logs the failure_log_message" do
@@ -11,6 +11,8 @@ module PactBroker
11
11
  let(:provider) { Pacticipant.new(name: 'Provider')}
12
12
  let(:request) { instance_double(PactBroker::Domain::WebhookRequest, execute: nil)}
13
13
  let(:options) { double('options') }
14
+ let(:pact) { double('pact') }
15
+
14
16
  subject { Webhook.new(request: request, consumer: consumer, provider: provider,) }
15
17
 
16
18
  describe "description" do
@@ -22,14 +24,14 @@ module PactBroker
22
24
  describe "execute" do
23
25
 
24
26
  it "executes the request" do
25
- expect(request).to receive(:execute).with(options)
26
- subject.execute options
27
+ expect(request).to receive(:execute).with(pact, options)
28
+ subject.execute pact, options
27
29
  end
28
30
 
29
31
  it "logs before and after" do
30
32
  allow(PactBroker.logger).to receive(:info)
31
33
  expect(PactBroker.logger).to receive(:info).with(/Executing/)
32
- subject.execute options
34
+ subject.execute pact, options
33
35
  end
34
36
  end
35
37
  end
@@ -555,6 +555,139 @@ module PactBroker
555
555
  end
556
556
  end
557
557
 
558
+ describe "find with global latest and tag specified" do
559
+ subject { shorten_rows(Repository.new.find(selectors, options)) }
560
+
561
+ context "with one consumer/version and latest tag specified for all the other pacticipants" do
562
+ before do
563
+ td.create_pact_with_hierarchy("A", "1", "B")
564
+ .create_verification(provider_version: "1")
565
+ .create_verification(provider_version: "2", number: 2)
566
+ .use_provider_version("1")
567
+ .create_provider_version_tag("prod")
568
+ .create_provider("C")
569
+ .create_pact
570
+ .create_verification(provider_version: "3")
571
+ .use_provider_version("3")
572
+ .create_provider_version_tag("prod")
573
+ .create_verification(provider_version: "4", number: 2)
574
+ end
575
+
576
+ let(:selectors) { build_selectors('A'=> '1') }
577
+ let(:options) { { tag: 'prod', latest: true } }
578
+
579
+ it "finds the matrix for the latest tagged versions of each of the other other pacticipants" do
580
+ expect(subject).to include "A1 B1 n1"
581
+ expect(subject).to include "A1 C3 n1"
582
+ expect(subject.size).to eq 2
583
+ end
584
+ end
585
+
586
+ context "with one consumer/version and latest specified for all the other pacticipants" do
587
+ before do
588
+ td.create_pact_with_hierarchy("A", "1", "B")
589
+ .create_verification(provider_version: "1")
590
+ .create_verification(provider_version: "2", number: 2)
591
+ .use_provider_version("1")
592
+ .create_provider("C")
593
+ .create_pact
594
+ .create_verification(provider_version: "3")
595
+ .create_verification(provider_version: "4", number: 2)
596
+ end
597
+
598
+ let(:selectors) { build_selectors('A'=> '1') }
599
+ let(:options) { { latest: true } }
600
+
601
+ it "finds the matrix for the latest tagged versions of each of the other other pacticipants" do
602
+ expect(subject).to include "A1 B2 n2"
603
+ expect(subject).to include "A1 C4 n2"
604
+ expect(subject.size).to eq 2
605
+ end
606
+ end
607
+
608
+ context "with one pacticipant without a version and latest tag specified for all the other pacticipants" do
609
+ before do
610
+ td.create_pact_with_hierarchy("A", "1", "B")
611
+ .create_verification(provider_version: "1")
612
+ .create_verification(provider_version: "2", number: 2)
613
+ .use_provider_version("1")
614
+ .create_provider_version_tag("prod")
615
+ .create_provider("C")
616
+ .create_pact
617
+ .create_verification(provider_version: "3")
618
+ .use_provider_version("3")
619
+ .create_provider_version_tag("prod")
620
+ .create_verification(provider_version: "4", number: 2)
621
+ .create_consumer_version("2")
622
+ .create_pact
623
+ end
624
+
625
+ let(:selectors) { build_selectors('A'=> nil) }
626
+ let(:options) { { tag: 'prod', latest: true } }
627
+
628
+ it "finds the matrix for the latest tagged versions of each of the other other pacticipants" do
629
+ expect(subject).to include "A1 B1 n1"
630
+ expect(subject).to include "A1 C3 n1"
631
+ expect(subject).to include "A2 C? n?"
632
+ expect(subject.size).to eq 3
633
+ end
634
+ end
635
+
636
+ context "with one pacticipant/version that is both a consumer and provider and latest tag specified for all the other pacticipants" do
637
+ before do
638
+ td.create_pact_with_hierarchy("A", "1", "B")
639
+ .create_consumer_version_tag("prod")
640
+ .create_verification(provider_version: "1")
641
+ .use_provider_version("1")
642
+ .use_consumer("B")
643
+ .use_consumer_version("1")
644
+ .create_provider("C")
645
+ .create_pact
646
+ .create_verification(provider_version: "3")
647
+ .use_provider_version("3")
648
+ .create_provider_version_tag("prod")
649
+ .create_verification(provider_version: "4", number: 2)
650
+ end
651
+
652
+ let(:selectors) { build_selectors('B'=> '1') }
653
+ let(:options) { { tag: 'prod', latest: true } }
654
+
655
+ it "finds the matrix for the latest tagged versions of each of the other other pacticipants" do
656
+ expect(subject).to include "A1 B1 n1"
657
+ expect(subject).to include "B1 C3 n1"
658
+ expect(subject.size).to eq 2
659
+ end
660
+ end
661
+
662
+ context "with one pacticipant/latest tag and latest tag specified for all the other pacticipants" do
663
+ before do
664
+ td.create_pact_with_hierarchy("A", "1", "B")
665
+ .create_consumer_version_tag("dev")
666
+ .create_verification(provider_version: "1")
667
+ .use_provider_version("1")
668
+ .create_provider_version_tag("prod")
669
+ .create_provider("C")
670
+ .create_pact
671
+ .create_verification(provider_version: "3")
672
+ .use_provider_version("3")
673
+ .create_provider_version_tag("prod")
674
+ .create_verification(provider_version: "4", number: 2)
675
+ end
676
+
677
+ let(:selectors) { [{ pacticipant_name: 'A', latest: true, tag: 'dev' } ] }
678
+ let(:options) { { tag: 'prod', latest: true } }
679
+
680
+ it "finds the matrix for the latest tagged versions of each of the other other pacticipants" do
681
+ expect(subject).to include "A1 B1 n1"
682
+ expect(subject).to include "A1 C3 n1"
683
+ expect(subject).to_not include "A1 C4 n2"
684
+ expect(subject.size).to eq 2
685
+ end
686
+ end
687
+
688
+
689
+ end
690
+
558
691
  describe "#find_for_consumer_and_provider" do
559
692
  before do
560
693
  TestDataBuilder.new
@@ -82,6 +82,17 @@ Pact.provider_states_for "Pact Broker Client" do
82
82
  end
83
83
  end
84
84
 
85
+ provider_state "the pact for Foo version 1.2.3 has been successfully verified by Bar version 4.5.6 (tagged prod) and version 5.6.7" do
86
+ set_up do
87
+ TestDataBuilder.new
88
+ .create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
89
+ .create_verification(provider_version: "4.5.6")
90
+ .use_provider_version("4.5.6")
91
+ .create_provider_version_tag("prod")
92
+ .create_verification(provider_version: "5.6.7", number: 2)
93
+ end
94
+ end
95
+
85
96
  provider_state "the 'Pricing Service' does not exist in the pact-broker" do
86
97
  no_op
87
98
  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.8.0.beta.5
4
+ version: 2.9.0.beta.5
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: 2017-11-06 00:00:00.000000000 Z
13
+ date: 2017-11-09 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: httparty
@@ -774,6 +774,7 @@ files:
774
774
  - lib/rack/pact_broker/database_transaction.rb
775
775
  - lib/rack/pact_broker/invalid_uri_protection.rb
776
776
  - lib/rack/pact_broker/no_auth.rb
777
+ - lib/rack/pact_broker/store_base_url.rb
777
778
  - lib/rack/pact_broker/ui_authentication.rb
778
779
  - pact_broker.gemspec
779
780
  - pact_broker_client-pact_broker.json