Skip to content

Commit f7ab8cc

Browse files
committed
feat(can-i-deploy): experimental - add a warning message if there are interactions missing verification test results.
1 parent 3c209a4 commit f7ab8cc

File tree

11 files changed

+294
-7
lines changed

11 files changed

+294
-7
lines changed

lib/pact_broker/api/decorators/reason_decorator.rb

+17
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ def to_s
2222
"There are no missing dependencies"
2323
when PactBroker::Matrix::Successful
2424
"All required verification results are published and successful"
25+
when PactBroker::Matrix::InteractionsMissingVerifications
26+
descriptions = reason.interactions.collect do | interaction |
27+
interaction_description(interaction)
28+
end.join('; ')
29+
"WARNING: Although the verification was reported as successful, the results for #{reason.consumer_selector.description} and #{reason.provider_selector.description} may be missing tests for the following interactions: #{descriptions}"
2530
else
2631
reason
2732
end
@@ -44,6 +49,18 @@ def version_does_not_exist_description selector
4449
""
4550
end
4651
end
52+
53+
# TODO move this somewhere else
54+
def interaction_description(interaction)
55+
if interaction['providerState'] && interaction['providerState'] != ''
56+
"#{interaction['description']} given #{interaction['providerState']}"
57+
elsif interaction['providerStates'] && interaction['providerStates'].is_a?(Array) && interaction['providerStates'].any?
58+
provider_states = interaction['providerStates'].collect{ |ps| ps['name'] }.compact.join(', ')
59+
"#{interaction['description']} given #{provider_states}"
60+
else
61+
interaction['description']
62+
end
63+
end
4764
end
4865
end
4966
end

lib/pact_broker/domain/verification.rb

+13
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
require 'sequel'
33
require 'pact_broker/repositories/helpers'
44
require 'pact_broker/tags/tag_with_latest_flag'
5+
require 'pact_broker/pacts/content'
56

67

78
module PactBroker
@@ -83,6 +84,18 @@ def provider_version_tag_names
8384
def latest_pact_publication
8485
pact_version.latest_pact_publication
8586
end
87+
88+
def interactions_missing_test_results
89+
@interactions_missing_test_results ||= pact_content_with_test_results.interactions_missing_test_results
90+
end
91+
92+
def all_interactions_missing_test_results?
93+
pact_content_with_test_results.interactions.count == pact_content_with_test_results.interactions_missing_test_results.count
94+
end
95+
96+
def pact_content_with_test_results
97+
@pact_content_with_test_results = PactBroker::Pacts::Content.from_json(pact_version.content).with_test_results(test_results)
98+
end
8699
end
87100

88101
Verification.plugin :timestamps

lib/pact_broker/matrix/deployment_status_summary.rb

+23-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ def deployable?
3131
end
3232

3333
def reasons
34-
error_messages.any? ? error_messages : success_messages
34+
error_messages.any? ? error_messages + warning_messages : success_messages + warning_messages
3535
end
3636

3737
private
@@ -51,6 +51,10 @@ def error_messages
5151
end
5252
end
5353

54+
def warning_messages
55+
warnings_for_missing_interactions
56+
end
57+
5458
def specified_selectors_that_do_not_exist
5559
resolved_selectors.select(&:specified_version_that_does_not_exist?)
5660
end
@@ -182,6 +186,24 @@ def dummy_selectors_from_rows
182186
[dummy_consumer_selector, dummy_provider_selector]
183187
end.flatten
184188
end
189+
190+
# experimental
191+
def warnings_for_missing_interactions
192+
rows.select(&:success).collect do | row |
193+
begin
194+
if row.verification.interactions_missing_test_results.any? && !row.verification.all_interactions_missing_test_results?
195+
InteractionsMissingVerifications.new(selector_for(row.consumer_name), selector_for(row.provider_name), row.verification.interactions_missing_test_results)
196+
end
197+
rescue StandardError => e
198+
log_error(e, "Error determining if there were missing interaction verifications")
199+
nil
200+
end
201+
end.compact.tap { |it| report_missing_interaction_verifications(it) if it.any? }
202+
end
203+
204+
def report_missing_interaction_verifications(messages)
205+
logger.warn("Interactions missing verifications", messages)
206+
end
185207
end
186208
end
187209
end

lib/pact_broker/matrix/reason.rb

+9
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,14 @@ class Successful < Reason
7373
# provider verifications.
7474
class NoDependenciesMissing < Reason
7575
end
76+
77+
class InteractionsMissingVerifications < ErrorReasonWithTwoSelectors
78+
attr_reader :interactions
79+
80+
def initialize(consumer_selector, provider_selector, interactions)
81+
super(consumer_selector, provider_selector)
82+
@interactions = interactions
83+
end
84+
end
7685
end
7786
end

lib/pact_broker/pacts/content.rb

+26-2
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,25 @@ def sort
3131
Content.from_hash(SortContent.call(pact_hash))
3232
end
3333

34+
def interactions_missing_test_results
35+
interactions.reject do | interaction |
36+
interaction['tests']&.any?
37+
end
38+
end
39+
3440
def with_test_results(test_results)
41+
tests = test_results && test_results['tests']
42+
if tests.nil? || !tests.is_a?(Array) || tests.empty?
43+
tests = []
44+
end
45+
3546
new_pact_hash = pact_hash.dup
3647
if interactions && interactions.is_a?(Array)
37-
new_pact_hash['interactions'] = merge_verification_results(interactions, test_results)
48+
new_pact_hash['interactions'] = merge_verification_results(interactions, tests)
3849
end
3950

4051
if messages && messages.is_a?(Array)
41-
new_pact_hash['messages'] = merge_verification_results(messages, test_results)
52+
new_pact_hash['messages'] = merge_verification_results(messages, tests)
4253
end
4354
Content.from_hash(new_pact_hash)
4455
end
@@ -107,6 +118,19 @@ def add_ids(interactions, overwrite_existing_id)
107118
end
108119
end
109120
end
121+
122+
def merge_verification_results(interactions, tests)
123+
interactions.collect(&:dup).collect do | interaction |
124+
interaction['tests'] = tests.select do | test |
125+
test_is_for_interaction(interaction, test)
126+
end
127+
interaction
128+
end
129+
end
130+
131+
def test_is_for_interaction(interaction, test)
132+
test.is_a?(Hash) && interaction.is_a?(Hash) && test['interactionDescription'] == interaction['description'] && test['interactionProviderState'] == interaction['providerState']
133+
end
110134
end
111135
end
112136
end

script/foo-bar-verification.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
"success": true,
33
"providerApplicationVersion": "1.0.0",
44
"testResults": {
5-
"examples": [
5+
"tests": [
66
{
7+
"interactionDescription": "a request for something",
8+
"interactionProviderState": null,
79
"description": "has status code 200",
810
"file_path": "/redacted/.gem/ruby/2.4.1/gems/pact-1.17.0/lib/pact/provider/rspec.rb",
911
"full_description": "Verifying a pact between me and they Greeting with GET / returns a response which has status code 200",

script/foo-bar.json

+11
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,17 @@
1717
"status": 200,
1818
"body" : "something"
1919
}
20+
},{
21+
"description" : "a request for something else",
22+
"providerState": null,
23+
"request": {
24+
"method": "get",
25+
"path" : "/something"
26+
},
27+
"response": {
28+
"status": 200,
29+
"body" : "something"
30+
}
2031
}
2132
]
2233
}

spec/lib/pact_broker/api/decorators/reason_decorator_spec.rb

+18-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module Decorators
1010

1111
describe "the number of Reason classes" do
1212
it "is 9 - add another spec here if a new Reason is added" do
13-
expect(REASON_CLASSES.size).to eq 9
13+
expect(REASON_CLASSES.size).to eq 10
1414
end
1515
end
1616

@@ -52,6 +52,23 @@ module Decorators
5252

5353
its(:to_s) { is_expected.to eq "All required verification results are published and successful" }
5454
end
55+
56+
context "when the reason is PactBroker::Matrix::InteractionsMissingVerifications" do
57+
let(:reason) { PactBroker::Matrix::InteractionsMissingVerifications.new(consumer_selector, provider_selector, interactions) }
58+
let(:interactions) do
59+
[
60+
{
61+
"description" => "desc1",
62+
"providerState" => "p2"
63+
},{
64+
"description" => "desc1",
65+
"providerStates" => [ { "name" => "desc3"}, { "name" => "desc4"} ]
66+
}
67+
]
68+
end
69+
70+
its(:to_s) { is_expected.to eq "WARNING: Although the verification was reported as successful, the results for version 2 of Foo and version 6 of Bar may be missing tests for the following interactions: desc1 given p2; desc1 given desc3, desc4" }
71+
end
5572
end
5673
end
5774
end

spec/lib/pact_broker/matrix/deployment_status_summary_spec.rb

+6-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ module Matrix
2929
provider_name: bar.name,
3030
provider_id: bar.id,
3131
success: row_1_success,
32-
pacticipant_names: [foo.name, bar.name]
32+
pacticipant_names: [foo.name, bar.name],
33+
verification: verification_1
3334
)
3435
end
3536

@@ -46,7 +47,8 @@ module Matrix
4647
provider_name: baz.name,
4748
provider_id: baz.id,
4849
success: true,
49-
pacticipant_names: [foo.name, baz.name]
50+
pacticipant_names: [foo.name, baz.name],
51+
verification: verification_2
5052
)
5153
end
5254

@@ -65,6 +67,8 @@ module Matrix
6567
let(:foo_version) { double('foo version', number: "ddec8101dabf4edf9125a69f9a161f0f294af43c", id: 10)}
6668
let(:bar_version) { double('bar version', number: "14131c5da3abf323ccf410b1b619edac76231243", id: 11)}
6769
let(:baz_version) { double('baz version', number: "4ee06460f10e8207ad904fa9fa6c4842e462ab59", id: 12)}
70+
let(:verification_1) { double('verification 1', interactions_missing_test_results: []) }
71+
let(:verification_2) { double('verification 2', interactions_missing_test_results: []) }
6872

6973
let(:resolved_selectors) do
7074
[

spec/lib/pact_broker/matrix/integration_spec.rb

+43
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,49 @@ module Matrix
416416
expect(subject.deployment_status_summary).to be_deployable
417417
end
418418
end
419+
420+
describe "when verification results are published missing tests for some interactions" do
421+
let(:pact_content) do
422+
{
423+
"interactions" => [
424+
{
425+
"description" => "desc1"
426+
},{
427+
"description" => "desc2"
428+
}
429+
]
430+
}
431+
end
432+
433+
let(:verification_tests) do
434+
[
435+
{
436+
"interactionDescription" => "desc1"
437+
}
438+
]
439+
end
440+
441+
before do
442+
td.create_consumer("Foo")
443+
.create_provider("Bar")
444+
.create_consumer_version
445+
.create_pact(json_content: pact_content.to_json)
446+
.create_verification(provider_version: "1", test_results: { tests: verification_tests })
447+
end
448+
449+
let(:selectors) do
450+
[
451+
UnresolvedSelector.new(pacticipant_name: "Foo", latest: true),
452+
UnresolvedSelector.new(pacticipant_name: "Bar", latest: true)
453+
]
454+
end
455+
456+
let(:options) { { latestby: "cvpv"} }
457+
458+
it "should include a warning" do
459+
expect(subject.deployment_status_summary.reasons.last).to be_a(PactBroker::Matrix::InteractionsMissingVerifications)
460+
end
461+
end
419462
end
420463
end
421464
end

0 commit comments

Comments
 (0)