Skip to content

Commit 86bc1ec

Browse files
committed
feat: add ${pactbroker.providerVersionNumber} to webhook templates
1 parent ec4e6e9 commit 86bc1ec

18 files changed

+134
-64
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Sequel.migration do
2+
change do
3+
alter_table(:triggered_webhooks) do
4+
add_foreign_key(:verification_id, :verifications)
5+
end
6+
end
7+
end

lib/pact_broker/doc/views/webhooks.markdown

+1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ The following variables may be used in the request parameters or body, and will
8888

8989
`${pactbroker.pactUrl}`: the "permalink" URL to the newly published pact (the URL specifying the consumer version URL, rather than the "/latest" format.)
9090
`${pactbroker.consumerVersionNumber}`: the version number of the most recent consumer version associated with the pact content.
91+
`${pactbroker.providerVersionNumber}`: the provider version number for the verification result
9192

9293
Example usage:
9394

lib/pact_broker/domain/webhook.rb

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ def request_description
3232
request && request.description
3333
end
3434

35-
def execute pact, options
35+
def execute pact, verification, options
3636
logger.info "Executing #{self}"
37-
request.execute pact, options
37+
request.execute pact, verification, options
3838
end
3939

4040
def to_s

lib/pact_broker/domain/webhook_request.rb

+12-12
Original file line numberDiff line numberDiff line change
@@ -52,21 +52,21 @@ def display_password
5252
password.nil? ? nil : "**********"
5353
end
5454

55-
def execute pact, options = {}
55+
def execute pact, verification, options = {}
5656
logs = StringIO.new
5757
execution_logger = Logger.new(logs)
5858
begin
59-
execute_and_build_result(pact, options, logs, execution_logger)
59+
execute_and_build_result(pact, verification, options, logs, execution_logger)
6060
rescue StandardError => e
6161
handle_error_and_build_result(e, options, logs, execution_logger)
6262
end
6363
end
6464

6565
private
6666

67-
def execute_and_build_result pact, options, logs, execution_logger
68-
uri = build_uri(pact)
69-
req = build_request(uri, pact, execution_logger)
67+
def execute_and_build_result pact, verification, options, logs, execution_logger
68+
uri = build_uri(pact, verification)
69+
req = build_request(uri, pact, verification, execution_logger)
7070
response = do_request(uri, req)
7171
log_response(response, execution_logger, options)
7272
result = WebhookExecutionResult.new(response, logs.string)
@@ -80,9 +80,9 @@ def handle_error_and_build_result e, options, logs, execution_logger
8080
WebhookExecutionResult.new(nil, logs.string, e)
8181
end
8282

83-
def build_request uri, pact, execution_logger
83+
def build_request uri, pact, verification, execution_logger
8484
req = http_request(uri)
85-
execution_logger.info "HTTP/1.1 #{method.upcase} #{url_with_credentials(pact)}"
85+
execution_logger.info "HTTP/1.1 #{method.upcase} #{url_with_credentials(pact, verification)}"
8686

8787
headers.each_pair do | name, value |
8888
execution_logger.info Webhooks::RedactLogs.call("#{name}: #{value}")
@@ -92,7 +92,7 @@ def build_request uri, pact, execution_logger
9292
req.basic_auth(username, password) if username
9393

9494
unless body.nil?
95-
req.body = PactBroker::Webhooks::Render.call(String === body ? body : body.to_json, pact)
95+
req.body = PactBroker::Webhooks::Render.call(String === body ? body : body.to_json, pact, verification)
9696
end
9797

9898
execution_logger.info(req.body) if req.body
@@ -173,12 +173,12 @@ def http_request(uri)
173173
Net::HTTP.const_get(method.capitalize).new(uri)
174174
end
175175

176-
def build_uri pact
177-
URI(PactBroker::Webhooks::Render.call(url, pact){ | value | CGI::escape(value)} )
176+
def build_uri(pact, verification)
177+
URI(PactBroker::Webhooks::Render.call(url, pact, verification){ | value | CGI::escape(value)} )
178178
end
179179

180-
def url_with_credentials pact
181-
u = build_uri(pact)
180+
def url_with_credentials pact, verification
181+
u = build_uri(pact, verification)
182182
u.userinfo = "#{CGI::escape username}:#{display_password}" if username
183183
u
184184
end

lib/pact_broker/pacts/service.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def update_pact params, existing_pact
107107
updated_pact = pact_repository.update existing_pact.id, params
108108

109109
if existing_pact.json_content != updated_pact.json_content
110-
webhook_service.execute_webhooks updated_pact, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED
110+
webhook_service.execute_webhooks updated_pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED
111111
end
112112

113113
updated_pact

lib/pact_broker/verifications/service.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ def create next_verification_number, params, pact
2222
provider_version_number = params.fetch('providerApplicationVersion')
2323
PactBroker::Api::Decorators::VerificationDecorator.new(verification).from_hash(params)
2424
verification.number = next_verification_number
25-
webhook_service.execute_webhooks pact, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED
2625
verification = verification_repository.create(verification, provider_version_number, pact)
26+
webhook_service.execute_webhooks pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED
27+
verification
2728
end
2829

2930
def errors params

lib/pact_broker/webhooks/render.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ def self.call(body, pact, verification = nil, &escaper)
55
base_url = PactBroker.configuration.base_url
66
params = {
77
'${pactbroker.pactUrl}' => PactBroker::Api::PactBrokerUrls.pact_url(base_url, pact),
8-
'${pactbroker.consumerVersionNumber}' => pact.consumer_version_number
8+
'${pactbroker.consumerVersionNumber}' => pact.consumer_version_number,
9+
'${pactbroker.providerVersionNumber}' => verification ? verification.provider_version_number : ""
910
}
1011

1112
if escaper

lib/pact_broker/webhooks/repository.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,12 @@ def find_by_consumer_and_provider_existing_at consumer, provider, date_time
7878
.collect(&:to_domain)
7979
end
8080

81-
def create_triggered_webhook trigger_uuid, webhook, pact, trigger_type
81+
def create_triggered_webhook trigger_uuid, webhook, pact, verification, trigger_type
8282
db_webhook = Webhook.where(uuid: webhook.uuid).single_record
8383
TriggeredWebhook.create(
8484
status: TriggeredWebhook::STATUS_NOT_RUN,
8585
pact_publication_id: pact.id,
86+
verification: verification,
8687
webhook: db_webhook,
8788
webhook_uuid: db_webhook.uuid,
8889
trigger_uuid: trigger_uuid,

lib/pact_broker/webhooks/service.rb

+6-6
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ def self.find_all
5959
webhook_repository.find_all
6060
end
6161

62-
def self.execute_webhook_now webhook, pact
63-
triggered_webhook = webhook_repository.create_triggered_webhook(next_uuid, webhook, pact, USER)
62+
def self.execute_webhook_now webhook, pact, verification = nil
63+
triggered_webhook = webhook_repository.create_triggered_webhook(next_uuid, webhook, pact, verification, USER)
6464
options = { failure_log_message: "Webhook execution failed", show_response: PactBroker.configuration.show_webhook_response?}
6565
webhook_execution_result = execute_triggered_webhook_now triggered_webhook, options
6666
if webhook_execution_result.success?
@@ -85,21 +85,21 @@ def self.find_by_consumer_and_provider consumer, provider
8585
webhook_repository.find_by_consumer_and_provider consumer, provider
8686
end
8787

88-
def self.execute_webhooks pact, event_name
88+
def self.execute_webhooks pact, verification, event_name
8989
webhooks = webhook_repository.find_by_consumer_and_provider_and_event_name pact.consumer, pact.provider, event_name
9090

9191
if webhooks.any?
92-
run_later(webhooks, pact, event_name)
92+
run_later(webhooks, pact, verification, event_name)
9393
else
9494
logger.debug "No webhook found for consumer \"#{pact.consumer.name}\" and provider \"#{pact.provider.name}\""
9595
end
9696
end
9797

98-
def self.run_later webhooks, pact, event_name
98+
def self.run_later webhooks, pact, verification, event_name
9999
trigger_uuid = next_uuid
100100
webhooks.each do | webhook |
101101
begin
102-
triggered_webhook = webhook_repository.create_triggered_webhook(trigger_uuid, webhook, pact, RESOURCE_CREATION)
102+
triggered_webhook = webhook_repository.create_triggered_webhook(trigger_uuid, webhook, pact, verification, RESOURCE_CREATION)
103103
logger.info "Scheduling job for #{webhook.description} with uuid #{webhook.uuid}"
104104
# Bit of a dodgey hack to make sure the request transaction has finished before we execute the webhook
105105
Job.perform_in(5, triggered_webhook: triggered_webhook)

lib/pact_broker/webhooks/triggered_webhook.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ def not_run
3737
associate(:one_to_many, :webhook_executions, :class => "PactBroker::Webhooks::Execution", :key => :triggered_webhook_id, :primary_key => :id, :order => :id)
3838
associate(:many_to_one, :webhook, :class => "PactBroker::Webhooks::Webhook", :key => :webhook_id, :primary_key => :id)
3939
associate(:many_to_one, :pact_publication, :class => "PactBroker::Pacts::PactPublication", :key => :pact_publication_id, :primary_key => :id)
40+
associate(:many_to_one, :verification, :class => "PactBroker::Domain::Verification", :key => :verification_id, :primary_key => :id)
4041
associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
4142
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
4243

@@ -49,7 +50,7 @@ def execute options
4950
# getting a random 'no method to_domain for null' error
5051
# not sure on which object, so splitting this out into two lines
5152
pact = pact_publication.to_domain
52-
webhook.to_domain.execute(pact, options)
53+
webhook.to_domain.execute(pact, verification, options)
5354
end
5455

5556
def consumer_name

spec/integration/webhooks/certificate_spec.rb

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
let(:pact) { td.create_pact_with_hierarchy.and_return(:pact) }
1818

19-
subject { webhook_request.execute(pact) }
19+
subject { webhook_request.execute(pact, nil) }
2020

2121
context "without the correct cacert" do
2222
it "fails" do

spec/lib/pact_broker/domain/webhook_request_spec.rb

+27-24
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ module Domain
2222
let(:options) { {failure_log_message: 'oops', show_response: show_response} }
2323
let(:show_response) { true }
2424
let(:pact) { instance_double('PactBroker::Domain::Pact') }
25+
let(:verification) { instance_double('PactBroker::Domain::Verification') }
26+
let(:logs) { execute.logs }
2527

2628
subject do
2729
WebhookRequest.new(
@@ -33,7 +35,8 @@ module Domain
3335
body: body)
3436
end
3537

36-
let(:logs) { subject.execute(pact, options).logs }
38+
let(:execute) { subject.execute(pact, verification, options) }
39+
3740

3841
describe "description" do
3942
it "returns a brief description of the HTTP request" do
@@ -65,20 +68,20 @@ module Domain
6568
let(:request_body) { 'body' }
6669

6770
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 |
71+
expect(PactBroker::Webhooks::Render).to receive(:call).with("http://example.org/hook", pact, verification) do | content, pact, verification, &block |
6972
expect(content).to eq "http://example.org/hook"
7073
expect(pact).to be pact
71-
expect(verification).to be nil
74+
expect(verification).to be verification
7275
expect(block.call("foo bar")).to eq "foo+bar"
7376
"http://example.org/hook"
7477
end
75-
subject.execute(pact, options)
78+
execute
7679
end
7780

7881
context "when the body is a string" do
7982
it "renders the body template with the String" do
80-
expect(PactBroker::Webhooks::Render).to receive(:call).with('body', pact)
81-
subject.execute(pact, options)
83+
expect(PactBroker::Webhooks::Render).to receive(:call).with('body', pact, verification)
84+
execute
8285
end
8386
end
8487

@@ -87,20 +90,20 @@ module Domain
8790
let(:request_body) { '{"foo":"bar"}' }
8891

8992
it "renders the body template with JSON" do
90-
expect(PactBroker::Webhooks::Render).to receive(:call).with(request_body, pact)
91-
subject.execute(pact, options)
93+
expect(PactBroker::Webhooks::Render).to receive(:call).with(request_body, pact, verification)
94+
execute
9295
end
9396
end
9497

9598
it "executes the configured request" do
96-
subject.execute(pact, options)
99+
execute
97100
expect(http_request).to have_been_made
98101
end
99102

100103
it "logs the request" do
101104
allow(PactBroker.logger).to receive(:info)
102105
expect(PactBroker.logger).to receive(:info).with(/POST.*example.*text.*body/)
103-
subject.execute(pact, options)
106+
execute
104107
end
105108

106109
it "logs the response" do
@@ -109,7 +112,7 @@ module Domain
109112
expect(PactBroker.logger).to receive(:info).with(/response.*200/)
110113
expect(PactBroker.logger).to receive(:debug).with(/content-type/)
111114
expect(PactBroker.logger).to receive(:debug).with(/respbod/)
112-
subject.execute(pact, options)
115+
execute
113116
end
114117

115118
describe "execution logs" do
@@ -204,7 +207,7 @@ module Domain
204207
let(:password) { "password" }
205208

206209
it "uses the credentials" do
207-
subject.execute(pact, options)
210+
execute
208211
expect(http_request_with_basic_auth).to have_been_made
209212
end
210213
end
@@ -214,7 +217,7 @@ module Domain
214217
let(:password) { "p@$$w0rd!" }
215218

216219
it "uses the credentials" do
217-
subject.execute(pact, options)
220+
execute
218221
expect(http_request_with_basic_auth).to have_been_made
219222
end
220223
end
@@ -231,7 +234,7 @@ module Domain
231234
end
232235

233236
it "uses SSL" do
234-
subject.execute(pact, options)
237+
execute
235238
expect(https_request).to have_been_made
236239
end
237240
end
@@ -246,18 +249,18 @@ module Domain
246249
end
247250

248251
it "executes the request without a body" do
249-
subject.execute(pact, options)
252+
execute
250253
expect(http_request).to have_been_made
251254
end
252255
end
253256

254257
context "when the request is successful" do
255258
it "returns a WebhookExecutionResult with success=true" do
256-
expect(subject.execute(pact, options).success?).to be true
259+
expect(execute.success?).to be true
257260
end
258261

259262
it "sets the response on the result" do
260-
expect(subject.execute(pact, options).response).to be_instance_of(Net::HTTPOK)
263+
expect(execute.response).to be_instance_of(Net::HTTPOK)
261264
end
262265
end
263266

@@ -270,11 +273,11 @@ module Domain
270273
end
271274

272275
it "returns a WebhookExecutionResult with success=false" do
273-
expect(subject.execute(pact, options).success?).to be false
276+
expect(execute.success?).to be false
274277
end
275278

276279
it "sets the response on the result" do
277-
expect(subject.execute(pact, options).response).to be_instance_of(Net::HTTPInternalServerError)
280+
expect(execute.response).to be_instance_of(Net::HTTPInternalServerError)
278281
end
279282
end
280283

@@ -285,15 +288,15 @@ module Domain
285288
end
286289

287290
it "removes the non UTF-8 characters before saving the logs so they don't blow up the database" do
288-
result = subject.execute(pact, options)
291+
result = execute
289292
expect(result.logs).to include "This has some invalid chars"
290293
end
291294

292295
it "logs that it has cleaned the string to the execution logger" do
293296
logger = double("logger").as_null_object
294297
allow(Logger).to receive(:new).and_return(logger)
295298
expect(logger).to receive(:debug).with(/Note that invalid UTF-8 byte sequences were removed/)
296-
subject.execute(pact, options)
299+
execute
297300
end
298301
end
299302

@@ -308,15 +311,15 @@ class WebhookTestError < StandardError; end
308311

309312
it "logs the error" do
310313
expect(PactBroker.logger).to receive(:error).with(/Error.*WebhookTestError.*blah/)
311-
subject.execute(pact, options)
314+
execute
312315
end
313316

314317
it "returns a WebhookExecutionResult with success=false" do
315-
expect(subject.execute(pact, options).success?).to be false
318+
expect(execute.success?).to be false
316319
end
317320

318321
it "returns a WebhookExecutionResult with an error" do
319-
expect(subject.execute(pact, options).error).to be_instance_of WebhookTestError
322+
expect(execute.error).to be_instance_of WebhookTestError
320323
end
321324

322325
it "logs the failure_log_message" do

0 commit comments

Comments
 (0)