pact 1.28.0 → 1.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +408 -0
- data/lib/pact/cli/run_pact_verification.rb +26 -7
- data/lib/pact/cli/spec_criteria.rb +3 -0
- data/lib/pact/cli.rb +7 -1
- data/lib/pact/consumer/configuration/dsl.rb +0 -1
- data/lib/pact/consumer/configuration/mock_service.rb +9 -3
- data/lib/pact/consumer/consumer_contract_builder.rb +6 -2
- data/lib/pact/consumer/interaction_builder.rb +6 -0
- data/lib/pact/consumer/spec_hooks.rb +4 -4
- data/lib/pact/doc/sort_interactions.rb +2 -3
- data/lib/pact/hal/authorization_header_redactor.rb +32 -0
- data/lib/pact/hal/entity.rb +27 -5
- data/lib/pact/hal/http_client.rb +25 -7
- data/lib/pact/hal/link.rb +67 -20
- data/lib/pact/hal/non_json_entity.rb +28 -0
- data/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb +93 -0
- data/lib/pact/pact_broker/fetch_pacts.rb +20 -18
- data/lib/pact/pact_broker/notices.rb +34 -0
- data/lib/pact/pact_broker/pact_selection_description.rb +24 -0
- data/lib/pact/pact_broker.rb +25 -0
- data/lib/pact/provider/configuration/dsl.rb +6 -1
- data/lib/pact/provider/configuration/message_provider_dsl.rb +59 -0
- data/lib/pact/provider/configuration/pact_verification_from_broker.rb +29 -4
- data/lib/pact/provider/configuration/service_provider_dsl.rb +1 -1
- data/lib/pact/provider/help/content.rb +4 -4
- data/lib/pact/provider/help/pact_diff.rb +10 -34
- data/lib/pact/provider/help/write.rb +6 -7
- data/lib/pact/provider/pact_helper_locator.rb +13 -11
- data/lib/pact/provider/pact_source.rb +10 -1
- data/lib/pact/provider/pact_spec_runner.rb +26 -13
- data/lib/pact/provider/pact_uri.rb +8 -6
- data/lib/pact/provider/request.rb +1 -1
- data/lib/pact/provider/rspec/formatter_rspec_3.rb +39 -8
- data/lib/pact/provider/rspec/json_formatter.rb +100 -0
- data/lib/pact/provider/rspec/pact_broker_formatter.rb +7 -17
- data/lib/pact/provider/rspec.rb +24 -11
- data/lib/pact/provider/state/provider_state.rb +6 -7
- data/lib/pact/provider/state/provider_state_manager.rb +10 -10
- data/lib/pact/provider/state/set_up.rb +1 -1
- data/lib/pact/provider/state/tear_down.rb +1 -1
- data/lib/pact/provider/test_methods.rb +22 -7
- data/lib/pact/provider/verification_results/create.rb +6 -0
- data/lib/pact/provider/verification_results/publish.rb +5 -8
- data/lib/pact/provider/verification_results/publish_all.rb +14 -1
- data/lib/pact/provider/verification_results/verification_result.rb +2 -5
- data/lib/pact/provider/world.rb +1 -1
- data/lib/pact/retry.rb +2 -0
- data/lib/pact/tasks/task_helper.rb +10 -4
- data/lib/pact/tasks/verification_task.rb +3 -1
- data/lib/pact/version.rb +1 -1
- data/pact.gemspec +19 -15
- metadata +75 -80
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'delegate'
|
|
2
|
+
|
|
3
|
+
module Pact
|
|
4
|
+
module Hal
|
|
5
|
+
class AuthorizationHeaderRedactor < SimpleDelegator
|
|
6
|
+
def puts(*args)
|
|
7
|
+
__getobj__().puts(*redact_args(args))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def print(*args)
|
|
11
|
+
__getobj__().puts(*redact_args(args))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def <<(*args)
|
|
15
|
+
__getobj__().send(:<<, *redact_args(args))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
attr_reader :redactions
|
|
21
|
+
|
|
22
|
+
def redact_args(args)
|
|
23
|
+
args.collect{ | s| redact(s) }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def redact(string)
|
|
27
|
+
return string unless string.is_a?(String)
|
|
28
|
+
string.gsub(/Authorization: .*\\r\\n/, "Authorization: [redacted]\\r\\n")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/lib/pact/hal/entity.rb
CHANGED
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
require 'uri'
|
|
2
2
|
require 'delegate'
|
|
3
3
|
require 'pact/hal/link'
|
|
4
|
+
require 'pact/errors'
|
|
4
5
|
|
|
5
6
|
module Pact
|
|
6
7
|
module Hal
|
|
8
|
+
class RelationNotFoundError < ::Pact::Error; end
|
|
9
|
+
|
|
10
|
+
class ErrorResponseReturned < ::Pact::Error; end
|
|
11
|
+
|
|
7
12
|
class Entity
|
|
8
|
-
|
|
13
|
+
|
|
14
|
+
def initialize(href, data, http_client, response = nil)
|
|
15
|
+
@href = href
|
|
9
16
|
@data = data
|
|
10
17
|
@links = (@data || {}).fetch("_links", {})
|
|
11
18
|
@client = http_client
|
|
@@ -32,14 +39,20 @@ module Pact
|
|
|
32
39
|
Link.new(@links[key].merge(method: http_method), @client).run(*args)
|
|
33
40
|
end
|
|
34
41
|
|
|
35
|
-
def _link(key)
|
|
42
|
+
def _link(key, fallback_key = nil)
|
|
36
43
|
if @links[key]
|
|
37
44
|
Link.new(@links[key], @client)
|
|
45
|
+
elsif fallback_key && @links[fallback_key]
|
|
46
|
+
Link.new(@links[fallback_key], @client)
|
|
38
47
|
else
|
|
39
48
|
nil
|
|
40
49
|
end
|
|
41
50
|
end
|
|
42
51
|
|
|
52
|
+
def _link!(key)
|
|
53
|
+
_link(key) or raise RelationNotFoundError.new("Could not find relation '#{key}' in resource at #{@href}")
|
|
54
|
+
end
|
|
55
|
+
|
|
43
56
|
def success?
|
|
44
57
|
true
|
|
45
58
|
end
|
|
@@ -48,8 +61,8 @@ module Pact
|
|
|
48
61
|
@response
|
|
49
62
|
end
|
|
50
63
|
|
|
51
|
-
def fetch(key)
|
|
52
|
-
@links[key]
|
|
64
|
+
def fetch(key, fallback_key = nil)
|
|
65
|
+
@links[key] || (fallback_key && @links[fallback_key])
|
|
53
66
|
end
|
|
54
67
|
|
|
55
68
|
def method_missing(method_name, *args, &block)
|
|
@@ -65,11 +78,16 @@ module Pact
|
|
|
65
78
|
def respond_to_missing?(method_name, include_private = false)
|
|
66
79
|
@data.key?(method_name) || @links.key?(method_name)
|
|
67
80
|
end
|
|
81
|
+
|
|
82
|
+
def assert_success!
|
|
83
|
+
self
|
|
84
|
+
end
|
|
68
85
|
end
|
|
69
86
|
|
|
70
87
|
class ErrorEntity < Entity
|
|
71
88
|
|
|
72
|
-
def initialize(data, http_client, response = nil)
|
|
89
|
+
def initialize(href, data, http_client, response = nil)
|
|
90
|
+
@href = href
|
|
73
91
|
@data = data
|
|
74
92
|
@links = {}
|
|
75
93
|
@client = http_client
|
|
@@ -79,6 +97,10 @@ module Pact
|
|
|
79
97
|
def success?
|
|
80
98
|
false
|
|
81
99
|
end
|
|
100
|
+
|
|
101
|
+
def assert_success!
|
|
102
|
+
raise ErrorResponseReturned.new("Error retrieving #{@href} status=#{response ? response.code: nil} #{response ? response.raw_body : ''}")
|
|
103
|
+
end
|
|
82
104
|
end
|
|
83
105
|
end
|
|
84
106
|
end
|
data/lib/pact/hal/http_client.rb
CHANGED
|
@@ -1,20 +1,26 @@
|
|
|
1
1
|
require 'pact/retry'
|
|
2
|
+
require 'pact/hal/authorization_header_redactor'
|
|
3
|
+
require 'net/http'
|
|
4
|
+
require 'rack'
|
|
2
5
|
|
|
3
6
|
module Pact
|
|
4
7
|
module Hal
|
|
5
8
|
class HttpClient
|
|
6
|
-
attr_accessor :username, :password, :verbose
|
|
9
|
+
attr_accessor :username, :password, :verbose, :token
|
|
7
10
|
|
|
8
11
|
def initialize options
|
|
9
12
|
@username = options[:username]
|
|
10
13
|
@password = options[:password]
|
|
11
14
|
@verbose = options[:verbose]
|
|
15
|
+
@token = options[:token]
|
|
12
16
|
end
|
|
13
17
|
|
|
14
18
|
def get href, params = {}, headers = {}
|
|
15
|
-
query = params.collect{ |(key, value)| "#{CGI::escape(key)}=#{CGI::escape(value)}" }.join("&")
|
|
16
19
|
uri = URI(href)
|
|
17
|
-
|
|
20
|
+
if params && params.any?
|
|
21
|
+
existing_params = Rack::Utils.parse_nested_query(uri.query)
|
|
22
|
+
uri.query = Rack::Utils.build_nested_query(existing_params.merge(params))
|
|
23
|
+
end
|
|
18
24
|
perform_request(create_request(uri, 'Get', nil, headers), uri)
|
|
19
25
|
end
|
|
20
26
|
|
|
@@ -30,22 +36,22 @@ module Pact
|
|
|
30
36
|
|
|
31
37
|
def create_request uri, http_method, body = nil, headers = {}
|
|
32
38
|
request = Net::HTTP.const_get(http_method).new(uri.request_uri)
|
|
33
|
-
request['Content-Type'] = "application/json" if ['Post', 'Put', 'Patch'].include?(http_method)
|
|
34
|
-
request['Accept'] = "application/hal+json"
|
|
35
39
|
headers.each do | key, value |
|
|
36
40
|
request[key] = value
|
|
37
41
|
end
|
|
38
|
-
|
|
39
42
|
request.body = body if body
|
|
40
43
|
request.basic_auth username, password if username
|
|
44
|
+
request['Authorization'] = "Bearer #{token}" if token
|
|
41
45
|
request
|
|
42
46
|
end
|
|
43
47
|
|
|
44
48
|
def perform_request request, uri
|
|
45
49
|
response = Retry.until_true do
|
|
46
50
|
http = Net::HTTP.new(uri.host, uri.port, :ENV)
|
|
47
|
-
http.set_debug_output(
|
|
51
|
+
http.set_debug_output(output_stream) if verbose
|
|
48
52
|
http.use_ssl = (uri.scheme == 'https')
|
|
53
|
+
http.ca_file = ENV['SSL_CERT_FILE'] if ENV['SSL_CERT_FILE'] && ENV['SSL_CERT_FILE'] != ''
|
|
54
|
+
http.ca_path = ENV['SSL_CERT_DIR'] if ENV['SSL_CERT_DIR'] && ENV['SSL_CERT_DIR'] != ''
|
|
49
55
|
http.start do |http|
|
|
50
56
|
http.request request
|
|
51
57
|
end
|
|
@@ -53,6 +59,10 @@ module Pact
|
|
|
53
59
|
Response.new(response)
|
|
54
60
|
end
|
|
55
61
|
|
|
62
|
+
def output_stream
|
|
63
|
+
AuthorizationHeaderRedactor.new(Pact.configuration.output_stream)
|
|
64
|
+
end
|
|
65
|
+
|
|
56
66
|
class Response < SimpleDelegator
|
|
57
67
|
def body
|
|
58
68
|
bod = raw_body
|
|
@@ -67,9 +77,17 @@ module Pact
|
|
|
67
77
|
__getobj__().body
|
|
68
78
|
end
|
|
69
79
|
|
|
80
|
+
def status
|
|
81
|
+
code.to_i
|
|
82
|
+
end
|
|
83
|
+
|
|
70
84
|
def success?
|
|
71
85
|
__getobj__().code.start_with?("2")
|
|
72
86
|
end
|
|
87
|
+
|
|
88
|
+
def json?
|
|
89
|
+
self['content-type'] && self['content-type'] =~ /json/
|
|
90
|
+
end
|
|
73
91
|
end
|
|
74
92
|
end
|
|
75
93
|
end
|
data/lib/pact/hal/link.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'erb'
|
|
2
2
|
require 'delegate'
|
|
3
3
|
|
|
4
4
|
module Pact
|
|
@@ -6,6 +6,15 @@ module Pact
|
|
|
6
6
|
class Link
|
|
7
7
|
attr_reader :request_method, :href
|
|
8
8
|
|
|
9
|
+
DEFAULT_GET_HEADERS = {
|
|
10
|
+
"Accept" => "application/hal+json"
|
|
11
|
+
}.freeze
|
|
12
|
+
|
|
13
|
+
DEFAULT_POST_HEADERS = {
|
|
14
|
+
"Accept" => "application/hal+json",
|
|
15
|
+
"Content-Type" => "application/json"
|
|
16
|
+
}.freeze
|
|
17
|
+
|
|
9
18
|
def initialize(attrs, http_client)
|
|
10
19
|
@attrs = attrs
|
|
11
20
|
@request_method = attrs.fetch(:method, :get).to_sym
|
|
@@ -14,51 +23,89 @@ module Pact
|
|
|
14
23
|
end
|
|
15
24
|
|
|
16
25
|
def run(payload = nil)
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
case request_method
|
|
27
|
+
when :get
|
|
28
|
+
get(payload)
|
|
29
|
+
when :put
|
|
30
|
+
put(payload)
|
|
31
|
+
when :post
|
|
32
|
+
post(payload)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def title_or_name
|
|
37
|
+
title || name
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def title
|
|
41
|
+
@attrs['title']
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def name
|
|
45
|
+
@attrs['name']
|
|
25
46
|
end
|
|
26
47
|
|
|
27
48
|
def get(payload = {}, headers = {})
|
|
28
|
-
wrap_response(@http_client.get(href, payload, headers))
|
|
49
|
+
wrap_response(href, @http_client.get(href, payload, DEFAULT_GET_HEADERS.merge(headers)))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def get!(*args)
|
|
53
|
+
get(*args).assert_success!
|
|
29
54
|
end
|
|
30
55
|
|
|
31
56
|
def put(payload = nil, headers = {})
|
|
32
|
-
wrap_response(@http_client.put(href, payload ?
|
|
57
|
+
wrap_response(href, @http_client.put(href, payload ? payload.to_json : nil, DEFAULT_POST_HEADERS.merge(headers)))
|
|
33
58
|
end
|
|
34
59
|
|
|
35
60
|
def post(payload = nil, headers = {})
|
|
36
|
-
wrap_response(@http_client.post(href, payload ?
|
|
61
|
+
wrap_response(href, @http_client.post(href, payload ? payload.to_json : nil, DEFAULT_POST_HEADERS.merge(headers)))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def post!(payload = nil, headers = {})
|
|
65
|
+
post(payload, headers).assert_success!
|
|
37
66
|
end
|
|
38
67
|
|
|
39
68
|
def expand(params)
|
|
40
69
|
expanded_url = expand_url(params, href)
|
|
41
70
|
new_attrs = @attrs.merge('href' => expanded_url)
|
|
42
|
-
Link.new(new_attrs,
|
|
71
|
+
Link.new(new_attrs, http_client)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def with_query(query)
|
|
75
|
+
if query && query.any?
|
|
76
|
+
uri = URI(href)
|
|
77
|
+
existing_query_params = Rack::Utils.parse_nested_query(uri.query)
|
|
78
|
+
uri.query = Rack::Utils.build_nested_query(existing_query_params.merge(query))
|
|
79
|
+
new_attrs = attrs.merge('href' => uri.to_s)
|
|
80
|
+
Link.new(new_attrs, http_client)
|
|
81
|
+
else
|
|
82
|
+
self
|
|
83
|
+
end
|
|
43
84
|
end
|
|
44
85
|
|
|
45
86
|
private
|
|
46
87
|
|
|
47
|
-
|
|
88
|
+
attr_reader :attrs, :http_client
|
|
89
|
+
|
|
90
|
+
def wrap_response(href, http_response)
|
|
48
91
|
require 'pact/hal/entity' # avoid circular reference
|
|
92
|
+
require 'pact/hal/non_json_entity'
|
|
93
|
+
|
|
49
94
|
if http_response.success?
|
|
50
|
-
|
|
95
|
+
if http_response.json?
|
|
96
|
+
Entity.new(href, http_response.body, @http_client, http_response)
|
|
97
|
+
else
|
|
98
|
+
NonJsonEntity.new(href, http_response.raw_body, @http_client, http_response)
|
|
99
|
+
end
|
|
51
100
|
else
|
|
52
|
-
ErrorEntity.new(http_response.raw_body, @http_client, http_response)
|
|
101
|
+
ErrorEntity.new(href, http_response.raw_body, @http_client, http_response)
|
|
53
102
|
end
|
|
54
103
|
end
|
|
55
104
|
|
|
56
105
|
def expand_url(params, url)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
new_url = new_url.gsub('{' + key.to_s + '}', URI.escape(value))
|
|
106
|
+
params.inject(url) do | url, (key, value) |
|
|
107
|
+
url.gsub('{' + key.to_s + '}', ERB::Util.url_encode(value))
|
|
60
108
|
end
|
|
61
|
-
new_url
|
|
62
109
|
end
|
|
63
110
|
end
|
|
64
111
|
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module Pact
|
|
2
|
+
module Hal
|
|
3
|
+
class NonJsonEntity
|
|
4
|
+
def initialize(href, body, http_client, response = nil)
|
|
5
|
+
@href = href
|
|
6
|
+
@body = body
|
|
7
|
+
@client = http_client
|
|
8
|
+
@response = response
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def success?
|
|
12
|
+
true
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def response
|
|
16
|
+
@response
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def body
|
|
20
|
+
@body
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def assert_success!
|
|
24
|
+
self
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
require 'pact/hal/entity'
|
|
2
|
+
require 'pact/hal/http_client'
|
|
3
|
+
require 'pact/provider/pact_uri'
|
|
4
|
+
require 'pact/errors'
|
|
5
|
+
require 'pact/pact_broker/fetch_pacts'
|
|
6
|
+
require 'pact/pact_broker/notices'
|
|
7
|
+
require 'pact/pact_broker/pact_selection_description'
|
|
8
|
+
|
|
9
|
+
module Pact
|
|
10
|
+
module PactBroker
|
|
11
|
+
class FetchPactURIsForVerification
|
|
12
|
+
include PactSelectionDescription
|
|
13
|
+
attr_reader :provider, :consumer_version_selectors, :provider_version_tags, :broker_base_url, :http_client_options, :http_client, :options
|
|
14
|
+
|
|
15
|
+
PACTS_FOR_VERIFICATION_RELATION = 'beta:provider-pacts-for-verification'.freeze
|
|
16
|
+
PACTS = 'pacts'.freeze
|
|
17
|
+
HREF = 'href'.freeze
|
|
18
|
+
LINKS = '_links'.freeze
|
|
19
|
+
SELF = 'self'.freeze
|
|
20
|
+
EMBEDDED = '_embedded'.freeze
|
|
21
|
+
|
|
22
|
+
def initialize(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options = {})
|
|
23
|
+
@provider = provider
|
|
24
|
+
@consumer_version_selectors = consumer_version_selectors || []
|
|
25
|
+
@provider_version_tags = [*provider_version_tags]
|
|
26
|
+
@http_client_options = http_client_options
|
|
27
|
+
@broker_base_url = broker_base_url
|
|
28
|
+
@http_client = Pact::Hal::HttpClient.new(http_client_options)
|
|
29
|
+
@options = options
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.call(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options = {})
|
|
33
|
+
new(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options).call
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def call
|
|
37
|
+
if index.can?(PACTS_FOR_VERIFICATION_RELATION)
|
|
38
|
+
log_message
|
|
39
|
+
pacts_for_verification
|
|
40
|
+
else
|
|
41
|
+
# Fall back to old method of fetching pacts
|
|
42
|
+
consumer_version_tags = consumer_version_selectors.collect{ | selector | selector[:tag] }
|
|
43
|
+
FetchPacts.call(provider, consumer_version_tags, broker_base_url, http_client_options)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def index
|
|
50
|
+
@index_entity ||= Pact::Hal::Link.new({ "href" => broker_base_url }, http_client).get.assert_success!
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def pacts_for_verification
|
|
54
|
+
pacts_for_verification_entity.response.body[EMBEDDED][PACTS].collect do | pact |
|
|
55
|
+
metadata = {
|
|
56
|
+
pending: pact["verificationProperties"]["pending"],
|
|
57
|
+
notices: extract_notices(pact),
|
|
58
|
+
short_description: pact["shortDescription"]
|
|
59
|
+
}
|
|
60
|
+
Pact::Provider::PactURI.new(pact[LINKS][SELF][HREF], http_client_options, metadata)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def pacts_for_verification_entity
|
|
65
|
+
index
|
|
66
|
+
._link(PACTS_FOR_VERIFICATION_RELATION)
|
|
67
|
+
.expand(provider: provider)
|
|
68
|
+
.post!(query)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def query
|
|
72
|
+
q = {}
|
|
73
|
+
q["includePendingStatus"] = true if options[:include_pending_status]
|
|
74
|
+
q["consumerVersionSelectors"] = consumer_version_selectors if consumer_version_selectors.any?
|
|
75
|
+
q["providerVersionTags"] = provider_version_tags if provider_version_tags.any?
|
|
76
|
+
q["includeWipPactsSince"] = options[:include_wip_pacts_since] if options[:include_wip_pacts_since]
|
|
77
|
+
q
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def extract_notices(pact)
|
|
81
|
+
Notices.new((pact["verificationProperties"]["notices"] || []).collect{ |notice| symbolize_keys(notice) })
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def symbolize_keys(hash)
|
|
85
|
+
hash.each_with_object({}){ |(k,v), h| h[k.to_sym] = v }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def log_message
|
|
89
|
+
Pact.configuration.output_stream.puts "INFO: #{pact_selection_description(provider, consumer_version_selectors, options, broker_base_url)}"
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'pact/hal/entity'
|
|
2
2
|
require 'pact/hal/http_client'
|
|
3
3
|
require 'pact/provider/pact_uri'
|
|
4
|
+
require 'pact/errors'
|
|
4
5
|
|
|
5
6
|
module Pact
|
|
6
7
|
module PactBroker
|
|
@@ -11,6 +12,7 @@ module Pact
|
|
|
11
12
|
LATEST_PROVIDER_TAG_RELATION = 'pb:latest-provider-pacts-with-tag'.freeze
|
|
12
13
|
LATEST_PROVIDER_RELATION = 'pb:latest-provider-pacts'.freeze
|
|
13
14
|
PACTS = 'pacts'.freeze
|
|
15
|
+
PB_PACTS = 'pb:pacts'.freeze
|
|
14
16
|
HREF = 'href'.freeze
|
|
15
17
|
|
|
16
18
|
def initialize(provider, tags, broker_base_url, http_client_options)
|
|
@@ -33,11 +35,11 @@ module Pact
|
|
|
33
35
|
|
|
34
36
|
def call
|
|
35
37
|
log_message
|
|
36
|
-
if
|
|
38
|
+
if index.success?
|
|
37
39
|
if any_tags?
|
|
38
|
-
|
|
40
|
+
tagged_pacts_for_provider
|
|
39
41
|
else
|
|
40
|
-
|
|
42
|
+
latest_pacts_for_provider
|
|
41
43
|
end
|
|
42
44
|
else
|
|
43
45
|
raise Pact::Error.new("Error retrieving #{broker_base_url} status=#{index_entity.response.code} #{index_entity.response.raw_body}")
|
|
@@ -50,36 +52,36 @@ module Pact
|
|
|
50
52
|
tags && tags.any?
|
|
51
53
|
end
|
|
52
54
|
|
|
53
|
-
def
|
|
55
|
+
def tagged_pacts_for_provider
|
|
54
56
|
tags.collect do |tag|
|
|
55
|
-
link =
|
|
56
|
-
urls =
|
|
57
|
-
if urls
|
|
58
|
-
urls =
|
|
57
|
+
link = link_for(tag)
|
|
58
|
+
urls = pact_urls(link.expand(provider: provider, tag: tag[:name]).get)
|
|
59
|
+
if urls.empty? && tag[:fallback]
|
|
60
|
+
urls = pact_urls(link.expand(provider: provider, tag: tag[:fallback]).get)
|
|
59
61
|
end
|
|
60
62
|
urls
|
|
61
63
|
end.flatten
|
|
62
64
|
end
|
|
63
65
|
|
|
64
|
-
def
|
|
66
|
+
def link_for(tag)
|
|
65
67
|
if !tag[:all]
|
|
66
|
-
index_entity._link(LATEST_PROVIDER_TAG_RELATION)
|
|
68
|
+
index_entity._link!(LATEST_PROVIDER_TAG_RELATION)
|
|
67
69
|
else
|
|
68
|
-
index_entity._link(ALL_PROVIDER_TAG_RELATION)
|
|
70
|
+
index_entity._link!(ALL_PROVIDER_TAG_RELATION)
|
|
69
71
|
end
|
|
70
72
|
end
|
|
71
73
|
|
|
72
|
-
def
|
|
73
|
-
@index_entity
|
|
74
|
+
def index
|
|
75
|
+
@index_entity ||= Pact::Hal::Link.new({ "href" => broker_base_url }, http_client).get.assert_success!
|
|
74
76
|
end
|
|
75
77
|
|
|
76
|
-
def
|
|
77
|
-
link = index_entity._link(LATEST_PROVIDER_RELATION)
|
|
78
|
-
|
|
78
|
+
def latest_pacts_for_provider
|
|
79
|
+
link = index_entity._link!(LATEST_PROVIDER_RELATION)
|
|
80
|
+
pact_urls(link.expand(provider: provider).get.assert_success!)
|
|
79
81
|
end
|
|
80
82
|
|
|
81
|
-
def
|
|
82
|
-
link_by_provider.fetch(PACTS).collect do |pact|
|
|
83
|
+
def pact_urls(link_by_provider)
|
|
84
|
+
link_by_provider.assert_success!.fetch(PB_PACTS, PACTS).collect do |pact|
|
|
83
85
|
Pact::Provider::PactURI.new(pact[HREF], http_client_options)
|
|
84
86
|
end
|
|
85
87
|
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
module Pact
|
|
2
|
+
module PactBroker
|
|
3
|
+
class Notices < Array
|
|
4
|
+
def before_verification_notices
|
|
5
|
+
select { | notice | notice[:when].nil? || notice[:when].start_with?('before_verification') }
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def before_verification_notices_text
|
|
9
|
+
before_verification_notices.collect{ | notice | notice[:text] }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def after_verification_notices(success, published)
|
|
13
|
+
select { | notice | notice[:when] == "after_verification:success_#{success}_published_#{published}" || notice[:when] == "after_verification" }
|
|
14
|
+
.collect do | notice |
|
|
15
|
+
notice.merge(:when => simplify_notice_when(notice[:when]))
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def after_verification_notices_text(success, published)
|
|
20
|
+
after_verification_notices(success, published).collect{ | notice | notice[:text] }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def all_notices(success, published)
|
|
24
|
+
before_verification_notices + after_verification_notices(success, published)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def simplify_notice_when(when_key)
|
|
30
|
+
when_key.split(":").first
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Pact
|
|
2
|
+
module PactBroker
|
|
3
|
+
module PactSelectionDescription
|
|
4
|
+
def pact_selection_description(provider, consumer_version_selectors, options, broker_base_url)
|
|
5
|
+
latest = consumer_version_selectors.any? ? "" : "latest "
|
|
6
|
+
message = "Fetching pacts for #{provider} from #{broker_base_url} with the selection criteria: "
|
|
7
|
+
if consumer_version_selectors.any?
|
|
8
|
+
desc = consumer_version_selectors.collect do |selector|
|
|
9
|
+
all_or_latest = !selector[:latest] ? "all for tag" : "latest for tag"
|
|
10
|
+
# TODO support fallback
|
|
11
|
+
fallback = selector[:fallback] || selector[:fallbackTag]
|
|
12
|
+
name = fallback ? "#{selector[:tag]} (or #{fallback} if not found)" : selector[:tag]
|
|
13
|
+
"#{all_or_latest} #{name}"
|
|
14
|
+
end.join(", ")
|
|
15
|
+
if options[:include_wip_pacts_since]
|
|
16
|
+
desc = "#{desc}, work in progress pacts created after #{options[:include_wip_pacts_since]}"
|
|
17
|
+
end
|
|
18
|
+
message << "#{desc}"
|
|
19
|
+
end
|
|
20
|
+
message
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'pact/pact_broker/fetch_pacts'
|
|
2
|
+
require 'pact/pact_broker/fetch_pact_uris_for_verification'
|
|
3
|
+
require 'pact/provider/pact_uri'
|
|
4
|
+
|
|
5
|
+
#
|
|
6
|
+
# @public Used by Pact Provider Verifier
|
|
7
|
+
#
|
|
8
|
+
module Pact
|
|
9
|
+
module PactBroker
|
|
10
|
+
extend self
|
|
11
|
+
|
|
12
|
+
# Keep for backwards compatibility with pact-provider-verifier < 1.23.1
|
|
13
|
+
def fetch_pact_uris *args
|
|
14
|
+
Pact::PactBroker::FetchPacts.call(*args).collect(&:uri)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def fetch_pact_uris_for_verification *args
|
|
18
|
+
Pact::PactBroker::FetchPactURIsForVerification.call(*args)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def build_pact_uri(*args)
|
|
22
|
+
Pact::Provider::PactURI.new(*args)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
require 'pact/provider/configuration/service_provider_dsl'
|
|
2
|
+
require 'pact/provider/configuration/message_provider_dsl'
|
|
2
3
|
|
|
3
4
|
module Pact
|
|
4
5
|
|
|
@@ -8,6 +9,10 @@ module Pact
|
|
|
8
9
|
def service_provider name, &block
|
|
9
10
|
Configuration::ServiceProviderDSL.build(name, &block)
|
|
10
11
|
end
|
|
12
|
+
|
|
13
|
+
def message_provider name, &block
|
|
14
|
+
Configuration::MessageProviderDSL.build(name, &block)
|
|
15
|
+
end
|
|
11
16
|
end
|
|
12
17
|
end
|
|
13
|
-
end
|
|
18
|
+
end
|