Skip to content

Commit

Permalink
feat: add resource to view the triggered webhooks for a pact publication
Browse files Browse the repository at this point in the history
  • Loading branch information
bethesque committed Jun 17, 2018
1 parent 7379e23 commit 00f60c1
Show file tree
Hide file tree
Showing 16 changed files with 301 additions and 26 deletions.
1 change: 1 addition & 0 deletions lib/pact_broker/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ module PactBroker
add ['webhooks', 'consumer', :consumer_name], Api::Resources::Webhooks, {resource_name: "consumer_webhooks"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'webhooks'], Api::Resources::PactWebhooks, {resource_name: "pact_webhooks"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'webhooks', 'status'], Api::Resources::PactWebhooksStatus, {resource_name: "pact_webhooks_status"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'version', :consumer_version_number, 'triggered-webhooks'], Api::Resources::PactTriggeredWebhooks, {resource_name: "pact_triggered_webhooks"}

add ['webhooks', :uuid ], Api::Resources::Webhook, {resource_name: "webhook"}
add ['webhooks', :uuid, 'trigger', :trigger_uuid, 'logs' ], Api::Resources::TriggeredWebhookLogs, {resource_name: "triggered_webhook_logs"}
Expand Down
7 changes: 7 additions & 0 deletions lib/pact_broker/api/decorators/pact_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ def to_hash(options = {})
}
end

link :'pb:triggered-webhooks' do | options |
{
title: "Webhooks triggered by the publication of this pact",
href: pact_triggered_webhooks_url(represented, options.fetch(:base_url))
}
end

curies do | options |
[{
name: :pb,
Expand Down
27 changes: 1 addition & 26 deletions lib/pact_broker/api/decorators/pact_webhooks_status_decorator.rb
Original file line number Diff line number Diff line change
@@ -1,37 +1,12 @@
require_relative 'base_decorator'
require_relative 'timestamps'
require_relative 'pact_version_decorator'
require_relative 'triggered_webhook_decorator'

module PactBroker
module Api
module Decorators

class TriggeredWebhookDecorator < BaseDecorator
property :request_description, as: :name
property :status
property :number_of_attempts_made, as: :attemptsMade
property :number_of_attempts_remaining, as: :attemptsRemaining
property :trigger_type, as: :triggerType

property :created_at, as: :triggeredAt

link :logs do | context |
{
href: triggered_webhook_logs_url(represented, context[:base_url]),
title: "Webhook execution logs",
name: represented.request_description
}
end

link :'pb:webhook' do | context |
{
href: webhook_url(represented.webhook_uuid, context[:base_url]),
title: "Webhook",
name: represented.request_description
}
end
end

class PactWebhooksStatusDecorator < BaseDecorator

property :summary, exec_context: :decorator do
Expand Down
33 changes: 33 additions & 0 deletions lib/pact_broker/api/decorators/triggered_webhook_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
require_relative 'base_decorator'

module PactBroker
module Api
module Decorators
class TriggeredWebhookDecorator < BaseDecorator
property :request_description, as: :name
property :status
property :number_of_attempts_made, as: :attemptsMade
property :number_of_attempts_remaining, as: :attemptsRemaining
property :trigger_type, as: :triggerType

property :created_at, as: :triggeredAt

link :logs do | context |
{
href: triggered_webhook_logs_url(represented, context[:base_url]),
title: "Webhook execution logs",
name: represented.request_description
}
end

link :'pb:webhook' do | context |
{
href: webhook_url(represented.webhook_uuid, context[:base_url]),
title: "Webhook",
name: represented.request_description
}
end
end
end
end
end
19 changes: 19 additions & 0 deletions lib/pact_broker/api/decorators/triggered_webhooks_decorator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require 'pact_broker/api/decorators/base_decorator'
require 'pact_broker/api/decorators/triggered_webhook_decorator'

module PactBroker
module Api
module Decorators
class TriggeredWebhooksDecorator < BaseDecorator
collection :entries, as: :triggeredWebhooks, embedded: true, :extend => PactBroker::Api::Decorators::TriggeredWebhookDecorator

link :self do | options |
{
title: options.fetch(:resource_title),
href: options.fetch(:resource_url)
}
end
end
end
end
end
4 changes: 4 additions & 0 deletions lib/pact_broker/api/pact_broker_urls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,10 @@ def webhooks_status_url consumer, provider, base_url = ''
"#{webhooks_for_pact_url(consumer, provider, base_url)}/status"
end

def pact_triggered_webhooks_url pact, base_url = ''
"#{pact_url(base_url, pact)}/triggered-webhooks"
end

def triggered_webhook_logs_url triggered_webhook, base_url
"#{base_url}/webhooks/#{triggered_webhook.webhook_uuid}/trigger/#{triggered_webhook.trigger_uuid}/logs"
end
Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/api/resources/base_resource.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ def consumer
def provider
@provider ||= identifier_from_path[:provider_name] && find_pacticipant(identifier_from_path[:provider_name], "provider")
end

def pact
@pact ||= pact_service.find_pact(pact_params)
end
end
end
end
Expand Down
41 changes: 41 additions & 0 deletions lib/pact_broker/api/resources/pact_triggered_webhooks.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
require 'pact_broker/api/decorators/triggered_webhooks_decorator'

module PactBroker
module Api
module Resources
class PactTriggeredWebhooks < BaseResource
def allowed_methods
["GET"]
end

def content_types_provided
[["application/hal+json", :to_json]]
end

def resource_exists?
!!pact
end

def to_json
Decorators::TriggeredWebhooksDecorator.new(triggered_webhooks).to_json(decorator_options)
end

private

def triggered_webhooks
webhook_service.find_triggered_webhooks_for_pact(pact)
end

def resource_title
"Webhooks triggered by the publication of the #{pact.name[0].downcase}#{pact.name[1..-1]}"
end

def decorator_options
{
user_options: decorator_context.merge(resource_title: resource_title)
}
end
end
end
end
end
4 changes: 4 additions & 0 deletions lib/pact_broker/domain/pact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ def version_and_updated_date
def content_hash
JSON.parse(json_content, PACT_PARSING_OPTIONS)
end

def pact_publication_id
id
end
end

end
Expand Down
8 changes: 8 additions & 0 deletions lib/pact_broker/webhooks/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ def find_latest_triggered_webhooks consumer, provider
.all
end

def find_triggered_webhooks_for_pact pact
PactBroker::Webhooks::TriggeredWebhook
.where(pact_publication_id: pact.pact_publication_id)
.eager(:webhook)
.eager(:webhook_executions)
.reverse(:created_at, :id)
end

def fail_retrying_triggered_webhooks
TriggeredWebhook.retrying.update(status: TriggeredWebhook::STATUS_FAILURE)
end
Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/webhooks/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@ def self.find_latest_triggered_webhooks consumer, provider
def self.fail_retrying_triggered_webhooks
webhook_repository.fail_retrying_triggered_webhooks
end

def self.find_triggered_webhooks_for_pact pact
webhook_repository.find_triggered_webhooks_for_pact(pact)
end
end
end
end
20 changes: 20 additions & 0 deletions spec/features/get_triggered_webhooks_for_pact_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
RSpec.describe "Get triggered webhooks for pact" do
before do
td.create_pact_with_hierarchy
.create_webhook
.create_triggered_webhook
.create_webhook_execution
end

let(:td) { TestDataBuilder.new }
let(:path) { PactBroker::Api::PactBrokerUrls.pact_triggered_webhooks_url(td.pact) }
let(:json_response_body) { JSON.parse(subject.body) }

subject { get(path); last_response }

it { is_expected.to be_a_hal_json_success_response }

it "contains a list of triggered webhooks" do
expect(json_response_body['_embedded']['triggeredWebhooks'].size).to be 1
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
require 'pact_broker/api/decorators/triggered_webhook_decorator'

module PactBroker
module Api
module Decorators
describe TriggeredWebhookDecorator do
let(:triggered_webhook) do
double('PactBroker::Webhooks::TriggeredWebhook',
trigger_type: PactBroker::Webhooks::TriggeredWebhook::TRIGGER_TYPE_RESOURCE_CREATION,
status: status,
failure?: failure,
retrying?: retrying,
trigger_uuid: '1234',
webhook_uuid: '4321',
request_description: "GET http://foo",
pact_publication: pact,
number_of_attempts_made: 1,
number_of_attempts_remaining: 2,
created_at: DateTime.new(2017),
updated_at: DateTime.new(2017)
)
end

let(:pact) do
double('pact',
provider: double(name: 'provider'),
consumer: double(name: 'consumer'),
consumer_version_number: '1',
name: 'foo '
)
end

let(:failure) { false }
let(:retrying) { false }
let(:status) { PactBroker::Webhooks::TriggeredWebhook::STATUS_SUCCESS }
let(:logs_url) { "http://example.org/webhooks/4321/trigger/1234/logs" }
let(:user_options) { { base_url: "http://example.org" } }

let(:json) do
TriggeredWebhookDecorator.new(triggered_webhook).to_json(user_options: user_options)
end

subject { JSON.parse(json, symbolize_names: true) }

it "includes a link to the logs" do
expect(subject[:_links][:logs][:href]).to eq logs_url
end

it "includes a link to the webhook" do
expect(subject[:_links][:'pb:webhook'][:href]).to eq "http://example.org/webhooks/4321"
end

it "includes the triggered webhooks properties" do
expect(subject).to include(
status: 'success',
triggerType: 'resource_creation',
attemptsMade: 1,
attemptsRemaining: 2
)
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
require 'pact_broker/api/decorators/triggered_webhooks_decorator'
require 'pact_broker/webhooks/triggered_webhook'

module PactBroker
module Api
module Decorators
describe TriggeredWebhooksDecorator do
let(:triggered_webhook) do
instance_double(PactBroker::Webhooks::TriggeredWebhook).as_null_object
end
let(:decorator) { TriggeredWebhooksDecorator.new([triggered_webhook]) }
let(:user_options) { { resource_title: "Title", resource_url: "http://url" } }
let(:json) { decorator.to_json(user_options: user_options) }

subject { JSON.parse(json) }

it "includes a self relation" do
expect(subject['_links']['self']['title']).to eq "Title"
expect(subject['_links']['self']['href']).to eq "http://url"
end

it "includes an embedded list of triggered webhooks" do
expect(subject['_embedded']['triggeredWebhooks']).to be_instance_of(Array)
end
end
end
end
end
9 changes: 9 additions & 0 deletions spec/lib/pact_broker/api/pact_broker_urls_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,21 @@ module Api
describe PactBrokerUrls do

let(:base_url) { "http://example.org" }
let(:pact) { double('pact', consumer: consumer, provider: provider, consumer_version_number: "123") }
let(:consumer) { double('pacticipant', name: "Foo") }
let(:provider) { double('pacticipant', name: "Bar") }

describe "templated_tag_url_for_pacticipant" do
subject { PactBrokerUrls.templated_tag_url_for_pacticipant("Bar", base_url) }

it { is_expected.to eq "http://example.org/pacticipants/Bar/versions/{version}/tags/{tag}" }
end

describe "pact_triggered_webhooks_url" do
subject { PactBrokerUrls.pact_triggered_webhooks_url(pact, base_url) }

it { is_expected.to eq "http://example.org/pacts/provider/Bar/consumer/Foo/version/123/triggered-webhooks" }
end
end
end
end
Loading

0 comments on commit 00f60c1

Please sign in to comment.