Skip to content

Commit

Permalink
feat: in the webhook body for contract_published and contract_content…
Browse files Browse the repository at this point in the history
…_changed, use the latest verification from the main branch if present
  • Loading branch information
bethesque committed Sep 16, 2021
1 parent d8e092b commit b45398b
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 4 deletions.
16 changes: 16 additions & 0 deletions lib/pact_broker/domain/verification.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,22 @@ def for_consumer_name(consumer_name)
where(consumer: PactBroker::Domain::Pacticipant.find_by_name(consumer_name))
end

# TODO optimise this
def from_provider_main_branch
providers_join = {
Sequel[:verifications][:provider_id] => Sequel[:providers][:id]
}

branch_versions_join = {
Sequel[:verifications][:provider_version_id] => Sequel[:branch_versions][:version_id],
Sequel[:providers][:main_branch] => Sequel[:branch_versions][:branch_name]
}

join(:pacticipants, providers_join, { table_alias: :providers })
.join(:branch_versions, branch_versions_join)
end

# TODO change this to a group by
def latest_by_pact_version
base_query = self
base_join = {
Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/pacts/pact_publication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ def latest_verification
pact_version.latest_verification
end

def latest_main_branch_verification
pact_version.latest_main_branch_verification
end

def latest_for_branch?
if !defined?(@latest_for_branch)
if consumer_version.branch_versions.empty?
Expand Down
24 changes: 24 additions & 0 deletions lib/pact_broker/pacts/pact_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,30 @@ class PactVersion < Sequel::Model(:pact_versions)
associate(:many_to_one, :consumer, class: "PactBroker::Domain::Pacticipant", key: :consumer_id, primary_key: :id)
associate(:many_to_many, :consumer_versions, class: "PactBroker::Domain::Version", join_table: :pact_publications, left_key: :pact_version_id, right_key: :consumer_version_id, order: :order)

one_to_one(:latest_main_branch_verification,
class: "PactBroker::Domain::Verification",
read_only: true,
dataset: lambda {
providers_join = {
Sequel[:providers][:id] => Sequel[:latest_verification_id_for_pact_version_and_provider_version][:provider_id]
}

branch_versions_join = {
Sequel[:latest_verification_id_for_pact_version_and_provider_version][:provider_version_id] => Sequel[:branch_versions][:version_id],
Sequel[:providers][:main_branch] => Sequel[:branch_versions][:branch_name]
}
max_verification_id_for_pact_version = PactBroker::Verifications::LatestVerificationIdForPactVersionAndProviderVersion
.join(:pacticipants, providers_join, { table_alias: :providers })
.join(:branch_versions, branch_versions_join)
.select(Sequel.function(:max, :verification_id))
.where(pact_version_id: id)
PactBroker::Domain::Verification.where(id: max_verification_id_for_pact_version)
},
key: :pact_version_id,
primary_key: :id,
eager_block: lambda { | ds | ds.from_provider_main_branch.latest_by_pact_version }
)

one_to_one(:latest_verification,
class: "PactBroker::Domain::Verification",
read_only: true,
Expand Down
2 changes: 1 addition & 1 deletion lib/pact_broker/test/test_data_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def create_webhook parameters = {}
params[:events] || [{ name: PactBroker::Webhooks::WebhookEvent::DEFAULT_EVENT_NAME }]
end
events = event_params.collect{ |e| PactBroker::Webhooks::WebhookEvent.new(e) }
template_params = { method: "POST", url: "http://example.org", headers: {"Content-Type" => "application/json"}, username: params[:username], password: params[:password]}
template_params = { method: "POST", url: "http://example.org", headers: {"Content-Type" => "application/json"}, username: params[:username], password: params[:password] }
request = PactBroker::Webhooks::WebhookRequestTemplate.new(template_params.merge(params))
@webhook = PactBroker::Webhooks::Repository.new.create uuid, PactBroker::Domain::Webhook.new(request: request, events: events, description: params[:description], enabled: enabled), consumer, provider
self
Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/verifications/repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def find_latest_for_pact(pact)
PactBroker::Pacts::PactPublication.where(id: pact.id).single_record.latest_verification
end

def find_latest_from_main_branch_for_pact(pact)
PactBroker::Pacts::PactPublication.where(id: pact.id).single_record.latest_main_branch_verification
end

def any_verifications?(consumer, provider)
PactBroker::Domain::Verification.where(consumer_id: consumer.id, provider_id: provider.id).any?
end
Expand Down
2 changes: 1 addition & 1 deletion lib/pact_broker/verifications/service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module Service
using PactBroker::HashRefinements
extend PactBroker::Events::Publisher

delegate [:any_verifications?] => :verification_repository
delegate [:any_verifications?, :find_latest_from_main_branch_for_pact] => :verification_repository

def next_number
verification_repository.next_number
Expand Down
6 changes: 4 additions & 2 deletions lib/pact_broker/webhooks/event_listener.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@ def initialize(webhook_options)
end

def contract_published(params)
handle_event_for_webhook(PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, params)
main_branch_verification = verification_service.find_latest_from_main_branch_for_pact(params.fetch(:pact))
handle_event_for_webhook(PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, { verification: main_branch_verification }.compact.merge(params))
if verification_service.calculate_required_verifications_for_pact(params.fetch(:pact)).any?
handle_event_for_webhook(PactBroker::Webhooks::WebhookEvent::CONTRACT_REQUIRING_VERIFICATION_PUBLISHED, params)
end
end

def contract_content_changed(params)
handle_event_for_webhook(PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, params)
main_branch_verification = verification_service.find_latest_from_main_branch_for_pact(params.fetch(:pact))
handle_event_for_webhook(PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, { verification: main_branch_verification }.compact.merge(params))
end

def contract_content_unchanged(params)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class PactAndVerificationParameters
CURRENTLY_DEPLOYED_PROVIDER_VERSION_NUMBER
]

# TODO change this verification to the latest main branch
def initialize(pact, trigger_verification, webhook_context)
@pact = pact
@verification = trigger_verification || (pact && pact.latest_verification)
Expand Down
51 changes: 51 additions & 0 deletions spec/integration/webhooks/pact_publication_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
RSpec.describe "triggering a webhook for a pact publication" do
before do
td.create_global_webhook(event_names: ["contract_published"], body: { "provider_version" => "${pactbroker.providerVersionNumber}"})
end

let(:pact_content) { td.random_json_content("Foo", "Bar") }

let!(:request) do
stub_request(:post, /http/).with(body: expected_webhook_body).to_return(:status => 200)
end

let(:database_connector) { ->(&block) { block.call } }

subject { put("/pacts/provider/Bar/consumer/Foo/version/2", pact_content, { "CONTENT_TYPE" => "application/json", "pactbroker.database_connector" => database_connector}) }

context "when there is a verification from the main branch of the provider" do
before do
td.create_consumer("Foo")
.create_provider("Bar", main_branch: "main")
.create_consumer_version("1")
.create_pact(json_content: pact_content)
.create_verification(provider_version: "1", branch: "main")
.create_verification(provider_version: "2", branch: "feat/x", number: 2)
end

let(:expected_webhook_body) { { provider_version: "1"}.to_json }

it "uses that in the webhook" do
subject
expect(request).to have_been_made
end
end

context "when there is not a verification from the main branch of the provider" do
before do
td.create_consumer("Foo")
.create_provider("Bar", main_branch: "main")
.create_consumer_version("1")
.create_pact(json_content: pact_content)
.create_verification(provider_version: "1", branch: "feat/y")
.create_verification(provider_version: "2", branch: "feat/x", number: 2)
end

let(:expected_webhook_body) { { provider_version: "2"}.to_json }

it "uses the latest verification in the webhook" do
subject
expect(request).to have_been_made
end
end
end
32 changes: 32 additions & 0 deletions spec/lib/pact_broker/pacts/pact_version_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,38 @@ module Pacts
end
end

describe "#latest_main_branch_verification" do
before do
td.create_pact_with_verification("Foo", "1", "Bar", "2")
.create_verification(provider_version: "3", number: 2, branch: "main")
.create_verification(provider_version: "3", number: 3)
.create_verification(provider_version: "3", number: 4)
.create_pact_with_verification("NotFoo", "1", "Bar", "4")
.create_verification(provider_version: "5", number: 5)
.create_pact_with_verification("NotFoo2", "1", "NotBar", "4")
.create_verification(provider_version: "6", number: 6)
.create_pact_with_verification("NotFoo3", "2", "NotBar", "5")
.create_verification(provider_version: "7", number: 7)
end

context "lazy loading" do
it "lazy loads" do
expect(PactPublication.order(:id).all.first.pact_version.latest_main_branch_verification).to have_attributes(provider_version_number: "3", number: 4)
expect(PactPublication.order(:id).all.last.pact_version.latest_main_branch_verification).to be_nil
end
end

context "eager loading" do
let(:pact_version_1) { PactVersion.eager(:latest_main_branch_verification).order(:id).all.first }
let(:pact_version_2) { PactVersion.eager(:latest_main_branch_verification).order(:id).all.last }

it "eager loads" do
expect(PactPublication.order(:id).all.first.pact_version.latest_main_branch_verification).to have_attributes(provider_version_number: "3", number: 4)
expect(pact_version_2.associations[:latest_main_branch_verification]).to be_nil
end
end
end

describe "latest_consumer_version" do
before do
td.create_consumer("consumer")
Expand Down

0 comments on commit b45398b

Please sign in to comment.