pact_broker 2.19.2 → 2.20.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 +4 -4
- data/CHANGELOG.md +17 -0
- data/example/README.md +7 -1
- data/example/config.ru +2 -3
- data/lib/pact_broker/api/contracts/webhook_contract.rb +73 -6
- data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +9 -13
- data/lib/pact_broker/api/resources/base_resource.rb +3 -3
- data/lib/pact_broker/api/resources/pact_webhooks.rb +1 -1
- data/lib/pact_broker/api/resources/webhook_execution.rb +5 -2
- data/lib/pact_broker/configuration.rb +9 -1
- data/lib/pact_broker/doc/views/webhooks.markdown +23 -0
- data/lib/pact_broker/domain/webhook_request.rb +49 -37
- data/lib/pact_broker/locale/en.yml +2 -0
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/check_host_whitelist.rb +22 -0
- data/lib/pact_broker/webhooks/render.rb +23 -0
- data/lib/pact_broker/webhooks/service.rb +2 -1
- data/lib/pact_broker/webhooks/webhook.rb +0 -5
- data/spec/features/create_webhook_spec.rb +2 -3
- data/spec/features/edit_webhook_spec.rb +2 -2
- data/spec/features/execute_webhook_spec.rb +32 -1
- data/spec/fixtures/webhook_valid.json +1 -1
- data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +64 -1
- data/spec/lib/pact_broker/api/decorators/webhook_execution_result_decorator_spec.rb +17 -9
- data/spec/lib/pact_broker/api/resources/pact_spec.rb +1 -1
- data/spec/lib/pact_broker/api/resources/pact_webhooks_spec.rb +3 -3
- data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -1
- data/spec/lib/pact_broker/domain/webhook_request_spec.rb +73 -68
- data/spec/lib/pact_broker/webhooks/check_host_whitelist_spec.rb +47 -0
- data/spec/lib/pact_broker/webhooks/render_spec.rb +36 -0
- data/spec/lib/pact_broker/webhooks/service_spec.rb +7 -0
- data/spec/support/shared_examples_for_responses.rb +2 -2
- metadata +8 -2
@@ -9,6 +9,8 @@ en:
|
|
9
9
|
valid_consumer_version_number?: "Consumer version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
10
10
|
|
11
11
|
pact_broker:
|
12
|
+
messages:
|
13
|
+
response_body_hidden: For security purposes, the response details are not logged. To enable response logging, configure the webhook_host_whitelist property. See /doc/webhooks#whitelist for more information.
|
12
14
|
errors:
|
13
15
|
validation:
|
14
16
|
blank: "cannot be blank."
|
data/lib/pact_broker/version.rb
CHANGED
@@ -0,0 +1,22 @@
|
|
1
|
+
module PactBroker
|
2
|
+
module Webhooks
|
3
|
+
class CheckHostWhitelist
|
4
|
+
|
5
|
+
def self.call(host, whitelist = PactBroker.configuration.webhook_host_whitelist)
|
6
|
+
whitelist.select{ | whitelist_host | match?(host, whitelist_host) }
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.match?(host, whitelist_host)
|
10
|
+
if whitelist_host.is_a?(Regexp)
|
11
|
+
host =~ whitelist_host
|
12
|
+
else
|
13
|
+
begin
|
14
|
+
IPAddr.new(whitelist_host) === IPAddr.new(host)
|
15
|
+
rescue IPAddr::Error
|
16
|
+
host == whitelist_host
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module PactBroker
|
2
|
+
module Webhooks
|
3
|
+
class Render
|
4
|
+
def self.call(body, pact, verification = nil, &escaper)
|
5
|
+
base_url = PactBroker.configuration.base_url
|
6
|
+
params = {
|
7
|
+
'${pactbroker.pactUrl}' => PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact),
|
8
|
+
'${pactbroker.consumerVersionNumber}' => pact.consumer_version_number
|
9
|
+
}
|
10
|
+
|
11
|
+
if escaper
|
12
|
+
params.keys.each do | key |
|
13
|
+
params[key] = escaper.call(params[key])
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
params.inject(body) do | body, (key, value) |
|
18
|
+
body.gsub(key, value)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -61,7 +61,8 @@ module PactBroker
|
|
61
61
|
|
62
62
|
def self.execute_webhook_now webhook, pact
|
63
63
|
triggered_webhook = webhook_repository.create_triggered_webhook(next_uuid, webhook, pact, USER)
|
64
|
-
|
64
|
+
options = { failure_log_message: "Webhook execution failed", show_response: PactBroker.configuration.show_webhook_response?}
|
65
|
+
webhook_execution_result = execute_triggered_webhook_now triggered_webhook, options
|
65
66
|
if webhook_execution_result.success?
|
66
67
|
webhook_repository.update_triggered_webhook_status triggered_webhook, TriggeredWebhook::STATUS_SUCCESS
|
67
68
|
else
|
@@ -5,7 +5,6 @@ require 'pact_broker/domain/pacticipant'
|
|
5
5
|
module PactBroker
|
6
6
|
module Webhooks
|
7
7
|
class Webhook < Sequel::Model
|
8
|
-
|
9
8
|
set_primary_key :id
|
10
9
|
associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
|
11
10
|
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
|
@@ -84,13 +83,11 @@ module PactBroker
|
|
84
83
|
is_json_request_body: is_json_request_body
|
85
84
|
}
|
86
85
|
end
|
87
|
-
|
88
86
|
end
|
89
87
|
|
90
88
|
Webhook.plugin :timestamps, :update_on_create=>true
|
91
89
|
|
92
90
|
class WebhookHeader < Sequel::Model
|
93
|
-
|
94
91
|
associate(:many_to_one, :webhook, :class => "PactBroker::Repositories::Webhook", :key => :webhook_id, :primary_key => :id)
|
95
92
|
|
96
93
|
def self.from_domain name, value, webhook_id
|
@@ -100,8 +97,6 @@ module PactBroker
|
|
100
97
|
db_header.webhook_id = webhook_id
|
101
98
|
db_header
|
102
99
|
end
|
103
|
-
|
104
100
|
end
|
105
101
|
end
|
106
|
-
|
107
102
|
end
|
@@ -24,7 +24,7 @@ describe "Creating a webhook" do
|
|
24
24
|
|
25
25
|
it "returns a JSON content type" do
|
26
26
|
subject
|
27
|
-
expect(last_response.headers['Content-Type']).to eq 'application/json;charset=utf-8'
|
27
|
+
expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
|
28
28
|
end
|
29
29
|
|
30
30
|
it "returns the validation errors" do
|
@@ -43,7 +43,7 @@ describe "Creating a webhook" do
|
|
43
43
|
}],
|
44
44
|
request: {
|
45
45
|
method: 'POST',
|
46
|
-
url: '
|
46
|
+
url: 'https://example.org',
|
47
47
|
headers: {
|
48
48
|
:"Content-Type" => "application/json"
|
49
49
|
},
|
@@ -76,5 +76,4 @@ describe "Creating a webhook" do
|
|
76
76
|
expect(response_body).to include webhook_hash
|
77
77
|
end
|
78
78
|
end
|
79
|
-
|
80
79
|
end
|
@@ -14,7 +14,7 @@ describe "Creating a webhook" do
|
|
14
14
|
let(:response_body) { JSON.parse(last_response.body, symbolize_names: true)}
|
15
15
|
let(:webhook_json) do
|
16
16
|
h = load_json_fixture('webhook_valid.json')
|
17
|
-
h['request']['
|
17
|
+
h['request']['url'] = 'https://bar.com'
|
18
18
|
h.to_json
|
19
19
|
end
|
20
20
|
|
@@ -55,7 +55,7 @@ describe "Creating a webhook" do
|
|
55
55
|
|
56
56
|
it "updates the webhook" do
|
57
57
|
subject
|
58
|
-
expect(reloaded_webhook.request.
|
58
|
+
expect(reloaded_webhook.request.url).to eq 'https://bar.com'
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -23,8 +23,9 @@ describe "Execute a webhook" do
|
|
23
23
|
|
24
24
|
context "when the execution is successful" do
|
25
25
|
let!(:request) do
|
26
|
-
stub_request(:post, /http/).with(body: 'http://example.org/pacts/provider/Bar/consumer/Foo/version/1').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, body: response_body)
|
27
27
|
end
|
28
|
+
let(:response_body) { "webhook-response-body" }
|
28
29
|
|
29
30
|
it "performs the HTTP request" do
|
30
31
|
subject
|
@@ -42,6 +43,36 @@ describe "Execute a webhook" do
|
|
42
43
|
it "saves a WebhookExecution" do
|
43
44
|
expect { subject }.to change { PactBroker::Webhooks::Execution.count }.by(1)
|
44
45
|
end
|
46
|
+
|
47
|
+
context "when a webhook host whitelist is not configured" do
|
48
|
+
before do
|
49
|
+
allow(PactBroker.configuration).to receive(:show_webhook_response?).and_return(false)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "does not show any response details" do
|
53
|
+
expect(subject.body).to_not include response_body
|
54
|
+
end
|
55
|
+
|
56
|
+
it "does not log any response details" do
|
57
|
+
subject
|
58
|
+
expect(PactBroker::Webhooks::Execution.order(:id).last.logs).to_not include response_body
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when a webhook host whitelist is configured" do
|
63
|
+
before do
|
64
|
+
allow(PactBroker.configuration).to receive(:show_webhook_response?).and_return(true)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "includes response details" do
|
68
|
+
expect(subject.body).to include response_body
|
69
|
+
end
|
70
|
+
|
71
|
+
it "logs the response details" do
|
72
|
+
subject
|
73
|
+
expect(PactBroker::Webhooks::Execution.order(:id).last.logs).to include response_body
|
74
|
+
end
|
75
|
+
end
|
45
76
|
end
|
46
77
|
|
47
78
|
context "when an error occurs", no_db_clean: true do
|
@@ -10,6 +10,7 @@ module PactBroker
|
|
10
10
|
let(:hash) { JSON.parse(json) }
|
11
11
|
let(:webhook) { PactBroker::Api::Decorators::WebhookDecorator.new(Domain::Webhook.new).from_json(json) }
|
12
12
|
let(:subject) { WebhookContract.new(webhook) }
|
13
|
+
let(:matching_hosts) { ['foo'] }
|
13
14
|
|
14
15
|
def valid_webhook_with
|
15
16
|
hash = load_json_fixture 'webhook_valid.json'
|
@@ -18,11 +19,17 @@ module PactBroker
|
|
18
19
|
end
|
19
20
|
|
20
21
|
describe "errors" do
|
21
|
-
|
22
22
|
before do
|
23
|
+
PactBroker.configuration.webhook_http_method_whitelist = webhook_http_method_whitelist
|
24
|
+
PactBroker.configuration.webhook_host_whitelist = webhook_host_whitelist
|
25
|
+
allow(PactBroker::Webhooks::CheckHostWhitelist).to receive(:call).and_return(whitelist_matches)
|
23
26
|
subject.validate(hash)
|
24
27
|
end
|
25
28
|
|
29
|
+
let(:webhook_http_method_whitelist) { ['POST'] }
|
30
|
+
let(:whitelist_matches) { ['foo'] }
|
31
|
+
let(:webhook_host_whitelist) { [] }
|
32
|
+
|
26
33
|
context "with valid fields" do
|
27
34
|
it "is empty" do
|
28
35
|
expect(subject.errors).to be_empty
|
@@ -81,6 +88,62 @@ module PactBroker
|
|
81
88
|
end
|
82
89
|
end
|
83
90
|
|
91
|
+
context "with an invalid scheme" do
|
92
|
+
let(:json) do
|
93
|
+
valid_webhook_with do |hash|
|
94
|
+
hash['request']['url'] = 'ftp://foo'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
it "contains an error for the URL" do
|
99
|
+
expect(subject.errors[:"request.url"]).to include "scheme must be https. See /doc/webhooks#whitelist for more information."
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "with an HTTP method that is not whitelisted" do
|
104
|
+
let(:json) do
|
105
|
+
valid_webhook_with do |hash|
|
106
|
+
hash['request']['method'] = 'DELETE'
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context "when there is only one allowed HTTP method" do
|
111
|
+
it "contains an error for invalid method" do
|
112
|
+
expect(subject.errors[:"request.http_method"]).to include "must be POST. See /doc/webhooks#whitelist for more information."
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context "when there is more than one allowed HTTP method", pending: "need to work out how to dynamically create this message" do
|
117
|
+
let(:webhook_http_method_whitelist) { ['POST', 'GET'] }
|
118
|
+
|
119
|
+
it "contains an error for invalid method" do
|
120
|
+
expect(subject.errors[:"request.http_method"]).to include "must be one of POST, GET"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "when the host whitelist is empty" do
|
126
|
+
it "does not attempt to validate the host" do
|
127
|
+
expect(PactBroker::Webhooks::CheckHostWhitelist).to_not have_received(:call)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "when the host whitelist is populated" do
|
132
|
+
let(:webhook_host_whitelist) { [/foo/, "bar"] }
|
133
|
+
|
134
|
+
it "validates the host" do
|
135
|
+
expect(PactBroker::Webhooks::CheckHostWhitelist).to have_received(:call).with("some.url", webhook_host_whitelist)
|
136
|
+
end
|
137
|
+
|
138
|
+
context "when the host does not match the whitelist" do
|
139
|
+
let(:whitelist_matches) { [] }
|
140
|
+
|
141
|
+
it "contains an error", pending: "need to work out how to do dynamic messages" do
|
142
|
+
expect(subject.errors[:"request.url"]).to include "host must be in the whitelist /foo/, \"bar\" . See /doc/webhooks#whitelist for more information."
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
84
147
|
context "with no URL" do
|
85
148
|
let(:json) do
|
86
149
|
valid_webhook_with do |hash|
|
@@ -14,10 +14,11 @@ module PactBroker
|
|
14
14
|
let(:response) { double('http_response', code: '200', body: response_body, to_hash: headers) }
|
15
15
|
let(:response_body) { 'body' }
|
16
16
|
let(:error) { nil }
|
17
|
-
let(:webhook) { instance_double(PactBroker::Domain::Webhook, uuid: 'some-uuid')}
|
17
|
+
let(:webhook) { instance_double(PactBroker::Domain::Webhook, uuid: 'some-uuid') }
|
18
|
+
let(:show_response) { true }
|
18
19
|
let(:json) {
|
19
20
|
WebhookExecutionResultDecorator.new(webhook_execution_result)
|
20
|
-
.to_json(user_options: { base_url: 'http://example.org', webhook: webhook })
|
21
|
+
.to_json(user_options: { base_url: 'http://example.org', webhook: webhook, show_response: show_response })
|
21
22
|
}
|
22
23
|
|
23
24
|
let(:subject) { JSON.parse(json, symbolize_names: true)}
|
@@ -30,11 +31,7 @@ module PactBroker
|
|
30
31
|
expect(subject[:_links][:webhook][:href]).to eq 'http://example.org/webhooks/some-uuid'
|
31
32
|
end
|
32
33
|
|
33
|
-
|
34
|
-
expect(subject[:message]).to match /redacted/
|
35
|
-
end
|
36
|
-
|
37
|
-
context "when there is an error", pending: "temporarily disabled" do
|
34
|
+
context "when there is an error" do
|
38
35
|
let(:error) { double('error', message: 'message', backtrace: ['blah','blah']) }
|
39
36
|
|
40
37
|
it "includes the message" do
|
@@ -46,7 +43,7 @@ module PactBroker
|
|
46
43
|
end
|
47
44
|
end
|
48
45
|
|
49
|
-
context "when there is a response"
|
46
|
+
context "when there is a response" do
|
50
47
|
it "includes the response code" do
|
51
48
|
expect(subject[:response][:status]).to eq 200
|
52
49
|
end
|
@@ -66,8 +63,19 @@ module PactBroker
|
|
66
63
|
end
|
67
64
|
end
|
68
65
|
end
|
69
|
-
end
|
70
66
|
|
67
|
+
context "when show_response is false" do
|
68
|
+
let(:show_response) { false }
|
69
|
+
|
70
|
+
it "does not include the response" do
|
71
|
+
expect(subject).to_not have_key(:response)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "includes a message about why the response is hidden" do
|
75
|
+
expect(subject[:message]).to match /security purposes/
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
71
79
|
end
|
72
80
|
end
|
73
81
|
end
|
@@ -76,7 +76,7 @@ module PactBroker::Api
|
|
76
76
|
end
|
77
77
|
|
78
78
|
it "returns a JSON content type" do
|
79
|
-
expect(response.headers['Content-Type']).to eq "application/json;charset=utf-8"
|
79
|
+
expect(response.headers['Content-Type']).to eq "application/hal+json;charset=utf-8"
|
80
80
|
end
|
81
81
|
|
82
82
|
it "returns an error message" do
|
@@ -93,7 +93,7 @@ module PactBroker::Api
|
|
93
93
|
|
94
94
|
it "returns a JSON content type" do
|
95
95
|
subject
|
96
|
-
expect(last_response.headers['Content-Type']).to eq 'application/json;charset=utf-8'
|
96
|
+
expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
|
97
97
|
end
|
98
98
|
|
99
99
|
it "returns an error message" do
|
@@ -111,7 +111,7 @@ module PactBroker::Api
|
|
111
111
|
|
112
112
|
it "returns a JSON content type" do
|
113
113
|
subject
|
114
|
-
expect(last_response.headers['Content-Type']).to eq 'application/json;charset=utf-8'
|
114
|
+
expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
|
115
115
|
end
|
116
116
|
|
117
117
|
it "returns an error message" do
|
@@ -132,7 +132,7 @@ module PactBroker::Api
|
|
132
132
|
|
133
133
|
it "returns a JSON content type" do
|
134
134
|
subject
|
135
|
-
expect(last_response.headers['Content-Type']).to eq 'application/json;charset=utf-8'
|
135
|
+
expect(last_response.headers['Content-Type']).to eq 'application/hal+json;charset=utf-8'
|
136
136
|
end
|
137
137
|
|
138
138
|
it "returns the validation errors" do
|
@@ -57,7 +57,8 @@ module PactBroker
|
|
57
57
|
end
|
58
58
|
|
59
59
|
it "generates a JSON response body for the execution result" do
|
60
|
-
|
60
|
+
allow(PactBroker.configuration).to receive(:show_webhook_response?).and_return('foo')
|
61
|
+
expect(decorator).to receive(:to_json).with(user_options: { base_url: 'http://example.org', webhook: webhook, show_response: 'foo' })
|
61
62
|
subject
|
62
63
|
end
|
63
64
|
|
@@ -69,6 +70,7 @@ module PactBroker
|
|
69
70
|
|
70
71
|
context "when execution is not successful" do
|
71
72
|
let(:success) { false }
|
73
|
+
|
72
74
|
it "returns a 500 JSON response" do
|
73
75
|
subject
|
74
76
|
expect(last_response.status).to eq 500
|
@@ -8,9 +8,9 @@ module PactBroker
|
|
8
8
|
before do
|
9
9
|
allow(PactBroker::Api::PactBrokerUrls).to receive(:pact_url).and_return('http://example.org/pact-url')
|
10
10
|
allow(PactBroker.configuration).to receive(:base_url).and_return('http://example.org')
|
11
|
-
allow(PactBroker
|
12
|
-
|
13
|
-
|
11
|
+
allow(PactBroker::Webhooks::Render).to receive(:call) do | content, pact, verification, &block |
|
12
|
+
content
|
13
|
+
end
|
14
14
|
end
|
15
15
|
|
16
16
|
let(:username) { nil }
|
@@ -19,7 +19,8 @@ module PactBroker
|
|
19
19
|
let(:body) { 'body' }
|
20
20
|
let(:logs) { StringIO.new }
|
21
21
|
let(:execution_logger) { Logger.new(logs) }
|
22
|
-
let(:options) { {failure_log_message: 'oops'}}
|
22
|
+
let(:options) { {failure_log_message: 'oops', show_response: show_response} }
|
23
|
+
let(:show_response) { true }
|
23
24
|
let(:pact) { instance_double('PactBroker::Domain::Pact') }
|
24
25
|
|
25
26
|
subject do
|
@@ -57,51 +58,37 @@ module PactBroker
|
|
57
58
|
describe "execute" do
|
58
59
|
let!(:http_request) do
|
59
60
|
stub_request(:post, "http://example.org/hook").
|
60
|
-
with(:headers => {'Content-Type'=>'text/plain'}, :body =>
|
61
|
+
with(:headers => {'Content-Type'=>'text/plain'}, :body => request_body).
|
61
62
|
to_return(:status => 200, :body => "respbod", :headers => {'Content-Type' => 'text/foo, blah'})
|
62
63
|
end
|
63
64
|
|
64
|
-
|
65
|
-
let!(:http_request) do
|
66
|
-
stub_request(:post, "http://example.org/hook").
|
67
|
-
with(:headers => {'Content-Type'=>'text/plain'}, :body => "<xml><url>http://example.org/pact-url</url></xml>").
|
68
|
-
to_return(:status => 200)
|
69
|
-
end
|
70
|
-
|
71
|
-
let(:body) { "<xml><url>${pactbroker.pactUrl}</url></xml>" }
|
65
|
+
let(:request_body) { 'body' }
|
72
66
|
|
73
|
-
|
74
|
-
|
75
|
-
expect(
|
67
|
+
it "renders the url template" do
|
68
|
+
expect(PactBroker::Webhooks::Render).to receive(:call).with("http://example.org/hook", pact) do | content, pact, verification, &block |
|
69
|
+
expect(content).to eq "http://example.org/hook"
|
70
|
+
expect(pact).to be pact
|
71
|
+
expect(verification).to be nil
|
72
|
+
expect(block.call("foo bar")).to eq "foo+bar"
|
73
|
+
"http://example.org/hook"
|
76
74
|
end
|
75
|
+
subject.execute(pact, options)
|
77
76
|
end
|
78
77
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
with(:headers => {'Content-Type'=>'text/plain'}, :body => '{"url":"http://example.org/pact-url"}').
|
83
|
-
to_return(:status => 200)
|
84
|
-
end
|
85
|
-
|
86
|
-
let(:body) { { url: '${pactbroker.pactUrl}' } }
|
87
|
-
|
88
|
-
it "replaces the token with the live value" do
|
78
|
+
context "when the body is a string" do
|
79
|
+
it "renders the body template with the String" do
|
80
|
+
expect(PactBroker::Webhooks::Render).to receive(:call).with('body', pact)
|
89
81
|
subject.execute(pact, options)
|
90
|
-
expect(http_request).to have_been_made
|
91
82
|
end
|
92
83
|
end
|
93
84
|
|
94
|
-
|
95
|
-
let
|
96
|
-
|
97
|
-
to_return(:status => 200)
|
98
|
-
end
|
99
|
-
|
100
|
-
let(:url) { 'http://example.org/hook?url=${pactbroker.pactUrl}' }
|
85
|
+
context "when the body is an object" do
|
86
|
+
let(:body) { {"foo" => "bar"} }
|
87
|
+
let(:request_body) { '{"foo":"bar"}' }
|
101
88
|
|
102
|
-
it "
|
89
|
+
it "renders the body template with JSON" do
|
90
|
+
expect(PactBroker::Webhooks::Render).to receive(:call).with(request_body, pact)
|
103
91
|
subject.execute(pact, options)
|
104
|
-
expect(http_request).to have_been_made
|
105
92
|
end
|
106
93
|
end
|
107
94
|
|
@@ -120,18 +107,11 @@ module PactBroker
|
|
120
107
|
allow(PactBroker.logger).to receive(:info)
|
121
108
|
allow(PactBroker.logger).to receive(:debug)
|
122
109
|
expect(PactBroker.logger).to receive(:info).with(/response.*200/)
|
110
|
+
expect(PactBroker.logger).to receive(:debug).with(/content-type/)
|
123
111
|
expect(PactBroker.logger).to receive(:debug).with(/respbod/)
|
124
112
|
subject.execute(pact, options)
|
125
113
|
end
|
126
114
|
|
127
|
-
it "does not write the response body to the exeuction log for security purposes" do
|
128
|
-
expect(logs).to_not include "An error"
|
129
|
-
end
|
130
|
-
|
131
|
-
it "logs a message about why there is no response information" do
|
132
|
-
expect(logs).to include "Webhook response has been redacted temporarily for security purposes"
|
133
|
-
end
|
134
|
-
|
135
115
|
describe "execution logs" do
|
136
116
|
|
137
117
|
it "logs the request method and path" do
|
@@ -150,16 +130,38 @@ module PactBroker
|
|
150
130
|
expect(logs).to include body
|
151
131
|
end
|
152
132
|
|
153
|
-
|
154
|
-
|
155
|
-
|
133
|
+
context "when show_response is true" do
|
134
|
+
it "logs the response status" do
|
135
|
+
expect(logs).to include "HTTP/1.0 200"
|
136
|
+
end
|
137
|
+
|
138
|
+
it "logs the response headers" do
|
139
|
+
expect(logs).to include "Content-Type: text/foo, blah"
|
140
|
+
end
|
156
141
|
|
157
|
-
|
158
|
-
|
142
|
+
it "logs the response body" do
|
143
|
+
expect(logs).to include "respbod"
|
144
|
+
end
|
159
145
|
end
|
160
146
|
|
161
|
-
|
162
|
-
|
147
|
+
context "when show_response is false" do
|
148
|
+
let(:show_response) { false }
|
149
|
+
|
150
|
+
it "does not log the response status" do
|
151
|
+
expect(logs).to_not include "HTTP/1.0 200"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "does not log the response headers" do
|
155
|
+
expect(logs).to_not include "Content-Type: text/foo, blah"
|
156
|
+
end
|
157
|
+
|
158
|
+
it "does not log the response body" do
|
159
|
+
expect(logs).to_not include "respbod"
|
160
|
+
end
|
161
|
+
|
162
|
+
it "logs a message about why the response is hidden" do
|
163
|
+
expect(logs).to include "security purposes"
|
164
|
+
end
|
163
165
|
end
|
164
166
|
|
165
167
|
context "when the response code is a success" do
|
@@ -234,21 +236,6 @@ module PactBroker
|
|
234
236
|
end
|
235
237
|
end
|
236
238
|
|
237
|
-
context "when the request has a JSONable body" do
|
238
|
-
let(:body) { [{"some": "json"}] }
|
239
|
-
|
240
|
-
let!(:http_request) do
|
241
|
-
stub_request(:post, "http://example.org/hook").
|
242
|
-
with(:headers => {'Content-Type'=>'text/plain'}, :body => body.to_json).
|
243
|
-
to_return(:status => 200, :body => "respbod", :headers => {'Content-Type' => 'text/foo, blah'})
|
244
|
-
end
|
245
|
-
|
246
|
-
it "converts the body to JSON before submitting the request" do
|
247
|
-
subject.execute(pact, options)
|
248
|
-
expect(http_request).to have_been_made
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
239
|
context "when the request has a nil body" do
|
253
240
|
let(:body) { nil }
|
254
241
|
|
@@ -291,7 +278,7 @@ module PactBroker
|
|
291
278
|
end
|
292
279
|
end
|
293
280
|
|
294
|
-
context "when the response body contains a non UTF-8 character"
|
281
|
+
context "when the response body contains a non UTF-8 character" do
|
295
282
|
let!(:http_request) do
|
296
283
|
stub_request(:post, "http://example.org/hook").
|
297
284
|
to_return(:status => 200, :body => "This has some \xC2 invalid chars")
|
@@ -316,10 +303,10 @@ module PactBroker
|
|
316
303
|
|
317
304
|
before do
|
318
305
|
allow(subject).to receive(:http_request).and_raise(WebhookTestError.new("blah"))
|
306
|
+
allow(PactBroker.logger).to receive(:error)
|
319
307
|
end
|
320
308
|
|
321
309
|
it "logs the error" do
|
322
|
-
allow(PactBroker.logger).to receive(:error)
|
323
310
|
expect(PactBroker.logger).to receive(:error).with(/Error.*WebhookTestError.*blah/)
|
324
311
|
subject.execute(pact, options)
|
325
312
|
end
|
@@ -335,6 +322,24 @@ module PactBroker
|
|
335
322
|
it "logs the failure_log_message" do
|
336
323
|
expect(logs).to include "oops"
|
337
324
|
end
|
325
|
+
|
326
|
+
context "when show_response is true" do
|
327
|
+
it "logs the exception information" do
|
328
|
+
expect(logs).to include "blah"
|
329
|
+
end
|
330
|
+
end
|
331
|
+
|
332
|
+
context "when show_response is false" do
|
333
|
+
let(:show_response) { false }
|
334
|
+
|
335
|
+
it "does not logs the exception information" do
|
336
|
+
expect(logs).to_not include "blah"
|
337
|
+
end
|
338
|
+
|
339
|
+
it "logs a message about why the response is hidden" do
|
340
|
+
expect(logs).to include "security purposes"
|
341
|
+
end
|
342
|
+
end
|
338
343
|
end
|
339
344
|
end
|
340
345
|
end
|