pact_broker 2.85.0 → 2.88.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (179) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/trigger_pact_docs_update.yml +22 -0
  3. data/CHANGELOG.md +67 -0
  4. data/DEVELOPER_DOCUMENTATION.md +0 -2
  5. data/db/migrations/20210914_add_labels_to_webhooks.rb +14 -0
  6. data/db/migrations/20210915_add_verified_by_to_verification.rb +6 -0
  7. data/db/migrations/20210929_increase_event_context_column_size.rb +14 -0
  8. data/docker-compose-ci-mysql.yml +1 -0
  9. data/docker-compose-test.yml +2 -0
  10. data/docs/CONFIGURATION.md +255 -66
  11. data/docs/api/WEBHOOKS.md +789 -0
  12. data/docs/configuration.yml +166 -101
  13. data/lib/db.rb +0 -1
  14. data/lib/pact/doc/interaction_view_model.rb +2 -2
  15. data/lib/pact/doc/markdown/consumer_contract_renderer.rb +1 -1
  16. data/lib/pact_broker/api/contracts/configuration.rb +33 -0
  17. data/lib/pact_broker/api/contracts/publish_contracts_schema.rb +35 -16
  18. data/lib/pact_broker/api/contracts/webhook_contract.rb +24 -2
  19. data/lib/pact_broker/api/decorators/matrix_decorator.rb +3 -1
  20. data/lib/pact_broker/api/decorators/pact_decorator.rb +12 -0
  21. data/lib/pact_broker/api/decorators/verification_decorator.rb +9 -3
  22. data/lib/pact_broker/api/decorators/webhook_decorator.rb +27 -4
  23. data/lib/pact_broker/api/pact_broker_urls.rb +30 -6
  24. data/lib/pact_broker/api/resources/all_webhooks.rb +2 -2
  25. data/lib/pact_broker/api/resources/default_base_resource.rb +5 -1
  26. data/lib/pact_broker/api/resources/environment.rb +4 -4
  27. data/lib/pact_broker/api/resources/environments.rb +1 -1
  28. data/lib/pact_broker/api/resources/index.rb +7 -1
  29. data/lib/pact_broker/api/resources/metadata_resource_methods.rb +33 -3
  30. data/lib/pact_broker/api/resources/pact_version.rb +4 -0
  31. data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +1 -1
  32. data/lib/pact_broker/api/resources/publish_contracts.rb +1 -1
  33. data/lib/pact_broker/api/resources/verification.rb +5 -2
  34. data/lib/pact_broker/api/resources/webhook_execution.rb +7 -3
  35. data/lib/pact_broker/api/resources/webhook_execution_methods.rb +23 -17
  36. data/lib/pact_broker/api.rb +6 -0
  37. data/lib/pact_broker/application_context.rb +5 -0
  38. data/lib/pact_broker/config/runtime_configuration.rb +4 -0
  39. data/lib/pact_broker/config/runtime_configuration_database_methods.rb +1 -1
  40. data/lib/pact_broker/db/clean.rb +1 -2
  41. data/lib/pact_broker/db/delete_overwritten_data.rb +41 -23
  42. data/lib/pact_broker/deployments/deployed_version.rb +1 -0
  43. data/lib/pact_broker/deployments/deployed_version_service.rb +1 -0
  44. data/lib/pact_broker/deployments/environment_service.rb +7 -2
  45. data/lib/pact_broker/deployments/released_version_service.rb +1 -0
  46. data/lib/pact_broker/doc/controllers/app.rb +1 -0
  47. data/lib/pact_broker/doc/views/can-i-deploy.markdown +2 -1
  48. data/lib/pact_broker/doc/views/index/publish-contracts.markdown +38 -9
  49. data/lib/pact_broker/doc/views/pacticipant/label.markdown +12 -0
  50. data/lib/pact_broker/doc/views/provider-pacts-for-verification.markdown +7 -7
  51. data/lib/pact_broker/doc/views/webhooks.markdown +17 -0
  52. data/lib/pact_broker/domain/index_item.rb +9 -0
  53. data/lib/pact_broker/domain/pacticipant.rb +4 -0
  54. data/lib/pact_broker/domain/verification.rb +19 -4
  55. data/lib/pact_broker/domain/webhook.rb +5 -5
  56. data/lib/pact_broker/domain/webhook_pacticipant.rb +6 -0
  57. data/lib/pact_broker/index/service.rb +4 -4
  58. data/lib/pact_broker/locale/en.yml +4 -1
  59. data/lib/pact_broker/matrix/head_row.rb +1 -1
  60. data/lib/pact_broker/matrix/parse_can_i_deploy_query.rb +5 -3
  61. data/lib/pact_broker/matrix/quick_row.rb +0 -1
  62. data/lib/pact_broker/matrix/repository.rb +0 -1
  63. data/lib/pact_broker/matrix/row.rb +2 -2
  64. data/lib/pact_broker/pacticipants/repository.rb +1 -1
  65. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +0 -1
  66. data/lib/pact_broker/pacts/metadata.rb +7 -1
  67. data/lib/pact_broker/pacts/pact_publication.rb +7 -0
  68. data/lib/pact_broker/pacts/pact_publication_clean_selector_dataset_module.rb +19 -0
  69. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +30 -2
  70. data/lib/pact_broker/pacts/pact_version.rb +24 -1
  71. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +5 -4
  72. data/lib/pact_broker/pacts/repository.rb +50 -47
  73. data/lib/pact_broker/pacts/service.rb +5 -5
  74. data/lib/pact_broker/string_refinements.rb +1 -1
  75. data/lib/pact_broker/test/http_test_data_builder.rb +40 -10
  76. data/lib/pact_broker/test/test_data_builder.rb +28 -5
  77. data/lib/pact_broker/ui/helpers/url_helper.rb +12 -0
  78. data/lib/pact_broker/ui/view_models/index_item.rb +15 -1
  79. data/lib/pact_broker/ui/view_models/index_item_branch_head.rb +39 -0
  80. data/lib/pact_broker/ui/view_models/index_item_provider_branch_head.rb +39 -0
  81. data/lib/pact_broker/ui/views/dashboard/show.haml +14 -7
  82. data/lib/pact_broker/verifications/repository.rb +5 -2
  83. data/lib/pact_broker/verifications/service.rb +7 -4
  84. data/lib/pact_broker/version.rb +1 -1
  85. data/lib/pact_broker/versions/abbreviate_number.rb +8 -4
  86. data/lib/pact_broker/versions/branch_head.rb +0 -2
  87. data/lib/pact_broker/versions/branch_version.rb +1 -0
  88. data/lib/pact_broker/versions/repository.rb +0 -1
  89. data/lib/pact_broker/webhooks/event_listener.rb +4 -2
  90. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +18 -3
  91. data/lib/pact_broker/webhooks/repository.rb +10 -4
  92. data/lib/pact_broker/webhooks/trigger_service.rb +1 -1
  93. data/lib/pact_broker/webhooks/webhook.rb +71 -8
  94. data/lib/webmachine/describe_routes.rb +62 -0
  95. data/public/stylesheets/index.css +5 -0
  96. data/script/data/auto-create-things-for-tags.rb +1 -0
  97. data/script/data/branches.rb +1 -1
  98. data/script/data/contract-published-requiring-verification.rb +0 -1
  99. data/script/data/verify-pact-for-multiple-selectors.rb +30 -0
  100. data/script/docs/generate-api-docs.rb +117 -0
  101. data/script/docs/generate-configuration-docs.rb +24 -3
  102. data/script/docs/regenerate-api-docs.sh +11 -0
  103. data/script/generate-erd +55 -0
  104. data/spec/features/create_webhook_spec.rb +55 -10
  105. data/spec/features/get_pact_spec.rb +2 -3
  106. data/spec/fixtures/approvals/docs_webhooks_executing_a_saved_webhook_options.approved.json +20 -0
  107. data/spec/fixtures/approvals/docs_webhooks_executing_a_saved_webhook_post.approved.json +43 -0
  108. data/spec/fixtures/approvals/docs_webhooks_executing_an_unsaved_webhook_options.approved.json +20 -0
  109. data/spec/fixtures/approvals/docs_webhooks_executing_an_unsaved_webhook_post.approved.json +63 -0
  110. data/spec/fixtures/approvals/docs_webhooks_logs_of_triggered_webhook_get.approved.json +20 -0
  111. data/spec/fixtures/approvals/docs_webhooks_logs_of_triggered_webhook_options.approved.json +20 -0
  112. data/spec/fixtures/approvals/docs_webhooks_pact_webhooks_get.approved.json +45 -0
  113. data/spec/fixtures/approvals/docs_webhooks_pact_webhooks_options.approved.json +20 -0
  114. data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_pact_publication_get.approved.json +52 -0
  115. data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_pact_publication_options.approved.json +20 -0
  116. data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_verification_publication_get.approved.json +32 -0
  117. data/spec/fixtures/approvals/docs_webhooks_triggered_webhooks_for_verification_publication_options.approved.json +20 -0
  118. data/spec/fixtures/approvals/docs_webhooks_webhook_get.approved.json +74 -0
  119. data/spec/fixtures/approvals/docs_webhooks_webhook_options.approved.json +20 -0
  120. data/spec/fixtures/approvals/docs_webhooks_webhook_put.approved.json +77 -0
  121. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_a_provider_get.approved.json +41 -0
  122. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_a_provider_options.approved.json +20 -0
  123. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_and_provider_get.approved.json +45 -0
  124. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_and_provider_options.approved.json +20 -0
  125. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_get.approved.json +41 -0
  126. data/spec/fixtures/approvals/docs_webhooks_webhooks_for_consumer_options.approved.json +20 -0
  127. data/spec/fixtures/approvals/docs_webhooks_webhooks_get.approved.json +45 -0
  128. data/spec/fixtures/approvals/docs_webhooks_webhooks_options.approved.json +20 -0
  129. data/spec/fixtures/approvals/docs_webhooks_webhooks_post.approved.json +78 -0
  130. data/spec/fixtures/approvals/docs_webhooks_webhooks_status_get.approved.json +79 -0
  131. data/spec/fixtures/approvals/docs_webhooks_webhooks_status_options.approved.json +20 -0
  132. data/spec/fixtures/approvals/get_provider_pacts_for_verification.approved.json +1 -2
  133. data/spec/fixtures/approvals/publish_contract_no_branch.approved.json +1 -2
  134. data/spec/fixtures/approvals/publish_contract_nothing_exists.approved.json +1 -2
  135. data/spec/fixtures/approvals/publish_contract_nothing_exists_with_webhook.approved.json +1 -2
  136. data/spec/fixtures/approvals/publish_contract_verification_already_exists.approved.json +1 -2
  137. data/spec/fixtures/approvals/publish_contract_with_validation_error.approved.json +1 -2
  138. data/spec/fixtures/invalid-publish-contract-body.json +38 -0
  139. data/spec/fixtures/verification.json +4 -0
  140. data/spec/integration/pact_metdata_spec.rb +105 -0
  141. data/spec/integration/webhooks/contract_publication_spec.rb +68 -0
  142. data/spec/integration/webhooks/contract_requiring_verification_published_spec.rb +67 -0
  143. data/spec/integration/webhooks/pact_publication_spec.rb +51 -0
  144. data/spec/integration/webhooks_documentation_spec.rb +348 -0
  145. data/spec/lib/pact/doc/markdown/consumer_contract_renderer_spec.rb +2 -2
  146. data/spec/lib/pact_broker/api/contracts/publish_contracts_schema_spec.rb +13 -0
  147. data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +50 -0
  148. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +1 -1
  149. data/spec/lib/pact_broker/api/decorators/verification_decorator_spec.rb +15 -7
  150. data/spec/lib/pact_broker/api/decorators/verification_summary_decorator_spec.rb +4 -2
  151. data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +4 -4
  152. data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +18 -0
  153. data/spec/lib/pact_broker/api/resources/triggered_webhook_logs_spec.rb +6 -5
  154. data/spec/lib/pact_broker/config/runtime_configuration_documentation_spec.rb +30 -0
  155. data/spec/lib/pact_broker/deployments/environment_service_spec.rb +22 -1
  156. data/spec/lib/pact_broker/domain/webhook_spec.rb +35 -0
  157. data/spec/lib/pact_broker/matrix/head_row_spec.rb +9 -5
  158. data/spec/lib/pact_broker/matrix/parse_can_i_deploy_query_spec.rb +13 -0
  159. data/spec/lib/pact_broker/pacts/{latest_tagged_pact_publications_spec.rb → pact_publication_clean_selector_dataset_module_spec.rb} +7 -9
  160. data/spec/lib/pact_broker/pacts/pact_version_spec.rb +32 -0
  161. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +4 -5
  162. data/spec/lib/pact_broker/pacts/repository_spec.rb +33 -0
  163. data/spec/lib/pact_broker/ui/view_models/index_item_spec.rb +1 -1
  164. data/spec/lib/pact_broker/verifications/service_spec.rb +22 -8
  165. data/spec/lib/pact_broker/versions/abbreviate_number_spec.rb +2 -1
  166. data/spec/lib/pact_broker/webhooks/render_spec.rb +3 -2
  167. data/spec/lib/pact_broker/webhooks/repository_spec.rb +158 -15
  168. data/spec/lib/pact_broker/webhooks/webhook_spec.rb +8 -5
  169. data/spec/support/documentation.rb +64 -0
  170. data/spec/support/rack_helpers.rb +1 -1
  171. data/tasks/db.rake +4 -1
  172. data/tasks/development.rake +14 -13
  173. metadata +89 -12
  174. data/lib/pact_broker/pacts/all_pact_publications.rb +0 -158
  175. data/lib/pact_broker/pacts/latest_pact_publications.rb +0 -48
  176. data/lib/pact_broker/pacts/latest_pact_publications_by_consumer_version.rb +0 -26
  177. data/lib/pact_broker/pacts/latest_tagged_pact_publications.rb +0 -45
  178. data/lib/pact_broker/verifications/latest_verification_for_pact_version.rb +0 -39
  179. data/spec/lib/pact_broker/verifications/latest_verification_for_pact_version_spec.rb +0 -18
@@ -0,0 +1,348 @@
1
+ require "timecop"
2
+
3
+ WEBHOOK_TESTED_PATHS = []
4
+ WEBHOOKS_NO_DOCUMENTATION = %w[
5
+ ]
6
+ WEBHOOK_ROUTES_REQURING_A_TEST = PactBroker.routes
7
+ .select { | route | route[:path].include?("webhook") }
8
+ .reject { | route | WEBHOOKS_NO_DOCUMENTATION.include?(route[:path]) }
9
+
10
+ # Fails on Github Actions
11
+ RSpec.describe "webhook routes", skip: true do
12
+ before do
13
+ Timecop.freeze(Time.new(2021, 9, 1, 10, 7, 21))
14
+ td.create_consumer("Foo")
15
+ .create_provider("Bar")
16
+ .create_consumer_version("2")
17
+ .create_pact(json_content: { integrations: [] }.to_json )
18
+ .create_verification(provider_version: "3")
19
+ .create_webhook(
20
+ uuid: "d2181b32-8b03-4daf-8cc0-d9168b2f6fac",
21
+ url: "https://example.org/example",
22
+ description: "an example webhook",
23
+ body: webhook_body
24
+ )
25
+ .create_triggered_webhook(uuid: "6cd5cc48-db3c-4a4c-a36d-e9bedeb9d91e")
26
+ .create_webhook_execution
27
+ end
28
+
29
+ after do
30
+ Timecop.return
31
+ end
32
+
33
+ let(:webhook_body) do
34
+ { "pactUrl" =>"${pactbroker.pactUrl}" }
35
+ end
36
+
37
+ before do
38
+ if ENV["DEBUG"] == "true"
39
+ PactBroker.routes.find{ | route| route[:path] == path_template }
40
+ end
41
+ WEBHOOK_TESTED_PATHS << path_template
42
+ end
43
+
44
+ after(:all) do
45
+ missed_routes = WEBHOOK_ROUTES_REQURING_A_TEST.reject { | route | WEBHOOK_TESTED_PATHS.include?(route[:path]) }
46
+
47
+ if missed_routes.any? && ENV["DEBUG"] != "true"
48
+ puts "WEBHOOK ROUTES MISSING COVERAGE:"
49
+ puts missed_routes.to_yaml
50
+ end
51
+ end
52
+
53
+ let(:category) { "Webhooks" }
54
+ let(:pact_version_sha) { PactBroker::Pacts::PactVersion.last.sha }
55
+ let(:triggered_webhook_uuid) { PactBroker::Webhooks::TriggeredWebhook.last.trigger_uuid }
56
+ let(:webhook_uuid) { PactBroker::Webhooks::TriggeredWebhook.last.webhook.uuid }
57
+
58
+ let(:webhook_hash) do
59
+ {
60
+ "description" => "an example webhook",
61
+ "events" => [{
62
+ "name" => "contract_content_changed"
63
+ }],
64
+ "request" =>{
65
+ "method" =>"POST",
66
+ "url" =>"https://example.org/example",
67
+ "username" =>"username",
68
+ "password" =>"password",
69
+ "headers" =>{
70
+ "Accept" =>"application/json"
71
+ },
72
+ "body" => webhook_body
73
+ }
74
+ }
75
+ end
76
+
77
+ let(:parameter_values) do
78
+ {
79
+ pact_version_sha: pact_version_sha,
80
+ provider_name: "Bar",
81
+ consumer_name: "Foo",
82
+ consumer_version_number: "2",
83
+ provider_version_number: "3",
84
+ trigger_uuid: triggered_webhook_uuid,
85
+ verification_number: "1"
86
+ }
87
+ end
88
+
89
+ let(:custom_parameter_values) do
90
+ {
91
+
92
+ }
93
+ end
94
+
95
+ let(:rack_headers) do
96
+ {
97
+ "ACCEPT" => "application/hal+json"
98
+ }
99
+ end
100
+
101
+ let(:http_params) { {} }
102
+ let(:http_method) { "GET" }
103
+
104
+ let(:path) do
105
+ build_path(path_template, parameter_values, custom_parameter_values)
106
+ end
107
+
108
+ let(:approval_request_example_name) do
109
+ build_approval_name(category, pact_broker_example_name, http_method)
110
+ end
111
+
112
+ let(:pact_broker_example_name) do | example |
113
+ example.example_group.parent_groups[-2].description
114
+ end
115
+
116
+ subject { send(http_method.downcase, path, http_params, rack_headers) }
117
+
118
+ shared_examples "request" do
119
+ it "returns a body" do
120
+ subject
121
+ Approvals.verify(expected_interaction(subject, WEBHOOK_TESTED_PATHS.size), :name => approval_request_example_name, format: :json)
122
+ end
123
+ end
124
+
125
+ shared_examples "supports GET" do
126
+ its(:status) { is_expected.to eq 200 }
127
+ include_examples "request"
128
+ end
129
+
130
+
131
+ shared_examples "supports POST" do
132
+ let(:http_method) { "POST" }
133
+ let(:rack_headers) do
134
+ {
135
+ "CONTENT_TYPE" => "application/json",
136
+ "ACCEPT" => "application/hal+json"
137
+ }
138
+ end
139
+
140
+ its(:status) { is_expected.to be_between(200, 201) }
141
+ include_examples "request"
142
+
143
+ end
144
+
145
+ shared_examples "supports PUT" do
146
+ describe "PUT" do
147
+ let(:http_method) { "PUT" }
148
+ let(:rack_headers) do
149
+ {
150
+ "CONTENT_TYPE" => "application/json",
151
+ "ACCEPT" => "application/hal+json"
152
+ }
153
+ end
154
+
155
+ its(:status) { is_expected.to be_between(200, 201) }
156
+
157
+ include_examples "request"
158
+ end
159
+ end
160
+
161
+ shared_examples "supports OPTIONS" do
162
+ let(:http_method) { "OPTIONS" }
163
+
164
+ its(:status) { is_expected.to eq 200 }
165
+ include_examples "request"
166
+ end
167
+
168
+ describe "Webhook" do
169
+ let(:path_template) { "/webhooks/:uuid" }
170
+ let(:custom_parameter_values) { { uuid: webhook_uuid } }
171
+
172
+ describe "GET" do
173
+ include_examples "supports GET"
174
+ end
175
+
176
+ describe "PUT" do
177
+ let(:http_params) { webhook_hash.to_json }
178
+ include_examples "supports PUT"
179
+ end
180
+
181
+ describe "OPTIONS" do
182
+ include_examples "supports OPTIONS"
183
+ end
184
+ end
185
+
186
+ describe "Webhooks" do
187
+ let(:path_template) { "/webhooks" }
188
+
189
+ describe "GET" do
190
+ include_examples "supports GET"
191
+ end
192
+
193
+ describe "POST" do
194
+ before do
195
+ allow(PactBroker::Webhooks::Service).to receive(:next_uuid).and_return("dCGCl-Ba3PqEFJ_iE9mJkQ")
196
+ end
197
+
198
+ let(:http_params) { webhook_hash.to_json }
199
+ include_examples "supports POST"
200
+ end
201
+
202
+ describe "OPTIONS" do
203
+ include_examples "supports OPTIONS"
204
+ end
205
+ end
206
+
207
+ describe "Webhooks for consumer" do
208
+ let(:path_template) { "/webhooks/consumer/:consumer_name" }
209
+
210
+ describe "GET" do
211
+ include_examples "supports GET"
212
+ end
213
+
214
+ describe "OPTIONS" do
215
+ include_examples "supports OPTIONS"
216
+ end
217
+ end
218
+
219
+ describe "Webhooks for a provider" do
220
+ let(:path_template) { "/webhooks/provider/:provider_name" }
221
+
222
+ describe "GET" do
223
+ include_examples "supports GET"
224
+ end
225
+
226
+ describe "OPTIONS" do
227
+ include_examples "supports OPTIONS"
228
+ end
229
+ end
230
+
231
+ describe "Webhooks for consumer and provider" do
232
+ let(:path_template) { "/webhooks/provider/:provider_name/consumer/:consumer_name" }
233
+
234
+ describe "GET" do
235
+ include_examples "supports GET"
236
+ end
237
+
238
+ describe "OPTIONS" do
239
+ include_examples "supports OPTIONS"
240
+ end
241
+ end
242
+
243
+ describe "Pact webhooks" do
244
+ let(:path_template) do
245
+ "/pacts/provider/:provider_name/consumer/:consumer_name/webhooks"
246
+ end
247
+
248
+ describe "GET" do
249
+ include_examples "supports GET"
250
+ end
251
+
252
+ describe "OPTIONS" do
253
+ include_examples "supports OPTIONS"
254
+ end
255
+ end
256
+
257
+ describe "Webhooks status" do
258
+ let(:path_template) do
259
+ "/pacts/provider/:provider_name/consumer/:consumer_name/webhooks/status"
260
+ end
261
+
262
+ describe "GET" do
263
+ include_examples "supports GET"
264
+ end
265
+
266
+ describe "OPTIONS" do
267
+ include_examples "supports OPTIONS"
268
+ end
269
+ end
270
+
271
+ describe "Executing a saved webhook" do
272
+ let(:path_template) { "/webhooks/:uuid/execute" }
273
+ let(:custom_parameter_values) { { uuid: webhook_uuid } }
274
+
275
+ include_examples "supports OPTIONS"
276
+
277
+ describe "POST" do
278
+ before do
279
+ stub_request(:post, /http/).to_return(:status => 200)
280
+ allow(PactBroker.configuration).to receive(:webhook_host_whitelist).and_return([/.*/])
281
+ end
282
+
283
+ include_examples "supports POST"
284
+ end
285
+
286
+ end
287
+
288
+ describe "Executing an unsaved webhook" do
289
+ let(:path_template) { "/webhooks/execute" }
290
+
291
+ describe "OPTIONS" do
292
+ include_examples "supports OPTIONS"
293
+ end
294
+
295
+ describe "POST" do
296
+ before do
297
+ stub_request(:post, /http/).to_return(:status => 200)
298
+ allow(PactBroker.configuration).to receive(:webhook_host_whitelist).and_return([/.*/])
299
+ end
300
+
301
+ let(:http_params) do
302
+ webhook_hash.to_json
303
+ end
304
+ include_examples "supports POST"
305
+ end
306
+ end
307
+
308
+ describe "Triggered webhooks for pact publication" do
309
+ let(:path_template) do
310
+ "/pacts/provider/:provider_name/consumer/:consumer_name/version/:consumer_version_number/triggered-webhooks"
311
+ end
312
+
313
+ describe "GET" do
314
+ include_examples "supports GET"
315
+ end
316
+
317
+ describe "OPTIONS" do
318
+ include_examples "supports OPTIONS"
319
+ end
320
+ end
321
+
322
+ describe "Triggered webhooks for verification publication" do
323
+ let(:path_template) do
324
+ "/pacts/provider/:provider_name/consumer/:consumer_name/pact-version/:pact_version_sha/verification-results/:verification_number/triggered-webhooks"
325
+ end
326
+
327
+ describe "GET" do
328
+ include_examples "supports GET"
329
+ end
330
+
331
+ describe "OPTIONS" do
332
+ include_examples "supports OPTIONS"
333
+ end
334
+ end
335
+
336
+ describe "Logs of triggered webhook" do
337
+ let(:path_template) { "/triggered-webhooks/:uuid/logs" }
338
+ let(:custom_parameter_values) { { uuid: triggered_webhook_uuid } }
339
+
340
+ describe "GET" do
341
+ include_examples "supports GET"
342
+ end
343
+
344
+ describe "OPTIONS" do
345
+ include_examples "supports OPTIONS"
346
+ end
347
+ end
348
+ end
@@ -27,8 +27,8 @@ module Pact
27
27
  let(:consumer_contract) { Pact::ConsumerContract.from_uri "./spec/support/markdown_pact_with_markdown_chars_in_names.json" }
28
28
 
29
29
  it "escapes the markdown characters" do
30
- expect(subject.call).to include '# A pact between Some\*Consumer\*App and Some\_Provider\_App'
31
- expect(subject.call).to include '### Requests from Some\*Consumer\*App to Some\_Provider\_App'
30
+ expect(subject.call).to include "# A pact between Some\\*Consumer\\*App and Some\\_Provider\\_App"
31
+ expect(subject.call).to include "### Requests from Some\\*Consumer\\*App to Some\\_Provider\\_App"
32
32
  end
33
33
  end
34
34
 
@@ -108,6 +108,19 @@ module PactBroker
108
108
 
109
109
  its([:contracts, 0]) { is_expected.to include "provider name in contract content ('WRONG') must match providerName ('Bar') in contracts at index 0" }
110
110
  end
111
+
112
+ context "when the consumer name is missing and there is a validation error with the content" do
113
+ let(:params) do
114
+ JSON.parse(File.read("spec/fixtures/invalid-publish-contract-body.json"), symbolize_names: true)
115
+ end
116
+
117
+ it "handles multiple errors" do
118
+ expect(subject[:contracts]).to include "consumerName is missing at index 0"
119
+ expect(subject[:contracts]).to include "providerName is missing at index 0"
120
+ expect(subject[:contracts]).to include "contentType is missing at index 0"
121
+ expect(subject[:contracts]).to include "specification is missing at index 0"
122
+ end
123
+ end
111
124
  end
112
125
  end
113
126
  end
@@ -85,6 +85,31 @@ module PactBroker
85
85
  end
86
86
  end
87
87
 
88
+ context "with a consumer label" do
89
+ let(:json) do
90
+ valid_webhook_with do |hash|
91
+ hash["consumer"].delete("name")
92
+ hash["consumer"]["label"] = "my_label"
93
+ end
94
+ end
95
+
96
+ it "contains no errors" do
97
+ expect(subject.errors).to be_empty
98
+ end
99
+ end
100
+
101
+ context "with a consumer label and name provided" do
102
+ let(:json) do
103
+ valid_webhook_with do |hash|
104
+ hash["consumer"]["label"] = "my_label"
105
+ end
106
+ end
107
+
108
+ it "contains consumer.label error" do
109
+ expect(subject.errors.messages).to eq({:'consumer.label' => ["cannot be provided"]})
110
+ end
111
+ end
112
+
88
113
  context "with a nil provider name" do
89
114
  let(:json) do
90
115
  valid_webhook_with do |hash|
@@ -131,6 +156,31 @@ module PactBroker
131
156
  end
132
157
  end
133
158
 
159
+ context "with provider label" do
160
+ let(:json) do
161
+ valid_webhook_with do |hash|
162
+ hash["provider"].delete("name")
163
+ hash["provider"]["label"] = "my_label"
164
+ end
165
+ end
166
+
167
+ it "contains no errors" do
168
+ expect(subject.errors).to be_empty
169
+ end
170
+ end
171
+
172
+ context "with a provider label and name" do
173
+ let(:json) do
174
+ valid_webhook_with do |hash|
175
+ hash["provider"]["label"] = "my_label"
176
+ end
177
+ end
178
+
179
+ it "contains provider.label error" do
180
+ expect(subject.errors.messages).to eq({:'provider.label' => ["cannot be provided"]})
181
+ end
182
+ end
183
+
134
184
  context "with no request defined" do
135
185
  let(:json) { {}.to_json }
136
186
 
@@ -129,7 +129,7 @@ module PactBroker
129
129
  verifiedAt: "2017-12-31T00:00:00+00:00",
130
130
  _links: {
131
131
  self: {
132
- href: "http://example.org/pacts/provider/Provider/consumer/Consumer/pact-version/1234/verification-results/1"
132
+ href: "http://example.org/pacts/provider/Provider/consumer/Consumer/pact-version/1234/metadata/Y3ZuPTEuMC4w/verification-results/1"
133
133
  }
134
134
  }
135
135
  }
@@ -6,6 +6,7 @@ module PactBroker
6
6
  describe VerificationDecorator do
7
7
  before do
8
8
  allow_any_instance_of(VerificationDecorator).to receive(:verification_triggered_webhooks_url).and_return("http://triggered-webhooks")
9
+ allow_any_instance_of(VerificationDecorator).to receive(:pact_version_with_consumer_version_metadata_url).and_return("http://pact")
9
10
  end
10
11
 
11
12
  let(:verification) do
@@ -18,23 +19,25 @@ module PactBroker
18
19
  test_results: { "arbitrary" => "json" },
19
20
  build_url: "http://build-url",
20
21
  pact_version_sha: "1234",
21
- latest_pact_publication: pact_publication,
22
22
  execution_date: DateTime.now,
23
- provider_version_tags: provider_version_tags)
23
+ provider_version_tags: provider_version_tags,
24
+ verified_by_implementation: "Ruby",
25
+ verified_by_version: "1234")
24
26
  end
25
27
 
26
- let(:pact_publication) do
27
- instance_double("PactBroker::Pacts::PactPublication",
28
+ let(:pact) do
29
+ instance_double("PactBroker::Domain::Pact",
28
30
  name: "A name",
29
31
  provider_name: "Provider",
30
32
  consumer_name: "Consumer",
31
- consumer_version_number: "1.2.3"
33
+ consumer_version_number: "1.2.3",
34
+ pact_version_sha: "1234",
32
35
  )
33
36
  end
34
37
 
35
38
  let(:provider_version_tags) { [instance_double(PactBroker::Tags::TagWithLatestFlag, name: "prod", latest?: true)] }
36
39
 
37
- let(:options) { { user_options: { base_url: "http://example.org" } } }
40
+ let(:options) { { user_options: { base_url: "http://example.org", pact: pact } } }
38
41
 
39
42
  let(:json) { VerificationDecorator.new(verification).to_json(options) }
40
43
 
@@ -61,12 +64,17 @@ module PactBroker
61
64
  end
62
65
 
63
66
  it "includes a link to its pact" do
64
- expect(subject[:_links][:'pb:pact-version'][:href]).to match %r{http://example.org/pacts/}
67
+ expect(subject[:_links][:'pb:pact-version'][:href]).to eq "http://pact"
65
68
  end
66
69
 
67
70
  it "includes a link to the triggered webhooks" do
68
71
  expect(subject[:_links][:'pb:triggered-webhooks'][:href]).to eq "http://triggered-webhooks"
69
72
  end
73
+
74
+ it "includes the framework that did the verification" do
75
+ expect(subject[:verifiedBy][:implementation]).to eq "Ruby"
76
+ expect(subject[:verifiedBy][:version]).to eq "1234"
77
+ end
70
78
  end
71
79
  end
72
80
  end
@@ -21,7 +21,9 @@ module PactBroker
21
21
  latest_pact_publication: pact,
22
22
  test_results: nil,
23
23
  execution_date: DateTime.now,
24
- provider_version_tags: provider_version_tags)
24
+ provider_version_tags: provider_version_tags,
25
+ verified_by_implementation: "Ruby",
26
+ verified_by_version: "1234")
25
27
  end
26
28
 
27
29
  let(:pact_version) do
@@ -29,7 +31,7 @@ module PactBroker
29
31
  end
30
32
 
31
33
  let(:provider_version_tags) { [instance_double(PactBroker::Tags::TagWithLatestFlag, name: "prod", latest?: true)] }
32
- let(:pact) { instance_double("PactBroker::Domain::Pact", name: "Some pact", consumer_name: "Foo", provider_name: "Bar", consumer_version_number: "1.2.3") }
34
+ let(:pact) { instance_double("PactBroker::Domain::Pact", name: "Some pact", consumer_name: "Foo", provider_name: "Bar", consumer_version_number: "1.2.3", pact_version_sha: "1234") }
33
35
  let(:is_pending) { true }
34
36
  let(:options) { {base_url: "http://example.org", consumer_name: "Foo", consumer_version_number: "1.2.3", resource_url: "http://self"} }
35
37
 
@@ -20,8 +20,8 @@ module PactBroker
20
20
  Webhooks::WebhookRequestTemplate.new(request)
21
21
  end
22
22
 
23
- let(:consumer) { Domain::Pacticipant.new(name: "Consumer") }
24
- let(:provider) { Domain::Pacticipant.new(name: "Provider") }
23
+ let(:consumer) { Domain::WebhookPacticipant.new(name: "Consumer") }
24
+ let(:provider) { Domain::WebhookPacticipant.new(name: "Provider") }
25
25
  let(:event) { Webhooks::WebhookEvent.new(name: "something_happened") }
26
26
  let(:created_at) { DateTime.now }
27
27
  let(:updated_at) { created_at + 1 }
@@ -193,8 +193,8 @@ module PactBroker
193
193
  context "when the decorated object has a consumer/provider but the incoming JSON does not" do
194
194
  let(:webhook) do
195
195
  Domain::Webhook.new(
196
- consumer: Domain::Pacticipant.new(name: "consumer"),
197
- provider: Domain::Pacticipant.new(name: "provider")
196
+ consumer: Domain::WebhookPacticipant.new(name: "consumer"),
197
+ provider: Domain::WebhookPacticipant.new(name: "provider")
198
198
  )
199
199
  end
200
200
 
@@ -100,6 +100,24 @@ module PactBroker
100
100
  end
101
101
  end
102
102
 
103
+ describe "verification_url_from_params" do
104
+ context "with consumer_version_number" do
105
+ let(:params) do
106
+ {
107
+ consumer_name: consumer_name,
108
+ provider_name: provider_name,
109
+ pact_version_sha: "1234",
110
+ consumer_version_number: "2",
111
+ verification_number: "1"
112
+ }
113
+ end
114
+
115
+ subject { PactBrokerUrls.verification_url_from_params(params, base_url)}
116
+
117
+ it { is_expected.to eq "http://example.org/pacts/provider/Bar%2FBar/consumer/Foo%2FFoo/pact-version/1234/metadata/Y3ZuPTI/verification-results/1" }
118
+ end
119
+ end
120
+
103
121
  describe "templated_diff_url" do
104
122
  subject { PactBrokerUrls.templated_diff_url(pact, base_url) }
105
123
 
@@ -15,15 +15,16 @@ module PactBroker
15
15
  .create_webhook_execution(logs: "waffle")
16
16
  end
17
17
 
18
- let(:path) { "/webhooks/5432/trigger/1234/logs" }
19
-
20
18
  subject { get(path) }
21
19
 
22
20
  let(:triggered_webhook_uuid) { PactBroker::Webhooks::TriggeredWebhook.first.uuid }
23
- let(:path) { "/triggered-webhooks/#{triggered_webhook_uuid}/logs" }
24
21
 
25
- it "returns the concatenated webhook execution logs" do
26
- expect(subject.body).to eq "foo\nbar"
22
+ describe "by triggered webhook uuid" do
23
+ let(:path) { "/triggered-webhooks/1234/logs" }
24
+
25
+ it "returns the concatenated webhook execution logs" do
26
+ expect(subject.body).to eq "foo\nbar"
27
+ end
27
28
  end
28
29
  end
29
30
  end
@@ -0,0 +1,30 @@
1
+ require "pact_broker/config/runtime_configuration"
2
+
3
+ module PactBroker
4
+ module Config
5
+ describe RuntimeConfiguration do
6
+ ATTRIBUTES = RuntimeConfiguration.config_attributes
7
+ DOCUMENTATION = File.read("docs/configuration.yml")
8
+ DOCUMENTED_ATTRIBUTES = YAML.load(DOCUMENTATION)["groups"].flat_map{ | group | group["vars"].keys.collect(&:to_sym) }
9
+ DELIBERATELY_UNDOCUMENTED_ATTRIBUTES = [
10
+ :warning_error_class_names,
11
+ :log_configuration_on_startup,
12
+ :use_hal_browser,
13
+ :use_rack_protection,
14
+ :use_case_sensitive_resource_names,
15
+ :order_versions_by_date,
16
+ :base_equality_only_on_content_that_affects_verification_results,
17
+ :semver_formats,
18
+ :seed_example_data,
19
+ :use_first_tag_as_branch_time_limit,
20
+ :validate_database_connection_config
21
+ ]
22
+
23
+ (ATTRIBUTES - DELIBERATELY_UNDOCUMENTED_ATTRIBUTES).each do | attribute_name |
24
+ it "has documentation for #{attribute_name}" do
25
+ expect(DOCUMENTED_ATTRIBUTES & [attribute_name]).to include(attribute_name)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -2,7 +2,7 @@ require "pact_broker/deployments/environment_service"
2
2
 
3
3
  module PactBroker
4
4
  module Deployments
5
- module EnvironmentService
5
+ describe EnvironmentService do
6
6
  describe ".create" do
7
7
  let(:environment) do
8
8
  Environment.new(
@@ -32,6 +32,27 @@ module PactBroker
32
32
  end
33
33
  end
34
34
  end
35
+
36
+ describe ".replace" do
37
+ before do
38
+ td.create_environment("foo", uuid: "1", display_name: "bar", production: false)
39
+ end
40
+
41
+ subject { EnvironmentService.replace("1", Environment.new(name: "bar", display_name: "bar-2", production: true) ) }
42
+
43
+ it "replaces the attributes" do
44
+ subject
45
+ expect(Environment.first).to have_attributes(name: "bar", display_name: "bar-2", production: true)
46
+ end
47
+
48
+ context "with missing attributes" do
49
+ subject { EnvironmentService.replace("1", Environment.new ) }
50
+
51
+ it "raises an error" do
52
+ expect { subject }.to raise_error Sequel::DatabaseError
53
+ end
54
+ end
55
+ end
35
56
  end
36
57
  end
37
58
  end