pact_broker 2.43.0 → 2.44.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -1
  3. data/DEVELOPER_DOCUMENTATION.md +10 -6
  4. data/README.md +1 -1
  5. data/lib/pact_broker/api.rb +2 -2
  6. data/lib/pact_broker/api/decorators/version_decorator.rb +8 -0
  7. data/lib/pact_broker/db/models.rb +1 -1
  8. data/lib/pact_broker/doc/views/matrix.markdown +92 -2
  9. data/lib/pact_broker/matrix/deployment_status_summary.rb +11 -2
  10. data/lib/pact_broker/matrix/every_row.rb +43 -0
  11. data/lib/pact_broker/matrix/query_builder.rb +5 -5
  12. data/lib/pact_broker/matrix/quick_row.rb +96 -28
  13. data/lib/pact_broker/matrix/reason.rb +3 -0
  14. data/lib/pact_broker/matrix/repository.rb +33 -35
  15. data/lib/pact_broker/pacticipants/repository.rb +9 -1
  16. data/lib/pact_broker/pacts/{latest_pact_publication_id_by_consumer_version.rb → latest_pact_publication_id_for_consumer_version.rb} +0 -0
  17. data/lib/pact_broker/pacts/repository.rb +1 -1
  18. data/lib/pact_broker/repositories/helpers.rb +12 -5
  19. data/lib/pact_broker/version.rb +1 -1
  20. data/pact_broker.gemspec +1 -1
  21. data/spec/lib/pact_broker/integrations/service_spec.rb +1 -0
  22. data/spec/lib/pact_broker/matrix/deployment_status_summary_spec.rb +38 -33
  23. data/spec/lib/pact_broker/matrix/every_row_spec.rb +136 -0
  24. data/spec/lib/pact_broker/matrix/integration_spec.rb +149 -30
  25. data/spec/lib/pact_broker/matrix/repository_dependency_spec.rb +3 -3
  26. data/spec/lib/pact_broker/matrix/repository_spec.rb +5 -4
  27. data/spec/lib/pact_broker/pacticipants/repository_spec.rb +37 -3
  28. data/spec/service_consumers/provider_states_for_pact_ruby.rb +12 -0
  29. data/spec/support/shared_examples_for_responses.rb +7 -0
  30. metadata +14 -5
@@ -25,7 +25,7 @@ module PactBroker
25
25
  end
26
26
 
27
27
  let(:options) do
28
- { latest: true, tag: "prod" }
28
+ { latest: true, tag: "prod", latestby: "cvp" }
29
29
  end
30
30
 
31
31
  before do
@@ -54,10 +54,10 @@ module PactBroker
54
54
  end
55
55
 
56
56
  let(:selectors) { [{ pacticipant_name: "Bar", latest: true, tag: "test" }]}
57
- let(:options) { { tag: "prod" } }
57
+ let(:options) { { tag: "prod", latestby: "cvp" } }
58
58
 
59
59
  it "does not allow the consumer to be deployed" do
60
- expect(subject.deployment_status_summary.deployable?).to_not be true
60
+ expect(subject.deployment_status_summary).to_not be_deployable
61
61
  end
62
62
  end
63
63
 
@@ -80,7 +80,7 @@ module PactBroker
80
80
  end
81
81
 
82
82
  it "does not allow the consumer to be deployed" do
83
- expect(subject.deployment_status_summary.deployable?).to_not be true
83
+ expect(subject.deployment_status_summary).to_not be_deployable
84
84
  end
85
85
  end
86
86
 
@@ -101,18 +101,22 @@ module PactBroker
101
101
  [ { pacticipant_name: "Foo", pacticipant_version_number: "3.0.0" } ]
102
102
  end
103
103
 
104
- let(:options) { {latest: true, tag: "prod"} }
104
+ let(:options) { {latest: true, tag: "prod", latestby: "cvp"} }
105
105
 
106
106
  it "returns 2 integrations" do
107
107
  expect(subject.integrations.size).to eq 2
108
108
  end
109
109
 
110
- it "returns 1 row" do
111
- expect(subject.rows.size).to eq 1
110
+ it "returns 1 row with a verification" do
111
+ expect(subject.rows.select(&:has_verification?).size).to eq 1
112
+ end
113
+
114
+ it "returns 1 row without a verification" do
115
+ expect(subject.rows.reject(&:has_verification?).size).to eq 1
112
116
  end
113
117
 
114
118
  it "does not allow the consumer to be deployed" do
115
- expect(subject.deployment_status_summary.deployable?).to_not be true
119
+ expect(subject.deployment_status_summary).to_not be_deployable
116
120
  end
117
121
  end
118
122
 
@@ -133,7 +137,7 @@ module PactBroker
133
137
  end
134
138
 
135
139
  it "allows the old version of the consumer to be deployed" do
136
- expect(subject.deployment_status_summary.deployable?).to be true
140
+ expect(subject.deployment_status_summary).to be_deployable
137
141
  end
138
142
  end
139
143
 
@@ -146,8 +150,8 @@ module PactBroker
146
150
  [ { pacticipant_name: "Bar", pacticipant_version_number: "5" } ]
147
151
  end
148
152
 
149
- it "does not allow the provider to be deployed" do
150
- expect(subject.deployment_status_summary.deployable?).to_not be true
153
+ it "does not allow the app to be deployed" do
154
+ expect(subject.deployment_status_summary).to_not be_deployable
151
155
  end
152
156
  end
153
157
 
@@ -162,20 +166,19 @@ module PactBroker
162
166
  end
163
167
 
164
168
  let(:options) do
165
- { latest: true, tag: "prod" }
169
+ { latest: true, tag: "prod", latestby: "cvp" }
166
170
  end
167
171
 
168
172
  subject { Service.find(selectors, options) }
169
173
 
170
- it "allows the provider to be deployed" do
171
- expect(subject.deployment_status_summary.deployable?).to be true
174
+ it "allows the app to be deployed" do
175
+ expect(subject.deployment_status_summary).to be_deployable
172
176
  end
173
177
  end
174
178
 
175
179
  describe "when deploying a consumer to prod for the first time and the provider is not yet deployed" do
176
180
  before do
177
- td.create_pact_with_hierarchy("Foo", "1", "Bar")
178
- .create_verification(provider_version: "2")
181
+ td.create_pact_with_verification("Foo", "1", "Bar", "2")
179
182
  end
180
183
 
181
184
  let(:selectors) do
@@ -183,18 +186,17 @@ module PactBroker
183
186
  end
184
187
 
185
188
  let(:options) do
186
- { latest: true, tag: "prod" }
189
+ { latest: true, tag: "prod", latestby: "cvp" }
187
190
  end
188
191
 
189
- it "does not allow the consumer to be deployed" do
190
- expect(subject.deployment_status_summary.deployable?).to_not be true
192
+ it "does not allow the app to be deployed" do
193
+ expect(subject.deployment_status_summary).to_not be_deployable
191
194
  end
192
195
  end
193
196
 
194
197
  describe "when deploying an app that is both a consumer and a provider to prod for the first time and the downstream provider is not yet deployed" do
195
198
  before do
196
- td.create_pact_with_hierarchy("Foo", "1", "Bar")
197
- .create_verification(provider_version: "2")
199
+ td.create_pact_with_verification("Foo", "1", "Bar", "2")
198
200
  .use_consumer("Bar")
199
201
  .use_consumer_version("2")
200
202
  .create_provider("Baz")
@@ -206,18 +208,19 @@ module PactBroker
206
208
  end
207
209
 
208
210
  let(:options) do
209
- { latest: true, tag: "prod" }
211
+ { latest: true, tag: "prod", latestby: "cvp" }
210
212
  end
211
213
 
212
214
  it "does not allow the app to be deployed" do
213
- expect(subject.deployment_status_summary.deployable?).to_not be true
215
+ expect(subject.deployment_status_summary).to_not be_deployable
214
216
  end
215
217
  end
216
218
 
217
219
  describe "when deploying an app that is both a consumer and a provider to prod for the first time and the downstream provider has been deployed" do
218
220
  before do
219
- td.create_pact_with_hierarchy("Foo", "1", "Bar")
220
- .create_verification(provider_version: "2")
221
+ # Foo v1 => Bar v2
222
+ # Bar v2 => Baz v4 (prod)
223
+ td.create_pact_with_verification("Foo", "1", "Bar", "2")
221
224
  .use_consumer("Bar")
222
225
  .use_consumer_version("2")
223
226
  .create_provider("Baz")
@@ -229,12 +232,64 @@ module PactBroker
229
232
  [ { pacticipant_name: "Bar", pacticipant_version_number: "2" } ]
230
233
  end
231
234
 
235
+ # Deploy Bar v2 to prod
232
236
  let(:options) do
233
- { latest: true, tag: "prod" }
237
+ { latest: true, tag: "prod", latestby: "cvp" }
234
238
  end
235
239
 
236
240
  it "allows the app to be deployed" do
237
- expect(subject.deployment_status_summary.deployable?).to be true
241
+ expect(subject.deployment_status_summary).to be_deployable
242
+ end
243
+ end
244
+
245
+ describe "when deploying a provider where the pact has not been verified" do
246
+ before do
247
+ # Foo v1 => Bar ?
248
+ td.create_pact_with_hierarchy("Foo", "1", "Bar")
249
+ .create_provider_version("2")
250
+ end
251
+
252
+ let(:selectors) do
253
+ [ { pacticipant_name: "Bar", pacticipant_version_number: "2" } ]
254
+ end
255
+
256
+ # Deploy Bar v2 to prod
257
+ let(:options) do
258
+ { latest: true, tag: "prod", latestby: "cvp" }
259
+ end
260
+
261
+ it "allows the app to be deployed" do
262
+ # no integrations and no matrix rows
263
+ expect(subject.deployment_status_summary).to be_deployable
264
+ end
265
+ end
266
+
267
+ describe "when deploying a consumer where the pact has been verified, but not by the required provider version" do
268
+ before do
269
+ # Foo v1 => Bar v2
270
+ td.create_pact_with_hierarchy("Foo", "1", "Bar")
271
+ .create_provider_version("2")
272
+ .create_provider_version_tag("prod")
273
+ .create_provider_version("3")
274
+ .create_verification(comment: "the verification is not from the required provider version")
275
+ end
276
+
277
+ let(:selectors) do
278
+ [ { pacticipant_name: "Foo", pacticipant_version_number: "1" } ]
279
+ end
280
+
281
+ # Deploy Foo v1 to prod
282
+ let(:options) do
283
+ { latest: true, tag: "prod", latestby: "cvp" }
284
+ end
285
+
286
+ # Currently returning PactNotEverVerifiedByProvider because the matrix response has changed from 'no row' to
287
+ # 'one row with no verification details' (left outer join stuff).
288
+ # Not sure if the 'no row' usecase can ever happen now.
289
+ # The messages shown to the user for 'not ever verified' and 'verified by the wrong provider version'
290
+ # are the same however, so the code does not need to be updated straight away.
291
+ it "returns a reason indicating that the pact has not been verified by the required provider version", pending: true do
292
+ expect(subject.deployment_status_summary.reasons.first).to be_a(PactBroker::Matrix::PactNotVerifiedByRequiredProviderVersion)
238
293
  end
239
294
  end
240
295
 
@@ -258,7 +313,7 @@ module PactBroker
258
313
  let(:options) { { latestby: "cvpv" } }
259
314
 
260
315
  it "does not allow the two apps to be deployed together" do
261
- expect(subject.deployment_status_summary.deployable?).to_not be true
316
+ expect(subject.deployment_status_summary).to_not be_deployable
262
317
  end
263
318
  end
264
319
 
@@ -272,11 +327,75 @@ module PactBroker
272
327
  let(:options) { { latestby: "cvp", latest: true } }
273
328
 
274
329
  it "does not allow the two apps to be deployed together" do
275
- expect(subject.deployment_status_summary.deployable?).to_not be true
330
+ expect(subject.deployment_status_summary).to_not be_deployable
331
+ end
332
+ end
333
+ end
334
+
335
+ describe "specifying a provider which has multiple prod versions of one consumer (explicit) and a single version of another (inferred)" do
336
+ before do
337
+ # Foo 1 (prod) -> Bar 2 [explicit]
338
+ # Foo 2 (prod) -> Bar 2 [explicit]
339
+ # Foo 3 -> Bar 2 failed [explicit]
340
+ # Cat 20 (prod) -> Bar ? [inferred, missing verification]
341
+ # Dog 40 -> Bar 2 failed [inferred, but not in prod]
342
+
343
+ td.create_pact_with_verification("Foo", "1", "Bar", "2")
344
+ .create_consumer_version_tag("prod")
345
+ .create_consumer_version("2")
346
+ .create_consumer_version_tag("prod")
347
+ .create_pact
348
+ .create_verification(provider_version: "2")
349
+ .create_consumer_version("3")
350
+ .create_pact
351
+ .create_verification(provider_version: "2", success: false, comment: "not prod, doesn't matter")
352
+ .create_consumer("Cat")
353
+ .create_consumer_version("20")
354
+ .create_consumer_version_tag("prod")
355
+ .create_pact
356
+ .comment("missing verification")
357
+ .create_consumer("Dog")
358
+ .create_consumer_version("40")
359
+ .create_pact
360
+ .create_verification(provider_version: "2")
361
+ end
362
+
363
+ let(:selector_1) { { pacticipant_name: "Bar", pacticipant_version_number: "2" } }
364
+ let(:selector_2) { { pacticipant_name: "Foo", tag: "prod" } }
365
+ let(:selectors) { [ selector_1, selector_2 ] }
366
+
367
+ subject { Service.find(selectors, options) }
368
+
369
+ context "with inferred selectors" do
370
+ let(:options) { { latest: true, tag: "prod"} }
371
+
372
+ it "determines the number of integrations" do
373
+ expect(subject.integrations.size).to eq 3
374
+ end
375
+
376
+ it "finds all prod versions of Foo" do
377
+ expect(subject.select { |row| row.consumer_name == "Foo"}.size).to eq 2
378
+ end
379
+
380
+ it "finds the single prod version of Cat" do
381
+ expect(subject.select { |row| row.consumer_name == "Cat"}.size).to eq 1
382
+ end
383
+
384
+ it "is not deployable because of the missing verification for Cat v20" do
385
+ expect(subject.deployment_status_summary.reasons.size).to eq 1
386
+ expect(subject.deployment_status_summary.reasons.first).to be_a_pact_never_verified_for_consumer "Cat"
387
+ end
388
+ end
389
+
390
+ context "without inferred selectors" do
391
+ let(:options) { {} }
392
+
393
+ it "is deployable" do
394
+ expect(subject.deployment_status_summary).to be_deployable
276
395
  end
277
396
  end
278
397
  end
279
398
  end
280
399
  end
281
400
  end
282
- end
401
+ end
@@ -48,9 +48,9 @@ module PactBroker
48
48
  subject { shorten_rows(rows) }
49
49
  let(:results) { Repository.new.find(selectors, options) }
50
50
 
51
- it "returns an empty array" do
52
- expect(results).to eq []
53
- expect(results.resolved_selectors.find{ |s | s[:pacticipant_name] == "Bar"}[:pacticipant_version_id]).to eq -1
51
+ it "returns an array with one row that does not have a verification" do
52
+ expect(results.first).to_not have_verification
53
+ expect(results.resolved_selectors.find{ |s | s[:pacticipant_name] == "Bar"}.pacticipant_version_id).to eq -1
54
54
  end
55
55
  end
56
56
  end
@@ -54,7 +54,7 @@ module PactBroker
54
54
 
55
55
  context "when a limit is specified" do
56
56
  let(:selectors) { build_selectors('A' => nil) }
57
- let(:options) { {limit: 1} }
57
+ let(:options) { { limit: 1 } }
58
58
 
59
59
  it "returns fewer rows than the limit (because some of the logic is done in the code, there may be fewer than the limit - need to fix this)" do
60
60
  expect(subject).to eq ["A2 B? n?"]
@@ -606,7 +606,7 @@ module PactBroker
606
606
  end
607
607
 
608
608
  it "returns the tag information" do
609
- expect(subject.first[:provider_version_tags]).to include_hash_matching name: 'prod', latest: 1
609
+ expect(subject.first.provider_version_tags).to include_hash_matching name: 'prod', latest: 1
610
610
  end
611
611
  end
612
612
 
@@ -647,8 +647,9 @@ module PactBroker
647
647
  ]
648
648
  end
649
649
 
650
- it "returns no data" do
651
- expect(subject.size).to eq 0
650
+ it "returns a row with no verification" do
651
+ expect(subject.size).to eq 1
652
+ expect(subject.first).to_not have_verification
652
653
  end
653
654
  end
654
655
  end
@@ -60,10 +60,10 @@ module PactBroker
60
60
  end
61
61
  describe "#find_by_name" do
62
62
  before do
63
- TestDataBuilder.new.create_pacticipant("Foo Bar")
63
+ td.create_pacticipant("Foo-Bar")
64
64
  end
65
65
 
66
- subject { Repository.new.find_by_name('foo bar') }
66
+ subject { Repository.new.find_by_name('foo-bar') }
67
67
 
68
68
  context "when the name is a different case" do
69
69
  context "with case sensitivity turned on" do
@@ -83,9 +83,43 @@ module PactBroker
83
83
 
84
84
  it "returns the pacticipant" do
85
85
  expect(subject).to_not be nil
86
- expect(subject.name).to eq "Foo Bar"
86
+ expect(subject.name).to eq "Foo-Bar"
87
87
  end
88
88
  end
89
+
90
+ context "with case sensitivity turned off and multiple records found", skip: DB.mysql? do
91
+ # Can't be created in MySQL - duplicate record
92
+ before do
93
+ td.create_pacticipant("Foo-bar")
94
+ allow(PactBroker.configuration).to receive(:use_case_sensitive_resource_names).and_return(false)
95
+ end
96
+
97
+ it "raises an error" do
98
+ expect { subject }.to raise_error PactBroker::Error, /Found multiple pacticipants.*foo-bar/
99
+ end
100
+ end
101
+
102
+ context "with case sensitivity turned off and searching for a name with an underscore" do
103
+ before do
104
+ allow(PactBroker.configuration).to receive(:use_case_sensitive_resource_names).and_return(false)
105
+ end
106
+
107
+ subject { Repository.new.find_by_name('foo_bar') }
108
+
109
+ it { is_expected.to be nil }
110
+ end
111
+
112
+ context "with case sensitivity turned on and searching for a name with an underscore" do
113
+ subject { Repository.new.find_by_name('foo_bar') }
114
+
115
+ it { is_expected.to be nil }
116
+ end
117
+
118
+ context "with case sensitivity turned off no record found" do
119
+ subject { Repository.new.find_by_name('blah') }
120
+
121
+ it { is_expected.to be nil }
122
+ end
89
123
  end
90
124
  end
91
125
 
@@ -143,4 +143,16 @@ Pact.provider_states_for "Pact Ruby" do
143
143
  .create_pact
144
144
  end
145
145
  end
146
+
147
+ provider_state "the relation for retrieving pacts for verifications exists in the index resource" do
148
+ no_op
149
+ end
150
+
151
+ provider_state "Foo has a pact tagged cdev with provider Bar" do
152
+ set_up do
153
+ TestDataBuilder.new
154
+ .create_pact_with_hierarchy("Foo", "1", "Bar")
155
+ .create_consumer_version_tag("cdev")
156
+ end
157
+ end
146
158
  end
@@ -76,3 +76,10 @@ RSpec::Matchers.define :include_hash_matching do |expected|
76
76
  end
77
77
  end
78
78
  end
79
+
80
+ RSpec::Matchers.define :be_a_pact_never_verified_for_consumer do | expected_consumer_name |
81
+ match do | actual_reason |
82
+ expect(actual_reason).to be_a(PactBroker::Matrix::PactNotEverVerifiedByProvider)
83
+ expect(actual_reason.consumer_selector.pacticipant_name).to eq expected_consumer_name
84
+ end
85
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact_broker
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.43.0
4
+ version: 2.44.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bethany Skurrie
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2020-01-05 00:00:00.000000000 Z
13
+ date: 2020-01-22 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: httparty
@@ -174,16 +174,22 @@ dependencies:
174
174
  name: pact-support
175
175
  requirement: !ruby/object:Gem::Requirement
176
176
  requirements:
177
+ - - "~>"
178
+ - !ruby/object:Gem::Version
179
+ version: '1.12'
177
180
  - - ">="
178
181
  - !ruby/object:Gem::Version
179
- version: '0'
182
+ version: 1.12.1
180
183
  type: :runtime
181
184
  prerelease: false
182
185
  version_requirements: !ruby/object:Gem::Requirement
183
186
  requirements:
187
+ - - "~>"
188
+ - !ruby/object:Gem::Version
189
+ version: '1.12'
184
190
  - - ">="
185
191
  - !ruby/object:Gem::Version
186
- version: '0'
192
+ version: 1.12.1
187
193
  - !ruby/object:Gem::Dependency
188
194
  name: padrino-core
189
195
  requirement: !ruby/object:Gem::Requirement
@@ -1006,6 +1012,7 @@ files:
1006
1012
  - lib/pact_broker/matrix/aggregated_row.rb
1007
1013
  - lib/pact_broker/matrix/can_i_deploy_query_schema.rb
1008
1014
  - lib/pact_broker/matrix/deployment_status_summary.rb
1015
+ - lib/pact_broker/matrix/every_row.rb
1009
1016
  - lib/pact_broker/matrix/head_row.rb
1010
1017
  - lib/pact_broker/matrix/integration.rb
1011
1018
  - lib/pact_broker/matrix/parse_can_i_deploy_query.rb
@@ -1032,7 +1039,7 @@ files:
1032
1039
  - lib/pact_broker/pacts/generate_interaction_sha.rb
1033
1040
  - lib/pact_broker/pacts/generate_sha.rb
1034
1041
  - lib/pact_broker/pacts/head_pact.rb
1035
- - lib/pact_broker/pacts/latest_pact_publication_id_by_consumer_version.rb
1042
+ - lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb
1036
1043
  - lib/pact_broker/pacts/latest_pact_publications.rb
1037
1044
  - lib/pact_broker/pacts/latest_pact_publications_by_consumer_version.rb
1038
1045
  - lib/pact_broker/pacts/latest_tagged_pact_publications.rb
@@ -1417,6 +1424,7 @@ files:
1417
1424
  - spec/lib/pact_broker/labels/service_spec.rb
1418
1425
  - spec/lib/pact_broker/matrix/aggregated_row_spec.rb
1419
1426
  - spec/lib/pact_broker/matrix/deployment_status_summary_spec.rb
1427
+ - spec/lib/pact_broker/matrix/every_row_spec.rb
1420
1428
  - spec/lib/pact_broker/matrix/head_row_spec.rb
1421
1429
  - spec/lib/pact_broker/matrix/integration_spec.rb
1422
1430
  - spec/lib/pact_broker/matrix/parse_query_spec.rb
@@ -1789,6 +1797,7 @@ test_files:
1789
1797
  - spec/lib/pact_broker/labels/service_spec.rb
1790
1798
  - spec/lib/pact_broker/matrix/aggregated_row_spec.rb
1791
1799
  - spec/lib/pact_broker/matrix/deployment_status_summary_spec.rb
1800
+ - spec/lib/pact_broker/matrix/every_row_spec.rb
1792
1801
  - spec/lib/pact_broker/matrix/head_row_spec.rb
1793
1802
  - spec/lib/pact_broker/matrix/integration_spec.rb
1794
1803
  - spec/lib/pact_broker/matrix/parse_query_spec.rb