pact_broker 2.76.1 → 2.79.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +12 -0
  3. data/.github/workflows/release_gem.yml +1 -0
  4. data/.github/workflows/test-ruby-3.yml +19 -0
  5. data/.github/workflows/test.yml +16 -7
  6. data/.gitignore +3 -1
  7. data/CHANGELOG.md +50 -0
  8. data/DEVELOPER_DOCUMENTATION.md +13 -0
  9. data/DEVELOPER_SETUP.md +62 -3
  10. data/Dockerfile +1 -0
  11. data/ISSUES.md +12 -4
  12. data/config.ru +2 -1
  13. data/db/ddl_statements/head_pact_tags.rb +24 -1
  14. data/db/ddl_statements/latest_tagged_pact_consumer_version_orders.rb +11 -0
  15. data/db/ddl_statements/latest_tagged_pact_publications.rb +6 -0
  16. data/db/ddl_statements/latest_verification_ids_for_consumer_version_tags.rb +13 -0
  17. data/db/migrations/20210117_add_branch_to_version.rb +9 -0
  18. data/db/migrations/20210202_add_created_at_to_head_pact_tags.rb +14 -0
  19. data/db/migrations/20210205_add_pacticipant_id_to_tag.rb +17 -0
  20. data/db/migrations/20210206_add_index_to_tags_and_versions.rb +27 -0
  21. data/db/migrations/20210207_optimise_latest_verification_ids_for_consumer_version_tags.rb +13 -0
  22. data/db/migrations/20210208_optimise_latest_tagged_pact_cv_orders.rb +13 -0
  23. data/db/migrations/20210210_create_environments_table.rb +16 -0
  24. data/docker-compose-dev-postgres.yml +9 -1
  25. data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +16 -5
  26. data/lib/pact_broker/api.rb +7 -2
  27. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
  28. data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
  29. data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
  30. data/lib/pact_broker/api/decorators/dashboard_decorator.rb +5 -1
  31. data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
  32. data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
  33. data/lib/pact_broker/api/decorators/matrix_decorator.rb +3 -1
  34. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +2 -0
  35. data/lib/pact_broker/api/decorators/version_decorator.rb +15 -2
  36. data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
  37. data/lib/pact_broker/api/resources/default_base_resource.rb +18 -0
  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 +1 -1
  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 +22 -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/views/index/environment.markdown +37 -0
  58. data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
  59. data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
  60. data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
  61. data/lib/pact_broker/doc/views/index/pacticipant-version.markdown +13 -0
  62. data/lib/pact_broker/domain/index_item.rb +18 -4
  63. data/lib/pact_broker/domain/pacticipant.rb +9 -5
  64. data/lib/pact_broker/domain/tag.rb +131 -71
  65. data/lib/pact_broker/domain/verification.rb +3 -2
  66. data/lib/pact_broker/domain/version.rb +58 -23
  67. data/lib/pact_broker/domain/webhook.rb +12 -9
  68. data/lib/pact_broker/hash_refinements.rb +4 -0
  69. data/lib/pact_broker/index/service.rb +55 -49
  70. data/lib/pact_broker/locale/en.yml +3 -1
  71. data/lib/pact_broker/matrix/quick_row.rb +8 -0
  72. data/lib/pact_broker/metrics/service.rb +1 -1
  73. data/lib/pact_broker/pacts/eager_loaders.rb +52 -0
  74. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +18 -13
  75. data/lib/pact_broker/pacts/lazy_loaders.rb +14 -0
  76. data/lib/pact_broker/pacts/pact_publication.rb +38 -84
  77. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +297 -0
  78. data/lib/pact_broker/pacts/pact_version.rb +1 -2
  79. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +286 -0
  80. data/lib/pact_broker/pacts/repository.rb +5 -240
  81. data/lib/pact_broker/pacts/selected_pact.rb +4 -0
  82. data/lib/pact_broker/pacts/selector.rb +56 -1
  83. data/lib/pact_broker/pacts/selectors.rb +16 -0
  84. data/lib/pact_broker/pacts/service.rb +6 -8
  85. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +1 -4
  86. data/lib/pact_broker/pacts/verifiable_pact.rb +23 -2
  87. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +56 -16
  88. data/lib/pact_broker/repositories/helpers.rb +4 -0
  89. data/lib/pact_broker/services.rb +9 -0
  90. data/lib/pact_broker/tags/eager_loaders.rb +47 -0
  91. data/lib/pact_broker/tags/repository.rb +3 -1
  92. data/lib/pact_broker/tags/service.rb +0 -3
  93. data/lib/pact_broker/tags/tag_with_latest_flag.rb +1 -0
  94. data/lib/pact_broker/test/http_test_data_builder.rb +86 -25
  95. data/lib/pact_broker/test/test_data_builder.rb +50 -3
  96. data/lib/pact_broker/ui/view_models/index_item.rb +19 -2
  97. data/lib/pact_broker/ui/view_models/matrix_line.rb +38 -2
  98. data/lib/pact_broker/ui/views/index/show-with-tags.haml +14 -6
  99. data/lib/pact_broker/ui/views/matrix/show.haml +12 -2
  100. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +7 -5
  101. data/lib/pact_broker/verifications/service.rb +2 -1
  102. data/lib/pact_broker/version.rb +1 -1
  103. data/lib/pact_broker/versions/eager_loaders.rb +71 -0
  104. data/lib/pact_broker/versions/lazy_loaders.rb +13 -0
  105. data/lib/pact_broker/versions/repository.rb +22 -2
  106. data/lib/pact_broker/versions/service.rb +5 -1
  107. data/lib/pact_broker/webhooks/execution.rb +3 -2
  108. data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +2 -0
  109. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +10 -3
  110. data/lib/pact_broker/webhooks/service.rb +8 -7
  111. data/lib/pact_broker/webhooks/trigger_service.rb +56 -23
  112. data/lib/pact_broker/webhooks/triggered_webhook.rb +14 -5
  113. data/lib/pact_broker/webhooks/webhook.rb +1 -1
  114. data/lib/pact_broker/webhooks/webhook_event.rb +1 -1
  115. data/lib/pact_broker/webhooks/webhook_execution_result.rb +6 -1
  116. data/lib/pact_broker/webhooks/webhook_request_logger.rb +7 -1
  117. data/lib/rack/pact_broker/set_base_url.rb +35 -5
  118. data/lib/sequel/plugins/upsert.rb +18 -4
  119. data/public/javascripts/clipboard.js +8 -2
  120. data/public/stylesheets/index.css +22 -1
  121. data/public/stylesheets/matrix.css +0 -21
  122. data/regression/can_i_deploy_spec.rb +5 -4
  123. data/regression/index_spec.rb +26 -0
  124. data/regression/regression_helper.rb +29 -3
  125. data/regression/script/clear.sh +3 -0
  126. data/regression/script/run.sh +3 -0
  127. data/script/demonstrate-version-branches.rb +33 -0
  128. data/script/pry.rb +2 -2
  129. data/script/reproduce-issue-starting-up.rb +13 -23
  130. data/script/reproduce-issue.rb +2 -1
  131. data/script/trigger-release.sh +1 -1
  132. data/script/webhook-server.ru +5 -5
  133. data/spec/features/create_environment_spec.rb +47 -0
  134. data/spec/features/create_tag_spec.rb +32 -0
  135. data/spec/features/create_version_spec.rb +70 -0
  136. data/spec/features/delete_environment_spec.rb +16 -0
  137. data/spec/features/end_deployment_spec.rb +29 -0
  138. data/spec/features/get_environment_spec.rb +19 -0
  139. data/spec/features/get_environments_spec.rb +20 -0
  140. data/spec/features/record_deployment_spec.rb +28 -0
  141. data/spec/features/update_environment_spec.rb +44 -0
  142. data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
  143. data/spec/fixtures/dashboard.json +4 -2
  144. data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
  145. data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +4 -2
  146. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +11 -6
  147. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +6 -0
  148. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
  149. data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
  150. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +4 -0
  151. data/spec/lib/pact_broker/api/resources/verifications_spec.rb +2 -5
  152. data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
  153. data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -2
  154. data/spec/lib/pact_broker/config/space_delimited_integer_list_spec.rb +47 -0
  155. data/spec/lib/pact_broker/configuration_spec.rb +12 -0
  156. data/spec/lib/pact_broker/domain/tag_spec.rb +101 -27
  157. data/spec/lib/pact_broker/domain/version_spec.rb +103 -15
  158. data/spec/lib/pact_broker/domain/webhook_spec.rb +7 -7
  159. data/spec/lib/pact_broker/index/service_spec.rb +89 -15
  160. data/spec/lib/pact_broker/pacts/pact_publication_dataset_module_spec.rb +400 -0
  161. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +434 -14
  162. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +1 -1
  163. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +1 -1
  164. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +224 -0
  165. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +20 -7
  166. data/spec/lib/pact_broker/pacts/selector_spec.rb +3 -2
  167. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +2 -3
  168. data/spec/lib/pact_broker/pacts/service_spec.rb +9 -7
  169. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +57 -10
  170. data/spec/lib/pact_broker/tags/repository_spec.rb +2 -0
  171. data/spec/lib/pact_broker/verifications/service_spec.rb +4 -1
  172. data/spec/lib/pact_broker/versions/repository_spec.rb +54 -0
  173. data/spec/lib/pact_broker/webhooks/render_spec.rb +6 -5
  174. data/spec/lib/pact_broker/webhooks/service_spec.rb +13 -9
  175. data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +60 -18
  176. data/spec/lib/pact_broker/webhooks/webhook_request_logger_spec.rb +8 -0
  177. data/spec/lib/rack/pact_broker/set_base_url_spec.rb +86 -0
  178. data/spec/lib/sequel/plugins/upsert_spec.rb +31 -3
  179. data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
  180. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
  181. data/spec/spec_helper.rb +17 -5
  182. data/spec/support/approvals.rb +24 -0
  183. data/spec/support/shared_examples_for_responses.rb +11 -0
  184. data/tasks/database.rb +1 -1
  185. data/tasks/db.rake +1 -0
  186. data/tasks/rspec.rake +1 -1
  187. metadata +68 -4
  188. data/docker-compose-issue-repro.yml +0 -22
@@ -23,6 +23,8 @@ module PactBroker
23
23
  it "sets the properties" do
24
24
  expect(subject.name).to eq "prod"
25
25
  expect(subject.version.id).to eq td.version.id
26
+ expect(subject.version_order).to eq td.version.order
27
+ expect(subject.pacticipant_id).to eq td.version.pacticipant_id
26
28
  end
27
29
 
28
30
  context "when the tag already exists" do
@@ -22,6 +22,8 @@ module PactBroker
22
22
  end
23
23
 
24
24
  let(:options) { { webhook_execution_configuration: webhook_execution_configuration } }
25
+ let(:event_context) { { some: "data" } }
26
+ let(:expected_event_context) { { some: "data", provider_version_tags: ["dev"] } }
25
27
  let(:webhook_execution_configuration) { instance_double(PactBroker::Webhooks::ExecutionConfiguration) }
26
28
  let(:params) { { 'success' => true, 'providerApplicationVersion' => '4.5.6', 'wip' => true, 'testResults' => { 'some' => 'results' }} }
27
29
  let(:pact) do
@@ -30,7 +32,7 @@ module PactBroker
30
32
  .create_provider_version_tag('dev')
31
33
  .and_return(:pact)
32
34
  end
33
- let(:create_verification) { subject.create 3, params, pact, options }
35
+ let(:create_verification) { subject.create 3, params, pact, event_context, options }
34
36
 
35
37
  it "logs the creation" do
36
38
  expect(logger).to receive(:info).with(/.*verification.*3/, payload: {"providerApplicationVersion"=>"4.5.6", "success"=>true, "wip"=>true})
@@ -67,6 +69,7 @@ module PactBroker
67
69
  expect(PactBroker::Webhooks::TriggerService).to have_received(:trigger_webhooks_for_verification_results_publication).with(
68
70
  pact,
69
71
  verification,
72
+ expected_event_context,
70
73
  options
71
74
  )
72
75
  end
@@ -122,6 +122,60 @@ module PactBroker
122
122
  end
123
123
  end
124
124
  end
125
+
126
+ describe "#create_or_overwrite" do
127
+ before do
128
+ td.subtract_day
129
+ .create_consumer("Foo")
130
+ .create_consumer_version(version_number, branch: "original-branch", build_url: "original-build-url")
131
+ .create_consumer_version_tag("dev")
132
+ end
133
+
134
+ let(:pacticipant) { td.and_return(:consumer) }
135
+ let(:version_number) { "1234" }
136
+ let(:tags) { nil }
137
+ let(:open_struct_version) { OpenStruct.new(branch: "new-branch", tags: tags) }
138
+
139
+ subject { Repository.new.create_or_overwrite(pacticipant, version_number, open_struct_version) }
140
+
141
+ it "overwrites the values" do
142
+ expect(subject.branch).to eq "new-branch"
143
+ expect(subject.build_url).to eq nil
144
+ end
145
+
146
+ it "does not change the tags" do
147
+ expect { subject }.to_not change { PactBroker::Domain::Version.for("Foo", "1234").tags }
148
+ end
149
+
150
+ context "when there are tags specified" do
151
+ let(:tags) { [ OpenStruct.new(name: "main")] }
152
+
153
+ it "overwrites the tags" do
154
+ expect(subject.tags.count).to eq 1
155
+ expect(subject.tags.first.name).to eq "main"
156
+ end
157
+ end
158
+
159
+ it "does not change the created date" do
160
+ expect { subject }.to_not change { PactBroker::Domain::Version.for("Foo", "1234").created_at }
161
+ end
162
+
163
+ it "does change the updated date" do
164
+ expect { subject }.to change { PactBroker::Domain::Version.for("Foo", "1234").updated_at }
165
+ end
166
+
167
+ it "maintains the order" do
168
+ expect { subject }.to_not change { PactBroker::Domain::Version.for("Foo", "1234").order }
169
+ end
170
+
171
+ context "when the version does not already exist" do
172
+ let(:version) { OpenStruct.new(number: "555", branch: "new-branch") }
173
+
174
+ it "sets the order" do
175
+ expect(subject.order).to_not be nil
176
+ end
177
+ end
178
+ end
125
179
  end
126
180
  end
127
181
  end
@@ -94,7 +94,7 @@ module PactBroker
94
94
  [ double("label", name: "foo"), double("label", name: "bar") ]
95
95
  end
96
96
 
97
- let(:webhook_context) { { base_url: base_url } }
97
+ let(:webhook_context) { { base_url: base_url, event_name: "something" } }
98
98
 
99
99
  let(:nil_pact) { nil }
100
100
  let(:nil_verification) { nil }
@@ -158,7 +158,8 @@ module PactBroker
158
158
  {
159
159
  consumer_version_number: "webhook-version-number",
160
160
  consumer_version_tags: %w[webhook tags],
161
- base_url: base_url
161
+ base_url: base_url,
162
+ event_name: "something"
162
163
 
163
164
  }
164
165
  end
@@ -186,16 +187,16 @@ module PactBroker
186
187
  let(:base_url) { "http://broker" }
187
188
 
188
189
  let(:template_parameters) do
189
- PactAndVerificationParameters.new(placeholder_pact, nil, { base_url: base_url }).to_hash
190
+ PactAndVerificationParameters.new(placeholder_pact, nil, { base_url: base_url, event_name: "something" }).to_hash
190
191
  end
191
192
 
192
193
  it "does not blow up with a placeholder pact" do
193
- template_parameters = PactAndVerificationParameters.new(placeholder_pact, nil, { base_url: base_url }).to_hash
194
+ template_parameters = PactAndVerificationParameters.new(placeholder_pact, nil, { base_url: base_url, event_name: "something" }).to_hash
194
195
  Render.call("", template_parameters)
195
196
  end
196
197
 
197
198
  it "does not blow up with a placeholder verification" do
198
- template_parameters = PactAndVerificationParameters.new(placeholder_pact, placeholder_verification, { base_url: base_url }).to_hash
199
+ template_parameters = PactAndVerificationParameters.new(placeholder_pact, placeholder_verification, { base_url: base_url, event_name: "something" }).to_hash
199
200
  Render.call("", template_parameters)
200
201
  end
201
202
  end
@@ -181,7 +181,9 @@ module PactBroker
181
181
  let(:webhooks) { [instance_double(PactBroker::Domain::Webhook, description: 'description', uuid: '1244')]}
182
182
  let(:triggered_webhook) { instance_double(PactBroker::Webhooks::TriggeredWebhook) }
183
183
  let(:webhook_execution_configuration) { double('webhook_execution_configuration', webhook_context: webhook_context) }
184
- let(:webhook_context) { double('webhook_context') }
184
+ let(:webhook_context) { { base_url: "http://example.org" } }
185
+ let(:event_context) { { some: "data" } }
186
+ let(:expected_event_context) { { some: "data", event_name: PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, base_url: "http://example.org" } }
185
187
  let(:options) do
186
188
  { database_connector: double('database_connector'),
187
189
  webhook_execution_configuration: webhook_execution_configuration,
@@ -196,7 +198,7 @@ module PactBroker
196
198
  allow(Job).to receive(:perform_in)
197
199
  end
198
200
 
199
- subject { Service.trigger_webhooks pact, verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, options }
201
+ subject { Service.trigger_webhooks(pact, verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, options) }
200
202
 
201
203
  it "finds the webhooks" do
202
204
  expect_any_instance_of(PactBroker::Webhooks::Repository).to receive(:find_by_consumer_and_or_provider_and_event_name).with(consumer, provider, PactBroker::Webhooks::WebhookEvent::DEFAULT_EVENT_NAME)
@@ -205,7 +207,7 @@ module PactBroker
205
207
 
206
208
  context "when webhooks are found" do
207
209
  it "executes the webhook" do
208
- expect(Service).to receive(:run_later).with(webhooks, pact, verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, options)
210
+ expect(Service).to receive(:run_later).with(webhooks, pact, verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, expected_event_context, options)
209
211
  subject
210
212
  end
211
213
 
@@ -258,6 +260,7 @@ module PactBroker
258
260
  instance_double(PactBroker::Webhooks::ExecutionConfiguration, to_hash: execution_configuration_hash)
259
261
  end
260
262
  let(:execution_configuration_hash) { { the: 'options' } }
263
+ let(:event_context) { { some: "data" } }
261
264
 
262
265
  before do
263
266
  allow(PactBroker::Pacts::Service).to receive(:search_for_latest_pact).and_return(pact)
@@ -266,7 +269,7 @@ module PactBroker
266
269
  allow(execution_configuration).to receive(:with_failure_log_message).and_return(execution_configuration)
267
270
  end
268
271
 
269
- subject { Service.test_execution(webhook, execution_configuration) }
272
+ subject { Service.test_execution(webhook, event_context, execution_configuration) }
270
273
 
271
274
  it "searches for the latest matching pact" do
272
275
  expect(PactBroker::Pacts::Service).to receive(:search_for_latest_pact).with(consumer_name: 'consumer', provider_name: 'provider')
@@ -279,7 +282,7 @@ module PactBroker
279
282
 
280
283
  context "when the trigger is not for a verification" do
281
284
  it "executes the webhook with the pact" do
282
- expect(webhook).to receive(:execute).with(pact, nil, execution_configuration_hash)
285
+ expect(webhook).to receive(:execute).with(pact, nil, event_context.merge(event_name: "test"), execution_configuration_hash)
283
286
  subject
284
287
  end
285
288
  end
@@ -288,7 +291,7 @@ module PactBroker
288
291
  let(:pact) { nil }
289
292
 
290
293
  it "executes the webhook with a placeholder pact" do
291
- expect(webhook).to receive(:execute).with(an_instance_of(PactBroker::Pacts::PlaceholderPact), anything, anything)
294
+ expect(webhook).to receive(:execute).with(an_instance_of(PactBroker::Pacts::PlaceholderPact), anything, anything, anything)
292
295
  subject
293
296
  end
294
297
  end
@@ -302,7 +305,7 @@ module PactBroker
302
305
  end
303
306
 
304
307
  it "executes the webhook with the pact and the verification" do
305
- expect(webhook).to receive(:execute).with(pact, verification, execution_configuration_hash)
308
+ expect(webhook).to receive(:execute).with(pact, verification, event_context.merge(event_name: "test"), execution_configuration_hash)
306
309
  subject
307
310
  end
308
311
 
@@ -310,7 +313,7 @@ module PactBroker
310
313
  let(:verification) { nil }
311
314
 
312
315
  it "executes the webhook with a placeholder verification" do
313
- expect(webhook).to receive(:execute).with(anything, an_instance_of(PactBroker::Verifications::PlaceholderVerification), anything)
316
+ expect(webhook).to receive(:execute).with(anything, an_instance_of(PactBroker::Verifications::PlaceholderVerification), anything, anything)
314
317
  subject
315
318
  end
316
319
  end
@@ -329,6 +332,7 @@ module PactBroker
329
332
  .with_webhook_context(base_url: 'http://example.org')
330
333
  .with_show_response(true)
331
334
  end
335
+ let(:event_context) { { some: "data", base_url: "http://example.org" }}
332
336
  let(:options) do
333
337
  {
334
338
  database_connector: database_connector,
@@ -347,7 +351,7 @@ module PactBroker
347
351
  .and_return(:pact)
348
352
  end
349
353
 
350
- subject { PactBroker::Webhooks::Service.trigger_webhooks pact, td.verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, options }
354
+ subject { PactBroker::Webhooks::Service.trigger_webhooks(pact, td.verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, options) }
351
355
 
352
356
  it "executes the HTTP request of the webhook" do
353
357
  subject
@@ -11,6 +11,7 @@ module PactBroker
11
11
  let(:previous_pact_version_sha) { "111" }
12
12
  let(:previous_pacts) { { untagged: previous_pact } }
13
13
  let(:logger) { double('logger').as_null_object }
14
+ let(:event_context) { { some: "data" } }
14
15
  let(:webhook_options) { { the: 'options'} }
15
16
 
16
17
  before do
@@ -21,27 +22,27 @@ module PactBroker
21
22
 
22
23
  shared_examples_for "triggering a contract_published event" do
23
24
  it "triggers a contract_published webhook" do
24
- expect(webhook_service).to receive(:trigger_webhooks).with(pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, webhook_options)
25
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, event_context, webhook_options)
25
26
  subject
26
27
  end
27
28
  end
28
29
 
29
30
  shared_examples_for "triggering a contract_content_changed event" do
30
31
  it "triggers a contract_content_changed webhook" do
31
- expect(webhook_service).to receive(:trigger_webhooks).with(pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, webhook_options)
32
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, webhook_options)
32
33
  subject
33
34
  end
34
35
  end
35
36
 
36
37
  shared_examples_for "not triggering a contract_content_changed event" do
37
38
  it "does not trigger a contract_content_changed webhook" do
38
- expect(webhook_service).to_not receive(:trigger_webhooks).with(anything, anything, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, anything)
39
+ expect(webhook_service).to_not receive(:trigger_webhooks).with(anything, anything, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, anything)
39
40
  subject
40
41
  end
41
42
  end
42
43
 
43
44
  describe "#trigger_webhooks_for_new_pact" do
44
- subject { TriggerService.trigger_webhooks_for_new_pact(pact, webhook_options) }
45
+ subject { TriggerService.trigger_webhooks_for_new_pact(pact, event_context, webhook_options) }
45
46
 
46
47
  context "when no previous untagged pact exists" do
47
48
  let(:previous_pact) { nil }
@@ -117,7 +118,7 @@ module PactBroker
117
118
  end
118
119
  let(:existing_pact_version_sha) { pact_version_sha }
119
120
 
120
- subject { TriggerService.trigger_webhooks_for_updated_pact(existing_pact, pact, webhook_options) }
121
+ subject { TriggerService.trigger_webhooks_for_updated_pact(existing_pact, pact, event_context, webhook_options) }
121
122
 
122
123
  context "when the pact version sha of the previous revision is different" do
123
124
  let(:existing_pact_version_sha) { "456" }
@@ -140,32 +141,73 @@ module PactBroker
140
141
  describe "#trigger_webhooks_for_verification_results_publication" do
141
142
  let(:verification) { double("verification", success: success) }
142
143
  let(:success) { true }
144
+ # See lib/pact_broker/pacts/metadata.rb build_metadata_for_pact_for_verification
145
+ let(:selector_1) { { latest: true, consumer_version_number: "1", tag: "prod" } }
146
+ let(:selector_2) { { latest: true, consumer_version_number: "1", tag: "main" } }
147
+ let(:selector_3) { { latest: true, consumer_version_number: "2", tag: "feat/2" } }
148
+ let(:event_context) do
149
+ {
150
+ consumer_version_selectors: [selector_1, selector_2, selector_3],
151
+ other: "foo"
152
+ }
153
+ end
154
+ let(:expected_event_context_1) { { consumer_version_number: "1", consumer_version_tags: ["prod", "main"], other: "foo" } }
155
+ let(:expected_event_context_2) { { consumer_version_number: "2", consumer_version_tags: ["feat/2"], other: "foo" } }
143
156
 
144
- subject { TriggerService.trigger_webhooks_for_verification_results_publication(pact, verification, webhook_options) }
157
+ subject { TriggerService.trigger_webhooks_for_verification_results_publication(pact, verification, event_context, webhook_options) }
145
158
 
146
159
  context "when the verification is successful" do
147
- it "triggers a provider_verification_succeeded webhook" do
148
- expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED, webhook_options)
149
- subject
160
+
161
+ context "when there are consumer_version_selectors in the event_context" do
162
+ it "triggers a provider_verification_succeeded webhook for each consumer version (ie. commit)" do
163
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED, expected_event_context_1, webhook_options)
164
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED, expected_event_context_2, webhook_options)
165
+ subject
166
+ end
167
+
168
+ it "triggers a provider_verification_published webhook for each consumer version (ie. commit)" do
169
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, expected_event_context_1, webhook_options)
170
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, expected_event_context_2, webhook_options)
171
+ subject
172
+ end
150
173
  end
151
174
 
152
- it "triggers a provider_verification_published webhook" do
153
- expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, webhook_options)
154
- subject
175
+ context "when there are no consumer_version_selectors" do
176
+ let(:event_context) { { some: "data" } }
177
+
178
+ it "passes through the event context" do
179
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED, event_context, webhook_options)
180
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, event_context, webhook_options)
181
+ subject
182
+ end
155
183
  end
156
184
  end
157
185
 
158
186
  context "when the verification is not successful" do
159
187
  let(:success) { false }
160
188
 
161
- it "triggers a provider_verification_failed webhook" do
162
- expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED, webhook_options)
163
- subject
189
+ context "when there are consumer_version_selectors in the event_context" do
190
+ it "triggers a provider_verification_failed webhook for each consumer version (ie. commit)" do
191
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED, expected_event_context_1, webhook_options)
192
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED, expected_event_context_2, webhook_options)
193
+ subject
194
+ end
195
+
196
+ it "triggeres a provider_verification_published webhook for each consumer version (ie. commit)" do
197
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, expected_event_context_1, webhook_options)
198
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, expected_event_context_2, webhook_options)
199
+ subject
200
+ end
164
201
  end
165
202
 
166
- it "triggeres a provider_verification_published webhook" do
167
- expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, webhook_options)
168
- subject
203
+ context "when there are no consumer_version_selectors" do
204
+ let(:event_context) { { some: "data" } }
205
+
206
+ it "passes through the event context" do
207
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED, event_context, webhook_options)
208
+ expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, event_context, webhook_options)
209
+ subject
210
+ end
169
211
  end
170
212
  end
171
213
  end
@@ -129,6 +129,14 @@ module PactBroker
129
129
  end
130
130
  end
131
131
 
132
+ context "when the response code '100' is not in 'webhook_http_code_success'" do
133
+ let(:status) { 100 }
134
+
135
+ it "not successful, code '100' not in 'webhook_http_code_success'" do
136
+ expect(logs).to include "oops"
137
+ end
138
+ end
139
+
132
140
  context "when the response code is not successful" do
133
141
  let(:status) { 400 }
134
142
 
@@ -0,0 +1,86 @@
1
+ require 'rack/pact_broker/set_base_url'
2
+
3
+ module Rack
4
+ module PactBroker
5
+ describe SetBaseUrl do
6
+ let(:base_urls) { ["http://pact-broker"] }
7
+ let(:rack_env) { {} }
8
+ let(:target_app) { double('app', call: [200, {}, []]) }
9
+ let(:app) { SetBaseUrl.new(target_app, base_urls) }
10
+
11
+ subject { get("/", {}, rack_env) }
12
+
13
+ describe "#call" do
14
+ context "when the base_url is already set" do
15
+ let(:rack_env) { { "pactbroker.base_url" => "http://foo"} }
16
+
17
+ it "does not overwrite it" do
18
+ expect(target_app).to receive(:call).with(hash_including("pactbroker.base_url" => "http://foo"))
19
+ subject
20
+ end
21
+ end
22
+
23
+ context "when there is one base URL" do
24
+ it "sets that base_url" do
25
+ expect(target_app).to receive(:call).with(hash_including("pactbroker.base_url" => "http://pact-broker"))
26
+ subject
27
+ end
28
+ end
29
+
30
+ context "when there are no base URLs" do
31
+ let(:base_urls) { [] }
32
+
33
+ it "sets the base URL to nil" do
34
+ expect(target_app).to receive(:call).with(hash_including("pactbroker.base_url" => nil))
35
+ subject
36
+ end
37
+ end
38
+
39
+ context "when there are multiple base URLs" do
40
+ let(:base_urls) { ["https://foo", "https://pact-broker-external", "http://pact-broker-internal"] }
41
+
42
+ let(:host) { "pact-broker-internal" }
43
+ let(:scheme) { "http" }
44
+ let(:forwarded_host) { "pact-broker-external" }
45
+ let(:forwarded_scheme) { "https" }
46
+ let(:rack_env) do
47
+ {
48
+ Rack::HTTP_HOST => host,
49
+ Rack::RACK_URL_SCHEME => scheme,
50
+ "HTTP_X_FORWARDED_HOST" => forwarded_host,
51
+ "HTTP_X_FORWARDED_SCHEME" => forwarded_scheme
52
+ }
53
+ end
54
+
55
+ context "when the base URL created taking any X-Forwarded headers into account matches one of the base URLs" do
56
+ it "uses that base URL" do
57
+ expect(target_app).to receive(:call).with(hash_including("pactbroker.base_url" => "https://pact-broker-external"))
58
+ subject
59
+ end
60
+ end
61
+
62
+ context "when the base URL created NOT taking the X-Forwarded headers into account matches one of the base URLs (potential cache poisoning)" do
63
+ let(:forwarded_host) { "pact-broker-external-wrong" }
64
+
65
+ it "uses that base URL" do
66
+ expect(target_app).to receive(:call).with(hash_including("pactbroker.base_url" => "http://pact-broker-internal"))
67
+ subject
68
+ end
69
+ end
70
+
71
+ context "when neither base URL matches the base URLs (potential cache poisoning)" do
72
+ before do
73
+ rack_env["HTTP_HOST"] = "silly-buggers-1"
74
+ rack_env["HTTP_X_FORWARDED_HOST"] = "silly-buggers-1"
75
+ end
76
+
77
+ it "uses the first base URL" do
78
+ expect(target_app).to receive(:call).with(hash_including("pactbroker.base_url" => "https://foo"))
79
+ subject
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end