pact_broker 2.6.0 → 2.7.0.beta.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -0
  3. data/db/migrations/42_delete_orphan_webhook_data.rb +0 -2
  4. data/db/migrations/43_add_provider_version_to_verification.rb +12 -0
  5. data/db/migrations/44_populate_verifications_provider_version_id.rb +25 -0
  6. data/db/migrations/45_set_verification_provider_number_nullable.rb +7 -0
  7. data/db/migrations/46_recreate_latest_verifications.rb +18 -0
  8. data/db/migrations/47_create_all_verifications.rb +19 -0
  9. data/lib/pact_broker/api.rb +4 -0
  10. data/lib/pact_broker/api/decorators/matrix_decorator.rb +114 -0
  11. data/lib/pact_broker/api/decorators/verification_decorator.rb +1 -1
  12. data/lib/pact_broker/api/pact_broker_urls.rb +2 -2
  13. data/lib/pact_broker/api/resources/index.rb +3 -5
  14. data/lib/pact_broker/api/resources/matrix.rb +48 -0
  15. data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +42 -0
  16. data/lib/pact_broker/domain/relationship.rb +26 -6
  17. data/lib/pact_broker/domain/verification.rb +5 -1
  18. data/lib/pact_broker/matrix/repository.rb +51 -0
  19. data/lib/pact_broker/matrix/service.rb +50 -0
  20. data/lib/pact_broker/pacticipants/service.rb +21 -5
  21. data/lib/pact_broker/pacts/all_pact_publications.rb +11 -0
  22. data/lib/pact_broker/pacts/pact_publication.rb +4 -0
  23. data/lib/pact_broker/pacts/repository.rb +1 -1
  24. data/lib/pact_broker/repositories.rb +5 -0
  25. data/lib/pact_broker/services.rb +5 -0
  26. data/lib/pact_broker/tags/service.rb +0 -1
  27. data/lib/pact_broker/ui/app.rb +5 -0
  28. data/lib/pact_broker/ui/controllers/matrix.rb +27 -0
  29. data/lib/pact_broker/ui/controllers/relationships.rb +2 -2
  30. data/lib/pact_broker/ui/view_models/matrix_line.rb +79 -0
  31. data/lib/pact_broker/ui/view_models/relationship.rb +22 -4
  32. data/lib/pact_broker/ui/views/matrix/show.haml +42 -0
  33. data/lib/pact_broker/ui/views/relationships/show-prod-tags.haml +83 -0
  34. data/lib/pact_broker/ui/views/relationships/show.haml +1 -1
  35. data/lib/pact_broker/verifications/repository.rb +8 -1
  36. data/lib/pact_broker/verifications/service.rb +2 -1
  37. data/lib/pact_broker/version.rb +1 -1
  38. data/lib/pact_broker/versions/service.rb +7 -0
  39. data/lib/pact_broker/webhooks/status.rb +1 -1
  40. data/lib/rack/pact_broker/convert_file_extension_to_accept_header.rb +1 -1
  41. data/script/seed.rb +5 -0
  42. data/spec/features/get_matrix_for_consumer_and_provider_spec.rb +25 -0
  43. data/spec/features/get_matrix_spec.rb +31 -0
  44. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +133 -0
  45. data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +2 -8
  46. data/spec/lib/pact_broker/api/decorators/verification_summary_decorator_spec.rb +3 -2
  47. data/spec/lib/pact_broker/api/resources/matrix_spec.rb +38 -0
  48. data/spec/lib/pact_broker/domain/relationship_spec.rb +1 -1
  49. data/spec/lib/pact_broker/matrix/repository_spec.rb +153 -0
  50. data/spec/lib/pact_broker/matrix/service_spec.rb +46 -0
  51. data/spec/lib/pact_broker/pacticipants/service_spec.rb +78 -4
  52. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +35 -0
  53. data/spec/lib/pact_broker/pacts/repository_spec.rb +16 -14
  54. data/spec/lib/pact_broker/ui/view_models/relationship_spec.rb +5 -6
  55. data/spec/lib/pact_broker/verifications/repository_spec.rb +7 -7
  56. data/spec/lib/pact_broker/verifications/service_spec.rb +6 -0
  57. data/spec/lib/pact_broker/versions/service_spec.rb +37 -0
  58. data/spec/lib/pact_broker/webhooks/status_spec.rb +6 -0
  59. data/spec/migrations/44_add_provider_version_to_verification_spec.rb +60 -0
  60. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +12 -0
  61. data/spec/support/shared_examples_for_responses.rb +4 -0
  62. data/spec/support/test_data_builder.rb +26 -3
  63. metadata +34 -4
@@ -13,7 +13,7 @@ module PactBroker
13
13
  allow(webhook_executions).to receive(:sort).and_return(webhook_executions)
14
14
  end
15
15
 
16
- subject { Relationship.create(nil, nil, nil, nil, [], webhook_executions) }
16
+ subject { Relationship.create(nil, nil, nil, true, nil, [], webhook_executions) }
17
17
 
18
18
  it "returns the created_at date of the last execution" do
19
19
  expect(subject.last_webhook_execution_date).to eq DateTime.new(2015)
@@ -0,0 +1,153 @@
1
+ require 'pact_broker/matrix/repository'
2
+
3
+ module PactBroker
4
+ module Matrix
5
+ describe Repository do
6
+ describe "#find" do
7
+ before do
8
+ TestDataBuilder.new
9
+ .create_pact_with_hierarchy("Consumer", "1.2.3", "Provider")
10
+ .create_verification(provider_version: "6.7.8", execution_date: DateTime.new(2016))
11
+ .revise_pact
12
+ .create_verification(provider_version: "4.5.6", execution_date: DateTime.new(2017))
13
+ .create_consumer_version("2.0.0")
14
+ .create_pact
15
+ end
16
+
17
+ subject { Repository.new.find("Consumer", "Provider") }
18
+
19
+ it "returns the latest revision of each pact" do
20
+ expect(subject.count).to eq 2
21
+ expect(subject[0][:consumer_version_number]).to eq "2.0.0"
22
+ expect(subject[1][:consumer_version_number]).to eq "1.2.3"
23
+ end
24
+
25
+ it "returns the latest verification for the pact version" do
26
+ expect(subject[1][:provider_version_number]).to eq "4.5.6"
27
+ end
28
+
29
+ it "doesn't matter which way you order the pacticipant names" do
30
+ expect(subject).to eq(Repository.new.find "Provider", "Consumer")
31
+ end
32
+ end
33
+
34
+ describe "#find_compatible_pacticipant_versions" do
35
+ let(:td) { TestDataBuilder.new }
36
+
37
+ context "when compatible versions can be found" do
38
+ before do
39
+ td.create_pact_with_hierarchy("A", "1", "B")
40
+ .create_verification(provider_version: '0')
41
+ .revise_pact
42
+ .create_verification(provider_version: '1')
43
+ .create_verification(provider_version: '2', number: 2)
44
+ .use_consumer("B")
45
+ .use_consumer_version("1")
46
+ .create_provider("C")
47
+ .create_pact
48
+ .create_verification(provider_version: '1')
49
+ .use_consumer_version("2")
50
+ .create_pact
51
+ .create_verification(provider_version: '2')
52
+ .create_verification(provider_version: '3', number: 2)
53
+ end
54
+
55
+ subject { Repository.new.find_compatible_pacticipant_versions("A" => "1", "B" => "2", "C" => "2") }
56
+
57
+ it "returns matrix lines for each compatible version pair" do
58
+ expect(subject.first[:consumer_name]).to eq "A"
59
+ expect(subject.first[:consumer_version_number]).to eq "1"
60
+ expect(subject.first[:provider_name]).to eq "B"
61
+ expect(subject.first[:provider_version_number]).to eq "2"
62
+ expect(subject.first[:number]).to eq 2
63
+ expect(subject.first[:pact_created_at]).to be_datey
64
+ expect(subject.first[:verification_executed_at]).to be_datey
65
+
66
+ expect(subject.last[:consumer_name]).to eq "B"
67
+ expect(subject.last[:consumer_version_number]).to eq "2"
68
+ expect(subject.last[:provider_name]).to eq "C"
69
+ expect(subject.last[:provider_version_number]).to eq "2"
70
+ expect(subject.last[:number]).to eq 1
71
+ expect(subject.last[:pact_created_at]).to be_datey
72
+
73
+ expect(subject.size).to eq 2
74
+ end
75
+
76
+ context "when one or more pacticipants does not have a version specified" do
77
+ subject { Repository.new.find_compatible_pacticipant_versions("A" => "1", "B" => "2", "C" => nil) }
78
+
79
+ it "returns all the rows for that pacticipant" do
80
+ expect(subject[1]).to include(provider_name: "C", provider_version_number: "2")
81
+ expect(subject[2]).to include(provider_name: "C", provider_version_number: "3")
82
+ expect(subject.size).to eq 3
83
+ end
84
+ end
85
+
86
+ context "none of the pacticipants have a version specified" do
87
+ subject { Repository.new.find_compatible_pacticipant_versions("A" => nil, "B" => nil, "C" => nil) }
88
+
89
+ it "returns all the rows" do
90
+ expect(subject.size).to eq 4
91
+ end
92
+ end
93
+ end
94
+
95
+ context "when there is more than one compatible version pair" do
96
+ before do
97
+ td.create_pact_with_hierarchy("X", "1", "Y")
98
+ .create_verification(provider_version: "1")
99
+ .create_verification(provider_version: "1", number: 2)
100
+ end
101
+ subject { Repository.new.find_compatible_pacticipant_versions("X" => "1", "Y" => "1") }
102
+
103
+ it "returns the last line" do
104
+ expect(subject.size).to eq 1
105
+ expect(subject.first[:number]).to eq 2
106
+ end
107
+ end
108
+
109
+ context "when there is more than one compatible verison pair and the last one is a failure" do
110
+ before do
111
+ td.create_pact_with_hierarchy("X", "1", "Y")
112
+ .create_verification(provider_version: "1")
113
+ .create_verification(provider_version: "1", number: 2, success: false)
114
+ end
115
+
116
+ subject { Repository.new.find_compatible_pacticipant_versions("X" => "1", "Y" => "1") }
117
+
118
+ it "does not return a matrix line" do
119
+ expect(subject.size).to eq 0
120
+ end
121
+ end
122
+
123
+ context "when a pact is verified, but then revised and the new revision is not verified" do
124
+ before do
125
+ td.create_pact_with_hierarchy("X", "1", "Y")
126
+ .create_verification(provider_version: "1")
127
+ .revise_pact
128
+ end
129
+
130
+ subject { Repository.new.find_compatible_pacticipant_versions("X" => "1", "Y" => "1") }
131
+
132
+ it "does not return a matrix line" do
133
+ expect(subject.size).to eq 0
134
+ end
135
+ end
136
+
137
+ context "when the verification result is false" do
138
+ before do
139
+ TestDataBuilder.new
140
+ .create_pact_with_hierarchy("D", "1", "E")
141
+ .create_verification(provider_version: '1', success: false)
142
+ end
143
+
144
+ subject { Repository.new.find_compatible_pacticipant_versions("D" => "1", "E" => "1") }
145
+
146
+ it "does not return the matrix line" do
147
+ expect(subject.count).to eq 0
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
@@ -0,0 +1,46 @@
1
+ require 'pact_broker/matrix/service'
2
+
3
+ module PactBroker
4
+ module Matrix
5
+ describe Service do
6
+ describe "validate_selectors" do
7
+ let(:td) { TestDataBuilder.new }
8
+
9
+ subject { Service.validate_selectors(selectors) }
10
+
11
+ context "when a selector format is invalid" do
12
+ let(:selectors) { ["Foo/1"] }
13
+
14
+ it "returns error messages" do
15
+ expect(subject.first).to eq "Invalid version selector 'Foo/1'. Format must be <pacticipant_name>/version/<version>"
16
+ end
17
+ end
18
+
19
+ context "when one or more of the selectors does not match any known version" do
20
+ before do
21
+ td.create_pacticipant("Foo")
22
+ .create_version("1")
23
+ .create_pacticipant("Bar")
24
+ .create_version("2")
25
+
26
+ end
27
+
28
+ let(:selectors) { ["Foo/version/1", "Bar/version/1"] }
29
+
30
+ it "returns error messages" do
31
+ expect(subject).to eq ["No pact or verification found for Bar/version/1"]
32
+ end
33
+ end
34
+
35
+ context "when the pacticipant does not exist" do
36
+ let(:selectors) { ["Foo/version/1"] }
37
+
38
+ it "returns error messages" do
39
+ expect(subject.first).to eq "Pacticipant 'Foo' not found"
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+
@@ -8,6 +8,8 @@ module PactBroker
8
8
  module Pacticipants
9
9
  describe Service do
10
10
 
11
+ let(:td) { TestDataBuilder.new }
12
+
11
13
  subject{ Service }
12
14
 
13
15
  describe ".messages_for_potential_duplicate_pacticipants" do
@@ -97,10 +99,9 @@ module PactBroker
97
99
  end
98
100
 
99
101
  describe ".find_relationships" do
100
-
101
102
  let(:consumer) { instance_double("PactBroker::Domain::Pacticipant")}
102
103
  let(:provider) { instance_double("PactBroker::Domain::Pacticipant")}
103
- let(:pact) { instance_double("PactBroker::Domain::Pact", consumer: consumer, provider: provider)}
104
+ let(:pact) { instance_double("PactBroker::Domain::Pact", id: 1, consumer: consumer, provider: provider, consumer_name: 'foo', provider_name: 'bar', consumer_version_tag_names: [])}
104
105
  let(:verification) { instance_double("PactBroker::Domain::Verification")}
105
106
  let(:pacts) { [pact]}
106
107
  let(:webhooks) { [instance_double("PactBroker::Domain::Webhook")]}
@@ -108,6 +109,7 @@ module PactBroker
108
109
 
109
110
  before do
110
111
  allow_any_instance_of(PactBroker::Pacts::Repository).to receive(:find_latest_pacts).and_return(pacts)
112
+ allow_any_instance_of(PactBroker::Pacts::Repository).to receive(:find_latest_pact).and_return(pact)
111
113
  allow(PactBroker::Verifications::Service).to receive(:find_latest_verification_for).and_return(verification)
112
114
  allow(PactBroker::Webhooks::Service).to receive(:find_by_consumer_and_provider).and_return(webhooks)
113
115
  allow(PactBroker::Webhooks::Service).to receive(:find_latest_triggered_webhooks).and_return(triggered_webhooks)
@@ -124,13 +126,85 @@ module PactBroker
124
126
  end
125
127
 
126
128
  it "returns a list of relationships" do
127
- expect(subject.find_relationships).to eq([PactBroker::Domain::Relationship.create(consumer, provider, pact, verification, webhooks)])
129
+ expect(subject.find_relationships).to eq([PactBroker::Domain::Relationship.create(consumer, provider, pact, true, verification, webhooks)])
128
130
  end
131
+ end
132
+
133
+ describe "find_relationships integration test" do
134
+ context "when a prod pact exists and is not the latest version" do
135
+ before do
136
+ td.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
137
+ .create_consumer_version_tag("prod")
138
+ .create_consumer_version_tag("ignored")
139
+ .create_verification(provider_version: "2.0.0")
140
+ .create_consumer_version("1.2.4")
141
+ .create_consumer_version_tag("also-ignored")
142
+ .create_pact
143
+ .create_verification(provider_version: "2.1.0")
144
+ end
129
145
 
146
+ let(:rows) { subject.find_relationships }
147
+
148
+ it "returns both rows" do
149
+ expect(rows.count).to eq 2
150
+ end
151
+
152
+ it "returns the latest row first" do
153
+ expect(rows.first.consumer_version_number).to eq "1.2.4"
154
+ expect(rows.last.consumer_version_number).to eq "1.2.3"
155
+ end
156
+
157
+ it "designates the first row as the latest row, and the second as not latest" do
158
+ expect(rows.first.latest?).to be true
159
+ expect(rows.last.latest?).to be false
160
+ end
161
+
162
+ it "doesn't return any tag names for the latest row" do
163
+ expect(rows.first.tag_names).to eq []
164
+ end
165
+
166
+ it "includes the prod tag name for the prod row" do
167
+ expect(rows.last.tag_names).to eq ['prod']
168
+ end
169
+
170
+ it "includes the latest overall verification for the latest pact" do
171
+ expect(rows.first.latest_verification.provider_version_number).to eq '2.1.0'
172
+ end
173
+
174
+ it "includes the latest prod verification for the prod pact" do
175
+ expect(rows.last.latest_verification.provider_version_number).to eq '2.0.0'
176
+ end
177
+ end
178
+
179
+ context "when the prod version is the latest version" do
180
+ before do
181
+ td.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
182
+ .create_consumer_version_tag("prod")
183
+ .create_consumer_version_tag("ignored")
184
+ .create_verification(provider_version: "2.0.0")
185
+ end
186
+
187
+ let(:rows) { subject.find_relationships }
188
+
189
+ it "returns one row" do
190
+ expect(rows.count).to eq 1
191
+ end
192
+
193
+ it "designates the row as the latest row" do
194
+ expect(rows.first.latest?).to be true
195
+ end
196
+
197
+ it "includes the prod tag name for the row" do
198
+ expect(rows.first.tag_names).to eq ['prod']
199
+ end
200
+
201
+ it "includes the latest overall verification for the latest pact" do
202
+ expect(rows.first.latest_verification.provider_version_number).to eq '2.0.0'
203
+ end
204
+ end
130
205
  end
131
206
 
132
207
  describe "delete" do
133
-
134
208
  before do
135
209
  TestDataBuilder.new
136
210
  .create_consumer("Consumer")
@@ -0,0 +1,35 @@
1
+ require 'pact_broker/pacts/pact_publication'
2
+
3
+ module PactBroker
4
+ module Pacts
5
+ describe PactPublication do
6
+
7
+ describe "#latest_tag_names" do
8
+ before do
9
+ td.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
10
+ .create_consumer_version_tag("no")
11
+ .create_consumer_version("3.4.5")
12
+ .create_consumer_version_tag("yes")
13
+ .create_pact
14
+ .create_consumer_version("5.6.7")
15
+ .create_consumer_version_tag("no")
16
+ end
17
+
18
+ let(:td) { TestDataBuilder.new }
19
+ let(:pact_publication) { PactPublication.find(id: td.pact.id) }
20
+
21
+ context "when the pact is the latest for a tag" do
22
+ it "returns the relevant tag names" do
23
+ expect(pact_publication.latest_tag_names).to eq ["yes"]
24
+ end
25
+ end
26
+
27
+ context "when the pact is not the latest for a tag" do
28
+ it "returns the relevant tag names" do
29
+ expect(pact_publication.latest_tag_names).to eq ["yes"]
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -576,19 +576,20 @@ module PactBroker
576
576
  describe "find_latest_pacts" do
577
577
  before do
578
578
  TestDataBuilder.new
579
- .create_condor
580
- .create_condor_version('1.3.0')
581
- .create_pricing_service
582
- .create_condor_pricing_service_pact
583
- .create_condor_version('1.4.0')
584
- .create_condor_pricing_service_pact
585
- .create_contract_email_service
586
- .create_contract_email_service_version('2.6.0')
587
- .create_contract_proposal_service
588
- .create_ces_cps_pact
589
- .create_contract_email_service_version('2.7.0')
590
- .create_ces_cps_pact
591
- .create_contract_email_service_version('2.8.0') # Create a version without a pact, it shouldn't be used
579
+ .create_consumer("Condor")
580
+ .create_consumer_version('1.3.0')
581
+ .create_provider("Pricing Service")
582
+ .create_pact
583
+ .create_consumer_version('1.4.0')
584
+ .create_consumer_version_tag("prod")
585
+ .create_pact
586
+ .create_consumer("Contract Email Service")
587
+ .create_consumer_version("2.6.0")
588
+ .create_provider("Contract Proposal Service")
589
+ .create_pact
590
+ .create_consumer_version('2.7.0')
591
+ .create_pact
592
+ .create_consumer_version('2.8.0') # Create a version without a pact, it shouldn't be used
592
593
  end
593
594
 
594
595
  it "finds the latest pact for each consumer/provider pair" do
@@ -600,12 +601,13 @@ module PactBroker
600
601
  expect(pacts[0].provider.name).to eq("Pricing Service")
601
602
  expect(pacts[0].provider.id).to_not be nil
602
603
  expect(pacts[0].consumer_version.number).to eq("1.4.0")
603
- expect(pacts[1].consumer_version.tags).to be nil # Not used, don't bother loading
604
+ expect(pacts[0].consumer_version.tags.collect(&:name)).to eq ["prod"]
604
605
 
605
606
  expect(pacts[1].consumer_version.pacticipant.name).to eq("Contract Email Service")
606
607
  expect(pacts[1].consumer.name).to eq("Contract Email Service")
607
608
  expect(pacts[1].provider.name).to eq("Contract Proposal Service")
608
609
  expect(pacts[1].consumer_version.number).to eq("2.7.0")
610
+ expect(pacts[1].consumer_version.tags.collect(&:name)).to eq []
609
611
  end
610
612
 
611
613
  it "includes the timestamps - need to update view" do
@@ -16,7 +16,7 @@ module PactBroker
16
16
 
17
17
  its(:consumer_name) { should eq 'Consumer Name'}
18
18
  its(:provider_name) { should eq 'Provider Name'}
19
- its(:latest_pact_url) { should eq "/pacts/provider/Provider%20Name/consumer/Consumer%20Name/latest" }
19
+ its(:pact_url) { should eq "/pacts/provider/Provider%20Name/consumer/Consumer%20Name/latest" }
20
20
  its(:consumer_group_url) { should eq "/groups/Consumer%20Name" }
21
21
  its(:provider_group_url) { should eq "/groups/Provider%20Name" }
22
22
 
@@ -25,7 +25,7 @@ module PactBroker
25
25
  instance_double("PactBroker::Domain::Relationship",
26
26
  verification_status: verification_status,
27
27
  provider_name: "Foo",
28
- latest_verification_provider_version: "4.5.6")
28
+ latest_verification_provider_version_number: "4.5.6")
29
29
  end
30
30
  let(:ever_verified) { true }
31
31
  let(:pact_changed) { false }
@@ -67,7 +67,8 @@ module PactBroker
67
67
  instance_double("PactBroker::Domain::Relationship",
68
68
  webhook_status: webhook_status,
69
69
  last_webhook_execution_date: DateTime.now - 1,
70
- latest_pact: double("pact", consumer: consumer, provider: provider)
70
+ latest_pact: double("pact", consumer: consumer, provider: provider),
71
+ latest?: true
71
72
  )
72
73
  end
73
74
  let(:webhook_status) { :none }
@@ -122,10 +123,8 @@ module PactBroker
122
123
  expect(relationship_view_models.sort.collect{ |r| [r.consumer_name, r.provider_name]})
123
124
  .to eq([["A", "X"],["a","y"],["A","Z"],["C", "A"]])
124
125
  end
125
-
126
126
  end
127
-
128
127
  end
129
128
  end
130
129
  end
131
- end
130
+ end