Skip to content

Commit c3e8df0

Browse files
committed
feat: add resource to view the triggered webhooks for a verification result
1 parent 00f60c1 commit c3e8df0

15 files changed

+240
-2
lines changed

lib/pact_broker/api.rb

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ module PactBroker
2222
# Verifications
2323
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'pact-version', :pact_version_sha, 'verification-results'], Api::Resources::Verifications, {resource_name: "verification_results"}
2424
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'pact-version', :pact_version_sha, 'verification-results', :verification_number], Api::Resources::Verification, {resource_name: "verification_result"}
25+
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'pact-version', :pact_version_sha, 'verification-results', :verification_number, 'triggered-webhooks'], Api::Resources::VerificationTriggeredWebhooks, {resource_name: "verification_result_triggered_webhooks"}
2526
add ['verification-results', 'consumer', :consumer_name, 'version', :consumer_version_number,'latest'], Api::Resources::LatestVerificationsForConsumerVersion, {resource_name: "verification_results_for_consumer_version"}
2627

2728
# Badges

lib/pact_broker/api/decorators/verification_decorator.rb

+6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ class VerificationDecorator < BaseDecorator
2828
}
2929
end
3030

31+
link 'pb:triggered-webhooks' do | options |
32+
{
33+
title: 'Webhooks triggered by the publication of this verification result',
34+
href: verification_triggered_webhooks_url(represented, options.fetch(:base_url))
35+
}
36+
end
3137
end
3238
end
3339
end

lib/pact_broker/api/pact_broker_urls.rb

+4
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ def latest_verifications_for_consumer_version_url version, base_url
120120
"#{base_url}/verification-results/consumer/#{url_encode(version.pacticipant.name)}/version/#{version.number}/latest"
121121
end
122122

123+
def verification_triggered_webhooks_url verification, base_url = ''
124+
"#{verification_url(verification, base_url)}/triggered-webhooks"
125+
end
126+
123127
def verification_publication_url pact, base_url
124128
"#{pactigration_base_url(base_url, pact)}/pact-version/#{pact.pact_version_sha}/verification-results"
125129
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
require 'pact_broker/api/decorators/triggered_webhooks_decorator'
2+
3+
module PactBroker
4+
module Api
5+
module Resources
6+
class VerificationTriggeredWebhooks < BaseResource
7+
def allowed_methods
8+
["GET"]
9+
end
10+
11+
def content_types_provided
12+
[["application/hal+json", :to_json]]
13+
end
14+
15+
def resource_exists?
16+
!!verification
17+
end
18+
19+
def to_json
20+
Decorators::TriggeredWebhooksDecorator.new(triggered_webhooks).to_json(decorator_options)
21+
end
22+
23+
private
24+
25+
def triggered_webhooks
26+
webhook_service.find_triggered_webhooks_for_verification(verification)
27+
end
28+
29+
def resource_title
30+
"Webhooks triggered by the publication of verification result #{verification.number}"
31+
end
32+
33+
def decorator_options
34+
{
35+
user_options: decorator_context.merge(resource_title: resource_title)
36+
}
37+
end
38+
39+
def verification
40+
@verification ||= verification_service.find(identifier_from_path)
41+
end
42+
end
43+
end
44+
end
45+
end

lib/pact_broker/domain/webhook.rb

+8
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ def consumer_name
5656
def provider_name
5757
provider && provider.name
5858
end
59+
60+
def trigger_on_contract_content_changed?
61+
events.any?(&:contract_content_changed?)
62+
end
63+
64+
def trigger_on_provider_verification_published?
65+
events.any?(&:provider_verification_published?)
66+
end
5967
end
6068
end
6169
end

lib/pact_broker/webhooks/repository.rb

+8
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,14 @@ def find_triggered_webhooks_for_pact pact
185185
.reverse(:created_at, :id)
186186
end
187187

188+
def find_triggered_webhooks_for_verification verification
189+
PactBroker::Webhooks::TriggeredWebhook
190+
.where(verification_id: verification.id)
191+
.eager(:webhook)
192+
.eager(:webhook_executions)
193+
.reverse(:created_at, :id)
194+
end
195+
188196
def fail_retrying_triggered_webhooks
189197
TriggeredWebhook.retrying.update(status: TriggeredWebhook::STATUS_FAILURE)
190198
end

lib/pact_broker/webhooks/service.rb

+4
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ def self.fail_retrying_triggered_webhooks
132132
def self.find_triggered_webhooks_for_pact pact
133133
webhook_repository.find_triggered_webhooks_for_pact(pact)
134134
end
135+
136+
def self.find_triggered_webhooks_for_verification verification
137+
webhook_repository.find_triggered_webhooks_for_verification(verification)
138+
end
135139
end
136140
end
137141
end

lib/pact_broker/webhooks/webhook_event.rb

+8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ class WebhookEvent < Sequel::Model
1717
include PactBroker::Repositories::Helpers
1818
end
1919

20+
def contract_content_changed?
21+
name == CONTRACT_CONTENT_CHANGED
22+
end
23+
24+
def provider_verification_published?
25+
name == VERIFICATION_PUBLISHED
26+
end
27+
2028
end
2129

2230
WebhookEvent.plugin :timestamps, update_on_create: true

script/seed.rb

+2
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,13 @@ def publish_pact params = {}
5454

5555
# .create_webhook(method: 'GET', url: 'https://localhost:9393?url=${pactbroker.pactUrl}', body: '${pactbroker.pactUrl}')
5656
TestDataBuilder.new
57+
.create_global_webhook(method: 'GET', url: "http://example.org?consumer=${pactbroker.consumerName}&provider=${pactbroker.providerName}")
5758
.create_certificate(path: 'spec/fixtures/certificates/self-signed.badssl.com.pem')
5859
.create_consumer("Foo")
5960
.create_label("microservice")
6061
.create_provider("Bar")
6162
.create_label("microservice")
63+
.create_verification_webhook(method: 'GET', url: "http://example.org")
6264
.create_consumer_webhook(method: 'GET', url: 'https://www.google.com.au', event_names: ['provider_verification_published'])
6365
.create_provider_webhook(method: 'GET', url: 'https://theage.com.au')
6466
.create_webhook(method: 'GET', url: 'https://self-signed.badssl.com')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
RSpec.describe "Get triggered webhooks for verification" do
2+
before do
3+
td.create_pact_with_hierarchy
4+
.create_verification_webhook
5+
.create_verification
6+
.create_triggered_webhook
7+
.create_webhook_execution
8+
end
9+
10+
let(:td) { TestDataBuilder.new }
11+
let(:path) { PactBroker::Api::PactBrokerUrls.verification_triggered_webhooks_url(td.verification) }
12+
let(:json_response_body) { JSON.parse(subject.body) }
13+
14+
subject { get(path); last_response }
15+
16+
it { is_expected.to be_a_hal_json_success_response }
17+
18+
it "contains a list of triggered webhooks" do
19+
expect(json_response_body['_embedded']['triggeredWebhooks'].size).to be 1
20+
end
21+
end

spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb

+8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ module PactBroker
44
module Api
55
module Decorators
66
describe VerificationDecorator do
7+
before do
8+
allow_any_instance_of(VerificationDecorator).to receive(:verification_triggered_webhooks_url).and_return("http://triggered-webhooks")
9+
end
710

811
let(:verification) do
912
instance_double('PactBroker::Domain::Verification',
@@ -30,6 +33,7 @@ module Decorators
3033

3134
let(:options) { { user_options: { base_url: 'http://example.org' } } }
3235

36+
3337
subject { JSON.parse VerificationDecorator.new(verification).to_json(options), symbolize_names: true }
3438

3539
it "includes the success status" do
@@ -55,6 +59,10 @@ module Decorators
5559
it "includes a link to its pact" do
5660
expect(subject[:_links][:'pb:pact-version'][:href]).to match %r{http://example.org/pacts/}
5761
end
62+
63+
it "includes a link to the triggered webhooks" do
64+
expect(subject[:_links][:'pb:triggered-webhooks'][:href]).to eq "http://triggered-webhooks"
65+
end
5866
end
5967
end
6068
end

spec/lib/pact_broker/api/pact_broker_urls_spec.rb

+13
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,13 @@ module Api
88
let(:pact) { double('pact', consumer: consumer, provider: provider, consumer_version_number: "123") }
99
let(:consumer) { double('pacticipant', name: "Foo") }
1010
let(:provider) { double('pacticipant', name: "Bar") }
11+
let(:verification) do
12+
instance_double(PactBroker::Domain::Verification,
13+
consumer_name: "Foo",
14+
provider_name: "Bar",
15+
pact_version_sha: "1234",
16+
number: "1")
17+
end
1118

1219
describe "templated_tag_url_for_pacticipant" do
1320
subject { PactBrokerUrls.templated_tag_url_for_pacticipant("Bar", base_url) }
@@ -20,6 +27,12 @@ module Api
2027

2128
it { is_expected.to eq "http://example.org/pacts/provider/Bar/consumer/Foo/version/123/triggered-webhooks" }
2229
end
30+
31+
describe "verification_triggered_webhooks_url" do
32+
subject { PactBrokerUrls.verification_triggered_webhooks_url(verification, base_url) }
33+
34+
it { is_expected.to eq "http://example.org/pacts/provider/Bar/consumer/Foo/pact-version/1234/verification-results/1/triggered-webhooks" }
35+
end
2336
end
2437
end
2538
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
require 'pact_broker/api/resources/verification_triggered_webhooks'
2+
3+
module PactBroker
4+
module Api
5+
module Resources
6+
describe VerificationTriggeredWebhooks do
7+
describe "GET" do
8+
before do
9+
allow(Decorators::TriggeredWebhooksDecorator).to receive(:new).and_return(decorator)
10+
allow_any_instance_of(VerificationTriggeredWebhooks).to receive(:webhook_service).and_return(webhook_service)
11+
allow_any_instance_of(VerificationTriggeredWebhooks).to receive(:verification_service).and_return(verification_service)
12+
allow(webhook_service).to receive(:find_triggered_webhooks_for_verification).and_return(triggered_webhooks)
13+
end
14+
15+
let(:decorator) { instance_double(Decorators::TriggeredWebhooksDecorator, to_json: 'json') }
16+
let(:webhook_service) { class_double(PactBroker::Webhooks::Service) }
17+
let(:verification_service) { class_double(PactBroker::Verifications::Service, find: verification) }
18+
let(:verification) { instance_double(PactBroker::Domain::Verification, number: "1") }
19+
let(:triggered_webhooks) { double('triggered_webhooks') }
20+
let(:path) { "/pacts/provider/bar/consumer/foo/pact-version/1234/verification-results/1/triggered-webhooks" }
21+
22+
subject { get path; last_response }
23+
24+
it "searchs for the verification" do
25+
expect(verification_service).to receive(:find).with(
26+
hash_including(
27+
provider_name: "bar",
28+
consumer_name: "foo",
29+
pact_version_sha: "1234",
30+
verification_number: "1"
31+
)
32+
)
33+
subject
34+
end
35+
36+
context "when the verification exists" do
37+
38+
it "finds the triggered webhooks for the verification" do
39+
expect(webhook_service).to receive(:find_triggered_webhooks_for_verification)
40+
subject
41+
end
42+
43+
it { is_expected.to be_a_hal_json_success_response }
44+
45+
it "generates the JSON response body" do
46+
expect(Decorators::TriggeredWebhooksDecorator).to receive(:new).with(triggered_webhooks)
47+
expect(decorator).to receive(:to_json) do | options |
48+
expect(options[:user_options]).to include(resource_title: "Webhooks triggered by the publication of verification result 1")
49+
expect(options[:user_options]).to include(resource_url: "http://example.org#{path}")
50+
end
51+
subject
52+
end
53+
54+
it "returns the generated JSON response body" do
55+
expect(subject.body).to eq 'json'
56+
end
57+
end
58+
59+
context "when the verification does not exist" do
60+
let(:verification) { nil }
61+
62+
it { is_expected.to be_a_404_response }
63+
end
64+
end
65+
end
66+
end
67+
end
68+
end

spec/lib/pact_broker/webhooks/repository_spec.rb

+38-1
Original file line numberDiff line numberDiff line change
@@ -625,7 +625,6 @@ module Webhooks
625625
.create_webhook_execution
626626
.create_triggered_webhook(trigger_uuid: '777', created_at: DateTime.new(2018))
627627
.create_webhook_execution
628-
629628
end
630629

631630
subject { Repository.new.find_latest_triggered_webhooks_for_pact(td.pact) }
@@ -635,6 +634,44 @@ module Webhooks
635634
end
636635
end
637636

637+
describe "find_triggered_webhooks_for_pact" do
638+
before do
639+
td
640+
.create_pact_with_hierarchy("Foo", "1", "Bar")
641+
.create_webhook
642+
.create_triggered_webhook(trigger_uuid: "1")
643+
.create_webhook_execution
644+
.create_consumer_version("2")
645+
.create_pact
646+
.create_triggered_webhook(trigger_uuid: "2")
647+
.create_webhook_execution
648+
end
649+
650+
subject { Repository.new.find_triggered_webhooks_for_pact(td.pact) }
651+
652+
it "finds the triggered webhooks" do
653+
expect(subject.collect(&:trigger_uuid).sort).to eq ["2"]
654+
end
655+
end
656+
657+
describe "find_triggered_webhooks_for_verification" do
658+
before do
659+
td
660+
.create_pact_with_hierarchy("Foo", "1", "Bar")
661+
.create_verification_webhook
662+
.create_verification(provider_version: "1")
663+
.create_triggered_webhook(trigger_uuid: "1")
664+
.create_verification(provider_version: "2", number: 2)
665+
.create_triggered_webhook(trigger_uuid: "2")
666+
end
667+
668+
subject { Repository.new.find_triggered_webhooks_for_verification(td.verification) }
669+
670+
it "finds the triggered webhooks" do
671+
expect(subject.collect(&:trigger_uuid).sort).to eq ["2"]
672+
end
673+
end
674+
638675
describe "fail_retrying_triggered_webhooks" do
639676
before do
640677
td.create_pact_with_hierarchy

spec/support/test_data_builder.rb

+6-1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,10 @@ def create_webhook parameters = {}
261261
self
262262
end
263263

264+
def create_verification_webhook parameters = {}
265+
create_webhook(parameters.merge(event_names: PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED))
266+
end
267+
264268
def create_global_webhook parameters = {}
265269
create_webhook(parameters.merge(consumer: nil, provider: nil))
266270
end
@@ -280,7 +284,8 @@ def create_verification_webhook params = {}
280284
def create_triggered_webhook params = {}
281285
params.delete(:comment)
282286
trigger_uuid = params[:trigger_uuid] || webhook_service.next_uuid
283-
@triggered_webhook = webhook_repository.create_triggered_webhook trigger_uuid, @webhook, @pact, nil, PactBroker::Webhooks::Service::RESOURCE_CREATION
287+
verification = @webhook.trigger_on_provider_verification_published? ? @verification : nil
288+
@triggered_webhook = webhook_repository.create_triggered_webhook trigger_uuid, @webhook, @pact, verification, PactBroker::Webhooks::Service::RESOURCE_CREATION
284289
@triggered_webhook.update(status: params[:status]) if params[:status]
285290
set_created_at_if_set params[:created_at], :triggered_webhooks, {id: @triggered_webhook.id}
286291
self

0 commit comments

Comments
 (0)