From d5255275eb42e403697fcb0a64dbfc6c01ea9b52 Mon Sep 17 00:00:00 2001 From: Beth Skurrie Date: Fri, 8 Jun 2018 07:56:52 +1000 Subject: [PATCH] feat: add ${pactbroker.consumerVersionNumber} to webhook templates --- lib/pact_broker/doc/views/webhooks.markdown | 1 + lib/pact_broker/domain/webhook_request.rb | 22 ++---- lib/pact_broker/webhooks/render.rb | 23 +++++++ .../domain/webhook_request_spec.rb | 69 ++++++------------- spec/lib/pact_broker/webhooks/render_spec.rb | 36 ++++++++++ 5 files changed, 85 insertions(+), 66 deletions(-) create mode 100644 lib/pact_broker/webhooks/render.rb create mode 100644 spec/lib/pact_broker/webhooks/render_spec.rb diff --git a/lib/pact_broker/doc/views/webhooks.markdown b/lib/pact_broker/doc/views/webhooks.markdown index d6aecb84d..c55feddaa 100644 --- a/lib/pact_broker/doc/views/webhooks.markdown +++ b/lib/pact_broker/doc/views/webhooks.markdown @@ -65,6 +65,7 @@ A request body can be specified as well. The following variables may be used in the request parameters or body, and will be replaced with their appropriate values at runtime. `${pactbroker.pactUrl}`: the "permalink" URL to the newly published pact (the URL specifying the consumer version URL, rather than the "/latest" format.) +`${pactbroker.consumerVersionNumber}`: the version number of the most recent consumer version associated with the pact content. Example usage: diff --git a/lib/pact_broker/domain/webhook_request.rb b/lib/pact_broker/domain/webhook_request.rb index 9315ce4bb..947d71127 100644 --- a/lib/pact_broker/domain/webhook_request.rb +++ b/lib/pact_broker/domain/webhook_request.rb @@ -5,8 +5,10 @@ require 'pact_broker/messages' require 'net/http' require 'pact_broker/webhooks/redact_logs' +require 'pact_broker/webhooks/render' require 'pact_broker/api/pact_broker_urls' require 'pact_broker/build_http_options' +require 'cgi' module PactBroker @@ -91,11 +93,7 @@ def build_request uri, pact, execution_logger req.basic_auth(username, password) if username unless body.nil? - if String === body - req.body = gsub_body(pact, body) - else - req.body = gsub_body(pact, body.to_json) - end + req.body = PactBroker::Webhooks::Render.call(String === body ? body : body.to_json, pact) end execution_logger.info req.body @@ -150,7 +148,7 @@ def http_request(uri) end def build_uri pact - URI(gsub_url(pact, url)) + URI(PactBroker::Webhooks::Render.call(url, pact){ | value | CGI::escape(value)} ) end def url_with_credentials pact @@ -158,18 +156,6 @@ def url_with_credentials pact u.userinfo = "#{CGI::escape username}:#{display_password}" if username u end - - def gsub_body pact, body - base_url = PactBroker.configuration.base_url - body.gsub('${pactbroker.pactUrl}', PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact)) - end - - def gsub_url pact, url - base_url = PactBroker.configuration.base_url - pact_url = PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact) - escaped_pact_url = CGI::escape(pact_url) - url.gsub('${pactbroker.pactUrl}', escaped_pact_url) - end end end end diff --git a/lib/pact_broker/webhooks/render.rb b/lib/pact_broker/webhooks/render.rb new file mode 100644 index 000000000..ec6ff0e97 --- /dev/null +++ b/lib/pact_broker/webhooks/render.rb @@ -0,0 +1,23 @@ +module PactBroker + module Webhooks + class Render + def self.call(body, pact, verification = nil, &escaper) + base_url = PactBroker.configuration.base_url + params = { + '${pactbroker.pactUrl}' => PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact), + '${pactbroker.consumerVersionNumber}' => pact.consumer_version_number + } + + if escaper + params.keys.each do | key | + params[key] = escaper.call(params[key]) + end + end + + params.inject(body) do | body, (key, value) | + body.gsub(key, value) + end + end + end + end +end diff --git a/spec/lib/pact_broker/domain/webhook_request_spec.rb b/spec/lib/pact_broker/domain/webhook_request_spec.rb index ddc4b9c51..a4fdb9587 100644 --- a/spec/lib/pact_broker/domain/webhook_request_spec.rb +++ b/spec/lib/pact_broker/domain/webhook_request_spec.rb @@ -11,6 +11,9 @@ module Domain allow(PactBroker.logger).to receive(:info).and_call_original allow(PactBroker.logger).to receive(:debug).and_call_original allow(PactBroker.logger).to receive(:warn).and_call_original + allow(PactBroker::Webhooks::Render).to receive(:call) do | content, pact, verification, &block | + content + end end let(:username) { nil } @@ -57,51 +60,37 @@ module Domain describe "execute" do let!(:http_request) do stub_request(:post, "http://example.org/hook"). - with(:headers => {'Content-Type'=>'text/plain'}, :body => 'body'). + with(:headers => {'Content-Type'=>'text/plain'}, :body => request_body). to_return(:status => 200, :body => "respbod", :headers => {'Content-Type' => 'text/foo, blah'}) end - describe "when the String body contains a ${pactbroker.pactUrl} parameter" do - let!(:http_request) do - stub_request(:post, "http://example.org/hook"). - with(:headers => {'Content-Type'=>'text/plain'}, :body => "http://example.org/pact-url"). - to_return(:status => 200) - end - - let(:body) { "${pactbroker.pactUrl}" } + let(:request_body) { 'body' } - it "replaces the token with the live value" do - subject.execute(pact, options) - expect(http_request).to have_been_made + it "renders the url template" do + expect(PactBroker::Webhooks::Render).to receive(:call).with("http://example.org/hook", pact) do | content, pact, verification, &block | + expect(content).to eq "http://example.org/hook" + expect(pact).to be pact + expect(verification).to be nil + expect(block.call("foo bar")).to eq "foo+bar" + "http://example.org/hook" end + subject.execute(pact, options) end - describe "when the JSON body contains a ${pactbroker.pactUrl} parameter" do - let!(:http_request) do - stub_request(:post, "http://example.org/hook"). - with(:headers => {'Content-Type'=>'text/plain'}, :body => '{"url":"http://example.org/pact-url"}'). - to_return(:status => 200) - end - - let(:body) { { url: '${pactbroker.pactUrl}' } } - - it "replaces the token with the live value" do + context "when the body is a string" do + it "renders the body template with the String" do + expect(PactBroker::Webhooks::Render).to receive(:call).with('body', pact) subject.execute(pact, options) - expect(http_request).to have_been_made end end - describe "when the URL contains a ${pactbroker.pactUrl} parameter" do - let!(:http_request) do - stub_request(:post, "http://example.org/hook?url=http%3A%2F%2Fexample.org%2Fpact-url"). - to_return(:status => 200) - end - - let(:url) { 'http://example.org/hook?url=${pactbroker.pactUrl}' } + context "when the body is an object" do + let(:body) { {"foo" => "bar"} } + let(:request_body) { '{"foo":"bar"}' } - it "replaces the token with the live value" do + it "renders the body template with JSON" do + expect(PactBroker::Webhooks::Render).to receive(:call).with(request_body, pact) subject.execute(pact, options) - expect(http_request).to have_been_made end end @@ -234,21 +223,6 @@ module Domain end end - context "when the request has a JSONable body" do - let(:body) { [{"some": "json"}] } - - let!(:http_request) do - stub_request(:post, "http://example.org/hook"). - with(:headers => {'Content-Type'=>'text/plain'}, :body => body.to_json). - to_return(:status => 200, :body => "respbod", :headers => {'Content-Type' => 'text/foo, blah'}) - end - - it "converts the body to JSON before submitting the request" do - subject.execute(pact, options) - expect(http_request).to have_been_made - end - end - context "when the request has a nil body" do let(:body) { nil } @@ -275,7 +249,6 @@ module Domain end context "when the request is not successful" do - let!(:http_request) do stub_request(:post, "http://example.org/hook"). with(:headers => {'Content-Type'=>'text/plain'}, :body => 'body'). diff --git a/spec/lib/pact_broker/webhooks/render_spec.rb b/spec/lib/pact_broker/webhooks/render_spec.rb new file mode 100644 index 000000000..ae79bb08c --- /dev/null +++ b/spec/lib/pact_broker/webhooks/render_spec.rb @@ -0,0 +1,36 @@ +require 'pact_broker/webhooks/render' +require 'cgi' + +module PactBroker + module Webhooks + describe Render do + describe "#call" do + before do + allow(PactBroker::Api::PactBrokerUrls).to receive(:pact_url).and_return("http://foo") + end + + let(:body) do + "Foo ${pactbroker.pactUrl} ${pactbroker.consumerVersionNumber}" + end + + let(:pact) do + instance_double("pact", consumer_version_number: "1.2.3+foo") + end + + subject { Render.call(body, pact, nil) } + + it { is_expected.to eq "Foo http://foo 1.2.3+foo" } + + context "with an escaper" do + subject do + Render.call(body, pact, nil) do | value | + CGI.escape(value) + end + end + + it { is_expected.to eq "Foo http%3A%2F%2Ffoo 1.2.3%2Bfoo" } + end + end + end + end +end