pact_broker 2.27.6 → 2.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +4 -1
- data/.travis.yml +1 -2
- data/CHANGELOG.md +38 -0
- data/MATRIX.md +4 -0
- data/README.md +3 -2
- data/Rakefile +1 -2
- data/config/database.yml +5 -0
- data/lib/pact_broker/api/decorators/matrix_decorator.rb +7 -1
- data/lib/pact_broker/api/decorators/reason_decorator.rb +50 -0
- data/lib/pact_broker/api/resources/base_resource.rb +1 -1
- data/lib/pact_broker/api/resources/error_handler.rb +32 -9
- data/lib/pact_broker/app.rb +16 -1
- data/lib/pact_broker/domain/webhook_request.rb +1 -1
- data/lib/pact_broker/matrix/deployment_status_summary.rb +123 -44
- data/lib/pact_broker/matrix/head_row.rb +20 -0
- data/lib/pact_broker/matrix/integration.rb +49 -7
- data/lib/pact_broker/matrix/query_results.rb +3 -2
- data/lib/pact_broker/matrix/query_results_with_deployment_status_summary.rb +2 -2
- data/lib/pact_broker/matrix/reason.rb +74 -0
- data/lib/pact_broker/matrix/repository.rb +97 -61
- data/lib/pact_broker/matrix/resolved_selector.rb +126 -0
- data/lib/pact_broker/matrix/row.rb +8 -1
- data/lib/pact_broker/matrix/service.rb +2 -16
- data/lib/pact_broker/pacts/repository.rb +15 -5
- data/lib/pact_broker/repositories/helpers.rb +3 -2
- data/lib/pact_broker/ui/views/index/_navbar.haml +14 -0
- data/lib/pact_broker/ui/views/index/show-with-tags.haml +1 -12
- data/lib/pact_broker/ui/views/index/show.haml +1 -12
- data/lib/pact_broker/ui/views/layouts/main.haml +3 -0
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/job.rb +11 -5
- data/lib/pact_broker/webhooks/service.rb +10 -2
- data/lib/pact_broker/webhooks/webhook.rb +4 -0
- data/lib/rack/pact_broker/database_transaction.rb +22 -0
- data/pact_broker.gemspec +25 -1
- data/script/restart.sh +18 -0
- data/script/watch.sh +7 -0
- data/spec/features/publish_verification_spec.rb +1 -1
- data/spec/integration/app_spec.rb +1 -1
- data/spec/integration/webhooks/certificate_spec.rb +10 -2
- data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +2 -1
- data/spec/lib/pact_broker/api/decorators/reason_decorator_spec.rb +59 -0
- data/spec/lib/pact_broker/api/resources/error_handler_spec.rb +84 -21
- data/spec/lib/pact_broker/app_spec.rb +22 -0
- data/spec/lib/pact_broker/domain/webhook_request_spec.rb +1 -1
- data/spec/lib/pact_broker/matrix/deployment_status_summary_spec.rb +116 -28
- data/spec/lib/pact_broker/matrix/head_row_spec.rb +23 -0
- data/spec/lib/pact_broker/matrix/integration_spec.rb +242 -0
- data/spec/lib/pact_broker/matrix/repository_dependency_spec.rb +58 -0
- data/spec/lib/pact_broker/matrix/repository_spec.rb +40 -7
- data/spec/lib/pact_broker/matrix/service_spec.rb +0 -50
- data/spec/lib/pact_broker/pacts/repository_spec.rb +20 -4
- data/spec/lib/pact_broker/webhooks/job_spec.rb +9 -9
- data/spec/lib/pact_broker/webhooks/service_spec.rb +3 -3
- data/spec/lib/pact_broker/webhooks/webhook_spec.rb +39 -0
- data/spec/lib/rack/pact_broker/database_transaction_spec.rb +40 -0
- data/spec/service_consumers/pact_helper.rb +2 -0
- data/spec/spec_helper.rb +2 -3
- data/spec/support/jobs.rb +12 -0
- data/spec/support/migration_helpers.rb +1 -1
- data/spec/support/simplecov.rb +10 -0
- data/tasks/audit.rake +2 -0
- data/tasks/pact.rake +5 -1
- data/tasks/rspec.rake +14 -0
- metadata +50 -5
- data/db/pact_broker_database.sqlite3 +0 -0
- data/spec/lib/pact_broker/matrix/repository_find_integrations_spec.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d618dcd0c7582bad7822bac6bf8b32db26a25cea
|
4
|
+
data.tar.gz: 2a0d1f85dbdb9d2291308e483d60422431fe4013
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f7ee32711c4be853ccfb0d0eefd62c87ec9aad7407c2344a0d12c9537aeaa88483e0fce93c33e1ed51389c98f41dae1125f11ce47869e5b73a11e866473c03aa
|
7
|
+
data.tar.gz: 3b8217e5d02bff7be409a8dbfa51a4caf8ca1f6dfb2132b470926100efa7aa5c2dd9c85525ae4bd54c8997091c2c2495ebce785342dc4341c41b7562b093edf8
|
data/.gitignore
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
.DS_Store
|
1
2
|
*.gem
|
2
3
|
*.rbc
|
3
4
|
.bundle
|
@@ -6,6 +7,7 @@ coverage
|
|
6
7
|
InstalledFiles
|
7
8
|
lib/bundler/man
|
8
9
|
log
|
10
|
+
*.log
|
9
11
|
pkg
|
10
12
|
rdoc
|
11
13
|
spec/reports
|
@@ -25,11 +27,12 @@ _yardoc
|
|
25
27
|
*.swp
|
26
28
|
.idea
|
27
29
|
|
28
|
-
*.
|
30
|
+
*.sqlite3
|
29
31
|
Gemfile.lock
|
30
32
|
|
31
33
|
bethtest/
|
32
34
|
*bethtest*
|
35
|
+
*bethtemp*
|
33
36
|
*dogfood*
|
34
37
|
bin/
|
35
38
|
db/test/change_migration_strategy/pact_broker_database.sqlite3
|
data/.travis.yml
CHANGED
@@ -26,5 +26,4 @@ before_script:
|
|
26
26
|
script:
|
27
27
|
- bundle exec rake
|
28
28
|
- if [ "$DATABASE_ADAPTER" == "postgres" ]; then ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT || true; fi
|
29
|
-
# - if [ ! -z "$(ruby --version | grep '2\.4\.')" ]; then ./script/db-spec.sh; fi
|
30
|
-
- bundle exec bundle-audit update && bundle exec bundle-audit
|
29
|
+
# - if [ ! -z "$(ruby --version | grep '2\.4\.')" ]; then ./script/db-spec.sh; fi
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,41 @@
|
|
1
|
+
<a name="v2.29.0"></a>
|
2
|
+
### v2.29.0 (2019-03-15)
|
3
|
+
|
4
|
+
|
5
|
+
#### Features
|
6
|
+
|
7
|
+
* **matrix**
|
8
|
+
* improve reasons in response when pacticipant cannot be deployed ([e96544f6](/../../commit/e96544f6))
|
9
|
+
* allow provider to be deployed to an environment without the consumer having to be deployed there already ([475a4010](/../../commit/475a4010))
|
10
|
+
|
11
|
+
* change webhook execution failure log to info ([7238bc49](/../../commit/7238bc49))
|
12
|
+
* remove db/pact_broker_database.sqlite3 so we don't have conflicts in fork ([f68fce8b](/../../commit/f68fce8b))
|
13
|
+
* change error logs to info logs ([700f6992](/../../commit/700f6992))
|
14
|
+
* lock dry-logic to version that works ([28769040](/../../commit/28769040))
|
15
|
+
* allow a custom UI to be configured ([23695b08](/../../commit/23695b08))
|
16
|
+
|
17
|
+
|
18
|
+
#### Bug Fixes
|
19
|
+
|
20
|
+
* gracefully handle race conditions when publishing a new revision of a pact ([012c54f0](/../../commit/012c54f0))
|
21
|
+
|
22
|
+
|
23
|
+
<a name="v2.28.0"></a>
|
24
|
+
### v2.28.0 (2019-01-15)
|
25
|
+
|
26
|
+
|
27
|
+
#### Features
|
28
|
+
|
29
|
+
* enable file list in gemspec to work without git ([6dd27e26](/../../commit/6dd27e26))
|
30
|
+
* allow the database connection to be configured for async jobs ([6a745d4b](/../../commit/6a745d4b))
|
31
|
+
* add error reference to API error response and ensure potentially sensitive details from the exception message are not exposed ([e7bb4a01](/../../commit/e7bb4a01))
|
32
|
+
|
33
|
+
|
34
|
+
#### Bug Fixes
|
35
|
+
|
36
|
+
* show consumer/provider/global webhooks in webhook column on index page ([35f8bfc1](/../../commit/35f8bfc1))
|
37
|
+
|
38
|
+
|
1
39
|
<a name="v2.27.6"></a>
|
2
40
|
### v2.27.6 (2018-11-23)
|
3
41
|
|
data/MATRIX.md
ADDED
@@ -0,0 +1,4 @@
|
|
1
|
+
# Interpreting the Matrix results
|
2
|
+
|
3
|
+
* If there is a row with a blank provider version, it's because the pact for that consumer version hasn't been verified by that provider (the result of a left outer join).
|
4
|
+
* If there is no row, it's because it has been verified, but not by the provider version you've specified.
|
data/README.md
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# Pact Broker
|
2
2
|
[](http://badge.fury.io/rb/pact_broker)
|
3
|
-
[](https://travis-ci.org/pact-foundation/pact_broker)
|
3
|
+
[](https://travis-ci.org/pact-foundation/pact_broker)
|
4
|
+
[](https://slack.pact.io)
|
5
|
+
[](https://hakiri.io/github/pact-foundation/pact_broker/master)
|
4
6
|
[](https://codeclimate.com/github/pact-foundation/pact_broker)
|
5
7
|
[](https://codeclimate.com/github/pact-foundation/pact_broker/coverage)
|
6
|
-
[](https://codeclimate.com/github/pact-foundation/pact_broker)
|
7
8
|
|
8
9
|
The Pact Broker is an application for sharing for consumer driven contracts and verification results. It is optimised for use with "pacts" (contracts created by the [Pact][pact-docs] framework), but can be used for any type of contract that can be serialized to JSON.
|
9
10
|
|
data/Rakefile
CHANGED
@@ -14,9 +14,8 @@ end
|
|
14
14
|
FileList['lib/tasks/**/*.rake'].each { |task| load "#{Dir.pwd}/#{task}" }
|
15
15
|
FileList['tasks/**/*.rake'].each { |task| load "#{Dir.pwd}/#{task}" }
|
16
16
|
|
17
|
-
task :default => ['db:prepare:test', :boot, :spec, 'pact:verify']
|
17
|
+
task :default => ['db:prepare:test', :boot, :spec, 'pact:verify', 'bundle:audit']
|
18
18
|
|
19
19
|
task :boot do
|
20
20
|
require File.join(File.dirname(__FILE__), 'config/boot')
|
21
21
|
end
|
22
|
-
|
data/config/database.yml
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'ostruct'
|
2
2
|
require 'pact_broker/api/pact_broker_urls'
|
3
|
+
require 'pact_broker/api/decorators/reason_decorator'
|
3
4
|
|
4
5
|
module PactBroker
|
5
6
|
module Api
|
@@ -33,7 +34,11 @@ module PactBroker
|
|
33
34
|
end
|
34
35
|
|
35
36
|
def reason
|
36
|
-
query_results_with_deployment_status_summary
|
37
|
+
query_results_with_deployment_status_summary
|
38
|
+
.deployment_status_summary
|
39
|
+
.reasons
|
40
|
+
.collect{ | reason | ReasonDecorator.new(reason).to_s }
|
41
|
+
.join("\n")
|
37
42
|
end
|
38
43
|
|
39
44
|
private
|
@@ -130,3 +135,4 @@ module PactBroker
|
|
130
135
|
end
|
131
136
|
end
|
132
137
|
end
|
138
|
+
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module PactBroker
|
2
|
+
module Api
|
3
|
+
module Decorators
|
4
|
+
class ReasonDecorator
|
5
|
+
def initialize(reason)
|
6
|
+
@reason = reason
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_s
|
10
|
+
case reason
|
11
|
+
when PactBroker::Matrix::PactNotEverVerifiedByProvider
|
12
|
+
"There is no verified pact between #{reason.consumer_selector.description} and #{reason.provider_selector.description}"
|
13
|
+
when PactBroker::Matrix::PactNotVerifiedByRequiredProviderVersion
|
14
|
+
"There is no verified pact between #{reason.consumer_selector.description} and #{reason.provider_selector.description}"
|
15
|
+
when PactBroker::Matrix::VerificationFailed
|
16
|
+
"The verification between #{reason.consumer_selector.description} and #{reason.provider_selector.description} failed"
|
17
|
+
when PactBroker::Matrix::SpecifiedVersionDoesNotExist
|
18
|
+
version_does_not_exist_description(reason.selector)
|
19
|
+
when PactBroker::Matrix::VerificationFailed
|
20
|
+
"The verification for the pact between #{reason.consumer_selector.description} and #{reason.provider_selector.description} failed"
|
21
|
+
when PactBroker::Matrix::NoDependenciesMissing
|
22
|
+
"There are no missing dependencies"
|
23
|
+
when PactBroker::Matrix::Successful
|
24
|
+
"All required verification results are published and successful"
|
25
|
+
else
|
26
|
+
reason
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_reader :reason
|
33
|
+
|
34
|
+
def version_does_not_exist_description selector
|
35
|
+
if selector.version_does_not_exist?
|
36
|
+
if selector.tag
|
37
|
+
"No version with tag #{selector.tag} exists for #{selector.pacticipant_name}"
|
38
|
+
elsif selector.pacticipant_version_number
|
39
|
+
"No pacts or verifications have been published for version #{selector.pacticipant_version_number} of #{selector.pacticipant_name}"
|
40
|
+
else
|
41
|
+
"No pacts or verifications have been published for #{selector.pacticipant_name}"
|
42
|
+
end
|
43
|
+
else
|
44
|
+
""
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -127,7 +127,7 @@ module PactBroker
|
|
127
127
|
JSON.parse(request_body, PACT_PARSING_OPTIONS) #Not load! Otherwise it will try to load Ruby classes.
|
128
128
|
false
|
129
129
|
rescue StandardError => e
|
130
|
-
logger.
|
130
|
+
logger.info "Error parsing JSON #{e} - #{request_body}"
|
131
131
|
set_json_error_message "Error parsing JSON - #{e.message}"
|
132
132
|
response.headers['Content-Type'] = 'application/hal+json;charset=utf-8'
|
133
133
|
true
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'webmachine/convert_request_to_rack_env'
|
2
2
|
require 'pact_broker/configuration'
|
3
|
+
require 'securerandom'
|
3
4
|
|
4
5
|
module PactBroker
|
5
6
|
module Api
|
@@ -10,24 +11,46 @@ module PactBroker
|
|
10
11
|
include PactBroker::Logging
|
11
12
|
|
12
13
|
def self.call e, request, response
|
13
|
-
|
14
|
+
error_reference = SecureRandom.urlsafe_base64.gsub(/[^a-z]/i, '')[0,10]
|
15
|
+
logger.error "#{e.message} - error reference #{error_reference}"
|
14
16
|
logger.error e.backtrace
|
15
|
-
|
16
|
-
if
|
17
|
-
response_body[:error][:backtrace] = e.backtrace
|
18
|
-
end
|
19
|
-
response.body = response_body.to_json
|
20
|
-
report(e, request) if reportable?(e)
|
17
|
+
response.body = response_body_hash(e, error_reference).to_json
|
18
|
+
report(e, error_reference, request) if reportable?(e)
|
21
19
|
end
|
22
20
|
|
23
21
|
def self.reportable? e
|
24
22
|
!e.is_a?(PactBroker::Error)
|
25
23
|
end
|
26
24
|
|
27
|
-
def self.
|
25
|
+
def self.display_message(e, error_reference)
|
26
|
+
if PactBroker.configuration.show_backtrace_in_error_response?
|
27
|
+
e.message
|
28
|
+
else
|
29
|
+
reportable?(e) ? obfuscated_error_message(error_reference) : e.message
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.obfuscated_error_message error_reference
|
34
|
+
"An error has occurred. The details have been logged with the reference #{error_reference}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.response_body_hash e, error_reference
|
38
|
+
response_body = {
|
39
|
+
error: {
|
40
|
+
message: display_message(e, error_reference),
|
41
|
+
reference: error_reference
|
42
|
+
}
|
43
|
+
}
|
44
|
+
if PactBroker.configuration.show_backtrace_in_error_response?
|
45
|
+
response_body[:error][:backtrace] = e.backtrace
|
46
|
+
end
|
47
|
+
response_body
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.report e, error_reference, request
|
28
51
|
PactBroker.configuration.api_error_reporters.each do | error_notifier |
|
29
52
|
begin
|
30
|
-
error_notifier.call(e, env: Webmachine::ConvertRequestToRackEnv.call(request))
|
53
|
+
error_notifier.call(e, env: Webmachine::ConvertRequestToRackEnv.call(request), error_reference: error_reference)
|
31
54
|
rescue StandardError => e
|
32
55
|
log_error(e, "Error executing api_error_reporter")
|
33
56
|
end
|
data/lib/pact_broker/app.rb
CHANGED
@@ -32,7 +32,6 @@ module PactBroker
|
|
32
32
|
yield configuration
|
33
33
|
post_configure
|
34
34
|
prepare_database
|
35
|
-
prepare_app
|
36
35
|
end
|
37
36
|
|
38
37
|
# Allows middleware to be inserted at the bottom of the shared middlware stack
|
@@ -54,12 +53,18 @@ module PactBroker
|
|
54
53
|
@make_it_later_ui_auth.make_it_later(middleware)
|
55
54
|
end
|
56
55
|
|
56
|
+
def use_custom_ui custom_ui
|
57
|
+
@custom_ui = custom_ui
|
58
|
+
end
|
59
|
+
|
57
60
|
def call env
|
58
61
|
running_app.call env
|
59
62
|
end
|
60
63
|
|
61
64
|
private
|
62
65
|
|
66
|
+
attr_reader :custom_ui
|
67
|
+
|
63
68
|
def post_configure
|
64
69
|
configure_logger
|
65
70
|
SuckerPunch.logger = configuration.custom_logger || SemanticLogger['SuckerPunch']
|
@@ -101,6 +106,7 @@ module PactBroker
|
|
101
106
|
configure_middleware
|
102
107
|
|
103
108
|
# need this first so UI login logic is performed before API login logic
|
109
|
+
@cascade_apps << build_custom_ui if custom_ui
|
104
110
|
@cascade_apps << build_ui
|
105
111
|
|
106
112
|
if configuration.enable_diagnostic_endpoints
|
@@ -139,6 +145,14 @@ module PactBroker
|
|
139
145
|
builder
|
140
146
|
end
|
141
147
|
|
148
|
+
def build_custom_ui
|
149
|
+
logger.info "Mounting Custom UI"
|
150
|
+
builder = ::Rack::Builder.new
|
151
|
+
builder.use Rack::PactBroker::AcceptsHtmlFilter
|
152
|
+
builder.run @custom_ui
|
153
|
+
builder
|
154
|
+
end
|
155
|
+
|
142
156
|
def build_api
|
143
157
|
logger.info "Mounting PactBroker::API"
|
144
158
|
require 'pact_broker/api'
|
@@ -174,6 +188,7 @@ module PactBroker
|
|
174
188
|
|
175
189
|
def running_app
|
176
190
|
@running_app ||= begin
|
191
|
+
prepare_app
|
177
192
|
apps = @cascade_apps
|
178
193
|
@app_builder.map "/" do
|
179
194
|
run Rack::Cascade.new(apps)
|
@@ -196,7 +196,7 @@ module PactBroker
|
|
196
196
|
end
|
197
197
|
|
198
198
|
def log_error e
|
199
|
-
logger.
|
199
|
+
logger.info "Error executing webhook #{uuid} #{e.class.name} - #{e.message} #{e.backtrace.join("\n")}"
|
200
200
|
|
201
201
|
if options[:show_response]
|
202
202
|
execution_logger.error "Error executing webhook #{uuid} #{e.class.name} - #{e.message}"
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'pact_broker/logging'
|
2
|
+
require 'pact_broker/matrix/reason'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Matrix
|
@@ -11,89 +12,167 @@ module PactBroker
|
|
11
12
|
@rows = rows
|
12
13
|
@resolved_selectors = resolved_selectors
|
13
14
|
@integrations = integrations
|
15
|
+
@dummy_selectors = create_dummy_selectors
|
14
16
|
end
|
15
17
|
|
16
18
|
def counts
|
17
19
|
{
|
18
20
|
success: rows.count{ |row| row.success },
|
19
21
|
failed: rows.count { |row| row.success == false },
|
20
|
-
unknown:
|
22
|
+
unknown: required_integrations_without_a_row.count + rows.count { |row| row.success.nil? }
|
21
23
|
}
|
22
24
|
end
|
23
25
|
|
24
26
|
def deployable?
|
25
|
-
return
|
27
|
+
return false if specified_selectors_that_do_not_exist.any?
|
26
28
|
return nil if rows.any?{ |row| row.success.nil? }
|
27
|
-
return nil if
|
28
|
-
rows.all?{ |row| row.success }
|
29
|
+
return nil if required_integrations_without_a_row.any?
|
30
|
+
rows.all?{ |row| row.success } # true if rows is empty
|
29
31
|
end
|
30
32
|
|
31
33
|
def reasons
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
error_messages.any? ? error_messages : success_messages
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
attr_reader :dummy_selectors
|
40
|
+
|
41
|
+
def error_messages
|
42
|
+
@error_messages ||= begin
|
43
|
+
messages = []
|
44
|
+
messages.concat(specified_selectors_do_not_exist_messages)
|
45
|
+
if messages.empty?
|
46
|
+
messages.concat(missing_reasons)
|
47
|
+
messages.concat(failure_messages)
|
48
|
+
messages.concat(not_ever_verified_reasons)
|
41
49
|
end
|
42
|
-
|
50
|
+
messages.uniq
|
43
51
|
end
|
44
52
|
end
|
45
53
|
|
46
|
-
def
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
54
|
+
def specified_selectors_that_do_not_exist
|
55
|
+
resolved_selectors.select(&:specified_version_that_does_not_exist?)
|
56
|
+
end
|
57
|
+
|
58
|
+
def specified_selectors_do_not_exist_messages
|
59
|
+
specified_selectors_that_do_not_exist.collect do | selector |
|
60
|
+
SpecifiedVersionDoesNotExist.new(selector)
|
51
61
|
end
|
52
62
|
end
|
53
63
|
|
64
|
+
def not_ever_verified_reasons
|
65
|
+
rows.select{ | row | row.success.nil? }.collect{ |row | pact_not_ever_verified_by_provider(row) }
|
66
|
+
end
|
67
|
+
|
54
68
|
def failure_messages
|
55
|
-
|
56
|
-
|
57
|
-
else
|
58
|
-
[]
|
69
|
+
rows.select{ |row| row.success == false }.collect do | row |
|
70
|
+
VerificationFailed.new(*selectors_for(row))
|
59
71
|
end
|
60
72
|
end
|
61
73
|
|
62
74
|
def success_messages
|
63
|
-
if rows.all?{ |row| row.success } &&
|
64
|
-
|
75
|
+
if rows.all?{ |row| row.success } && required_integrations_without_a_row.empty?
|
76
|
+
if rows.any?
|
77
|
+
[Successful.new]
|
78
|
+
else
|
79
|
+
[NoDependenciesMissing.new]
|
80
|
+
end
|
65
81
|
else
|
66
82
|
[]
|
67
|
-
end
|
83
|
+
end.flatten.uniq
|
68
84
|
end
|
69
85
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
86
|
+
# For deployment, the consumer requires the provider,
|
87
|
+
# but the provider does not require the consumer
|
88
|
+
# This method tells us which providers are missing.
|
89
|
+
# Technically, it tells us which integrations do not have a row
|
90
|
+
# because the pact that belongs to the consumer version has
|
91
|
+
# in fact been verified, but not by the provider version specified
|
92
|
+
# in the query (because left outer join)
|
93
|
+
#
|
94
|
+
# Imagine query for deploying Foo v3 to prod with the following matrix:
|
95
|
+
# Foo v2 -> Bar v1 (latest prod) [this line not included because CV doesn't match]
|
96
|
+
# Foo v3 -> Bar v2 [this line not included because PV doesn't match]
|
97
|
+
#
|
98
|
+
# No matrix rows would be returned. This method identifies that we have no row for
|
99
|
+
# the Foo -> Bar integration, and therefore cannot deploy Foo.
|
100
|
+
# However, if we were to try and deploy the provider, Bar, that would be ok
|
101
|
+
# as Bar does not rely on Foo, so this method would not return that integration.
|
102
|
+
def required_integrations_without_a_row
|
103
|
+
@required_integrations_without_a_row ||= begin
|
104
|
+
integrations.select(&:required?).select do | integration |
|
105
|
+
!row_exists_for_integration(integration)
|
76
106
|
end
|
77
107
|
end
|
78
108
|
end
|
79
109
|
|
110
|
+
def row_exists_for_integration(integration)
|
111
|
+
rows.find { | row | integration == row }
|
112
|
+
end
|
113
|
+
|
80
114
|
def missing_reasons
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
"There is no verified pact between #{consumer_version_desc} and #{provider_version_desc}"
|
85
|
-
end
|
115
|
+
required_integrations_without_a_row.collect do | integration |
|
116
|
+
pact_not_verified_by_required_provider_version(integration)
|
117
|
+
end.flatten
|
86
118
|
end
|
87
119
|
|
88
|
-
def
|
89
|
-
|
90
|
-
|
91
|
-
resolved_selector[:pacticipant_version_number]
|
92
|
-
else
|
93
|
-
logger.warn "Could not find the resolved version for pacticipant_id #{pacticipant_id} from integrations #{integrations.collect(&:to_s).join(", ")} in resolved selectors #{resolved_selectors.inspect}"
|
94
|
-
"unresolved version"
|
120
|
+
def selectors_without_a_version_for(integration)
|
121
|
+
selectors_with_non_existing_versions.select do | selector |
|
122
|
+
integration.involves_pacticipant_with_name?(selector.pacticipant_name)
|
95
123
|
end
|
96
124
|
end
|
125
|
+
|
126
|
+
def selectors_with_non_existing_versions
|
127
|
+
@selectors_with_non_existing_versions ||= resolved_selectors.select(&:latest_tagged_version_that_does_not_exist?)
|
128
|
+
end
|
129
|
+
|
130
|
+
def missing_specified_version_reasons(selectors)
|
131
|
+
selectors.collect(&:version_does_not_exist_description)
|
132
|
+
end
|
133
|
+
|
134
|
+
def pact_not_verified_by_required_provider_version(integration)
|
135
|
+
PactNotVerifiedByRequiredProviderVersion.new(*selectors_for(integration))
|
136
|
+
end
|
137
|
+
|
138
|
+
def pact_not_ever_verified_by_provider(row)
|
139
|
+
PactNotEverVerifiedByProvider.new(*selectors_for(row))
|
140
|
+
end
|
141
|
+
|
142
|
+
def selector_for(pacticipant_name)
|
143
|
+
resolved_selectors.find{ | s| s.pacticipant_name == pacticipant_name } ||
|
144
|
+
dummy_selectors.find{ | s| s.pacticipant_name == pacticipant_name }
|
145
|
+
end
|
146
|
+
|
147
|
+
def selectors_for(row)
|
148
|
+
[selector_for(row.consumer_name), selector_for(row.provider_name)]
|
149
|
+
end
|
150
|
+
|
151
|
+
# When the user has not specified a version of the provider (eg no 'latest' and/or 'tag')
|
152
|
+
# so the "add inferred selectors" code in the Matrix::Repository has not run,
|
153
|
+
# we may end up with rows for which we do not have a selector.
|
154
|
+
# To solve this, create dummy selectors from the row and integration data.
|
155
|
+
def create_dummy_selectors
|
156
|
+
(dummy_selectors_from_rows + dummy_selectors_from_integrations).uniq
|
157
|
+
end
|
158
|
+
|
159
|
+
def dummy_selectors_from_integrations
|
160
|
+
integrations.collect do | row |
|
161
|
+
dummy_consumer_selector = ResolvedSelector.for_pacticipant(row.consumer, :inferred)
|
162
|
+
dummy_provider_selector = ResolvedSelector.for_pacticipant(row.provider, :inferred)
|
163
|
+
[dummy_consumer_selector, dummy_provider_selector]
|
164
|
+
end.flatten
|
165
|
+
end
|
166
|
+
|
167
|
+
def dummy_selectors_from_rows
|
168
|
+
rows.collect do | row |
|
169
|
+
dummy_consumer_selector = ResolvedSelector.for_pacticipant_and_version(row.consumer, row.consumer_version, {}, :inferred)
|
170
|
+
dummy_provider_selector = row.provider_version ?
|
171
|
+
ResolvedSelector.for_pacticipant_and_version(row.provider, row.provider_version, {}, :inferred) :
|
172
|
+
ResolvedSelector.for_pacticipant(row.provider, :inferred)
|
173
|
+
[dummy_consumer_selector, dummy_provider_selector]
|
174
|
+
end.flatten
|
175
|
+
end
|
97
176
|
end
|
98
177
|
end
|
99
178
|
end
|