pact_broker 2.6.0 → 2.7.0.beta.1

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.
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