pact_broker 2.104.0 → 2.106.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -1
  3. data/README.md +1 -1
  4. data/db/migrations/20221130_add_provider_version_id_index_to_verifications.rb +28 -0
  5. data/db/migrations/20221208_add_index_to_pact_version_provider_tag_successful_verifications.rb +21 -0
  6. data/db/migrations/20221215_add_prov_ver_id_ndx_to_latest_verifi_id_for_pact_ver_and_prov_ver.rb +21 -0
  7. data/db/migrations/20230131_add_cons_ver_id_ndx_to_latest_pp_id_for_cons_ver.rb +17 -0
  8. data/docs/CONFIGURATION.md +1 -1
  9. data/docs/api/PAGINATION.md +43 -0
  10. data/lib/pact_broker/api/contracts/publish_contracts_schema.rb +13 -1
  11. data/lib/pact_broker/api/contracts/utf_8_validation.rb +17 -0
  12. data/lib/pact_broker/api/contracts/webhook_contract.rb +2 -0
  13. data/lib/pact_broker/api/decorators/custom_error_problem_json_decorator.rb +36 -0
  14. data/lib/pact_broker/api/decorators/pacticipant_collection_decorator.rb +3 -0
  15. data/lib/pact_broker/api/decorators/pagination_links.rb +11 -0
  16. data/lib/pact_broker/api/decorators/runtime_error_problem_json_decorator.rb +34 -0
  17. data/lib/pact_broker/api/decorators/validation_errors_problem_json_decorator.rb +66 -0
  18. data/lib/pact_broker/api/middleware/http_debug_logs.rb +2 -2
  19. data/lib/pact_broker/api/resources/badge_methods.rb +1 -1
  20. data/lib/pact_broker/api/resources/base_resource.rb +28 -48
  21. data/lib/pact_broker/api/resources/error_handling_methods.rb +57 -0
  22. data/lib/pact_broker/api/resources/error_response_generator.rb +70 -0
  23. data/lib/pact_broker/api/resources/latest_verifications_for_consumer_version.rb +1 -1
  24. data/lib/pact_broker/api/resources/pact_version.rb +1 -1
  25. data/lib/pact_broker/api/resources/pacticipants.rb +4 -1
  26. data/lib/pact_broker/api/resources/pagination_methods.rb +8 -4
  27. data/lib/pact_broker/api/resources/publish_contracts.rb +1 -1
  28. data/lib/pact_broker/api/resources/versions.rb +5 -12
  29. data/lib/pact_broker/api.rb +3 -4
  30. data/lib/pact_broker/app.rb +1 -3
  31. data/lib/pact_broker/application_context.rb +4 -4
  32. data/lib/pact_broker/config/runtime_configuration.rb +1 -0
  33. data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +3 -0
  34. data/lib/pact_broker/configuration.rb +1 -1
  35. data/lib/pact_broker/db/clean_incremental.rb +67 -59
  36. data/lib/pact_broker/db/data_migrations/set_pacticipant_main_branch.rb +2 -2
  37. data/lib/pact_broker/domain/pact.rb +7 -1
  38. data/lib/pact_broker/index/service.rb +1 -1
  39. data/lib/pact_broker/initializers/database_connection.rb +1 -1
  40. data/lib/pact_broker/locale/en.yml +2 -0
  41. data/lib/pact_broker/matrix/can_i_deploy_query_schema.rb +6 -0
  42. data/lib/pact_broker/matrix/deployment_status_summary.rb +1 -1
  43. data/lib/pact_broker/matrix/resolved_selector.rb +2 -2
  44. data/lib/pact_broker/pacticipants/repository.rb +4 -11
  45. data/lib/pact_broker/pacticipants/service.rb +4 -8
  46. data/lib/pact_broker/pacts/pact_version.rb +39 -0
  47. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +74 -47
  48. data/lib/pact_broker/pacts/repository.rb +2 -2
  49. data/lib/pact_broker/pacts/selected_pact.rb +4 -0
  50. data/lib/pact_broker/pacts/service.rb +7 -8
  51. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +7 -4
  52. data/lib/pact_broker/repositories/helpers.rb +11 -0
  53. data/lib/pact_broker/repositories/page.rb +24 -0
  54. data/lib/pact_broker/string_refinements.rb +4 -0
  55. data/lib/pact_broker/tasks/clean_task.rb +8 -4
  56. data/lib/pact_broker/tasks/delete_overwritten_data_task.rb +1 -1
  57. data/lib/pact_broker/test/http_test_data_builder.rb +34 -26
  58. data/lib/pact_broker/test/test_data_builder.rb +28 -12
  59. data/lib/pact_broker/ui/views/matrix/show.haml +1 -1
  60. data/lib/pact_broker/verifications/repository.rb +14 -11
  61. data/lib/pact_broker/verifications/service.rb +1 -1
  62. data/lib/pact_broker/version.rb +1 -1
  63. data/lib/pact_broker/versions/branch.rb +1 -0
  64. data/lib/pact_broker/versions/repository.rb +12 -0
  65. data/lib/pact_broker/versions/service.rb +4 -0
  66. data/lib/pact_broker/webhooks/event_listener.rb +2 -2
  67. data/lib/pact_broker/webhooks/execution_configuration.rb +4 -0
  68. data/lib/pact_broker/webhooks/execution_configuration_creator.rb +1 -0
  69. data/lib/pact_broker/webhooks/webhook_request_logger.rb +1 -1
  70. data/lib/rack/pact_broker/request_target.rb +1 -1
  71. data/lib/webmachine/application_monkey_patch.rb +10 -0
  72. data/lib/webmachine/render_error_monkey_patch.rb +70 -0
  73. data/pact_broker.gemspec +2 -2
  74. metadata +21 -9
  75. data/lib/pact_broker/api/resources/error_response_body_generator.rb +0 -41
  76. data/lib/rack/pact_broker/convert_404_to_hal.rb +0 -20
@@ -265,7 +265,9 @@ module PactBroker
265
265
  "request" => {
266
266
  "method" => "POST",
267
267
  "url" => url,
268
- "body" => body || default_body
268
+ "body" => body || default_body,
269
+ "username" => "user",
270
+ "password" => "pass"
269
271
  }
270
272
  }.compact
271
273
  path = "webhooks/#{uuid}"
@@ -286,32 +288,9 @@ module PactBroker
286
288
  def create_global_webhook_for_anything_published(uuid: nil, url: "https://postman-echo.com/post")
287
289
  puts "Creating global webhook for contract changed event with uuid #{uuid}"
288
290
  uuid ||= SecureRandom.uuid
289
- request_body = {
290
- "description" => "A webhook for all consumers and providers",
291
- "events" => [{
292
- "name" => "contract_published"
293
- },{
294
- "name" => "provider_verification_published"
295
- }],
296
- "request" => {
297
- "method" => "POST",
298
- "url" => url,
299
- "headers" => { "Content-Type" => "application/json"},
300
- "body" => {
301
- "eventName" => "${pactbroker.eventName}",
302
- "consumerVersionNumber" => "${pactbroker.consumerVersionNumber}",
303
- "consumerVersionTags" => "${pactbroker.consumerVersionTags}",
304
- "consumerVersionBranch" => "${pactbroker.consumerVersionBranch}",
305
- "githubVerificationStatus" => "${pactbroker.githubVerificationStatus}",
306
- "providerVersionNumber" => "${pactbroker.providerVersionNumber}",
307
- "providerVersionTags" => "${pactbroker.providerVersionTags}",
308
- "providerVersionBranch" => "${pactbroker.providerVersionBranch}",
309
- "canIMerge" => "${pactbroker.providerMainBranchGithubVerificationStatus}"
310
- }
311
- }
312
- }
291
+
313
292
  path = "webhooks/#{uuid}"
314
- client.put(path, request_body.to_json).tap { |response| check_for_error(response) }
293
+ client.put(path, webhook_body_with_all_parameters(url).to_json).tap { |response| check_for_error(response) }
315
294
  separate
316
295
  self
317
296
  end
@@ -438,6 +417,35 @@ module PactBroker
438
417
  puts response.body
439
418
  end
440
419
  end
420
+
421
+ def webhook_body_with_all_parameters(url)
422
+ {
423
+ "description" => "A webhook for all consumers and providers",
424
+ "events" => [{
425
+ "name" => "contract_published"
426
+ },{
427
+ "name" => "provider_verification_published"
428
+ }],
429
+ "request" => {
430
+ "method" => "POST",
431
+ "url" => url,
432
+ "headers" => { "Content-Type" => "application/json"},
433
+ "username" => "user",
434
+ "password" => "pass",
435
+ "body" => {
436
+ "eventName" => "${pactbroker.eventName}",
437
+ "consumerVersionNumber" => "${pactbroker.consumerVersionNumber}",
438
+ "consumerVersionTags" => "${pactbroker.consumerVersionTags}",
439
+ "consumerVersionBranch" => "${pactbroker.consumerVersionBranch}",
440
+ "githubVerificationStatus" => "${pactbroker.githubVerificationStatus}",
441
+ "providerVersionNumber" => "${pactbroker.providerVersionNumber}",
442
+ "providerVersionTags" => "${pactbroker.providerVersionTags}",
443
+ "providerVersionBranch" => "${pactbroker.providerVersionBranch}",
444
+ "canIMerge" => "${pactbroker.providerMainBranchGithubVerificationStatus}"
445
+ }
446
+ }
447
+ }
448
+ end
441
449
  end
442
450
  end
443
451
  end
@@ -399,22 +399,13 @@ module PactBroker
399
399
  verification = PactBroker::Domain::Verification.new(parameters)
400
400
  pact_version = PactBroker::Pacts::Repository.new.find_pact_version(@consumer, @provider, pact.pact_version_sha)
401
401
  @provider_version = version_repository.find_by_pacticipant_id_and_number_or_create(provider.id, provider_version_number)
402
- PactBroker::Versions::BranchVersionRepository.new.add_branch(@provider_version, branch) if branch
402
+ branch_version = PactBroker::Versions::BranchVersionRepository.new.add_branch(@provider_version, branch) if branch
403
403
 
404
- if tag_names.any?
405
- tag_names.each do | tag_name |
406
- PactBroker::Domain::Tag.new(name: tag_name, version: @provider_version, version_order: @provider_version.order).insert_ignore
407
- set_created_at_if_set(parameters[:created_at], :tags, version_id: @provider_version.id, name: tag_name)
408
- end
409
- end
404
+ set_created_at_for_provider_tags(parameters, tag_names)
410
405
 
411
406
  @verification = PactBroker::Verifications::Repository.new.create(verification, provider_version_number, pact_version)
412
407
 
413
- set_created_at_if_set(parameters[:created_at], :verifications, id: @verification.id)
414
- set_created_at_if_set(parameters[:created_at], :versions, id: @provider_version.id)
415
- set_created_at_if_set(parameters[:created_at], :latest_verification_id_for_pact_version_and_provider_version, pact_version_id: pact_version_id, provider_version_id: @provider_version.id)
416
- set_created_at_if_set(parameters[:created_at], :pact_version_provider_tag_successful_verifications, { verification_id: @verification.id }, :execution_date)
417
-
408
+ set_created_at_for_verification_resources(parameters, pact_version.id, branch, branch_version)
418
409
  self
419
410
  end
420
411
 
@@ -674,6 +665,31 @@ module PactBroker
674
665
  [nil, Domain::WebhookPacticipant.new(label: label)]
675
666
  end
676
667
  end
668
+
669
+ def set_created_at_for_provider_tags(parameters, tag_names)
670
+ if tag_names.any?
671
+ tag_names.each do | tag_name |
672
+ PactBroker::Domain::Tag.new(name: tag_name, version: @provider_version, version_order: @provider_version.order).insert_ignore
673
+ set_created_at_if_set(parameters[:created_at], :tags, version_id: @provider_version.id, name: tag_name)
674
+ end
675
+ end
676
+ end
677
+
678
+ def set_created_at_for_verification_resources(parameters, pact_version_id, branch, branch_version)
679
+ if branch
680
+ set_created_at_if_set(parameters[:created_at], :branch_versions, id: branch_version.id)
681
+
682
+ # if the branch has just been created...
683
+ if branch_version.branch.branch_versions.size == 1
684
+ set_created_at_if_set(parameters[:created_at], :branches, id: branch_version.branch.id)
685
+ end
686
+ end
687
+
688
+ set_created_at_if_set(parameters[:created_at], :verifications, id: @verification.id)
689
+ set_created_at_if_set(parameters[:created_at], :versions, id: @provider_version.id)
690
+ set_created_at_if_set(parameters[:created_at], :latest_verification_id_for_pact_version_and_provider_version, pact_version_id: pact_version_id, provider_version_id: @provider_version.id)
691
+ set_created_at_if_set(parameters[:created_at], :pact_version_provider_tag_successful_verifications, { verification_id: @verification.id }, :execution_date)
692
+ end
677
693
  end
678
694
  end
679
695
  end
@@ -195,7 +195,7 @@
195
195
  .tag-parent{"title": tag.tooltip, "data-toggle": "tooltip", "data-placement": "right"}
196
196
  %a{href: tag.url}
197
197
  .tag.badge.badge-primary
198
- = "tag:" + ellipsisize(tag.name)
198
+ = "tag: " + ellipsisize(tag.name)
199
199
  - line.other_provider_version_tags.each do | tag |
200
200
  .tag-parent{"title": tag.tooltip, "data-toggle": "tooltip", "data-placement": "right"}
201
201
  %a{href: tag.url}
@@ -3,6 +3,7 @@ require "pact_broker/domain/verification"
3
3
  require "pact_broker/verifications/sequence"
4
4
  require "pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version"
5
5
  require "pact_broker/verifications/pact_version_provider_tag_successful_verification"
6
+ require "pact_broker/repositories/scopes"
6
7
 
7
8
  module PactBroker
8
9
  module Verifications
@@ -10,6 +11,7 @@ module PactBroker
10
11
 
11
12
  include PactBroker::Repositories::Helpers
12
13
  include PactBroker::Repositories
14
+ include PactBroker::Repositories::Scopes
13
15
 
14
16
  # Ideally this would just be a sequence, but Sqlite and MySQL don't support sequences
15
17
  # in the way we need to use them ie. determining what the next number will be before we
@@ -33,7 +35,7 @@ module PactBroker
33
35
  end
34
36
 
35
37
  def delete(verification_id)
36
- PactBroker::Domain::Verification.where(id: verification_id).delete
38
+ scope_for(PactBroker::Domain::Verification).where(id: verification_id).delete
37
39
  end
38
40
 
39
41
  def update_latest_verification_id verification
@@ -62,8 +64,9 @@ module PactBroker
62
64
  end
63
65
  end
64
66
 
67
+ # policy should be applied in resource
65
68
  def find consumer_name, provider_name, pact_version_sha, verification_number
66
- PactBroker::Domain::Verification
69
+ unscoped(PactBroker::Domain::Verification)
67
70
  .select_all_qualified
68
71
  .join(:all_pact_publications, pact_version_id: :pact_version_id)
69
72
  .consumer(consumer_name)
@@ -73,19 +76,19 @@ module PactBroker
73
76
  end
74
77
 
75
78
  def find_latest_for_pact(pact)
76
- PactBroker::Pacts::PactPublication.where(id: pact.id).single_record.latest_verification
79
+ scope_for(PactBroker::Pacts::PactPublication).where(id: pact.id).single_record.latest_verification
77
80
  end
78
81
 
79
82
  def find_latest_from_main_branch_for_pact(pact)
80
- PactBroker::Pacts::PactPublication.where(id: pact.id).single_record.latest_main_branch_verification
83
+ scope_for(PactBroker::Pacts::PactPublication).where(id: pact.id).single_record.latest_main_branch_verification
81
84
  end
82
85
 
83
86
  def any_verifications?(consumer, provider)
84
- PactBroker::Domain::Verification.where(consumer_id: consumer.id, provider_id: provider.id).any?
87
+ scope_for(PactBroker::Domain::Verification).where(consumer_id: consumer.id, provider_id: provider.id).any?
85
88
  end
86
89
 
87
90
  def search_for_latest consumer_name, provider_name
88
- query = PactBroker::Domain::Verification.select_all_qualified
91
+ query = scope_for(PactBroker::Domain::Verification).select_all_qualified
89
92
  query = query.for_consumer_name(consumer_name) if consumer_name
90
93
  query = query.for_provider_name(provider_name) if provider_name
91
94
  query.reverse(:execution_date, :id).first
@@ -94,7 +97,7 @@ module PactBroker
94
97
  def find_latest_verifications_for_consumer_version consumer_name, consumer_version_number
95
98
  # Use remove_verifications_for_overridden_consumer_versions because we don't
96
99
  # want verifications for shadowed revisions as it would be misleading.
97
- PactBroker::Domain::Verification
100
+ scope_for(PactBroker::Domain::Verification)
98
101
  .select_all_qualified
99
102
  .remove_verifications_for_overridden_consumer_versions
100
103
  .for_consumer_name_and_consumer_version_number(consumer_name, consumer_version_number)
@@ -115,7 +118,7 @@ module PactBroker
115
118
  Sequel[:lp][:consumer_id] => consumer.id,
116
119
  Sequel[:lp][:provider_id] => provider.id
117
120
  }
118
- query = PactBroker::Domain::Verification
121
+ query = scope_for(PactBroker::Domain::Verification)
119
122
  .select_all_qualified
120
123
  .join(:latest_verification_ids_for_pact_versions, { Sequel[:verifications][:id] => Sequel[:lv][:latest_verification_id] }, { table_alias: :lv })
121
124
  .join(:latest_pact_publication_ids_for_consumer_versions, join_cols, { table_alias: :lp })
@@ -140,7 +143,7 @@ module PactBroker
140
143
  consumer_tag_filter = PactBroker::Repositories::Helpers.name_like(Sequel.qualify(:consumer_tags, :name), consumer_version_tag)
141
144
  provider_tag_filter = PactBroker::Repositories::Helpers.name_like(Sequel.qualify(:provider_tags, :name), provider_version_tag)
142
145
 
143
- query = PactBroker::Domain::Verification
146
+ query = scope_for(PactBroker::Domain::Verification)
144
147
  .select_all_qualified
145
148
  .join(:versions, { Sequel[:provider_versions][:id] => Sequel[view_name][:provider_version_id] }, { table_alias: :provider_versions })
146
149
  .join(:latest_verification_id_for_pact_version_and_provider_version, { Sequel[:lv][:verification_id] => Sequel[view_name][:id] }, { table_alias: :lv })
@@ -160,13 +163,13 @@ module PactBroker
160
163
  end
161
164
 
162
165
  def delete_by_provider_version_id version_id
163
- PactBroker::Domain::Verification.where(provider_version_id: version_id).delete
166
+ scope_for(PactBroker::Domain::Verification).where(provider_version_id: version_id).delete
164
167
  end
165
168
 
166
169
  def delete_all_verifications_between(consumer_name, options)
167
170
  consumer = pacticipant_repository.find_by_name!(consumer_name)
168
171
  provider = pacticipant_repository.find_by_name!(options.fetch(:and))
169
- PactBroker::Domain::Verification.where(provider: provider, consumer: consumer).delete
172
+ scope_for(PactBroker::Domain::Verification).where(provider: provider, consumer: consumer).delete
170
173
  end
171
174
  end
172
175
  end
@@ -33,7 +33,7 @@ module PactBroker
33
33
  # verified_pacts is an array of SelectedPact objects
34
34
  def create next_verification_number, params, verified_pacts, event_context
35
35
  first_verified_pact = verified_pacts.first
36
- logger.info "Creating verification #{next_verification_number} for pact_version_sha=#{first_verified_pact.pact_version_sha}", payload: params.reject{ |k,_| k == "testResults"}
36
+ logger.info("Creating verification #{next_verification_number} for pact_version_sha=#{first_verified_pact.pact_version_sha}", params.without("testResults"))
37
37
  verification = PactBroker::Domain::Verification.new
38
38
  provider_version_number = params.fetch("providerApplicationVersion")
39
39
  PactBroker::Api::Decorators::VerificationDecorator.new(verification).from_hash(params)
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = "2.104.0"
2
+ VERSION = "2.106.0"
3
3
  end
@@ -8,6 +8,7 @@ module PactBroker
8
8
  plugin :insert_ignore, identifying_columns: [:name, :pacticipant_id]
9
9
 
10
10
  associate(:many_to_one, :pacticipant, :class => "PactBroker::Domain::Pacticipant", :key => :pacticipant_id, :primary_key => :id)
11
+ associate(:one_to_many, :branch_versions, :class => "PactBroker::Versions::BranchVersion", :key => :branch_id, :primary_key => :id)
11
12
 
12
13
  dataset_module do
13
14
  include PactBroker::Repositories::Helpers
@@ -59,6 +59,18 @@ module PactBroker
59
59
  .single_record
60
60
  end
61
61
 
62
+ def find_all_pacticipant_versions_in_reverse_order name, pagination_options = {}
63
+ pacticipant = pacticipant_repository.find_by_name!(name)
64
+ query = PactBroker::Domain::Version
65
+ .where(pacticipant: pacticipant)
66
+ .eager(:pacticipant)
67
+ .eager(branch_versions: [:version, :branch_head, { branch: :pacticipant }])
68
+ .eager(tags: :head_tag)
69
+ .eager(:pact_publications)
70
+ .reverse_order(:order)
71
+ query.all_with_pagination_options(pagination_options)
72
+ end
73
+
62
74
  # There may be a race condition if two simultaneous requests come in to create the same version
63
75
  def create(args)
64
76
  version_params = {
@@ -26,6 +26,10 @@ module PactBroker
26
26
  version_repository.find_latest_by_pacticipant_name_and_branch_name(pacticipant_name, branch_name)
27
27
  end
28
28
 
29
+ def self.find_all_pacticipant_versions_in_reverse_order(name, pagination_options = {})
30
+ version_repository.find_all_pacticipant_versions_in_reverse_order(name, pagination_options)
31
+ end
32
+
29
33
  def self.create_or_overwrite(pacticipant_name, version_number, version)
30
34
  pacticipant = pacticipant_repository.find_by_name_or_create(pacticipant_name)
31
35
  version = version_repository.create_or_overwrite(pacticipant, version_number, version)
@@ -53,10 +53,10 @@ module PactBroker
53
53
 
54
54
  def log_detected_event
55
55
  event = detected_events.last
56
- logger.debug "Event detected", payload: { event_name: event.name, event_comment: event.comment }
56
+ logger.debug("Event detected", event_name: event.name, event_comment: event.comment)
57
57
  if event.triggered_webhooks&.any?
58
58
  triggered_webhook_descriptions = event.triggered_webhooks.collect{ |tw| { event_name: event.name, webhook_uuid: tw.webhook_uuid, triggered_webhook_uuid: tw.uuid, webhook_description: tw.webhook.description } }
59
- logger.info "Triggered webhooks for #{event.name}", payload: { triggered_webhooks: triggered_webhook_descriptions }
59
+ logger.info("Triggered webhooks for #{event.name}", triggered_webhooks: triggered_webhook_descriptions)
60
60
  else
61
61
  logger.debug "No enabled webhooks found for event #{event.name}"
62
62
  end
@@ -25,6 +25,10 @@ module PactBroker
25
25
  with_updated_attribute(logging_options: { failure_log_message: value })
26
26
  end
27
27
 
28
+ def with_redact_sensitive_data(value)
29
+ with_updated_attribute(logging_options: { redact_sensitive_data: value })
30
+ end
31
+
28
32
  def with_retry_schedule(value)
29
33
  with_updated_attribute(retry_schedule: value)
30
34
  end
@@ -10,6 +10,7 @@ module PactBroker
10
10
  def self.call(resource)
11
11
  PactBroker::Webhooks::ExecutionConfiguration.new
12
12
  .with_show_response(PactBroker.configuration.show_webhook_response?)
13
+ .with_redact_sensitive_data(PactBroker.configuration.webhook_redact_sensitive_data)
13
14
  .with_retry_schedule(PactBroker.configuration.webhook_retry_schedule)
14
15
  .with_http_success_codes(PactBroker.configuration.webhook_http_code_success)
15
16
  .with_user_agent(PactBroker.configuration.user_agent)
@@ -51,7 +51,7 @@ module PactBroker
51
51
  end
52
52
 
53
53
  def log_request(webhook_request)
54
- http_request = HttpRequestWithRedactedHeaders.new(webhook_request.http_request)
54
+ http_request = options[:redact_sensitive_data] ? HttpRequestWithRedactedHeaders.new(webhook_request.http_request) : webhook_request.http_request
55
55
  logger.info "Making webhook #{webhook_request.uuid} request #{http_request.method.upcase} URI=#{webhook_request.url} (headers and body in debug logs)"
56
56
  logger.debug "Webhook #{webhook_request.uuid} request headers=#{http_request.to_hash}"
57
57
  logger.debug "Webhook #{webhook_request.uuid} request body=#{http_request.body}"
@@ -7,7 +7,7 @@ module Rack
7
7
  extend self
8
8
 
9
9
  WEB_ASSET_EXTENSIONS = %w[.js .woff .woff2 .css .png .html .map .ttf .ico].freeze
10
- API_CONTENT_TYPES = %w[application/hal+json application/json text/csv application/yaml text/plain].freeze
10
+ API_CONTENT_TYPES = %w[application/hal+json application/problem+json application/json text/csv application/yaml text/plain].freeze
11
11
 
12
12
  def request_for_ui?(env)
13
13
  !(request_for_api?(env))
@@ -0,0 +1,10 @@
1
+ require "webmachine/application"
2
+
3
+ class Webmachine::Application
4
+ def application_context= application_context
5
+ # naughty, but better than setting each route manually
6
+ routes.each do | route |
7
+ route.instance_variable_get(:@bindings)[:application_context] = application_context
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,70 @@
1
+ require "webmachine/errors"
2
+ require "pact_broker/string_refinements"
3
+
4
+ # Monkey patches the render_error method so that it returns hal+json or problem+json instead of text/html
5
+
6
+ module Webmachine
7
+ using PactBroker::StringRefinements
8
+
9
+ class << self
10
+ alias_method :original_render_error, :render_error
11
+ end
12
+
13
+ # Renders a standard error message body for the response. The
14
+ # standard messages are defined in localization files.
15
+ # @param [Integer] code the response status code
16
+ # @param [Request] req the request object
17
+ # @param [Response] req the response object
18
+ # @param [Hash] options keys to override the defaults when rendering
19
+ # the response body
20
+ def self.render_error(code, req, res, options={})
21
+ if text_html_error_content_type?(req)
22
+ Webmachine.original_render_error(code, req, res, options)
23
+ else
24
+ render_error_for_api(code, req, res, options)
25
+ end
26
+ end
27
+
28
+ def self.render_error_for_api(code, req, res, options)
29
+ res.code = code
30
+ unless res.body
31
+ title, message = t(["errors.#{code}.title", "errors.#{code}.message"],
32
+ { :method => req.method,
33
+ :error => res.error}.merge(options))
34
+
35
+ title = options[:title] if options[:title]
36
+ message = options[:message] if options[:message]
37
+
38
+ res.body = error_response_body(message, title, title.dasherize.gsub(/^\d+\-/, ""), code, req)
39
+ res.headers[CONTENT_TYPE] = error_response_content_type(req)
40
+ end
41
+ ensure_content_length(res)
42
+ ensure_date_header(res)
43
+ end
44
+
45
+ def self.text_html_error_content_type?(request)
46
+ request.headers["Accept"]&.include?("text/html")
47
+ end
48
+
49
+ def self.problem_json_error_content_type?(request)
50
+ request.headers["Accept"]&.include?("application/problem+json")
51
+ end
52
+
53
+ def self.error_response_content_type(request)
54
+ if problem_json_error_content_type?(request)
55
+ "application/problem+json;charset=utf-8"
56
+ elsif text_html_error_content_type?(request)
57
+ "text/html;charset=utf-8"
58
+ else
59
+ "application/json;charset=utf-8"
60
+ end
61
+ end
62
+
63
+ def self.error_response_body(detail, title, type, status, request)
64
+ if problem_json_error_content_type?(request)
65
+ PactBroker::Api::Decorators::CustomErrorProblemJSONDecorator.new(detail: detail, title: title, type: type, status: status).to_json
66
+ else
67
+ { error: detail }.to_json
68
+ end
69
+ end
70
+ end
data/pact_broker.gemspec CHANGED
@@ -78,8 +78,8 @@ Gem::Specification.new do |gem|
78
78
  gem.add_runtime_dependency "dry-types", "~> 0.10.3" # https://travis-ci.org/pact-foundation/pact_broker/jobs/249448621
79
79
  gem.add_runtime_dependency "dry-logic", "0.4.2" # Later version cases ArgumentError: wrong number of arguments
80
80
  gem.add_runtime_dependency "table_print", "~> 1.5"
81
- gem.add_runtime_dependency "semantic_logger", "~> 4.3"
82
- gem.add_runtime_dependency "sanitize", "6.0"
81
+ gem.add_runtime_dependency "semantic_logger", "~> 4.11"
82
+ gem.add_runtime_dependency "sanitize", "~> 6.0"
83
83
  gem.add_runtime_dependency "wisper", "~> 2.0"
84
84
  gem.add_runtime_dependency "anyway_config", "~> 2.1"
85
85
  gem.add_runtime_dependency "request_store", "~> 1.5"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact_broker
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.104.0
4
+ version: 2.106.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bethany Skurrie
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-09-17 00:00:00.000000000 Z
13
+ date: 2023-02-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -334,26 +334,26 @@ dependencies:
334
334
  requirements:
335
335
  - - "~>"
336
336
  - !ruby/object:Gem::Version
337
- version: '4.3'
337
+ version: '4.11'
338
338
  type: :runtime
339
339
  prerelease: false
340
340
  version_requirements: !ruby/object:Gem::Requirement
341
341
  requirements:
342
342
  - - "~>"
343
343
  - !ruby/object:Gem::Version
344
- version: '4.3'
344
+ version: '4.11'
345
345
  - !ruby/object:Gem::Dependency
346
346
  name: sanitize
347
347
  requirement: !ruby/object:Gem::Requirement
348
348
  requirements:
349
- - - '='
349
+ - - "~>"
350
350
  - !ruby/object:Gem::Version
351
351
  version: '6.0'
352
352
  type: :runtime
353
353
  prerelease: false
354
354
  version_requirements: !ruby/object:Gem::Requirement
355
355
  requirements:
356
- - - '='
356
+ - - "~>"
357
357
  - !ruby/object:Gem::Version
358
358
  version: '6.0'
359
359
  - !ruby/object:Gem::Dependency
@@ -587,9 +587,14 @@ files:
587
587
  - db/migrations/20220303_increase_consumer_version_selector_hashes_column_size.rb
588
588
  - db/migrations/20220622_default_allow_dangerous_contract_modification_to_false_for_new_installations.rb
589
589
  - db/migrations/20220625_delete_pacticipants_with_no_name.rb
590
+ - db/migrations/20221130_add_provider_version_id_index_to_verifications.rb
591
+ - db/migrations/20221208_add_index_to_pact_version_provider_tag_successful_verifications.rb
592
+ - db/migrations/20221215_add_prov_ver_id_ndx_to_latest_verifi_id_for_pact_ver_and_prov_ver.rb
593
+ - db/migrations/20230131_add_cons_ver_id_ndx_to_latest_pp_id_for_cons_ver.rb
590
594
  - db/migrations/migration_helper.rb
591
595
  - docs/CONFIGURATION.md
592
596
  - docs/api/PACTICIPANTS.md
597
+ - docs/api/PAGINATION.md
593
598
  - docs/api/WEBHOOKS.md
594
599
  - lib/pact/doc/README.md
595
600
  - lib/pact/doc/doc_file.rb
@@ -620,6 +625,7 @@ files:
620
625
  - lib/pact_broker/api/contracts/publish_contracts_schema.rb
621
626
  - lib/pact_broker/api/contracts/put_pact_params_contract.rb
622
627
  - lib/pact_broker/api/contracts/request_validations.rb
628
+ - lib/pact_broker/api/contracts/utf_8_validation.rb
623
629
  - lib/pact_broker/api/contracts/verification_contract.rb
624
630
  - lib/pact_broker/api/contracts/webhook_contract.rb
625
631
  - lib/pact_broker/api/decorators.rb
@@ -627,6 +633,7 @@ files:
627
633
  - lib/pact_broker/api/decorators/basic_pacticipant_decorator.rb
628
634
  - lib/pact_broker/api/decorators/branch_version_decorator.rb
629
635
  - lib/pact_broker/api/decorators/configuration.rb
636
+ - lib/pact_broker/api/decorators/custom_error_problem_json_decorator.rb
630
637
  - lib/pact_broker/api/decorators/dashboard_decorator.rb
631
638
  - lib/pact_broker/api/decorators/dashboard_text_decorator.rb
632
639
  - lib/pact_broker/api/decorators/decorator_context.rb
@@ -670,11 +677,13 @@ files:
670
677
  - lib/pact_broker/api/decorators/released_version_decorator.rb
671
678
  - lib/pact_broker/api/decorators/released_versions_decorator.rb
672
679
  - lib/pact_broker/api/decorators/representable_pact.rb
680
+ - lib/pact_broker/api/decorators/runtime_error_problem_json_decorator.rb
673
681
  - lib/pact_broker/api/decorators/tag_decorator.rb
674
682
  - lib/pact_broker/api/decorators/tagged_pact_versions_decorator.rb
675
683
  - lib/pact_broker/api/decorators/timestamps.rb
676
684
  - lib/pact_broker/api/decorators/triggered_webhook_decorator.rb
677
685
  - lib/pact_broker/api/decorators/triggered_webhooks_decorator.rb
686
+ - lib/pact_broker/api/decorators/validation_errors_problem_json_decorator.rb
678
687
  - lib/pact_broker/api/decorators/verifiable_pact_decorator.rb
679
688
  - lib/pact_broker/api/decorators/verifiable_pacts_decorator.rb
680
689
  - lib/pact_broker/api/decorators/verification_decorator.rb
@@ -714,7 +723,8 @@ files:
714
723
  - lib/pact_broker/api/resources/environment.rb
715
724
  - lib/pact_broker/api/resources/environments.rb
716
725
  - lib/pact_broker/api/resources/error_handler.rb
717
- - lib/pact_broker/api/resources/error_response_body_generator.rb
726
+ - lib/pact_broker/api/resources/error_handling_methods.rb
727
+ - lib/pact_broker/api/resources/error_response_generator.rb
718
728
  - lib/pact_broker/api/resources/error_test.rb
719
729
  - lib/pact_broker/api/resources/group.rb
720
730
  - lib/pact_broker/api/resources/index.rb
@@ -976,6 +986,7 @@ files:
976
986
  - lib/pact_broker/relationships/groupify.rb
977
987
  - lib/pact_broker/repositories.rb
978
988
  - lib/pact_broker/repositories/helpers.rb
989
+ - lib/pact_broker/repositories/page.rb
979
990
  - lib/pact_broker/repositories/scopes.rb
980
991
  - lib/pact_broker/services.rb
981
992
  - lib/pact_broker/string_refinements.rb
@@ -1082,7 +1093,6 @@ files:
1082
1093
  - lib/rack/pact_broker/add_vary_header.rb
1083
1094
  - lib/rack/pact_broker/cascade.rb
1084
1095
  - lib/rack/pact_broker/configurable_make_it_later.rb
1085
- - lib/rack/pact_broker/convert_404_to_hal.rb
1086
1096
  - lib/rack/pact_broker/convert_file_extension_to_accept_header.rb
1087
1097
  - lib/rack/pact_broker/database_transaction.rb
1088
1098
  - lib/rack/pact_broker/invalid_uri_protection.rb
@@ -1097,7 +1107,9 @@ files:
1097
1107
  - lib/sequel/extensions/statement_timeout.rb
1098
1108
  - lib/sequel/plugins/insert_ignore.rb
1099
1109
  - lib/sequel/plugins/upsert.rb
1110
+ - lib/webmachine/application_monkey_patch.rb
1100
1111
  - lib/webmachine/describe_routes.rb
1112
+ - lib/webmachine/render_error_monkey_patch.rb
1101
1113
  - pact_broker.gemspec
1102
1114
  - public/Network Graph_files/d3.v3.js
1103
1115
  - public/Network Graph_files/ga.js
@@ -1227,7 +1239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1227
1239
  - !ruby/object:Gem::Version
1228
1240
  version: '0'
1229
1241
  requirements: []
1230
- rubygems_version: 3.3.22
1242
+ rubygems_version: 3.4.6
1231
1243
  signing_key:
1232
1244
  specification_version: 4
1233
1245
  summary: See description
@@ -1,41 +0,0 @@
1
- require "pact_broker/configuration"
2
-
3
- module PactBroker
4
- module Api
5
- module Resources
6
- class ErrorResponseBodyGenerator
7
- include PactBroker::Logging
8
-
9
- # env not needed, just passing in in case PF ever needs it
10
- def self.call error, error_reference, _env = {}
11
- response_body_hash(error, error_reference).to_json
12
- end
13
-
14
- def self.display_message(error, obfuscated_message)
15
- if PactBroker.configuration.show_backtrace_in_error_response?
16
- error.message || obfuscated_message
17
- else
18
- PactBroker::Errors.reportable_error?(error) ? obfuscated_message : error.message
19
- end
20
- end
21
-
22
- def self.obfuscated_error_message(error_reference)
23
- "An error has occurred. The details have been logged with the reference #{error_reference}"
24
- end
25
-
26
- def self.response_body_hash(error, error_reference)
27
- response_body = {
28
- error: {
29
- message: display_message(error, obfuscated_error_message(error_reference)),
30
- reference: error_reference
31
- }
32
- }
33
- if PactBroker.configuration.show_backtrace_in_error_response?
34
- response_body[:error][:backtrace] = error.backtrace
35
- end
36
- response_body
37
- end
38
- end
39
- end
40
- end
41
- end
@@ -1,20 +0,0 @@
1
- module Rack
2
- module PactBroker
3
- class Convert404ToHal
4
-
5
- def initialize app
6
- @app = app
7
- end
8
-
9
- def call env
10
- response = @app.call(env)
11
-
12
- if response.first == 404 && response[1]["Content-Type"] == "text/html" && !(env["HTTP_ACCEPT"] =~ /html|javascript|css/)
13
- [404, { "Content-Type" => "application/hal+json;charset=utf-8"},[]]
14
- else
15
- response
16
- end
17
- end
18
- end
19
- end
20
- end