pact 1.41.2 → 1.49.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 +142 -0
- data/lib/pact/cli/run_pact_verification.rb +23 -7
- data/lib/pact/consumer/configuration/dsl.rb +0 -1
- data/lib/pact/consumer/spec_hooks.rb +2 -2
- data/lib/pact/doc/sort_interactions.rb +2 -3
- data/lib/pact/hal/http_client.rb +11 -5
- data/lib/pact/hal/link.rb +50 -13
- data/lib/pact/hal/non_json_entity.rb +28 -0
- data/lib/pact/pact_broker/fetch_pact_uris_for_verification.rb +102 -0
- data/lib/pact/pact_broker/notices.rb +34 -0
- data/lib/pact/pact_broker.rb +10 -4
- data/lib/pact/provider/configuration/dsl.rb +6 -1
- data/lib/pact/provider/configuration/message_provider_dsl.rb +32 -0
- data/lib/pact/provider/configuration/pact_verification_from_broker.rb +22 -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 +0 -1
- data/lib/pact/provider/pact_source.rb +10 -1
- data/lib/pact/provider/pact_spec_runner.rb +24 -16
- data/lib/pact/provider/pact_uri.rb +6 -4
- data/lib/pact/provider/request.rb +1 -1
- data/lib/pact/provider/rspec/formatter_rspec_3.rb +1 -1
- data/lib/pact/provider/rspec/json_formatter.rb +98 -0
- data/lib/pact/provider/rspec/pact_broker_formatter.rb +1 -1
- data/lib/pact/provider/rspec.rb +17 -7
- data/lib/pact/provider/test_methods.rb +1 -1
- data/lib/pact/provider/verification_results/publish.rb +3 -0
- data/lib/pact/provider/verification_results/publish_all.rb +14 -1
- data/lib/pact/provider/verification_results/verification_result.rb +1 -4
- data/lib/pact/provider/world.rb +1 -1
- data/lib/pact/version.rb +1 -1
- data/pact.gemspec +11 -13
- metadata +55 -58
- data/lib/pact/pact_broker/fetch_pending_pacts.rb +0 -58
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: d23bb31e12922ffa6334faa9105770afc780d97310296dd48f120613e12cee63
|
|
4
|
+
data.tar.gz: 89178f9552aabbf8099e65f3a10864303f53370b7ea76f841be6401d5667a66d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0a1f2a19a89eacda8db9a85b08d538821bf8ff25986ea6e8d5df4b84ea798bd41dd9136b6a0f894b3a513bf538055b734d7335d585279653822c81e3bfb49fb0
|
|
7
|
+
data.tar.gz: e9b962314733660dd23127eab1076abda1391000de6d9f0f647fbdb5353cc37c79c6c308be6e04c16d9b1e5e341a38ea531f6e6fa7174852edbcb5f4c9dfc46e
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,145 @@
|
|
|
1
|
+
<a name="v1.49.0"></a>
|
|
2
|
+
### v1.49.0 (2020-02-18)
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
#### Features
|
|
6
|
+
|
|
7
|
+
* use environment variables PACT_BROKER_USERNAME and PACT_BROKER_PASSWORD when verifying a pact by URL, if the environment variables are present ([308f25d](/../../commit/308f25d))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
<a name="v1.48.0"></a>
|
|
11
|
+
### v1.48.0 (2020-02-13)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
#### Features
|
|
15
|
+
|
|
16
|
+
* use certificates from SSL_CERT_FILE and SSL_CERT_DIR environment variables in HTTP connections ([164912b](/../../commit/164912b))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
<a name="v1.47.0"></a>
|
|
20
|
+
### v1.47.0 (2020-02-08)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
#### Features
|
|
24
|
+
|
|
25
|
+
* update json formatter output ([376e47a](/../../commit/376e47a))
|
|
26
|
+
* add pact metadata to json formatter ([6c6ddb8](/../../commit/6c6ddb8))
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
<a name="v1.46.1"></a>
|
|
30
|
+
### v1.46.1 (2020-01-22)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
#### Bug Fixes
|
|
34
|
+
|
|
35
|
+
* send output messages to the correct stream when using the XML formatter ([e768a33](/../../commit/e768a33))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
<a name="v1.46.0"></a>
|
|
39
|
+
### v1.46.0 (2020-01-22)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
#### Features
|
|
43
|
+
|
|
44
|
+
* expose full notice object in JSON output ([bdc2711](/../../commit/bdc2711))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
#### Bug Fixes
|
|
48
|
+
|
|
49
|
+
* remove accidentally committed verbose: true ([498518c](/../../commit/498518c))
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
<a name="v1.45.0"></a>
|
|
53
|
+
### v1.45.0 (2020-01-21)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
#### Features
|
|
57
|
+
|
|
58
|
+
* use custom json formatter when --format json is specified and send it straight to stdout or the configured file ([6c703a1](/../../commit/6c703a1))
|
|
59
|
+
* support pending pacts in json formatter ([2c0d20d](/../../commit/2c0d20d))
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
#### Bug Fixes
|
|
63
|
+
|
|
64
|
+
* show pending test output in yellow instead of red ([e8d4a55](/../../commit/e8d4a55))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
<a name="v1.44.1"></a>
|
|
68
|
+
### v1.44.1 (2020-01-20)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
#### Bug Fixes
|
|
72
|
+
|
|
73
|
+
* print notices from 'pacts for verification' response to indicate why pacts are included an/or pending ([b107348](/../../commit/b107348))
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
<a name="v1.44.0"></a>
|
|
77
|
+
### v1.44.0 (2020-01-16)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
#### Features
|
|
81
|
+
|
|
82
|
+
* **message pact**
|
|
83
|
+
* add DSL for configuring Message Pact verifications ([a5181b6](/../../commit/a5181b6))
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
<a name="v1.43.1"></a>
|
|
87
|
+
### v1.43.1 (2020-01-11)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
#### Bug Fixes
|
|
91
|
+
|
|
92
|
+
* use configured credentials when fetching the diff with previous version ([b9deb09](/../../commit/b9deb09))
|
|
93
|
+
* use URI.open instead of Kernel.open ([7b3ea81](/../../commit/7b3ea81))
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
<a name="v1.43.0"></a>
|
|
97
|
+
### v1.43.0 (2020-01-11)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
#### Features
|
|
101
|
+
|
|
102
|
+
* **verify**
|
|
103
|
+
* allow includePendingStatus to be specified when fetching pacts ([1f5fc9c](/../../commit/1f5fc9c))
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
<a name="v1.42.3"></a>
|
|
107
|
+
### v1.42.3 (2019-11-15)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
#### Bug Fixes
|
|
111
|
+
|
|
112
|
+
* **verify**
|
|
113
|
+
* exit with status 0 if all pacts are in pending state ([2f7110b](/../../commit/2f7110b))
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
<a name="v1.42.2"></a>
|
|
117
|
+
### v1.42.2 (2019-11-09)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
#### Bug Fixes
|
|
121
|
+
|
|
122
|
+
* remove missed &. ([be700d8](/../../commit/be700d8))
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
<a name="v1.42.1"></a>
|
|
126
|
+
### v1.42.1 (2019-11-09)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
#### Bug Fixes
|
|
130
|
+
|
|
131
|
+
* can't use safe navigation operator because of Ruby 2.2 in Travelling Ruby for the pact-ruby-standalone ([3068ceb](/../../commit/3068ceb))
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
<a name="v1.42.0"></a>
|
|
135
|
+
### v1.42.0 (2019-09-26)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
#### Features
|
|
139
|
+
|
|
140
|
+
* use new 'pacts for verification' endpoint to retrieve pacts (#199) ([55bb935](/../../commit/55bb935))
|
|
141
|
+
|
|
142
|
+
|
|
1
143
|
<a name="v1.41.2"></a>
|
|
2
144
|
### v1.41.2 (2019-09-10)
|
|
3
145
|
|
|
@@ -3,7 +3,6 @@ require 'pact/cli/spec_criteria'
|
|
|
3
3
|
module Pact
|
|
4
4
|
module Cli
|
|
5
5
|
class RunPactVerification
|
|
6
|
-
|
|
7
6
|
attr_reader :options
|
|
8
7
|
|
|
9
8
|
def initialize options
|
|
@@ -15,6 +14,7 @@ module Pact
|
|
|
15
14
|
end
|
|
16
15
|
|
|
17
16
|
def call
|
|
17
|
+
configure_output
|
|
18
18
|
initialize_rspec
|
|
19
19
|
setup_load_path
|
|
20
20
|
load_pact_helper
|
|
@@ -44,24 +44,32 @@ module Pact
|
|
|
44
44
|
end
|
|
45
45
|
|
|
46
46
|
def run_specs
|
|
47
|
-
exit_code = if options[:pact_uri]
|
|
48
|
-
|
|
47
|
+
exit_code = if options[:pact_uri].is_a?(String)
|
|
48
|
+
run_with_pact_url_string
|
|
49
|
+
elsif options[:pact_uri]
|
|
50
|
+
run_with_pact_uri_object # from pact-provider-verifier
|
|
49
51
|
else
|
|
50
|
-
|
|
52
|
+
run_with_configured_pacts_from_pact_helper
|
|
51
53
|
end
|
|
52
54
|
exit exit_code
|
|
53
55
|
end
|
|
54
56
|
|
|
55
|
-
def
|
|
57
|
+
def run_with_pact_url_string
|
|
56
58
|
pact_repository_uri_options = {}
|
|
59
|
+
pact_repository_uri_options[:username] = ENV['PACT_BROKER_USERNAME'] if ENV['PACT_BROKER_USERNAME']
|
|
60
|
+
pact_repository_uri_options[:password] = ENV['PACT_BROKER_PASSWORD'] if ENV['PACT_BROKER_PASSWORD']
|
|
61
|
+
pact_repository_uri_options[:token] = ENV['PACT_BROKER_TOKEN']
|
|
57
62
|
pact_repository_uri_options[:username] = options[:pact_broker_username] if options[:pact_broker_username]
|
|
58
63
|
pact_repository_uri_options[:password] = options[:pact_broker_password] if options[:pact_broker_password]
|
|
59
|
-
pact_repository_uri_options[:token] = ENV['PACT_BROKER_TOKEN']
|
|
60
64
|
pact_uri = ::Pact::Provider::PactURI.new(options[:pact_uri], pact_repository_uri_options)
|
|
61
65
|
Pact::Provider::PactSpecRunner.new([pact_uri], pact_spec_options).run
|
|
62
66
|
end
|
|
63
67
|
|
|
64
|
-
def
|
|
68
|
+
def run_with_pact_uri_object
|
|
69
|
+
Pact::Provider::PactSpecRunner.new([options[:pact_uri]], pact_spec_options).run
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def run_with_configured_pacts_from_pact_helper
|
|
65
73
|
pact_urls = Pact.provider_world.pact_urls
|
|
66
74
|
raise "Please configure a pact to verify" if pact_urls.empty?
|
|
67
75
|
Pact::Provider::PactSpecRunner.new(pact_urls, pact_spec_options).run
|
|
@@ -77,6 +85,14 @@ module Pact
|
|
|
77
85
|
request_customizer: options[:request_customizer]
|
|
78
86
|
}
|
|
79
87
|
end
|
|
88
|
+
|
|
89
|
+
def configure_output
|
|
90
|
+
if options[:format] == 'json' && !options[:out]
|
|
91
|
+
# Don't want to mess up the JSON parsing with messages to stdout, so send it to stderr
|
|
92
|
+
require 'pact/configuration'
|
|
93
|
+
Pact.configuration.output_stream = Pact.configuration.error_stream
|
|
94
|
+
end
|
|
95
|
+
end
|
|
80
96
|
end
|
|
81
97
|
end
|
|
82
98
|
end
|
|
@@ -29,7 +29,7 @@ module Pact
|
|
|
29
29
|
|
|
30
30
|
def after_suite
|
|
31
31
|
if Pact.consumer_world.any_pact_examples_ran?
|
|
32
|
-
Pact.consumer_world.consumer_contract_builders.each
|
|
32
|
+
Pact.consumer_world.consumer_contract_builders.each(&:write_pact)
|
|
33
33
|
Pact::Doc::Generate.call
|
|
34
34
|
Pact::MockService::AppManager.instance.kill_all
|
|
35
35
|
Pact::MockService::AppManager.instance.clear_all
|
|
@@ -37,4 +37,4 @@ module Pact
|
|
|
37
37
|
end
|
|
38
38
|
end
|
|
39
39
|
end
|
|
40
|
-
end
|
|
40
|
+
end
|
|
@@ -3,7 +3,7 @@ module Pact
|
|
|
3
3
|
class SortInteractions
|
|
4
4
|
|
|
5
5
|
def self.call interactions
|
|
6
|
-
interactions.
|
|
6
|
+
interactions.sort_by { |interaction| sortable_id(interaction) }
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
private
|
|
@@ -11,7 +11,6 @@ module Pact
|
|
|
11
11
|
def self.sortable_id interaction
|
|
12
12
|
"#{interaction.description.downcase} #{interaction.response.status} #{(interaction.provider_state || '').downcase}"
|
|
13
13
|
end
|
|
14
|
-
|
|
15
14
|
end
|
|
16
15
|
end
|
|
17
|
-
end
|
|
16
|
+
end
|
data/lib/pact/hal/http_client.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require 'pact/retry'
|
|
2
2
|
require 'pact/hal/authorization_header_redactor'
|
|
3
3
|
require 'net/http'
|
|
4
|
+
require 'rack'
|
|
4
5
|
|
|
5
6
|
module Pact
|
|
6
7
|
module Hal
|
|
@@ -15,9 +16,11 @@ module Pact
|
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
def get href, params = {}, headers = {}
|
|
18
|
-
query = params.collect{ |(key, value)| "#{CGI::escape(key)}=#{CGI::escape(value)}" }.join("&")
|
|
19
19
|
uri = URI(href)
|
|
20
|
-
|
|
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
|
|
21
24
|
perform_request(create_request(uri, 'Get', nil, headers), uri)
|
|
22
25
|
end
|
|
23
26
|
|
|
@@ -33,12 +36,9 @@ module Pact
|
|
|
33
36
|
|
|
34
37
|
def create_request uri, http_method, body = nil, headers = {}
|
|
35
38
|
request = Net::HTTP.const_get(http_method).new(uri.request_uri)
|
|
36
|
-
request['Content-Type'] = "application/json" if ['Post', 'Put', 'Patch'].include?(http_method)
|
|
37
|
-
request['Accept'] = "application/hal+json"
|
|
38
39
|
headers.each do | key, value |
|
|
39
40
|
request[key] = value
|
|
40
41
|
end
|
|
41
|
-
|
|
42
42
|
request.body = body if body
|
|
43
43
|
request.basic_auth username, password if username
|
|
44
44
|
request['Authorization'] = "Bearer #{token}" if token
|
|
@@ -50,6 +50,8 @@ module Pact
|
|
|
50
50
|
http = Net::HTTP.new(uri.host, uri.port, :ENV)
|
|
51
51
|
http.set_debug_output(output_stream) if verbose
|
|
52
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'] != ''
|
|
53
55
|
http.start do |http|
|
|
54
56
|
http.request request
|
|
55
57
|
end
|
|
@@ -82,6 +84,10 @@ module Pact
|
|
|
82
84
|
def success?
|
|
83
85
|
__getobj__().code.start_with?("2")
|
|
84
86
|
end
|
|
87
|
+
|
|
88
|
+
def json?
|
|
89
|
+
self['content-type'] && self['content-type'] =~ /json/
|
|
90
|
+
end
|
|
85
91
|
end
|
|
86
92
|
end
|
|
87
93
|
end
|
data/lib/pact/hal/link.rb
CHANGED
|
@@ -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,14 +23,14 @@ 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
|
|
25
34
|
end
|
|
26
35
|
|
|
27
36
|
def title_or_name
|
|
@@ -37,29 +46,57 @@ module Pact
|
|
|
37
46
|
end
|
|
38
47
|
|
|
39
48
|
def get(payload = {}, headers = {})
|
|
40
|
-
wrap_response(href, @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!
|
|
41
54
|
end
|
|
42
55
|
|
|
43
56
|
def put(payload = nil, headers = {})
|
|
44
|
-
wrap_response(href, @http_client.put(href, payload ? payload.to_json : nil, headers))
|
|
57
|
+
wrap_response(href, @http_client.put(href, payload ? payload.to_json : nil, DEFAULT_POST_HEADERS.merge(headers)))
|
|
45
58
|
end
|
|
46
59
|
|
|
47
60
|
def post(payload = nil, headers = {})
|
|
48
|
-
wrap_response(href, @http_client.post(href, payload ? payload.to_json : nil, headers))
|
|
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!
|
|
49
66
|
end
|
|
50
67
|
|
|
51
68
|
def expand(params)
|
|
52
69
|
expanded_url = expand_url(params, href)
|
|
53
70
|
new_attrs = @attrs.merge('href' => expanded_url)
|
|
54
|
-
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
|
|
55
84
|
end
|
|
56
85
|
|
|
57
86
|
private
|
|
58
87
|
|
|
88
|
+
attr_reader :attrs, :http_client
|
|
89
|
+
|
|
59
90
|
def wrap_response(href, http_response)
|
|
60
91
|
require 'pact/hal/entity' # avoid circular reference
|
|
92
|
+
require 'pact/hal/non_json_entity'
|
|
93
|
+
|
|
61
94
|
if http_response.success?
|
|
62
|
-
|
|
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
|
|
63
100
|
else
|
|
64
101
|
ErrorEntity.new(href, http_response.raw_body, @http_client, http_response)
|
|
65
102
|
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,102 @@
|
|
|
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
|
+
|
|
8
|
+
module Pact
|
|
9
|
+
module PactBroker
|
|
10
|
+
class FetchPactURIsForVerification
|
|
11
|
+
attr_reader :provider, :consumer_version_selectors, :provider_version_tags, :broker_base_url, :http_client_options, :http_client, :options
|
|
12
|
+
|
|
13
|
+
PACTS_FOR_VERIFICATION_RELATION = 'beta:provider-pacts-for-verification'.freeze
|
|
14
|
+
PACTS = 'pacts'.freeze
|
|
15
|
+
HREF = 'href'.freeze
|
|
16
|
+
LINKS = '_links'.freeze
|
|
17
|
+
SELF = 'self'.freeze
|
|
18
|
+
EMBEDDED = '_embedded'.freeze
|
|
19
|
+
|
|
20
|
+
def initialize(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options = {})
|
|
21
|
+
@provider = provider
|
|
22
|
+
@consumer_version_selectors = consumer_version_selectors || []
|
|
23
|
+
@provider_version_tags = provider_version_tags || []
|
|
24
|
+
@http_client_options = http_client_options
|
|
25
|
+
@broker_base_url = broker_base_url
|
|
26
|
+
@http_client = Pact::Hal::HttpClient.new(http_client_options)
|
|
27
|
+
@options = options
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.call(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options = {})
|
|
31
|
+
new(provider, consumer_version_selectors, provider_version_tags, broker_base_url, http_client_options, options).call
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def call
|
|
35
|
+
if index.can?(PACTS_FOR_VERIFICATION_RELATION)
|
|
36
|
+
log_message
|
|
37
|
+
pacts_for_verification
|
|
38
|
+
else
|
|
39
|
+
# Fall back to old method of fetching pacts
|
|
40
|
+
consumer_version_tags = consumer_version_selectors.collect{ | selector | selector[:tag] }
|
|
41
|
+
FetchPacts.call(provider, consumer_version_tags, broker_base_url, http_client_options)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def index
|
|
48
|
+
@index_entity ||= Pact::Hal::Link.new({ "href" => broker_base_url }, http_client).get.assert_success!
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def pacts_for_verification
|
|
52
|
+
pacts_for_verification_entity.response.body[EMBEDDED][PACTS].collect do | pact |
|
|
53
|
+
metadata = {
|
|
54
|
+
pending: pact["verificationProperties"]["pending"],
|
|
55
|
+
notices: extract_notices(pact),
|
|
56
|
+
short_description: pact["shortDescription"]
|
|
57
|
+
}
|
|
58
|
+
Pact::Provider::PactURI.new(pact[LINKS][SELF][HREF], http_client_options, metadata)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def pacts_for_verification_entity
|
|
63
|
+
index
|
|
64
|
+
._link(PACTS_FOR_VERIFICATION_RELATION)
|
|
65
|
+
.expand(provider: provider)
|
|
66
|
+
.post!(query)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def query
|
|
70
|
+
q = {}
|
|
71
|
+
q["includePendingStatus"] = true if options[:include_pending_status]
|
|
72
|
+
q["consumerVersionSelectors"] = consumer_version_selectors if consumer_version_selectors.any?
|
|
73
|
+
q["providerVersionTags"] = provider_version_tags if provider_version_tags.any?
|
|
74
|
+
q["includeWipPactsSince"] = options[:include_wip_pacts_since] if options[:include_wip_pacts_since]
|
|
75
|
+
q
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def extract_notices(pact)
|
|
79
|
+
Notices.new((pact["verificationProperties"]["notices"] || []).collect{ |notice| symbolize_keys(notice) })
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def symbolize_keys(hash)
|
|
83
|
+
hash.each_with_object({}){ |(k,v), h| h[k.to_sym] = v }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def log_message
|
|
87
|
+
latest = consumer_version_selectors.any? ? "" : "latest "
|
|
88
|
+
message = "INFO: Fetching pacts for #{provider} from #{broker_base_url} with the selection criteria: "
|
|
89
|
+
if consumer_version_selectors.any?
|
|
90
|
+
desc = consumer_version_selectors.collect do |selector|
|
|
91
|
+
all_or_latest = selector[:all] ? "all for tag" : "latest for tag"
|
|
92
|
+
# TODO support fallback
|
|
93
|
+
name = selector[:fallback] ? "#{selector[:tag]} (or #{selector[:fallback]} if not found)" : selector[:tag]
|
|
94
|
+
"#{all_or_latest} #{name}"
|
|
95
|
+
end.join(", ")
|
|
96
|
+
message << ": #{desc}"
|
|
97
|
+
end
|
|
98
|
+
Pact.configuration.output_stream.puts message
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
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
|
data/lib/pact/pact_broker.rb
CHANGED
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
require 'pact/pact_broker/fetch_pacts'
|
|
2
|
-
require 'pact/pact_broker/
|
|
2
|
+
require 'pact/pact_broker/fetch_pact_uris_for_verification'
|
|
3
|
+
require 'pact/provider/pact_uri'
|
|
3
4
|
|
|
4
5
|
#
|
|
5
|
-
# @public
|
|
6
|
+
# @public Used by Pact Provider Verifier
|
|
6
7
|
#
|
|
7
8
|
module Pact
|
|
8
9
|
module PactBroker
|
|
9
10
|
extend self
|
|
10
11
|
|
|
12
|
+
# Keep for backwards compatibility with pact-provider-verifier < 1.23.1
|
|
11
13
|
def fetch_pact_uris *args
|
|
12
14
|
Pact::PactBroker::FetchPacts.call(*args).collect(&:uri)
|
|
13
15
|
end
|
|
14
16
|
|
|
15
|
-
def
|
|
16
|
-
Pact::PactBroker::
|
|
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)
|
|
17
23
|
end
|
|
18
24
|
end
|
|
19
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
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
require 'pact/provider/configuration/service_provider_dsl'
|
|
2
|
+
|
|
3
|
+
module Pact
|
|
4
|
+
module Provider
|
|
5
|
+
module Configuration
|
|
6
|
+
class MessageProviderDSL < ServiceProviderDSL
|
|
7
|
+
class RackToMessageAdapter
|
|
8
|
+
def initialize(message_builder)
|
|
9
|
+
@message_builder = message_builder
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def call(env)
|
|
13
|
+
request_body_json = JSON.parse(env['rack.input'].read)
|
|
14
|
+
contents = @message_builder.call(request_body_json['description'])
|
|
15
|
+
[200, {"Content-Type" => "application/json"}, [{ contents: contents }.to_json]]
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def initialize name
|
|
20
|
+
super
|
|
21
|
+
@mapper_block = lambda { |args| }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
dsl do
|
|
25
|
+
def builder &block
|
|
26
|
+
self.app_block = lambda { RackToMessageAdapter.new(block) }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|