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

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
  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