pact_broker 2.38.1 → 2.39.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/ISSUE_TEMPLATE.md +2 -2
- data/CHANGELOG.md +45 -0
- data/DEVELOPER_DOCUMENTATION.md +9 -0
- data/Dockerfile +2 -0
- data/Gemfile +1 -1
- data/README.md +10 -3
- data/config/database.yml +10 -2
- data/docs/images/Pactflow logo - black small.png +0 -0
- data/lib/pact_broker/api.rb +5 -2
- data/lib/pact_broker/api/contracts/verifiable_pacts_query_schema.rb +41 -0
- data/lib/pact_broker/api/decorators/dashboard_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/dashboard_text_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/integration_decorator.rb +2 -0
- data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +34 -0
- data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +27 -0
- data/lib/pact_broker/api/resources/badge.rb +4 -4
- data/lib/pact_broker/api/resources/can_i_deploy.rb +41 -0
- data/lib/pact_broker/api/resources/dashboard.rb +1 -1
- data/lib/pact_broker/api/resources/index.rb +15 -4
- data/lib/pact_broker/api/resources/latest_pact.rb +10 -4
- data/lib/pact_broker/api/resources/latest_verification_for_latest_pact.rb +19 -0
- data/lib/pact_broker/api/resources/pact.rb +5 -4
- data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +54 -0
- data/lib/pact_broker/api/resources/verification.rb +6 -1
- data/lib/pact_broker/badges/service.rb +11 -11
- data/lib/pact_broker/db/clean.rb +72 -12
- data/lib/pact_broker/doc/controllers/app.rb +3 -1
- data/lib/pact_broker/doc/views/can-i-deploy.markdown +14 -0
- data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +8 -0
- data/lib/pact_broker/doc/views/integrations.markdown +1 -1
- data/lib/pact_broker/doc/views/matrix.markdown +7 -0
- data/lib/pact_broker/doc/views/metrics.markdown +5 -0
- data/lib/pact_broker/domain/index_item.rb +3 -3
- data/lib/pact_broker/domain/pact.rb +28 -1
- data/lib/pact_broker/index/service.rb +38 -20
- data/lib/pact_broker/integrations/integration.rb +16 -0
- data/lib/pact_broker/integrations/service.rb +15 -1
- data/lib/pact_broker/matrix/can_i_deploy_query_schema.rb +25 -0
- data/lib/pact_broker/matrix/parse_can_i_deploy_query.rb +29 -0
- data/lib/pact_broker/matrix/quick_row.rb +255 -0
- data/lib/pact_broker/matrix/repository.rb +5 -17
- data/lib/pact_broker/matrix/row.rb +0 -1
- data/lib/pact_broker/metrics/service.rb +36 -2
- data/lib/pact_broker/pacts/all_pact_publications.rb +3 -2
- data/lib/pact_broker/pacts/head_pact.rb +30 -0
- data/lib/pact_broker/pacts/latest_pact_publications.rb +8 -1
- data/lib/pact_broker/pacts/latest_tagged_pact_publications.rb +5 -1
- data/lib/pact_broker/pacts/pact_publication.rb +2 -1
- data/lib/pact_broker/pacts/pact_version.rb +20 -0
- data/lib/pact_broker/pacts/repository.rb +33 -4
- data/lib/pact_broker/pacts/service.rb +15 -2
- data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +37 -0
- data/lib/pact_broker/pacts/verifiable_pact.rb +30 -0
- data/lib/pact_broker/pacts/verifiable_pact_messages.rb +75 -0
- data/lib/pact_broker/test/test_data_builder.rb +30 -2
- data/lib/pact_broker/ui/view_models/index_item.rb +4 -4
- data/lib/pact_broker/ui/view_models/matrix_line.rb +1 -1
- data/lib/pact_broker/ui/views/index/show-with-tags.haml +1 -1
- data/lib/pact_broker/ui/views/index/show.haml +1 -1
- data/lib/pact_broker/ui/views/matrix/show.haml +2 -2
- data/lib/pact_broker/verifications/{verification_status.rb → pseudo_branch_status.rb} +10 -4
- data/lib/pact_broker/version.rb +1 -1
- data/script/docker/mysql-db-start.sh +10 -0
- data/spec/features/can_i_deploy_spec.rb +31 -0
- data/spec/features/get_latest_verification_for_pact_spec.rb +17 -0
- data/spec/features/get_provider_pacts_for_verification_spec.rb +39 -0
- data/spec/features/metrics_spec.rb +1 -1
- data/spec/features/pending_pacts_spec.rb +109 -0
- data/spec/integration/ui/matrix_spec.rb +30 -0
- data/spec/lib/pact_broker/api/contracts/verifiable_pacts_query_schema_spec.rb +62 -0
- data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +1 -1
- data/spec/lib/pact_broker/api/decorators/integration_decorator_spec.rb +5 -1
- data/spec/lib/pact_broker/api/decorators/verifiable_pact_decorator_spec.rb +30 -5
- data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +46 -0
- data/spec/lib/pact_broker/api/resources/badge_spec.rb +3 -3
- data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +35 -0
- data/spec/lib/pact_broker/api/resources/verification_spec.rb +18 -0
- data/spec/lib/pact_broker/badges/service_spec.rb +18 -18
- data/spec/lib/pact_broker/db/clean_spec.rb +69 -8
- data/spec/lib/pact_broker/doc/coverage_spec.rb +8 -2
- data/spec/lib/pact_broker/index/service_spec.rb +28 -14
- data/spec/lib/pact_broker/integrations/integration_spec.rb +60 -0
- data/spec/lib/pact_broker/integrations/service_spec.rb +27 -0
- data/spec/lib/pact_broker/matrix/quick_row_spec.rb +31 -0
- data/spec/lib/pact_broker/matrix/repository_spec.rb +8 -8
- data/spec/lib/pact_broker/matrix/service_spec.rb +4 -4
- data/spec/lib/pact_broker/metrics/service_spec.rb +56 -0
- data/spec/lib/pact_broker/pacts/pact_version_spec.rb +69 -0
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +65 -0
- data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +54 -24
- data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +51 -0
- data/spec/lib/pact_broker/pacts/squash_pacts_for_verification_spec.rb +92 -0
- data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +93 -0
- data/spec/lib/pact_broker/pacts/verifiable_pact_spec.rb +0 -0
- data/spec/lib/pact_broker/ui/view_models/index_item_spec.rb +10 -10
- data/spec/lib/pact_broker/verifications/{verification_status_spec.rb → pseudo_branch_status_spec.rb} +4 -4
- data/spec/support/shared_examples_for_responses.rb +7 -1
- metadata +56 -13
- data/lib/pact_broker/api/resources/pending_provider_pacts.rb +0 -21
- data/spec/features/get_pacts_to_verify_spec.rb +0 -41
- data/spec/features/get_wip_provider_pacts_spec.rb +0 -26
- data/spec/lib/pact_broker/api/resources/pending_provider_pacts_spec.rb +0 -34
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'pact_broker/repositories/helpers'
|
2
2
|
require 'pact_broker/matrix/row'
|
3
|
+
require 'pact_broker/matrix/quick_row'
|
3
4
|
require 'pact_broker/matrix/head_row'
|
4
5
|
require 'pact_broker/error'
|
5
6
|
require 'pact_broker/matrix/query_results'
|
@@ -80,7 +81,7 @@ module PactBroker
|
|
80
81
|
# If two or more are specified, just return the integrations that involve the specified pacticipants
|
81
82
|
def find_integrations_for_specified_selectors(resolved_specified_selectors)
|
82
83
|
specified_pacticipant_names = resolved_specified_selectors.collect(&:pacticipant_name)
|
83
|
-
|
84
|
+
QuickRow
|
84
85
|
.select(:consumer_name, :consumer_id, :provider_name, :provider_id)
|
85
86
|
.matching_selectors(resolved_specified_selectors)
|
86
87
|
.distinct
|
@@ -116,28 +117,15 @@ module PactBroker
|
|
116
117
|
|
117
118
|
# The group with the nil provider_version_numbers will be the results of the left outer join
|
118
119
|
# that don't have verifications, so we need to include them all.
|
119
|
-
|
120
|
+
lines.group_by{|line| group_by_columns.collect{|key| line.send(key) }}
|
120
121
|
.values
|
121
122
|
.collect{ | lines | lines.first.provider_version_number.nil? ? lines : lines.first }
|
122
123
|
.flatten
|
123
124
|
end
|
124
125
|
|
125
|
-
# It would be nicer to do this in the SQL, but it requires time that I don't have at the moment
|
126
|
-
def remove_overwritten_revisions lines
|
127
|
-
latest_revisions_keys = {}
|
128
|
-
latest_revisions = []
|
129
|
-
lines.each do | line |
|
130
|
-
key = "#{line.consumer_name}-#{line.provider_name}-#{line.consumer_version_number}"
|
131
|
-
if !latest_revisions_keys.key?(key) || latest_revisions_keys[key] == line.pact_revision_number
|
132
|
-
latest_revisions << line
|
133
|
-
latest_revisions_keys[key] ||= line.pact_revision_number
|
134
|
-
end
|
135
|
-
end
|
136
|
-
latest_revisions
|
137
|
-
end
|
138
|
-
|
139
126
|
def query_matrix selectors, options
|
140
|
-
query = Row
|
127
|
+
query = options[:latestby] ? QuickRow.eager_all_the_things : Row
|
128
|
+
query = query.select_all.matching_selectors(selectors)
|
141
129
|
query = query.limit(options[:limit]) if options[:limit]
|
142
130
|
query
|
143
131
|
.order_by_names_ascending_most_recent_first
|
@@ -8,6 +8,8 @@ require 'pact_broker/api/decorators/format_date_time'
|
|
8
8
|
require 'pact_broker/webhooks/webhook'
|
9
9
|
require 'pact_broker/webhooks/triggered_webhook'
|
10
10
|
require 'pact_broker/webhooks/execution'
|
11
|
+
require 'pact_broker/matrix/row'
|
12
|
+
require 'pact_broker/matrix/head_row'
|
11
13
|
|
12
14
|
module PactBroker
|
13
15
|
module Metrics
|
@@ -32,10 +34,19 @@ module PactBroker
|
|
32
34
|
pactVersions: {
|
33
35
|
count: PactBroker::Pacts::PactVersion.count
|
34
36
|
},
|
37
|
+
pactRevisionsPerConsumerVersion: {
|
38
|
+
distribution: pact_revision_counts
|
39
|
+
},
|
35
40
|
verificationResults: {
|
36
41
|
count: PactBroker::Domain::Verification.count,
|
37
|
-
|
38
|
-
|
42
|
+
successCount: PactBroker::Domain::Verification.where(success: true).count,
|
43
|
+
failureCount: PactBroker::Domain::Verification.where(success: false).count,
|
44
|
+
distinctCount: PactBroker::Domain::Verification.distinct.select(:provider_version_id, :pact_version_id, :success).count,
|
45
|
+
first: format_date_time(PactBroker::Domain::Verification.order(:id).first&.created_at),
|
46
|
+
last: format_date_time(PactBroker::Domain::Verification.order(:id).last&.created_at),
|
47
|
+
},
|
48
|
+
verificationResultsPerPactVersion: {
|
49
|
+
distribution: verification_distribution
|
39
50
|
},
|
40
51
|
pacticipantVersions: {
|
41
52
|
count: PactBroker::Domain::Version.count
|
@@ -48,9 +59,32 @@ module PactBroker
|
|
48
59
|
},
|
49
60
|
webhookExecutions: {
|
50
61
|
count: PactBroker::Webhooks::Execution.count
|
62
|
+
},
|
63
|
+
matrix: {
|
64
|
+
count: PactBroker::Matrix::Row.count
|
65
|
+
},
|
66
|
+
headMatrix: {
|
67
|
+
count: PactBroker::Matrix::HeadRow.count
|
51
68
|
}
|
52
69
|
}
|
53
70
|
end
|
71
|
+
|
72
|
+
def pact_revision_counts
|
73
|
+
query = "select revision_count as number_of_revisions, count(consumer_version_id) as consumer_version_count
|
74
|
+
from (select consumer_version_id, count(*) as revision_count from pact_publications group by consumer_version_id) foo
|
75
|
+
group by revision_count
|
76
|
+
order by 1"
|
77
|
+
PactBroker::Pacts::PactPublication.db[query].all.each_with_object({}) { |row, hash| hash[row[:number_of_revisions]] = row[:consumer_version_count] }
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
def verification_distribution
|
82
|
+
query = "select verification_count as number_of_verifications, count(*) as pact_version_count
|
83
|
+
from (select pact_version_id, count(*) as verification_count from verifications group by pact_version_id) foo
|
84
|
+
group by verification_count
|
85
|
+
order by 1"
|
86
|
+
PactBroker::Pacts::PactPublication.db[query].all.each_with_object({}) { |row, hash| hash[row[:number_of_verifications]] = row[:pact_version_count] }
|
87
|
+
end
|
54
88
|
end
|
55
89
|
end
|
56
90
|
end
|
@@ -6,7 +6,6 @@ require 'pact_broker/repositories/helpers'
|
|
6
6
|
|
7
7
|
module PactBroker
|
8
8
|
module Pacts
|
9
|
-
|
10
9
|
class AllPactPublications < Sequel::Model(:all_pact_publications)
|
11
10
|
|
12
11
|
extend Forwardable
|
@@ -16,6 +15,7 @@ module PactBroker
|
|
16
15
|
set_primary_key :id
|
17
16
|
associate(:one_to_many, :tags, :class => "PactBroker::Domain::Tag", :reciprocal => :version, :key => :version_id, :primary_key => :consumer_version_id)
|
18
17
|
associate(:many_to_one, :pact_version, :key => :pact_version_id, :primary_key => :id)
|
18
|
+
associate(:many_to_one, :latest_verification, :class => "PactBroker::Verifications::LatestVerificationForPactVersion", key: :pact_version_id, primary_key: :pact_version_id)
|
19
19
|
|
20
20
|
dataset_module do
|
21
21
|
include PactBroker::Repositories::Helpers
|
@@ -102,7 +102,8 @@ module PactBroker
|
|
102
102
|
revision_number: revision_number,
|
103
103
|
pact_version_sha: pact_version_sha,
|
104
104
|
created_at: created_at,
|
105
|
-
head_tag_names: head_tag_names
|
105
|
+
head_tag_names: head_tag_names,
|
106
|
+
db_model: self)
|
106
107
|
end
|
107
108
|
|
108
109
|
def head_tag_names
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
# A head pact is the pact for the latest consumer version with the specified tag
|
4
|
+
# (ignoring later versions that might have the specified tag but no pact)
|
5
|
+
|
6
|
+
module PactBroker
|
7
|
+
module Pacts
|
8
|
+
class HeadPact < SimpleDelegator
|
9
|
+
attr_reader :tag, :consumer_version_number
|
10
|
+
|
11
|
+
def initialize(pact, consumer_version_number, tag)
|
12
|
+
super(pact)
|
13
|
+
@consumer_version_number = consumer_version_number
|
14
|
+
@tag = tag
|
15
|
+
end
|
16
|
+
|
17
|
+
# The underlying pact publication may well be the overall latest as well, but
|
18
|
+
# this row does not know that, as there will be a row with a nil tag
|
19
|
+
# if it is the overall latest as well as a row with the
|
20
|
+
# tag set, as the data is denormalised in the LatestTaggedPactPublications table.
|
21
|
+
def overall_latest?
|
22
|
+
tag.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def pact
|
26
|
+
__getobj__()
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -1,12 +1,19 @@
|
|
1
1
|
require 'pact_broker/pacts/latest_pact_publications_by_consumer_version'
|
2
|
+
require 'pact_broker/pacts/head_pact'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Pacts
|
5
6
|
|
7
|
+
# latest pact for each consumer/provider pair
|
6
8
|
class LatestPactPublications < LatestPactPublicationsByConsumerVersion
|
7
9
|
set_dataset(:latest_pact_publications)
|
8
|
-
end
|
9
10
|
|
11
|
+
# This pact may well be the latest for certain tags, but in this query
|
12
|
+
# we don't know what they are
|
13
|
+
def to_domain
|
14
|
+
HeadPact.new(super, consumer_version_number, nil)
|
15
|
+
end
|
16
|
+
end
|
10
17
|
end
|
11
18
|
end
|
12
19
|
|
@@ -1,12 +1,16 @@
|
|
1
1
|
require 'pact_broker/pacts/latest_pact_publications_by_consumer_version'
|
2
|
+
require 'pact_broker/pacts/head_pact'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Pacts
|
5
6
|
|
6
7
|
class LatestTaggedPactPublications < LatestPactPublicationsByConsumerVersion
|
7
8
|
set_dataset(:latest_tagged_pact_publications)
|
8
|
-
end
|
9
9
|
|
10
|
+
def to_domain
|
11
|
+
HeadPact.new(super, consumer_version_number, tag_name)
|
12
|
+
end
|
13
|
+
end
|
10
14
|
end
|
11
15
|
end
|
12
16
|
|
@@ -50,6 +50,26 @@ module PactBroker
|
|
50
50
|
latest_consumer_version.number
|
51
51
|
end
|
52
52
|
|
53
|
+
def select_provider_tags_with_successful_verifications(tags)
|
54
|
+
tags.select do | tag |
|
55
|
+
PactVersion.where(Sequel[:pact_versions][:id] => id)
|
56
|
+
.join(:verifications, Sequel[:verifications][:pact_version_id] => Sequel[:pact_versions][:id])
|
57
|
+
.join(:versions, Sequel[:versions][:id] => Sequel[:verifications][:provider_version_id])
|
58
|
+
.join(:tags, Sequel[:tags][:version_id] => Sequel[:versions][:id])
|
59
|
+
.where(Sequel[:tags][:name] => tag)
|
60
|
+
.where(Sequel[:verifications][:success] => true)
|
61
|
+
.any?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def verified_successfully_by_any_provider_version?
|
66
|
+
PactVersion.where(Sequel[:pact_versions][:id] => id)
|
67
|
+
.join(:verifications, Sequel[:verifications][:pact_version_id] => Sequel[:pact_versions][:id])
|
68
|
+
.join(:versions, Sequel[:versions][:id] => Sequel[:verifications][:provider_version_id])
|
69
|
+
.where(Sequel[:verifications][:success] => true)
|
70
|
+
.any?
|
71
|
+
end
|
72
|
+
|
53
73
|
def upsert
|
54
74
|
self.class.upsert(to_hash, [:consumer_id, :provider_id, :sha])
|
55
75
|
end
|
@@ -12,6 +12,7 @@ require 'pact_broker/domain'
|
|
12
12
|
require 'pact_broker/pacts/parse'
|
13
13
|
require 'pact_broker/matrix/head_row'
|
14
14
|
require 'pact_broker/pacts/latest_pact_publication_id_by_consumer_version'
|
15
|
+
require 'pact_broker/pacts/verifiable_pact'
|
15
16
|
|
16
17
|
module PactBroker
|
17
18
|
module Pacts
|
@@ -124,10 +125,30 @@ module PactBroker
|
|
124
125
|
end
|
125
126
|
end
|
126
127
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
130
|
-
|
128
|
+
def find_wip_pact_versions_for_provider provider_name, provider_tags = []
|
129
|
+
return [] if provider_tags.empty?
|
130
|
+
successfully_verified_pact_publication_ids_for_each_tag = provider_tags.collect do | provider_tag |
|
131
|
+
ids = LatestTaggedPactPublications
|
132
|
+
.join(:verifications, { pact_version_id: :pact_version_id })
|
133
|
+
.join(:tags, { Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id] }, {table_alias: :provider_tags})
|
134
|
+
.where(Sequel[:provider_tags][:name] => provider_tag)
|
135
|
+
.provider(provider_name)
|
136
|
+
.where(Sequel[:verifications][:success] => true)
|
137
|
+
.select(Sequel[:latest_tagged_pact_publications][:id].as(:id))
|
138
|
+
.collect(&:id)
|
139
|
+
[provider_tag, ids]
|
140
|
+
end
|
141
|
+
|
142
|
+
successfully_verified_pact_publication_ids_for_all_tags = successfully_verified_pact_publication_ids_for_each_tag.collect(&:last).reduce(:&)
|
143
|
+
pact_publication_ids = LatestTaggedPactPublications.provider(provider_name).exclude(id: successfully_verified_pact_publication_ids_for_all_tags).select_for_subquery(:id)
|
144
|
+
|
145
|
+
pacts = AllPactPublications.where(id: pact_publication_ids).order_ignore_case(:consumer_name).order_append(:consumer_version_order).collect(&:to_domain)
|
146
|
+
pacts.collect do | pact|
|
147
|
+
pending_tags = successfully_verified_pact_publication_ids_for_each_tag.select do | (provider_tag, pact_publication_ids) |
|
148
|
+
!pact_publication_ids.include?(pact.id)
|
149
|
+
end.collect(&:first)
|
150
|
+
VerifiablePact.new(pact, true, pending_tags, [], pact.consumer_version_tag_names)
|
151
|
+
end
|
131
152
|
end
|
132
153
|
|
133
154
|
def find_pact_versions_for_provider provider_name, tag = nil
|
@@ -263,6 +284,14 @@ module PactBroker
|
|
263
284
|
end
|
264
285
|
end
|
265
286
|
|
287
|
+
# Returns a list of Domain::Pact objects the represent pact publications
|
288
|
+
def find_for_verification(provider_name, consumer_version_selectors)
|
289
|
+
latest_tags = consumer_version_selectors.any? ?
|
290
|
+
consumer_version_selectors.select(&:latest).collect(&:tag) :
|
291
|
+
nil
|
292
|
+
find_latest_pact_versions_for_provider(provider_name, latest_tags)
|
293
|
+
end
|
294
|
+
|
266
295
|
private
|
267
296
|
|
268
297
|
def find_previous_distinct_pact_by_sha pact
|
@@ -2,6 +2,8 @@ require 'pact_broker/repositories'
|
|
2
2
|
require 'pact_broker/services'
|
3
3
|
require 'pact_broker/logging'
|
4
4
|
require 'pact_broker/pacts/merger'
|
5
|
+
require 'pact_broker/pacts/verifiable_pact'
|
6
|
+
require 'pact_broker/pacts/squash_pacts_for_verification'
|
5
7
|
|
6
8
|
module PactBroker
|
7
9
|
module Pacts
|
@@ -12,6 +14,7 @@ module PactBroker
|
|
12
14
|
extend PactBroker::Repositories
|
13
15
|
extend PactBroker::Services
|
14
16
|
include PactBroker::Logging
|
17
|
+
extend SquashPactsForVerification
|
15
18
|
|
16
19
|
def find_latest_pact params
|
17
20
|
pact_repository.find_latest_pact(params[:consumer_name], params[:provider_name], params[:tag])
|
@@ -80,8 +83,8 @@ module PactBroker
|
|
80
83
|
pact_repository.find_latest_pact_versions_for_provider provider_name, options[:tag]
|
81
84
|
end
|
82
85
|
|
83
|
-
def
|
84
|
-
pact_repository.
|
86
|
+
def find_wip_pact_versions_for_provider provider_name
|
87
|
+
pact_repository.find_wip_pact_versions_for_provider provider_name
|
85
88
|
end
|
86
89
|
|
87
90
|
def find_pact_versions_for_provider provider_name, options = {}
|
@@ -110,6 +113,16 @@ module PactBroker
|
|
110
113
|
distinct
|
111
114
|
end
|
112
115
|
|
116
|
+
def find_for_verification(provider_name, provider_version_tags, consumer_version_selectors)
|
117
|
+
pact_repository
|
118
|
+
.find_for_verification(provider_name, consumer_version_selectors)
|
119
|
+
.group_by(&:pact_version_sha)
|
120
|
+
.values
|
121
|
+
.collect do | head_pacts |
|
122
|
+
squash_pacts_for_verification(provider_version_tags, head_pacts)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
113
126
|
private
|
114
127
|
|
115
128
|
# Overwriting an existing pact with the same consumer/provider/consumer version number
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# All of these pacts have the same underlying pact_version_sha (content)
|
2
|
+
# No point verifying them multiple times, so squash all the relevant info into one
|
3
|
+
# "verifiable pact"
|
4
|
+
|
5
|
+
module PactBroker
|
6
|
+
module Pacts
|
7
|
+
module SquashPactsForVerification
|
8
|
+
def self.call(provider_version_tags, head_pacts)
|
9
|
+
domain_pact = head_pacts.first.pact
|
10
|
+
pending_provider_tags = []
|
11
|
+
pending = nil
|
12
|
+
if provider_version_tags.any?
|
13
|
+
pending_provider_tags = domain_pact.select_pending_provider_version_tags(provider_version_tags)
|
14
|
+
pending = pending_provider_tags.any?
|
15
|
+
else
|
16
|
+
pending = domain_pact.pending?
|
17
|
+
end
|
18
|
+
|
19
|
+
non_pending_provider_tags = provider_version_tags - pending_provider_tags
|
20
|
+
|
21
|
+
head_consumer_tags = head_pacts.collect(&:tag)
|
22
|
+
overall_latest = head_consumer_tags.include?(nil)
|
23
|
+
VerifiablePact.new(domain_pact,
|
24
|
+
pending,
|
25
|
+
pending_provider_tags,
|
26
|
+
non_pending_provider_tags,
|
27
|
+
head_consumer_tags.compact,
|
28
|
+
overall_latest
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
def squash_pacts_for_verification(*args)
|
33
|
+
SquashPactsForVerification.call(*args)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Pacts
|
5
|
+
class VerifiablePact < SimpleDelegator
|
6
|
+
attr_reader :pending, :pending_provider_tags, :non_pending_provider_tags, :head_consumer_tags
|
7
|
+
|
8
|
+
def initialize(pact, pending, pending_provider_tags = [], non_pending_provider_tags = [], head_consumer_tags = [], overall_latest = false)
|
9
|
+
super(pact)
|
10
|
+
@pending = pending
|
11
|
+
@pending_provider_tags = pending_provider_tags
|
12
|
+
@non_pending_provider_tags = non_pending_provider_tags
|
13
|
+
@head_consumer_tags = head_consumer_tags
|
14
|
+
@overall_latest = overall_latest
|
15
|
+
end
|
16
|
+
|
17
|
+
def consumer_tags
|
18
|
+
head_consumer_tags
|
19
|
+
end
|
20
|
+
|
21
|
+
def overall_latest?
|
22
|
+
@overall_latest
|
23
|
+
end
|
24
|
+
|
25
|
+
def pending?
|
26
|
+
pending
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module PactBroker
|
2
|
+
module Pacts
|
3
|
+
class VerifiablePactMessages
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
READ_MORE = "Read more at https://pact.io/pending"
|
7
|
+
|
8
|
+
delegate [:consumer_name, :provider_name, :head_consumer_tags, :pending_provider_tags, :non_pending_provider_tags, :pending?] => :verifiable_pact
|
9
|
+
|
10
|
+
def initialize(verifiable_pact)
|
11
|
+
@verifiable_pact = verifiable_pact
|
12
|
+
end
|
13
|
+
|
14
|
+
def inclusion_reason
|
15
|
+
if head_consumer_tags.any?
|
16
|
+
version_text = head_consumer_tags.size == 1 ? "version" : "versions"
|
17
|
+
"This pact is being verified because it is the pact for the latest #{version_text} of Foo tagged with #{joined_head_consumer_tags}"
|
18
|
+
else
|
19
|
+
"This pact is being verified because it is the latest pact between #{consumer_name} and #{provider_name}."
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def pending_reason
|
24
|
+
if pending?
|
25
|
+
"This pact is in pending state because it has not yet been successfully verified by #{pending_provider_tags_description}. If this verification fails, it will not cause the overall build to fail. #{READ_MORE}"
|
26
|
+
else
|
27
|
+
"This pact has previously been successfully verified by #{non_pending_provider_tags_description}. If this verification fails, it will fail the build. #{READ_MORE}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :verifiable_pact
|
34
|
+
|
35
|
+
def join(list, last_joiner = " and ")
|
36
|
+
quoted_list = list.collect { | tag | "'#{tag}'" }
|
37
|
+
comma_joined = quoted_list[0..-3] || []
|
38
|
+
and_joined = quoted_list[-2..-1] || quoted_list
|
39
|
+
if comma_joined.any?
|
40
|
+
"#{comma_joined.join(', ')}, #{and_joined.join(last_joiner)}"
|
41
|
+
else
|
42
|
+
and_joined.join(last_joiner)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def joined_head_consumer_tags
|
47
|
+
join(head_consumer_tags) + same_content_note
|
48
|
+
end
|
49
|
+
|
50
|
+
def same_content_note
|
51
|
+
case head_consumer_tags.size
|
52
|
+
when 1 then ""
|
53
|
+
when 2 then " (both have the same content)"
|
54
|
+
else " (all have the same content)"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def pending_provider_tags_description
|
59
|
+
case pending_provider_tags.size
|
60
|
+
when 0 then provider_name
|
61
|
+
when 1 then "any version of #{provider_name} with tag '#{pending_provider_tags.first}'"
|
62
|
+
else "any versions of #{provider_name} with tag #{join(pending_provider_tags)}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def non_pending_provider_tags_description
|
67
|
+
case non_pending_provider_tags.size
|
68
|
+
when 0 then provider_name
|
69
|
+
when 1 then "a version of #{provider_name} with tag '#{non_pending_provider_tags.first}'"
|
70
|
+
else "a version of #{provider_name} with tag #{join(non_pending_provider_tags)}"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|