pact_broker 2.75.0 → 2.78.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (193) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +12 -0
  3. data/.github/workflows/test-ruby-3.yml +19 -0
  4. data/.github/workflows/test.yml +19 -4
  5. data/.gitignore +3 -1
  6. data/CHANGELOG.md +48 -0
  7. data/DEVELOPER_SETUP.md +62 -3
  8. data/Dockerfile +1 -0
  9. data/ISSUES.md +13 -5
  10. data/README.md +1 -1
  11. data/config.ru +1 -0
  12. data/db/ddl_statements/head_pact_tags.rb +24 -1
  13. data/db/ddl_statements/latest_tagged_pact_consumer_version_orders.rb +11 -0
  14. data/db/ddl_statements/latest_tagged_pact_publications.rb +6 -0
  15. data/db/ddl_statements/latest_verification_ids_for_consumer_version_tags.rb +13 -0
  16. data/db/migrations/20210117_add_branch_to_version.rb +9 -0
  17. data/db/migrations/20210202_add_created_at_to_head_pact_tags.rb +14 -0
  18. data/db/migrations/20210205_add_pacticipant_id_to_tag.rb +17 -0
  19. data/db/migrations/20210206_add_index_to_tags_and_versions.rb +27 -0
  20. data/db/migrations/20210207_optimise_latest_verification_ids_for_consumer_version_tags.rb +13 -0
  21. data/db/migrations/20210208_optimise_latest_tagged_pact_cv_orders.rb +13 -0
  22. data/db/migrations/20210210_create_environments_table.rb +16 -0
  23. data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +44 -0
  24. data/lib/pact_broker/api.rb +7 -2
  25. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
  26. data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
  27. data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
  28. data/lib/pact_broker/api/decorators/dashboard_decorator.rb +5 -1
  29. data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
  30. data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
  31. data/lib/pact_broker/api/decorators/matrix_decorator.rb +8 -2
  32. data/lib/pact_broker/api/decorators/reason_decorator.rb +2 -2
  33. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +2 -0
  34. data/lib/pact_broker/api/decorators/version_decorator.rb +15 -2
  35. data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
  36. data/lib/pact_broker/api/paths.rb +5 -0
  37. data/lib/pact_broker/api/resources/default_base_resource.rb +15 -2
  38. data/lib/pact_broker/api/resources/environment.rb +76 -0
  39. data/lib/pact_broker/api/resources/environments.rb +75 -0
  40. data/lib/pact_broker/api/resources/index.rb +20 -0
  41. data/lib/pact_broker/api/resources/latest_version.rb +27 -0
  42. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +1 -0
  43. data/lib/pact_broker/api/resources/verifications.rb +5 -2
  44. data/lib/pact_broker/api/resources/version.rb +15 -9
  45. data/lib/pact_broker/api/resources/webhook_execution.rb +1 -1
  46. data/lib/pact_broker/app.rb +3 -0
  47. data/lib/pact_broker/certificates/certificate.rb +1 -1
  48. data/lib/pact_broker/config/setting.rb +1 -1
  49. data/lib/pact_broker/config/space_delimited_integer_list.rb +25 -0
  50. data/lib/pact_broker/configuration.rb +18 -1
  51. data/lib/pact_broker/db/data_migrations/helpers.rb +4 -0
  52. data/lib/pact_broker/db/data_migrations/set_extra_columns_for_tags.rb +29 -0
  53. data/lib/pact_broker/db/migrate_data.rb +1 -0
  54. data/lib/pact_broker/db/seed_example_data.rb +13 -13
  55. data/lib/pact_broker/deployments/environment.rb +15 -0
  56. data/lib/pact_broker/deployments/environment_service.rb +39 -0
  57. data/lib/pact_broker/doc/controllers/app.rb +1 -1
  58. data/lib/pact_broker/doc/views/index/environment.markdown +37 -0
  59. data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
  60. data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
  61. data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
  62. data/lib/pact_broker/doc/views/index/pacticipant-version.markdown +13 -0
  63. data/lib/pact_broker/domain/index_item.rb +18 -4
  64. data/lib/pact_broker/domain/pacticipant.rb +9 -5
  65. data/lib/pact_broker/domain/tag.rb +131 -71
  66. data/lib/pact_broker/domain/verification.rb +3 -2
  67. data/lib/pact_broker/domain/version.rb +58 -23
  68. data/lib/pact_broker/domain/webhook.rb +12 -9
  69. data/lib/pact_broker/hash_refinements.rb +4 -0
  70. data/lib/pact_broker/index/service.rb +55 -49
  71. data/lib/pact_broker/locale/en.yml +3 -1
  72. data/lib/pact_broker/matrix/quick_row.rb +8 -0
  73. data/lib/pact_broker/metrics/service.rb +1 -1
  74. data/lib/pact_broker/pacts/eager_loaders.rb +52 -0
  75. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +18 -13
  76. data/lib/pact_broker/pacts/lazy_loaders.rb +14 -0
  77. data/lib/pact_broker/pacts/pact_publication.rb +38 -84
  78. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +297 -0
  79. data/lib/pact_broker/pacts/pact_version.rb +1 -2
  80. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +286 -0
  81. data/lib/pact_broker/pacts/repository.rb +5 -231
  82. data/lib/pact_broker/pacts/selected_pact.rb +4 -0
  83. data/lib/pact_broker/pacts/selector.rb +56 -1
  84. data/lib/pact_broker/pacts/selectors.rb +16 -0
  85. data/lib/pact_broker/pacts/service.rb +6 -8
  86. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +1 -4
  87. data/lib/pact_broker/pacts/verifiable_pact.rb +45 -2
  88. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +56 -16
  89. data/lib/pact_broker/repositories/helpers.rb +4 -0
  90. data/lib/pact_broker/services.rb +9 -0
  91. data/lib/pact_broker/tags/eager_loaders.rb +47 -0
  92. data/lib/pact_broker/tags/repository.rb +3 -1
  93. data/lib/pact_broker/tags/service.rb +0 -3
  94. data/lib/pact_broker/tags/tag_with_latest_flag.rb +1 -0
  95. data/lib/pact_broker/test/http_test_data_builder.rb +101 -35
  96. data/lib/pact_broker/test/test_data_builder.rb +50 -3
  97. data/lib/pact_broker/ui/app.rb +6 -0
  98. data/lib/pact_broker/ui/controllers/base_controller.rb +5 -1
  99. data/lib/pact_broker/ui/controllers/pacts.rb +18 -0
  100. data/lib/pact_broker/ui/view_models/index_item.rb +9 -0
  101. data/lib/pact_broker/ui/view_models/matrix_line.rb +36 -0
  102. data/lib/pact_broker/ui/views/index/show-with-tags.haml +8 -0
  103. data/lib/pact_broker/ui/views/matrix/show.haml +10 -0
  104. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +7 -5
  105. data/lib/pact_broker/verifications/service.rb +2 -1
  106. data/lib/pact_broker/version.rb +1 -1
  107. data/lib/pact_broker/versions/eager_loaders.rb +71 -0
  108. data/lib/pact_broker/versions/lazy_loaders.rb +13 -0
  109. data/lib/pact_broker/versions/repository.rb +22 -2
  110. data/lib/pact_broker/versions/service.rb +5 -1
  111. data/lib/pact_broker/webhooks/execution.rb +3 -2
  112. data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +2 -0
  113. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +10 -3
  114. data/lib/pact_broker/webhooks/service.rb +8 -7
  115. data/lib/pact_broker/webhooks/trigger_service.rb +56 -23
  116. data/lib/pact_broker/webhooks/triggered_webhook.rb +14 -5
  117. data/lib/pact_broker/webhooks/webhook.rb +1 -1
  118. data/lib/pact_broker/webhooks/webhook_event.rb +1 -1
  119. data/lib/pact_broker/webhooks/webhook_execution_result.rb +4 -1
  120. data/lib/pact_broker/webhooks/webhook_request_logger.rb +5 -1
  121. data/lib/rack/pact_broker/set_base_url.rb +22 -0
  122. data/lib/sequel/plugins/upsert.rb +18 -4
  123. data/public/stylesheets/index.css +22 -1
  124. data/public/stylesheets/matrix.css +0 -21
  125. data/regression/can_i_deploy_spec.rb +5 -4
  126. data/regression/index_spec.rb +26 -0
  127. data/regression/regression_helper.rb +29 -3
  128. data/regression/script/clear.sh +3 -0
  129. data/regression/script/run.sh +3 -0
  130. data/script/demonstrate-version-branches.rb +33 -0
  131. data/script/pry.rb +2 -2
  132. data/script/reproduce-issue-starting-up.rb +13 -23
  133. data/script/reproduce-issue.rb +18 -14
  134. data/script/trigger-release.sh +1 -1
  135. data/script/webhook-server.ru +5 -5
  136. data/spec/features/create_environment_spec.rb +47 -0
  137. data/spec/features/create_tag_spec.rb +32 -0
  138. data/spec/features/create_version_spec.rb +70 -0
  139. data/spec/features/delete_environment_spec.rb +16 -0
  140. data/spec/features/end_deployment_spec.rb +29 -0
  141. data/spec/features/get_environment_spec.rb +19 -0
  142. data/spec/features/get_environments_spec.rb +20 -0
  143. data/spec/features/record_deployment_spec.rb +28 -0
  144. data/spec/features/update_environment_spec.rb +44 -0
  145. data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
  146. data/spec/fixtures/dashboard.json +4 -2
  147. data/spec/integration/ui/index_spec.rb +4 -4
  148. data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
  149. data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +4 -2
  150. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +11 -6
  151. data/spec/lib/pact_broker/api/decorators/reason_decorator_spec.rb +6 -6
  152. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +6 -0
  153. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
  154. data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
  155. data/spec/lib/pact_broker/api/resources/default_base_resource_spec.rb +1 -12
  156. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +4 -0
  157. data/spec/lib/pact_broker/api/resources/verifications_spec.rb +2 -5
  158. data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
  159. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -2
  160. data/spec/lib/pact_broker/config/space_delimited_integer_list_spec.rb +47 -0
  161. data/spec/lib/pact_broker/configuration_spec.rb +12 -0
  162. data/spec/lib/pact_broker/doc/controllers/app_spec.rb +3 -5
  163. data/spec/lib/pact_broker/domain/tag_spec.rb +101 -27
  164. data/spec/lib/pact_broker/domain/version_spec.rb +103 -15
  165. data/spec/lib/pact_broker/domain/webhook_spec.rb +7 -7
  166. data/spec/lib/pact_broker/index/service_spec.rb +89 -15
  167. data/spec/lib/pact_broker/pacts/pact_publication_dataset_module_spec.rb +400 -0
  168. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +434 -14
  169. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +1 -1
  170. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +1 -1
  171. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +224 -0
  172. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +46 -7
  173. data/spec/lib/pact_broker/pacts/selector_spec.rb +3 -2
  174. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +2 -3
  175. data/spec/lib/pact_broker/pacts/service_spec.rb +9 -7
  176. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +57 -10
  177. data/spec/lib/pact_broker/tags/repository_spec.rb +2 -0
  178. data/spec/lib/pact_broker/verifications/service_spec.rb +4 -1
  179. data/spec/lib/pact_broker/versions/repository_spec.rb +54 -0
  180. data/spec/lib/pact_broker/webhooks/render_spec.rb +6 -5
  181. data/spec/lib/pact_broker/webhooks/service_spec.rb +13 -9
  182. data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +60 -18
  183. data/spec/lib/pact_broker/webhooks/webhook_request_logger_spec.rb +8 -0
  184. data/spec/lib/sequel/plugins/upsert_spec.rb +31 -3
  185. data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
  186. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
  187. data/spec/spec_helper.rb +17 -5
  188. data/spec/support/approvals.rb +24 -0
  189. data/spec/support/shared_examples_for_responses.rb +11 -0
  190. data/tasks/db.rake +1 -0
  191. data/tasks/rspec.rake +1 -1
  192. metadata +69 -4
  193. data/docker-compose-issue-repro.yml +0 -22
@@ -11,10 +11,10 @@ module PactBroker
11
11
  let(:webhook_template_parameters) { instance_double(PactBroker::Webhooks::PactAndVerificationParameters, to_hash: webhook_template_parameters_hash) }
12
12
  let(:webhook_template_parameters_hash) { { 'foo' => 'bar' } }
13
13
  let(:http_request) { double('http request') }
14
- let(:http_response) { double('http response') }
15
- let(:webhook_context) { { some: 'things' } }
14
+ let(:http_response) { double('http response', code: "200") }
15
+ let(:event_context) { { some: 'things' } }
16
16
  let(:logging_options) { { other: 'options' } }
17
- let(:options) { { webhook_context: webhook_context, logging_options: logging_options } }
17
+ let(:options) { { logging_options: logging_options } }
18
18
  let(:pact) { double('pact') }
19
19
  let(:verification) { double('verification') }
20
20
  let(:logger) { double('logger').as_null_object }
@@ -61,11 +61,11 @@ module PactBroker
61
61
 
62
62
  let(:webhook_request_logger) { instance_double(PactBroker::Webhooks::WebhookRequestLogger, log: "logs") }
63
63
 
64
- let(:execute) { subject.execute pact, verification, options }
64
+ let(:execute) { subject.execute(pact, verification, event_context, options) }
65
65
 
66
66
  it "creates the template parameters" do
67
67
  expect(PactBroker::Webhooks::PactAndVerificationParameters).to receive(:new).with(
68
- pact, verification, webhook_context
68
+ pact, verification, event_context
69
69
  )
70
70
  execute
71
71
  end
@@ -81,7 +81,7 @@ module PactBroker
81
81
  end
82
82
 
83
83
  it "generates the execution logs" do
84
- expect(webhook_request_logger).to receive(:log).with(uuid, webhook_request, http_response, nil, webhook_context)
84
+ expect(webhook_request_logger).to receive(:log).with(uuid, webhook_request, http_response, nil, event_context)
85
85
  execute
86
86
  end
87
87
 
@@ -106,7 +106,7 @@ module PactBroker
106
106
  end
107
107
 
108
108
  it "generates the execution logs" do
109
- expect(webhook_request_logger).to receive(:log).with(uuid, webhook_request, nil, instance_of(error_class), webhook_context)
109
+ expect(webhook_request_logger).to receive(:log).with(uuid, webhook_request, nil, instance_of(error_class), event_context)
110
110
  execute
111
111
  end
112
112
 
@@ -192,6 +192,43 @@ module PactBroker
192
192
  expect(rows[1].provider_name).to eq "Wiffle"
193
193
  end
194
194
  end
195
+
196
+ context "with tags[]=" do
197
+ before do
198
+ td.create_pact_with_hierarchy("Foo", "1.0.0", "Bar")
199
+ .create_verification(provider_version: "4.5.6")
200
+ .create_consumer_version("2.0.0")
201
+ .create_consumer_version_tag("dev")
202
+ .create_pact
203
+ .revise_pact
204
+ .create_consumer_version("2.1.0")
205
+ .create_consumer_version_tag("prod")
206
+ .create_consumer_version_tag("not-prod")
207
+ .create_pact
208
+ .revise_pact
209
+ .create_verification(provider_version: "4.5.6", number: 1)
210
+ .create_verification(provider_version: "4.5.7", number: 2)
211
+ .create_verification(provider_version: "4.5.8", number: 3)
212
+ .create_verification(provider_version: "4.5.9", number: 4)
213
+ .create_provider("Wiffle")
214
+ .create_pact
215
+ end
216
+
217
+ let(:options) { {tags: ["prod"]} }
218
+
219
+ it "returns a row for for the latest pact and a row for the prod pact (maybe it shouldn't return the latest as well)" do
220
+ expect(rows.size).to eq 2
221
+
222
+ expect(rows[0].latest?).to be true
223
+ expect(rows[0].provider_name).to eq "Bar"
224
+ expect(rows[0].tag_names).to eq ["prod"]
225
+ expect(rows[0].provider_version_number).to eq "4.5.9"
226
+
227
+ expect(rows[1].latest?).to be true
228
+ expect(rows[1].provider_name).to eq "Wiffle"
229
+ expect(rows[1].tag_names).to eq ["prod"]
230
+ end
231
+ end
195
232
  end
196
233
 
197
234
  context "when a pact with a tag has been verified, and then a new changed version has been published with the same tag" do
@@ -263,29 +300,66 @@ module PactBroker
263
300
  let(:page_size) { 2 }
264
301
  let(:tags) { nil }
265
302
 
266
- before do
267
- td.create_pact_with_hierarchy("Foo1", "1", "Bar1")
268
- .create_pact_with_hierarchy("Foo2", "1", "Bar2")
269
- .create_pact_with_hierarchy("Foo3", "1", "Bar3")
270
- end
303
+ context "with no tags" do
304
+ before do
305
+ td.create_pact_with_hierarchy("Foo1", "1", "Bar1")
306
+ .create_pact_with_hierarchy("Foo2", "1", "Bar2")
307
+ .create_pact_with_hierarchy("Foo3", "1", "Bar3")
308
+ end
271
309
 
272
- it "it returns the total number of records" do
273
- expect(rows.pagination_record_count).to eq 3
274
- end
310
+ it "it returns the total number of records" do
311
+ expect(rows.pagination_record_count).to eq 3
312
+ end
275
313
 
276
- describe "the first page" do
277
- it "contains 2 rows" do
278
- expect(rows.count).to eq 2
314
+ describe "the first page" do
315
+ it "contains 2 rows" do
316
+ expect(rows.count).to eq 2
317
+ end
318
+ end
319
+
320
+ describe "the second page" do
321
+ let(:page_number) { 2 }
322
+
323
+ it "contains 1 row" do
324
+ expect(rows.count).to eq 1
325
+ end
279
326
  end
280
327
  end
281
328
 
282
- describe "the second page" do
283
- let(:page_number) { 2 }
329
+ context "with tags" do
330
+ before do
331
+ td.create_pact_with_hierarchy("Foo1", "1", "Bar1")
332
+ .create_consumer_version_tag("prod")
333
+ .create_consumer_version_tag("dev")
334
+ .create_pact_with_hierarchy("Foo2", "1", "Bar2")
335
+ .create_consumer_version_tag("prod")
336
+ .create_consumer_version_tag("dev")
337
+ .create_pact_with_hierarchy("Foo3", "1", "Bar3")
338
+ .create_consumer_version_tag("prod")
339
+ .create_consumer_version_tag("dev")
340
+ end
341
+
342
+ let(:tags) { true }
284
343
 
285
- it "contains 1 row" do
286
- expect(rows.count).to eq 1
344
+ it "it returns the total number of records" do
345
+ expect(rows.pagination_record_count).to eq 3
346
+ end
347
+
348
+ describe "the first page" do
349
+ it "contains 2 rows" do
350
+ expect(rows.count).to eq 2
351
+ end
352
+ end
353
+
354
+ describe "the second page" do
355
+ let(:page_number) { 2 }
356
+
357
+ it "contains 1 row" do
358
+ expect(rows.count).to eq 1
359
+ end
287
360
  end
288
361
  end
362
+
289
363
  end
290
364
  end
291
365
 
@@ -0,0 +1,400 @@
1
+ require 'pact_broker/pacts/pact_publication'
2
+
3
+ module PactBroker
4
+ module Pacts
5
+ describe PactPublication do
6
+ describe "latest_by_consumer_branch" do
7
+ before do
8
+ td.set_now(Date.new(2020, 1, 1))
9
+ .create_consumer("Foo")
10
+ .create_provider("Bar")
11
+ .create_consumer_version("1", branch: "main")
12
+ .create_pact
13
+ .set_now(Date.new(2020, 1, 2))
14
+ .create_consumer_version("2", branch: "feat/x")
15
+ .create_pact
16
+ .set_now(Date.new(2020, 1, 3))
17
+ .create_consumer_version("3", branch: "main", comment: "latest")
18
+ .create_pact
19
+ .set_now(Date.new(2020, 1, 4))
20
+ .create_consumer_version("4", branch: "feat/x", comment: "latest")
21
+ .create_pact
22
+ .set_now(Date.new(2020, 1, 5))
23
+ .create_consumer("FooZ")
24
+ .create_consumer_version("6", branch: "main", comment: "latest, different consumer")
25
+ .create_pact
26
+ .set_now(Date.new(2020, 1, 6))
27
+ .create_consumer_version("7", comment: "No branch")
28
+ .create_pact
29
+ .set_now(Date.new(2020, 1, 7))
30
+ .create_consumer_version("8", branch: "main", comment: "No pact")
31
+ end
32
+
33
+ subject { PactPublication.latest_by_consumer_branch.all }
34
+
35
+ let(:foo) { PactBroker::Domain::Pacticipant.where(name: "Foo").single_record }
36
+ let(:bar) { PactBroker::Domain::Pacticipant.where(name: "Bar").single_record }
37
+ let(:foo_z) { PactBroker::Domain::Pacticipant.where(name: "FooZ").single_record }
38
+
39
+ it "returns the latest pact publications for each consumer/branch" do
40
+ expect(subject.size).to eq 3
41
+
42
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:branch] == "main" }.consumer_version.number).to eq "3"
43
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:branch] == "feat/x" }.consumer_version.number).to eq "4"
44
+ expect(subject.find { |pp| pp.consumer_id == foo_z.id && pp[:branch] == "main" }.consumer_version.number).to eq "6"
45
+ end
46
+
47
+ it "does not return extra columns" do
48
+ expect(subject.first.values.keys.sort).to eq (PactPublication.columns + [:branch]).sort
49
+ end
50
+
51
+ context "chained with created after" do
52
+ subject { PactPublication.created_after(DateTime.new(2020, 1, 3)).latest_by_consumer_branch.all }
53
+
54
+ its(:size) { is_expected.to eq 2 }
55
+
56
+ it "returns the right versions" do
57
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:branch] == "feat/x" }.consumer_version.number).to eq "4"
58
+ expect(subject.find { |pp| pp.consumer_id == foo_z.id && pp[:branch] == "main" }.consumer_version.number).to eq "6"
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "latest_for_consumer_branch" do
64
+ before do
65
+ td.create_consumer("Foo")
66
+ .create_provider("Bar")
67
+ .create_consumer_version("1", branch: "main")
68
+ .create_pact
69
+ .create_consumer_version("2", branch: "main")
70
+ .create_pact
71
+ .create_consumer_version("3", branch: "feat-x")
72
+ .create_pact
73
+ .create_consumer("Foo2")
74
+ .create_provider("Bar2")
75
+ .create_consumer_version("10", branch: "main")
76
+ .create_pact
77
+ .create_consumer_version("11", branch: "main")
78
+ .create_pact
79
+ end
80
+
81
+ subject { PactPublication.latest_for_consumer_branch("main") }
82
+
83
+ it "returns the latest pacts for the branches with the specified name (for any consumer/provider)" do
84
+ all = subject.all.sort_by{ |pact_publication| pact_publication.consumer_version.order }
85
+ expect(all.size).to eq 2
86
+ expect(all.first.consumer.name).to eq "Foo"
87
+ expect(all.first.provider.name).to eq "Bar"
88
+ expect(all.first.consumer_version.number).to eq "2"
89
+
90
+ expect(all.last.consumer.name).to eq "Foo2"
91
+ expect(all.last.provider.name).to eq "Bar2"
92
+ expect(all.last.consumer_version.number).to eq "11"
93
+ end
94
+
95
+ it "does not return extra columns" do
96
+ expect(subject.first.values.keys.sort).to eq (PactPublication.columns + [:branch]).sort
97
+ end
98
+
99
+ context "when columns are already selected" do
100
+ subject { PactPublication.select(Sequel[:pact_publications][:id]).latest_for_consumer_branch("main") }
101
+
102
+ it "does not override them" do
103
+ expect(subject.all.first.values.keys).to eq [:id]
104
+ end
105
+ end
106
+
107
+ context "when chained" do
108
+ it "works" do
109
+ all = PactPublication.for_provider(td.find_pacticipant("Bar")).latest_for_consumer_branch("main").all
110
+ expect(all.first.provider.name).to eq "Bar"
111
+ end
112
+ end
113
+ end
114
+
115
+ describe "latest_by_consumer_tag" do
116
+ before do
117
+ td.create_consumer("Foo")
118
+ .create_provider("Bar")
119
+ .create_consumer_version("1", tag_names: ["main"])
120
+ .create_pact
121
+ .create_consumer_version("2", tag_names: ["feat/x"])
122
+ .create_pact
123
+ .create_consumer_version("3", tag_names: ["main"], comment: "latest")
124
+ .create_pact
125
+ .create_consumer_version("4", tag_names: ["feat/x"], comment: "latest")
126
+ .create_pact
127
+ .create_consumer("FooZ")
128
+ .create_consumer_version("6", tag_names: ["main"], comment: "Different consumer")
129
+ .create_pact
130
+ .create_consumer_version("7", comment: "No branch")
131
+ .create_pact
132
+ .create_consumer_version("8", tag_names: ["main"], comment: "No pact")
133
+ end
134
+
135
+ subject { PactPublication.latest_by_consumer_tag.all }
136
+
137
+ let(:foo) { PactBroker::Domain::Pacticipant.where(name: "Foo").single_record }
138
+ let(:bar) { PactBroker::Domain::Pacticipant.where(name: "Bar").single_record }
139
+ let(:foo_z) { PactBroker::Domain::Pacticipant.where(name: "FooZ").single_record }
140
+
141
+ it "returns the latest pact publications for each consumer/branch" do
142
+ expect(subject.size).to eq 3
143
+ hashes = subject.collect(&:values)
144
+
145
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:tag_name] == "main" }.consumer_version.number).to eq "3"
146
+ expect(subject.find { |pp| pp.consumer_id == foo.id && pp[:tag_name] == "feat/x" }.consumer_version.number).to eq "4"
147
+ expect(subject.find { |pp| pp.consumer_id == foo_z.id && pp[:tag_name] == "main" }.consumer_version.number).to eq "6"
148
+ end
149
+
150
+ it "does not return extra columns" do
151
+ expect(subject.first.values.keys.sort).to eq (PactPublication.columns + [:tag_name]).sort
152
+ end
153
+
154
+ context "when columns are already selected" do
155
+ subject { PactPublication.select(Sequel[:pact_publications][:id]).latest_by_consumer_tag }
156
+
157
+ it "does not override them" do
158
+ expect(subject.all.first.values.keys).to eq [:id]
159
+ end
160
+ end
161
+ end
162
+
163
+ describe "overall_latest" do
164
+ before do
165
+ td.create_consumer("Foo")
166
+ .create_provider("Bar")
167
+ .create_consumer_version("1", tag_names: ["main"])
168
+ .create_pact
169
+ .create_consumer_version("2", tag_names: ["main"])
170
+ .create_pact
171
+ .create_consumer_version("3", tag_names: ["feat/x"])
172
+ .create_pact
173
+ .create_consumer("Foo2")
174
+ .create_provider("Bar2")
175
+ .create_consumer_version("10", tag_names: ["main"])
176
+ .create_pact
177
+ .create_consumer_version("11", tag_names: ["main"])
178
+ .create_pact
179
+ end
180
+
181
+ subject { PactPublication.overall_latest }
182
+
183
+ it "returns the latest by consumer/provider" do
184
+ all = subject.all.sort_by{ | pact_publication | pact_publication.consumer_version.order }
185
+ expect(all.size).to eq 2
186
+ end
187
+
188
+ it "does not return extra columns" do
189
+ expect(subject.all.first.values.keys.sort).to eq PactPublication.columns.sort
190
+ end
191
+
192
+ context "when columns are already selected" do
193
+ subject { PactPublication.select(Sequel[:pact_publications][:id]).overall_latest }
194
+
195
+ it "does not override them" do
196
+ expect(subject.all.first.values.keys).to eq [:id]
197
+ end
198
+ end
199
+
200
+ context "when chained" do
201
+ it "works with a consumer" do
202
+ expect(PactPublication.for_consumer(td.find_pacticipant("Foo")).overall_latest.all.first.consumer.name).to eq "Foo"
203
+ end
204
+
205
+ it "works with a consumer and provider" do
206
+ td.create_pact_with_hierarchy("Foo", "666", "Nope")
207
+ all = PactPublication
208
+ .for_consumer(td.find_pacticipant("Foo"))
209
+ .for_provider(td.find_pacticipant("Bar"))
210
+ .overall_latest.all
211
+ expect(all.size).to eq 1
212
+ expect(all.first.consumer.name).to eq "Foo"
213
+ expect(all.first.provider.name).to eq "Bar"
214
+ end
215
+ end
216
+ end
217
+
218
+ describe "latest_for_consumer_tag" do
219
+ before do
220
+ td.create_consumer("Foo")
221
+ .create_provider("Bar")
222
+ .create_consumer_version("1", tag_names: ["main"])
223
+ .create_pact
224
+ .create_consumer_version("2", tag_names: ["main"])
225
+ .create_pact
226
+ .revise_pact
227
+ .create_consumer_version("3", tag_names: ["feat/x"])
228
+ .create_pact
229
+ .create_consumer("Foo2")
230
+ .create_provider("Bar2")
231
+ .create_consumer_version("10", tag_names: ["main"])
232
+ .create_pact
233
+ .create_consumer_version("11", tag_names: ["main"])
234
+ .create_pact
235
+ end
236
+
237
+ subject { PactPublication.latest_for_consumer_tag("main") }
238
+
239
+ it "returns the latest pacts for the tags with the specified name (for any consumer/provider)" do
240
+ all = subject.all.sort_by{ |pact_publication| pact_publication.consumer_version.order }
241
+ expect(all.size).to eq 2
242
+ expect(all.first.consumer.name).to eq "Foo"
243
+ expect(all.first.provider.name).to eq "Bar"
244
+ expect(all.first.consumer_version.number).to eq "2"
245
+
246
+ expect(all.last.consumer.name).to eq "Foo2"
247
+ expect(all.last.provider.name).to eq "Bar2"
248
+ expect(all.last.consumer_version.number).to eq "11"
249
+ end
250
+
251
+ it "does not return extra columns" do
252
+ expect(subject.all.first.values.keys.sort).to eq (PactPublication.columns + [:tag_name]).sort
253
+ end
254
+
255
+ context "when columns are already selected" do
256
+ subject { PactPublication.select(Sequel[:pact_publications][:id]).latest_for_consumer_tag("main") }
257
+
258
+ it "does not override them" do
259
+ expect(subject.all.first.values.keys).to eq [:id]
260
+ end
261
+ end
262
+
263
+ context "when chained" do
264
+ it "works" do
265
+ all = PactPublication.for_provider(td.find_pacticipant("Bar")).latest_for_consumer_tag("main").all
266
+ expect(all.first.provider.name).to eq "Bar"
267
+ end
268
+ end
269
+ end
270
+
271
+ describe "#successfully_verified_by_provider_branch" do
272
+ let(:bar) { td.find_pacticipant("Bar") }
273
+
274
+ subject { PactPublication.successfully_verified_by_provider_branch(bar.id, "main").all }
275
+
276
+ context "PactPublication" do
277
+ before do
278
+ td.create_pact_with_hierarchy("Foo", "1", "Bar")
279
+ .create_verification(provider_version: "2", branch: "main", success: false)
280
+ .create_pact_with_hierarchy("Foo", "2", "Bar")
281
+ .create_verification(provider_version: "2", branch: "main", success: true)
282
+ .create_pact_with_hierarchy("Foo", "3", "Bar")
283
+ .create_verification(provider_version: "3", branch: "not-main", success: true)
284
+ end
285
+
286
+ it "returns the pact publications that have been succesfully verified by the given provider id and branch" do
287
+ expect(subject.size).to eq 1
288
+ expect(subject.first.consumer_version.number).to eq "2"
289
+ end
290
+
291
+ it "does not return extra columns" do
292
+ expect(subject.first.values.keys.sort).to eq PactPublication.columns.sort
293
+ end
294
+ end
295
+
296
+
297
+ context "with chained scopes" do
298
+ subject { PactPublication.latest_by_consumer_branch.successfully_verified_by_provider_branch(bar.id, "provider-main").all }
299
+
300
+ context "when there are no latest branch pacts that have been successfully verified by the specified provider branch" do
301
+ before do
302
+ td.create_consumer("Foo")
303
+ .create_provider("Bar")
304
+ .create_consumer_version("1", branch: "main", comment: "not latest")
305
+ .create_pact
306
+ .create_verification(provider_version: "1", success: true, branch: "provider-main", comment: "successful but not latest")
307
+ .create_consumer_version("2", branch: "main", comment: "latest")
308
+ .create_pact
309
+ .create_verification(provider_version: "2", success: false, branch: "provider-main", comment: "latest but not successful")
310
+ .create_consumer_version("3", branch: "feat/x", comment: "latest")
311
+ .create_pact
312
+ .create_verification(provider_version: "3", success: true, branch: "not-provider-main", comment: "latest, successful, but wrong branch")
313
+ end
314
+
315
+ it { is_expected.to eq [] }
316
+ end
317
+
318
+ context "when there are latest branch pacts that have been successfully verified by the specified provider branch" do
319
+ before do
320
+ td.create_consumer("Foo")
321
+ .create_provider("Bar")
322
+ .create_consumer_version("1", branch: "main", comment: "not latest")
323
+ .create_pact
324
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
325
+ .create_consumer_version("2", branch: "main", comment: "latest")
326
+ .create_pact
327
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
328
+ .create_verification(provider_version: "2", success: true, branch: "provider-main", number: "2")
329
+ end
330
+
331
+ its(:size) { is_expected.to eq 1 }
332
+
333
+ it "returns them" do
334
+ expect(subject.first.consumer_version.number).to eq "2"
335
+ end
336
+ end
337
+
338
+ context "when there are latest tagged pacts that have been successfully verified by the specified provider branch" do
339
+ before do
340
+ td.create_consumer("Foo")
341
+ .create_provider("Bar")
342
+ .create_consumer_version("1", tag_names: ["main"], comment: "not latest")
343
+ .create_pact
344
+ .create_verification(provider_version: "1", success: true, tag_names: ["provider-main"])
345
+ .create_consumer_version("2", tag_names: ["main"], comment: "latest")
346
+ .create_pact
347
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
348
+ .create_verification(provider_version: "2", success: true, branch: "provider-main", number: "2")
349
+ end
350
+
351
+ subject { PactPublication.latest_by_consumer_tag.successfully_verified_by_provider_branch(bar.id, "provider-main").all }
352
+
353
+ its(:size) { is_expected.to eq 1 }
354
+
355
+ it "returns them" do
356
+ expect(subject.first.consumer_version.number).to eq "2"
357
+ end
358
+ end
359
+
360
+ context "subtracting Pact Publications" do
361
+ before do
362
+ td.create_consumer("Foo")
363
+ .create_provider("Bar")
364
+ .create_consumer_version("1", branch: "main", tag_names: ["main"], comment: "not latest")
365
+ .create_pact
366
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
367
+ .create_consumer_version("2", branch: "main", tag_names: ["main"], comment: "latest")
368
+ .create_pact
369
+ .create_verification(provider_version: "1", success: true, branch: "provider-main")
370
+ .create_verification(provider_version: "2", success: true, branch: "provider-main", number: "2")
371
+ .create_consumer_version("3", branch: "feat/x", tag_names: ["feat/x"], )
372
+ .create_pact
373
+ end
374
+
375
+ let(:bar) { td.find_pacticipant("Bar") }
376
+
377
+ it "with branches" do
378
+ potential = PactPublication.for_provider(bar).latest_by_consumer_branch
379
+ already_verified = potential.successfully_verified_by_provider_branch(bar.id, "provider-main")
380
+ not_verified = PactPublication.subtract(potential.all, already_verified.all)
381
+
382
+ expect(not_verified.size).to eq 1
383
+ expect(not_verified.first.consumer_version_number).to eq "3"
384
+ end
385
+
386
+ it "with tags" do
387
+ potential = PactPublication.for_provider(bar).latest_by_consumer_tag
388
+ already_verified = potential.successfully_verified_by_provider_branch(bar.id, "provider-main")
389
+ not_verified = PactPublication.subtract(potential.all, already_verified.all)
390
+
391
+ expect(not_verified.size).to eq 1
392
+ expect(not_verified.first.consumer_version_number).to eq "3"
393
+ end
394
+ end
395
+ end
396
+ end
397
+ end
398
+ end
399
+ end
400
+