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 +4 -4
- data/CHANGELOG.md +13 -0
- data/lib/pact_broker/app.rb +2 -0
- data/lib/pact_broker/configuration.rb +4 -0
- data/lib/pact_broker/domain/webhook.rb +2 -2
- data/lib/pact_broker/domain/webhook_request.rb +31 -17
- data/lib/pact_broker/matrix/parse_query.rb +6 -0
- data/lib/pact_broker/matrix/repository.rb +77 -51
- data/lib/pact_broker/matrix/row.rb +41 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -1
- data/lib/rack/pact_broker/store_base_url.rb +14 -0
- data/script/seed.rb +1 -1
- data/script/webhook-server.ru +5 -1
- data/spec/features/execute_webhook_spec.rb +8 -3
- data/spec/lib/pact_broker/domain/webhook_request_spec.rb +65 -15
- data/spec/lib/pact_broker/domain/webhook_spec.rb +5 -3
- data/spec/lib/pact_broker/matrix/repository_spec.rb +133 -0
- data/spec/service_consumers/provider_states_for_pact_broker_client.rb +11 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf490a74cabeccee8ad6973db3e32c96a0ff2f6b
|
4
|
+
data.tar.gz: a4983395d117314b3c7da784a7855a20d5483147
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/lib/pact_broker/app.rb
CHANGED
@@ -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'
|
@@ -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
|
-
|
64
|
-
|
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(
|
131
|
+
def http_request(uri)
|
132
|
+
Net::HTTP.const_get(method.capitalize).new(uri)
|
131
133
|
end
|
132
134
|
|
133
|
-
def
|
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 =
|
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 =
|
22
|
-
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
|
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
|
-
|
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
|
-
|
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.
|
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
|
82
|
-
|
83
|
-
return LatestRow
|
61
|
+
def view_for(options)
|
62
|
+
options[:latestby] ? LatestRow : Row
|
84
63
|
end
|
85
64
|
|
86
|
-
def
|
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
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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
|
123
|
-
query.
|
124
|
-
|
125
|
-
|
126
|
-
|
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),
|
data/lib/pact_broker/version.rb
CHANGED
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)
|
data/script/webhook-server.ru
CHANGED
@@ -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
|
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
|
-
|
11
|
-
|
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.
|
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-
|
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
|