Skip to content

Commit

Permalink
feat: updating pending and wip logic to exclude pacts already verifie…
Browse files Browse the repository at this point in the history
…d by another branch before the specified branch was created (#432)

* feat: keep pact not-pending if it has a successful verification from another branch from before this branch was created

* feat: update WIP logic to exclude pacts already verified successfully by other branches

* feat: update WIP logic to exclude pacts already verified successfully by other branches (by version branch)
  • Loading branch information
bethesque authored May 21, 2021
1 parent 2540564 commit db643d3
Show file tree
Hide file tree
Showing 16 changed files with 583 additions and 148 deletions.
4 changes: 3 additions & 1 deletion lib/pact_broker/domain/pact.rb
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,9 @@ def pact_publication_id
end

def select_pending_provider_version_tags(provider_version_tags)
provider_version_tags - db_model.pact_version.select_provider_tags_with_successful_verifications(provider_version_tags)
tags_with_successful_verifications_from_that_branch = db_model.pact_version.select_provider_tags_with_successful_verifications(provider_version_tags)
tags_with_previous_successful_verifications_from_other_branches = db_model.pact_version.select_provider_tags_with_successful_verifications_from_another_branch_from_before_this_branch_created(provider_version_tags)
provider_version_tags - tags_with_successful_verifications_from_that_branch - tags_with_previous_successful_verifications_from_other_branches
end

def pending?
Expand Down
4 changes: 4 additions & 0 deletions lib/pact_broker/domain/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ def for(pacticipant_name, version_number)
where_pacticipant_name(pacticipant_name).where_number(version_number).single_record
end

def first_for_pacticipant_id_and_branch(pacticipant_id, branch)
where(pacticipant_id: pacticipant_id, branch: branch).order(:created_at).first
end

def latest_versions_for_pacticipant_branches(pacticipant_id, branches)
query = Version.where(Sequel[:versions][:pacticipant_id] => pacticipant_id, Sequel[:versions][:branch] => branches)

Expand Down
2 changes: 2 additions & 0 deletions lib/pact_broker/pacts/pact_publication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
require 'pact_broker/integrations/integration'
require 'pact_broker/tags/head_pact_tags'
require 'pact_broker/pacts/pact_publication_dataset_module'
require 'pact_broker/pacts/pact_publication_wip_dataset_module'
require 'pact_broker/pacts/eager_loaders'
require 'pact_broker/pacts/lazy_loaders'

Expand Down Expand Up @@ -37,6 +38,7 @@ class PactPublication < Sequel::Model(:pact_publications)
dataset_module do
include PactBroker::Repositories::Helpers
include PactPublicationDatasetModule
include PactPublicationWipDatasetModule
end

def self.subtract(a, b)
Expand Down
39 changes: 2 additions & 37 deletions lib/pact_broker/pacts/pact_publication_dataset_module.rb
Original file line number Diff line number Diff line change
Expand Up @@ -168,43 +168,8 @@ def for_currently_deployed_versions(environment_name)
.join(:environments, environments_join)
end

def successfully_verified_by_provider_branch(provider_id, provider_version_branch)
verifications_join = {
pact_version_id: :pact_version_id,
Sequel[:verifications][:success] => true,
Sequel[:verifications][:wip] => false,
Sequel[:verifications][:provider_id] => provider_id
}
versions_join = {
Sequel[:verifications][:provider_version_id] => Sequel[:provider_versions][:id],
Sequel[:provider_versions][:branch] => provider_version_branch,
Sequel[:provider_versions][:pacticipant_id] => provider_id
}

from_self(alias: :pp).select(Sequel[:pp].*)
.join(:verifications, verifications_join)
.join(:versions, versions_join, { table_alias: :provider_versions } )
.where(Sequel[:pp][:provider_id] => provider_id)
.distinct
end

def successfully_verified_by_provider_tag(provider_id, provider_tag)
verifications_join = {
pact_version_id: :pact_version_id,
Sequel[:verifications][:success] => true,
Sequel[:verifications][:wip] => false,
Sequel[:verifications][:provider_id] => provider_id
}
tags_join = {
Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id],
Sequel[:provider_tags][:name] => provider_tag
}

from_self(alias: :pp).select(Sequel[:pp].*)
.join(:verifications, verifications_join)
.join(:tags, tags_join, { table_alias: :provider_tags } )
.where(Sequel[:pp][:provider_id] => provider_id)
.distinct
def verified_before_date(date)
where { Sequel[:verifications][:execution_date] < date }
end

def created_after date
Expand Down
106 changes: 106 additions & 0 deletions lib/pact_broker/pacts/pact_publication_wip_dataset_module.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
module PactBroker
module Pacts
module PactPublicationWipDatasetModule
def successfully_verified_by_provider_branch_when_not_wip(provider_id, provider_version_branch)
from_self(alias: :pp)
.select(Sequel[:pp].*)
.where(Sequel[:pp][:provider_id] => provider_id)
.join_successful_non_wip_verifications_for_provider_id(provider_id)
.join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
.distinct
end

def successfully_verified_by_provider_another_branch_before_this_branch_first_created(provider_id, provider_version_branch)
first_version_for_branch = PactBroker::Domain::Version.first_for_pacticipant_id_and_branch(provider_id, provider_version_branch)

from_self(alias: :pp)
.select(Sequel[:pp].*)
.join_successful_non_wip_verifications_for_provider_id(provider_id)
.join_provider_versions_for_provider_id(provider_id) do
Sequel.lit('provider_versions.branch != ?', provider_version_branch)
end
.where(Sequel[:pp][:provider_id] => provider_id)
.verified_before_creation_date_of(first_version_for_branch)
.distinct
end

def successfully_verified_by_provider_tag_when_not_wip(provider_id, provider_tag)
from_self(alias: :pp)
.select(Sequel[:pp].*)
.where(Sequel[:pp][:provider_id] => provider_id)
.join_successful_non_wip_verifications_for_provider_id(provider_id)
.join_provider_version_tags_for_tag(provider_tag)
.distinct
end

def successfully_verified_by_provider_another_tag_before_this_tag_first_created(provider_id, provider_tag)
first_tag_with_name = PactBroker::Domain::Tag.where(pacticipant_id: provider_id, name: provider_tag).order(:created_at).first
from_self(alias: :pp)
.select(Sequel[:pp].*)
.where(Sequel[:pp][:provider_id] => provider_id)
.join_successful_non_wip_verifications_for_provider_id(provider_id)
.join_provider_version_tags do
Sequel.lit('provider_tags.name != ?', provider_tag)
end
.verified_before_creation_date_of(first_tag_with_name)
.distinct
end

protected

def verified_before_date(date)
where { Sequel[:verifications][:execution_date] < date }
end

def join_successful_non_wip_verifications_for_provider_id(provider_id, &block)
verifications_join = {
pact_version_id: :pact_version_id,
Sequel[:verifications][:success] => true,
Sequel[:verifications][:wip] => false,
Sequel[:verifications][:provider_id] => provider_id
}
join(:verifications, verifications_join, {}, &block)
end

def join_provider_version_tags &block
tags_join = {
Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id],
}
join(:tags, tags_join, { table_alias: :provider_tags }, &block)
end

def join_provider_version_tags_for_tag(tag)
tags_join = {
Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id],
Sequel[:provider_tags][:name] => tag
}
join(:tags, tags_join, { table_alias: :provider_tags } )
end

def join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
versions_join = {
Sequel[:verifications][:provider_version_id] => Sequel[:provider_versions][:id],
Sequel[:provider_versions][:branch] => provider_version_branch,
Sequel[:provider_versions][:pacticipant_id] => provider_id
}
join(:versions, versions_join, { table_alias: :provider_versions } )
end

def join_provider_versions_for_provider_id(provider_id, &block)
versions_join = {
Sequel[:verifications][:provider_version_id] => Sequel[:provider_versions][:id],
Sequel[:provider_versions][:pacticipant_id] => provider_id
}
join(:versions, versions_join, { table_alias: :provider_versions }, &block)
end

def verified_before_creation_date_of(record)
if record
verified_before_date(record.created_at)
else
self
end
end
end
end
end
54 changes: 43 additions & 11 deletions lib/pact_broker/pacts/pact_version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,26 @@ class PactVersion < Sequel::Model(:pact_versions)

dataset_module do
include PactBroker::Repositories::Helpers

def join_successful_verifications
verifications_join = {
Sequel[:verifications][:pact_version_id] => Sequel[:pact_versions][:id],
Sequel[:verifications][:success] => true
}
join(:verifications, verifications_join)
end

def join_provider_versions
join(:versions, { Sequel[:provider_versions][:id] => Sequel[:verifications][:provider_version_id] }, { table_alias: :provider_versions })
end

def join_provider_version_tags_for_tag(tag)
tags_join = {
Sequel[:tags][:version_id] => Sequel[:provider_versions][:id],
Sequel[:tags][:name] => tag
}
join(:tags, tags_join)
end
end

def name
Expand Down Expand Up @@ -52,33 +72,45 @@ def latest_consumer_version_number
latest_consumer_version.number
end

def select_provider_tags_with_successful_verifications(tags)
def select_provider_tags_with_successful_verifications_from_another_branch_from_before_this_branch_created(tags)
tags.select do | tag |
first_tag_with_name = PactBroker::Domain::Tag.where(pacticipant_id: provider_id, name: tag).order(:created_at).first

verifications_join = {
Sequel[:verifications][:pact_version_id] => Sequel[:pact_versions][:id],
Sequel[:verifications][:success] => true
}
tags_join = {
Sequel[:tags][:version_id] => Sequel[:versions][:id],
Sequel[:tags][:name] => tag
}
PactVersion.where(Sequel[:pact_versions][:id] => id)
query = PactVersion.where(Sequel[:pact_versions][:id] => id)
.join(:verifications, verifications_join)
.join(:versions, Sequel[:versions][:id] => Sequel[:verifications][:provider_version_id])
.join(:tags, tags_join)
.join(:tags, tags_join) do
Sequel.lit('tags.name != ?', tag)
end

if first_tag_with_name
query = query.where { Sequel[:verifications][:created_at] < first_tag_with_name.created_at }
end

query.any?
end
end

def select_provider_tags_with_successful_verifications(tags)
tags.select do | tag |
PactVersion.where(Sequel[:pact_versions][:id] => id)
.join_successful_verifications
.join_provider_versions
.join_provider_version_tags_for_tag(tag)
.any?
end
end

def verified_successfully_by_any_provider_version?
verifications_join = {
Sequel[:verifications][:pact_version_id] => Sequel[:pact_versions][:id],
Sequel[:verifications][:pact_version_id] => id,
Sequel[:verifications][:success] => true
}
PactVersion.where(Sequel[:pact_versions][:id] => id)
.join(:verifications, verifications_join)
.join(:versions, Sequel[:versions][:id] => Sequel[:verifications][:provider_version_id])
.join_successful_verifications
.any?
end
end
Expand Down
35 changes: 13 additions & 22 deletions lib/pact_broker/pacts/pacts_for_verification_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ def merge_selected_pacts(selected_pacts)
end
end

# Tag object with created_at date for the first time that tag was created
def provider_tag_objects_for(provider, provider_tags_names)
PactBroker::Domain::Tag
.select_group(Sequel[:tags][:name], Sequel[:pacticipant_id])
Expand All @@ -185,36 +186,24 @@ def provider_tag_objects_for(provider, provider_tags_names)
.all
end

# TODO ? find the WIP pacts by consumer branch
def find_wip_pact_versions_for_provider_by_provider_tags(provider, provider_tags_names, provider_tags, wip_start_date, pact_publication_scope)
potential_wip_pacts_by_consumer_tag_query = PactPublication.for_provider(provider).created_after(wip_start_date).send(pact_publication_scope)
potential_wip_pacts_by_consumer_tag = potential_wip_pacts_by_consumer_tag_query.all

tag_to_pact_publications = provider_tags_names.each_with_object({}) do | provider_tag_name, tag_to_pact_publications |
tag_to_pact_publications[provider_tag_name] = remove_already_verified_by_tag(
tag_to_pact_publications[provider_tag_name] = remove_non_wip_for_tag(
potential_wip_pacts_by_consumer_tag,
potential_wip_pacts_by_consumer_tag_query,
provider,
provider_tag_name
)
end

provider_has_no_versions = !provider.any_versions?

tag_to_pact_publications.flat_map do | provider_tag_name, pact_publications |
pact_publications.collect do | pact_publication |
force_include = PactBroker.feature_enabled?(:experimental_no_provider_versions_makes_all_head_pacts_wip) && provider_has_no_versions

pending_tag_names_to_use = if force_include
[provider_tag_name]
else
pre_existing_tag_names = find_provider_tag_names_that_were_first_used_before_pact_published(pact_publication, provider_tags)
[provider_tag_name] & pre_existing_tag_names
end

if pending_tag_names_to_use.any?
selectors = create_selectors_for_wip_pact(pact_publication)
VerifiablePact.create_for_wip_for_provider_tags(pact_publication.to_domain, selectors, pending_tag_names_to_use)
end
selectors = create_selectors_for_wip_pact(pact_publication)
VerifiablePact.create_for_wip_for_provider_tags(pact_publication.to_domain, selectors, [provider_tag_name])
end
end.compact
end
Expand All @@ -231,13 +220,13 @@ def find_wip_pact_versions_for_provider_by_provider_branch(provider_name, provid
provider = pacticipant_repository.find_by_name(provider_name)
wip_start_date = options.fetch(:include_wip_pacts_since)

wip_pact_publications_by_branch = remove_already_verified_by_branch(
wip_pact_publications_by_branch = remove_non_wip_for_branch(
PactPublication.for_provider(provider).created_after(wip_start_date).latest_by_consumer_branch,
provider,
provider_version_branch
)

wip_pact_publications_by_tag = remove_already_verified_by_branch(
wip_pact_publications_by_tag = remove_non_wip_for_branch(
PactPublication.for_provider(provider).created_after(wip_start_date).latest_by_consumer_tag,
provider,
provider_version_branch
Expand Down Expand Up @@ -277,12 +266,14 @@ def find_all_pact_versions_for_provider_with_consumer_version_tags provider_name
end
end

def remove_already_verified_by_branch(pact_publications, provider, provider_version_branch)
PactPublication.subtract(pact_publications.all, pact_publications.successfully_verified_by_provider_branch(provider.id, provider_version_branch).all)
def remove_non_wip_for_branch(pact_publications, provider, provider_version_branch)
remaining_pact_publications = PactPublication.subtract(pact_publications.all, pact_publications.successfully_verified_by_provider_branch_when_not_wip(provider.id, provider_version_branch).all)
PactPublication.subtract(remaining_pact_publications, pact_publications.successfully_verified_by_provider_another_branch_before_this_branch_first_created(provider.id, provider_version_branch).all)
end

def remove_already_verified_by_tag(pact_publications, query, provider, tag)
PactPublication.subtract(pact_publications, query.successfully_verified_by_provider_tag(provider.id, tag).all)
def remove_non_wip_for_tag(pact_publications, query, provider, tag)
pact_publications = PactPublication.subtract(pact_publications, query.successfully_verified_by_provider_tag_when_not_wip(provider.id, tag).all)
PactPublication.subtract(pact_publications, query.successfully_verified_by_provider_another_tag_before_this_tag_first_created(provider.id, tag).all)
end

def scope_for(scope)
Expand Down
8 changes: 8 additions & 0 deletions lib/pact_broker/test/http_test_data_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,13 @@ def separate
puts "\n=============================================================\n\n"
end

def comment string
puts "**********************************************************"
puts string
puts "**********************************************************\n\n"
self
end

def create_tagged_pacticipant_version(pacticipant:, version:, tag:)
[*tag].each do | tag |
create_tag(pacticipant: pacticipant, version: version, tag: tag)
Expand All @@ -51,6 +58,7 @@ def create_version(pacticipant:, version:, branch:)
branch: branch
}
client.put("pacticipants/#{encode(pacticipant)}/versions/#{encode(version)}", request_body).tap { |response| check_for_error(response) }
self
end

def deploy_to_prod(pacticipant:, version:)
Expand Down
Loading

0 comments on commit db643d3

Please sign in to comment.