Skip to content

Commit d525527

Browse files
committed
feat: add ${pactbroker.consumerVersionNumber} to webhook templates
1 parent 690e39b commit d525527

File tree

5 files changed

+85
-66
lines changed

5 files changed

+85
-66
lines changed

lib/pact_broker/doc/views/webhooks.markdown

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ A request body can be specified as well.
6565
The following variables may be used in the request parameters or body, and will be replaced with their appropriate values at runtime.
6666

6767
`${pactbroker.pactUrl}`: the "permalink" URL to the newly published pact (the URL specifying the consumer version URL, rather than the "/latest" format.)
68+
`${pactbroker.consumerVersionNumber}`: the version number of the most recent consumer version associated with the pact content.
6869

6970
Example usage:
7071

lib/pact_broker/domain/webhook_request.rb

+4-18
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
require 'pact_broker/messages'
66
require 'net/http'
77
require 'pact_broker/webhooks/redact_logs'
8+
require 'pact_broker/webhooks/render'
89
require 'pact_broker/api/pact_broker_urls'
910
require 'pact_broker/build_http_options'
11+
require 'cgi'
1012

1113
module PactBroker
1214

@@ -91,11 +93,7 @@ def build_request uri, pact, execution_logger
9193
req.basic_auth(username, password) if username
9294

9395
unless body.nil?
94-
if String === body
95-
req.body = gsub_body(pact, body)
96-
else
97-
req.body = gsub_body(pact, body.to_json)
98-
end
96+
req.body = PactBroker::Webhooks::Render.call(String === body ? body : body.to_json, pact)
9997
end
10098

10199
execution_logger.info req.body
@@ -150,26 +148,14 @@ def http_request(uri)
150148
end
151149

152150
def build_uri pact
153-
URI(gsub_url(pact, url))
151+
URI(PactBroker::Webhooks::Render.call(url, pact){ | value | CGI::escape(value)} )
154152
end
155153

156154
def url_with_credentials pact
157155
u = build_uri(pact)
158156
u.userinfo = "#{CGI::escape username}:#{display_password}" if username
159157
u
160158
end
161-
162-
def gsub_body pact, body
163-
base_url = PactBroker.configuration.base_url
164-
body.gsub('${pactbroker.pactUrl}', PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact))
165-
end
166-
167-
def gsub_url pact, url
168-
base_url = PactBroker.configuration.base_url
169-
pact_url = PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact)
170-
escaped_pact_url = CGI::escape(pact_url)
171-
url.gsub('${pactbroker.pactUrl}', escaped_pact_url)
172-
end
173159
end
174160
end
175161
end

lib/pact_broker/webhooks/render.rb

+23
Original file line numberDiff line numberDiff line change
@@ -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

spec/lib/pact_broker/domain/webhook_request_spec.rb

+21-48
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ module Domain
1111
allow(PactBroker.logger).to receive(:info).and_call_original
1212
allow(PactBroker.logger).to receive(:debug).and_call_original
1313
allow(PactBroker.logger).to receive(:warn).and_call_original
14+
allow(PactBroker::Webhooks::Render).to receive(:call) do | content, pact, verification, &block |
15+
content
16+
end
1417
end
1518

1619
let(:username) { nil }
@@ -57,51 +60,37 @@ module Domain
5760
describe "execute" do
5861
let!(:http_request) do
5962
stub_request(:post, "http://example.org/hook").
60-
with(:headers => {'Content-Type'=>'text/plain'}, :body => 'body').
63+
with(:headers => {'Content-Type'=>'text/plain'}, :body => request_body).
6164
to_return(:status => 200, :body => "respbod", :headers => {'Content-Type' => 'text/foo, blah'})
6265
end
6366

64-
describe "when the String body contains a ${pactbroker.pactUrl} parameter" do
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>" }
67+
let(:request_body) { 'body' }
7268

73-
it "replaces the token with the live value" do
74-
subject.execute(pact, options)
75-
expect(http_request).to have_been_made
69+
it "renders the url template" do
70+
expect(PactBroker::Webhooks::Render).to receive(:call).with("http://example.org/hook", pact) do | content, pact, verification, &block |
71+
expect(content).to eq "http://example.org/hook"
72+
expect(pact).to be pact
73+
expect(verification).to be nil
74+
expect(block.call("foo bar")).to eq "foo+bar"
75+
"http://example.org/hook"
7676
end
77+
subject.execute(pact, options)
7778
end
7879

79-
describe "when the JSON body contains a ${pactbroker.pactUrl} parameter" do
80-
let!(:http_request) do
81-
stub_request(:post, "http://example.org/hook").
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
80+
context "when the body is a string" do
81+
it "renders the body template with the String" do
82+
expect(PactBroker::Webhooks::Render).to receive(:call).with('body', pact)
8983
subject.execute(pact, options)
90-
expect(http_request).to have_been_made
9184
end
9285
end
9386

94-
describe "when the URL contains a ${pactbroker.pactUrl} parameter" do
95-
let!(:http_request) do
96-
stub_request(:post, "http://example.org/hook?url=http%3A%2F%2Fexample.org%2Fpact-url").
97-
to_return(:status => 200)
98-
end
99-
100-
let(:url) { 'http://example.org/hook?url=${pactbroker.pactUrl}' }
87+
context "when the body is an object" do
88+
let(:body) { {"foo" => "bar"} }
89+
let(:request_body) { '{"foo":"bar"}' }
10190

102-
it "replaces the token with the live value" do
91+
it "renders the body template with JSON" do
92+
expect(PactBroker::Webhooks::Render).to receive(:call).with(request_body, pact)
10393
subject.execute(pact, options)
104-
expect(http_request).to have_been_made
10594
end
10695
end
10796

@@ -234,21 +223,6 @@ module Domain
234223
end
235224
end
236225

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-
252226
context "when the request has a nil body" do
253227
let(:body) { nil }
254228

@@ -275,7 +249,6 @@ module Domain
275249
end
276250

277251
context "when the request is not successful" do
278-
279252
let!(:http_request) do
280253
stub_request(:post, "http://example.org/hook").
281254
with(:headers => {'Content-Type'=>'text/plain'}, :body => 'body').
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
require 'pact_broker/webhooks/render'
2+
require 'cgi'
3+
4+
module PactBroker
5+
module Webhooks
6+
describe Render do
7+
describe "#call" do
8+
before do
9+
allow(PactBroker::Api::PactBrokerUrls).to receive(:pact_url).and_return("http://foo")
10+
end
11+
12+
let(:body) do
13+
"Foo ${pactbroker.pactUrl} ${pactbroker.consumerVersionNumber}"
14+
end
15+
16+
let(:pact) do
17+
instance_double("pact", consumer_version_number: "1.2.3+foo")
18+
end
19+
20+
subject { Render.call(body, pact, nil) }
21+
22+
it { is_expected.to eq "Foo http://foo 1.2.3+foo" }
23+
24+
context "with an escaper" do
25+
subject do
26+
Render.call(body, pact, nil) do | value |
27+
CGI.escape(value)
28+
end
29+
end
30+
31+
it { is_expected.to eq "Foo http%3A%2F%2Ffoo 1.2.3%2Bfoo" }
32+
end
33+
end
34+
end
35+
end
36+
end

0 commit comments

Comments
 (0)