Skip to content

Commit

Permalink
feat: add metadata to webhook and verification URLs to correctly trac…
Browse files Browse the repository at this point in the history
…k relevant versions and tags (#274)

* refactor: pass in database_connector from rack env instead of thread for verifications, and refactor webhook options

* refactor: pass in database_connector from rack env instead of thread for pact publications, and refactor webhook options

* refactor: pass in webhook show_response setting from resource via execution options

* test: add code for manual webhook testing
  • Loading branch information
bethesque authored May 23, 2019
1 parent 55d7f4a commit 426b0b1
Show file tree
Hide file tree
Showing 41 changed files with 716 additions and 269 deletions.
2 changes: 2 additions & 0 deletions lib/pact_broker/api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ module PactBroker
# Pacts
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'version', :consumer_version_number], Api::Resources::Pact, {resource_name: "pact_publication"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'pact-version', :pact_version_sha], Api::Resources::PactVersion, {resource_name: "pact_publication"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'pact-version', :pact_version_sha, 'metadata', :metadata], Api::Resources::PactVersion, {resource_name: "pact_publication"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'version', :consumer_version_number, 'previous-distinct'], Api::Resources::PreviousDistinctPactVersion, {resource_name: "previous_distinct_pact_version"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'version', :consumer_version_number, 'diff', 'previous-distinct'], Api::Resources::PactContentDiff, {resource_name: "previous_distinct_pact_version_diff"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'version', :consumer_version_number, 'diff', 'version', :comparison_consumer_version], Api::Resources::PactContentDiff, {resource_name: "pact_version_diff_by_consumer_version"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'pact-version', :pact_version_sha, 'diff', 'pact-version', :comparison_pact_version_sha], Api::Resources::PactContentDiff, {resource_name: "pact_version_diff_by_pact_version_sha"}

# Verifications
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'pact-version', :pact_version_sha, 'verification-results'], Api::Resources::Verifications, {resource_name: "verification_results"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'pact-version', :pact_version_sha, 'metadata', :metadata, 'verification-results'], Api::Resources::Verifications, {resource_name: "verification_results"}
add ['pacts', 'provider', :provider_name, 'consumer', :consumer_name, 'pact-version', :pact_version_sha, 'verification-results', :verification_number], Api::Resources::Verification, {resource_name: "verification_result"}
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"}
add ['verification-results', 'consumer', :consumer_name, 'version', :consumer_version_number,'latest'], Api::Resources::LatestVerificationsForConsumerVersion, {resource_name: "verification_results_for_consumer_version"}
Expand Down
2 changes: 1 addition & 1 deletion lib/pact_broker/api/decorators/pact_decorator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ def to_hash(options = {})
link :'pb:publish-verification-results' do | options |
{
title: "Publish verification results",
href: verification_publication_url(represented, options.fetch(:base_url))
href: verification_publication_url(represented, options.fetch(:base_url), options[:metadata])
}
end

Expand Down
26 changes: 24 additions & 2 deletions lib/pact_broker/api/pact_broker_urls.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,27 @@ def pact_version_url pact, base_url = ''
"#{pactigration_base_url(base_url, pact)}/pact-version/#{pact.pact_version_sha}"
end

def pact_version_url_with_metadata pact, base_url = ''
"#{pactigration_base_url(base_url, pact)}/pact-version/#{pact.pact_version_sha}/metadata/#{build_webhook_metadata(pact)}"
end

def build_webhook_metadata(pact)
Base64.strict_encode64(Rack::Utils.build_nested_query(
consumer_version_number: pact.consumer_version_number,
consumer_version_tags: pact.consumer_version_tag_names
))
end

def parse_webhook_metadata(metadata)
if metadata
Rack::Utils.parse_nested_query(Base64.strict_decode64(metadata)).each_with_object({}) do | (k, v), new_hash |
new_hash[k.to_sym] = v
end
else
{}
end
end

def pact_url_from_params base_url, params
[ base_url, 'pacts',
'provider', url_encode(params[:provider_name]),
Expand Down Expand Up @@ -136,8 +157,9 @@ def verification_triggered_webhooks_url verification, base_url = ''
"#{verification_url(verification, base_url)}/triggered-webhooks"
end

def verification_publication_url pact, base_url
"#{pactigration_base_url(base_url, pact)}/pact-version/#{pact.pact_version_sha}/verification-results"
def verification_publication_url pact, base_url, metadata = ""
metadata_part = metadata ? "/metadata/#{metadata}" : ""
"#{pactigration_base_url(base_url, pact)}/pact-version/#{pact.pact_version_sha}#{metadata_part}/verification-results"
end

def tag_url base_url, tag
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 @@ -167,6 +167,10 @@ def provider
def pact
@pact ||= pact_service.find_pact(pact_params)
end

def database_connector
request.env["pactbroker.database_connector"]
end
end
end
end
Expand Down
18 changes: 15 additions & 3 deletions lib/pact_broker/api/resources/pact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,17 @@ def from_json
response_code = pact ? 200 : 201

if request.patch? && resource_exists?
@pact = pact_service.merge_pact(pact_params)
@pact = pact_service.merge_pact(pact_params, webhook_options)
else
@pact = pact_service.create_or_update_pact(pact_params)
@pact = pact_service.create_or_update_pact(pact_params, webhook_options)
end

response.body = to_json
response_code
end

def to_json
PactBroker::Api::Decorators::PactDecorator.new(pact).to_json(user_options: { base_url: base_url })
PactBroker::Api::Decorators::PactDecorator.new(pact).to_json(user_options: decorator_context(metadata: identifier_from_path[:metadata]))
end

def to_html
Expand Down Expand Up @@ -118,6 +118,18 @@ def set_post_deletion_response
response.body = response_body.to_json
response.headers["Content-Type" => "application/hal+json;charset=utf-8"]
end

def webhook_options
{
database_connector: database_connector,
execution_options: {
show_response: PactBroker.configuration.show_webhook_response?
},
webhook_context: {
base_url: base_url
}
}
end
end
end
end
Expand Down
2 changes: 0 additions & 2 deletions lib/pact_broker/api/resources/verification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
module PactBroker
module Api
module Resources

class Verification < BaseResource

def content_types_provided
[["application/hal+json", :to_json], ["application/json", :to_json]]
end
Expand Down
19 changes: 18 additions & 1 deletion lib/pact_broker/api/resources/verifications.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def create_path
end

def from_json
verification = verification_service.create(next_verification_number, params_with_string_keys, pact)
verification = verification_service.create(next_verification_number, params_with_string_keys, pact, webhook_options)
response.body = decorator_for(verification).to_json(user_options: {base_url: base_url})
true
end
Expand All @@ -69,6 +69,23 @@ def decorator_for model
def update_matrix_after_request?
request.post?
end


def metadata
PactBrokerUrls.parse_webhook_metadata(identifier_from_path[:metadata])
end

def webhook_options
{
database_connector: database_connector,
execution_options: {
show_response: PactBroker.configuration.show_webhook_response?
},
webhook_context: metadata.merge(
base_url: base_url
)
}
end
end
end
end
Expand Down
19 changes: 17 additions & 2 deletions lib/pact_broker/api/resources/webhook_execution.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def allowed_methods
end

def process_post
webhook_execution_result = webhook_service.test_execution(webhook)
webhook_execution_result = webhook_service.test_execution(webhook, webhook_options)
response.headers['Content-Type'] = 'application/hal+json;charset=utf-8'
response.body = post_response_body webhook_execution_result
if webhook_execution_result.success?
Expand Down Expand Up @@ -44,7 +44,22 @@ def uuid
end

def user_options
{ base_url: base_url, webhook: webhook, show_response: PactBroker.configuration.show_webhook_response? }
{
base_url: base_url,
webhook: webhook,
show_response: PactBroker.configuration.show_webhook_response?
}
end

def webhook_options
{
execution_options: {
show_response: PactBroker.configuration.show_webhook_response?
},
webhook_context: {
base_url: base_url
}
}
end
end
end
Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/domain/verification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ def provider_version_number
provider_version.number
end

def provider_version_tag_names
provider_version.tags.collect(&:name)
end

def latest_pact_publication
pact_version.latest_pact_publication
end
Expand Down
2 changes: 1 addition & 1 deletion lib/pact_broker/domain/webhook.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def request_description

def execute pact, verification, options
logger.info "Executing #{self}"
request.build(pact: pact, verification: verification, base_url: options[:base_url]).execute(options)
request.build(pact: pact, verification: verification, webhook_context: options.fetch(:webhook_context)).execute(options.fetch(:execution_options))
end

def to_s
Expand Down
2 changes: 1 addition & 1 deletion lib/pact_broker/domain/webhook_request.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ def log_request

def log_response response
log_response_to_application_logger(response)
if options[:show_response]
if options.fetch(:show_response)
log_response_to_execution_logger(response)
else
execution_logger.info response_body_hidden_message
Expand Down
25 changes: 16 additions & 9 deletions lib/pact_broker/pacts/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,28 @@ def delete params
pact_repository.delete(params)
end

def create_or_update_pact params
def create_or_update_pact params, webhook_options
provider = pacticipant_repository.find_by_name_or_create params[:provider_name]
consumer = pacticipant_repository.find_by_name_or_create params[:consumer_name]
consumer_version = version_repository.find_by_pacticipant_id_and_number_or_create consumer.id, params[:consumer_version_number]
existing_pact = pact_repository.find_by_version_and_provider(consumer_version.id, provider.id)

if existing_pact
update_pact params, existing_pact
update_pact params, existing_pact, webhook_options
else
create_pact params, consumer_version, provider
create_pact params, consumer_version, provider, webhook_options
end
end

def merge_pact params
def merge_pact params, webhook_options
provider = pacticipant_repository.find_by_name_or_create params[:provider_name]
consumer = pacticipant_repository.find_by_name_or_create params[:consumer_name]
consumer_version = version_repository.find_by_pacticipant_id_and_number_or_create consumer.id, params[:consumer_version_number]
existing_pact = pact_repository.find_by_version_and_provider(consumer_version.id, provider.id)

params.merge!(json_content: Merger.merge_pacts(existing_pact.json_content, params[:json_content]))

update_pact params, existing_pact
update_pact params, existing_pact, webhook_options
end

def find_all_pact_versions_between consumer, options
Expand Down Expand Up @@ -113,21 +113,21 @@ def find_distinct_pacts_between consumer, options
private

# Overwriting an existing pact with the same consumer/provider/consumer version number
def update_pact params, existing_pact
def update_pact params, existing_pact, webhook_options
logger.info "Updating existing pact publication with params #{params.reject{ |k, v| k == :json_content}}"
logger.debug "Content #{params[:json_content]}"
pact_version_sha = generate_sha(params[:json_content])
json_content = add_interaction_ids(params[:json_content])
update_params = { pact_version_sha: pact_version_sha, json_content: json_content }
updated_pact = pact_repository.update(existing_pact.id, update_params)

webhook_trigger_service.trigger_webhooks_for_updated_pact(existing_pact, updated_pact)
webhook_trigger_service.trigger_webhooks_for_updated_pact(existing_pact, updated_pact, merge_consumer_version_info(webhook_options, updated_pact))

updated_pact
end

# When no publication for the given consumer/provider/consumer version number exists
def create_pact params, version, provider
def create_pact params, version, provider, webhook_options
logger.info "Creating new pact publication with params #{params.reject{ |k, v| k == :json_content}}"
logger.debug "Content #{params[:json_content]}"
pact_version_sha = generate_sha(params[:json_content])
Expand All @@ -139,7 +139,7 @@ def create_pact params, version, provider
pact_version_sha: pact_version_sha,
json_content: json_content
)
webhook_trigger_service.trigger_webhooks_for_new_pact pact
webhook_trigger_service.trigger_webhooks_for_new_pact(pact, merge_consumer_version_info(webhook_options, pact))
pact
end

Expand All @@ -150,6 +150,13 @@ def generate_sha(json_content)
def add_interaction_ids(json_content)
Content.from_json(json_content).with_ids.to_json
end

def merge_consumer_version_info(webhook_options, pact)
webhook_context = webhook_options.fetch(:webhook_context, {}).merge(
consumer_version_tags: pact.consumer_version_tag_names
)
webhook_options.merge(webhook_context: webhook_context)
end
end
end
end
4 changes: 4 additions & 0 deletions lib/pact_broker/test/test_data_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ def create_global_webhook parameters = {}
create_webhook(parameters.merge(consumer: nil, provider: nil))
end

def create_global_verification_webhook parameters = {}
create_webhook(parameters.merge(consumer: nil, provider: nil, event_names: [PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED]))
end

def create_provider_webhook parameters = {}
create_webhook(parameters.merge(consumer: nil))
end
Expand Down
12 changes: 10 additions & 2 deletions lib/pact_broker/verifications/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,22 @@ def next_number
verification_repository.next_number
end

def create next_verification_number, params, pact
def create next_verification_number, params, pact, webhook_options
logger.info "Creating verification #{next_verification_number} for pact_id=#{pact.id} from params #{params}"
verification = PactBroker::Domain::Verification.new
provider_version_number = params.fetch('providerApplicationVersion')
PactBroker::Api::Decorators::VerificationDecorator.new(verification).from_hash(params)
verification.number = next_verification_number
verification = verification_repository.create(verification, provider_version_number, pact)
webhook_service.trigger_webhooks pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED
webhook_context = webhook_options[:webhook_context].merge(
provider_version_tags: verification.provider_version_tag_names
)

webhook_service.trigger_webhooks(pact,
verification,
PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED,
webhook_options.merge(webhook_context: webhook_context)
)
verification
end

Expand Down
13 changes: 8 additions & 5 deletions lib/pact_broker/webhooks/job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def perform_with_connection(data)
def perform_with_triggered_webhook
@error_count = data[:error_count] || 0
begin
webhook_execution_result = PactBroker::Webhooks::Service.execute_triggered_webhook_now triggered_webhook, execution_options(data)
webhook_execution_result = PactBroker::Webhooks::Service.execute_triggered_webhook_now(triggered_webhook, webhook_options(data))
if webhook_execution_result.success?
handle_success
else
Expand All @@ -45,11 +45,14 @@ def perform_with_triggered_webhook
end
end

def execution_options(data)
{
def webhook_options(data)
execution_options = data[:execution_options].merge(
success_log_message: "Successfully executed webhook",
failure_log_message: failure_log_message,
base_url: data.fetch(:base_url)
failure_log_message: failure_log_message
)
{
execution_options: execution_options,
webhook_context: data[:webhook_context]
}
end

Expand Down
Loading

0 comments on commit 426b0b1

Please sign in to comment.