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
@@ -15,20 +15,26 @@ module PactBroker
15
15
  property :execution_date, as: :verificationDate
16
16
  property :build_url, as: :buildUrl
17
17
  property :test_results, as: :testResults
18
+ nested :verifiedBy do
19
+ property :verified_by_implementation, as: :implementation
20
+ property :verified_by_version, as: :version
21
+ end
18
22
 
19
23
  link :self do | options |
24
+ pact = options[:pact] || represented.latest_pact_publication
20
25
  {
21
26
  title: "Verification result",
22
- name: "Verification result #{represented.number} for #{represented.latest_pact_publication.name}",
27
+ name: "Verification result #{represented.number} for #{pact.name}",
23
28
  href: verification_url(represented, options.fetch(:base_url), )
24
29
  }
25
30
  end
26
31
 
27
32
  link "pb:pact-version" do | options |
33
+ pact = options[:pact] || represented.latest_pact_publication
28
34
  {
29
35
  title: "Pact",
30
- name: represented.latest_pact_publication.name,
31
- href: pact_url(options.fetch(:base_url), represented.latest_pact_publication)
36
+ name: pact.name,
37
+ href: pact_version_with_consumer_version_metadata_url(pact, options.fetch(:base_url))
32
38
  }
33
39
  end
34
40
 
@@ -1,4 +1,5 @@
1
1
  require_relative "base_decorator"
2
+ require "pact_broker/domain/webhook_pacticipant"
2
3
  require "pact_broker/api/decorators/webhook_request_template_decorator"
3
4
  require "pact_broker/api/decorators/timestamps"
4
5
  require "pact_broker/webhooks/webhook_request_template"
@@ -19,12 +20,14 @@ module PactBroker
19
20
 
20
21
  property :description, getter: lambda { |context| context[:represented].display_description }
21
22
 
22
- property :consumer, :class => PactBroker::Domain::Pacticipant, default: nil do
23
+ property :consumer, class: Domain::WebhookPacticipant, default: nil do
23
24
  property :name
25
+ property :label
24
26
  end
25
27
 
26
- property :provider, :class => PactBroker::Domain::Pacticipant, default: nil do
28
+ property :provider, class: Domain::WebhookPacticipant, default: nil do
27
29
  property :name
30
+ property :label
28
31
  end
29
32
 
30
33
  property :enabled, default: true
@@ -50,7 +53,7 @@ module PactBroker
50
53
  end
51
54
 
52
55
  link :'pb:consumer' do | options |
53
- if represented.consumer
56
+ if represented.consumer&.name
54
57
  {
55
58
  title: "Consumer",
56
59
  name: represented.consumer.name,
@@ -59,8 +62,18 @@ module PactBroker
59
62
  end
60
63
  end
61
64
 
65
+ link :'pb:consumers' do | options |
66
+ if represented.consumer&.label
67
+ {
68
+ title: "Consumers by label",
69
+ name: represented.consumer.label,
70
+ href: pacticipants_with_label_url(options.fetch(:base_url), represented.consumer.label)
71
+ }
72
+ end
73
+ end
74
+
62
75
  link :'pb:provider' do | options |
63
- if represented.provider
76
+ if represented.provider&.name
64
77
  {
65
78
  title: "Provider",
66
79
  name: represented.provider.name,
@@ -69,6 +82,16 @@ module PactBroker
69
82
  end
70
83
  end
71
84
 
85
+ link :'pb:providers' do | options |
86
+ if represented.provider&.label
87
+ {
88
+ title: "Providers by label",
89
+ name: represented.provider.label,
90
+ href: pacticipants_with_label_url(options.fetch(:base_url), represented.provider.label)
91
+ }
92
+ end
93
+ end
94
+
72
95
  link :'pb:pact-webhooks' do | options |
73
96
  if represented.consumer && represented.provider
74
97
  {
@@ -22,6 +22,10 @@ module PactBroker
22
22
  "#{pacticipants_url(base_url)}/#{url_encode(pacticipant.name)}"
23
23
  end
24
24
 
25
+ def pacticipants_with_label_url base_url, label_name
26
+ "#{pacticipants_url(base_url)}/label/#{url_encode(label_name)}"
27
+ end
28
+
25
29
  def pacticipant_url_from_params params, base_url = ""
26
30
  [
27
31
  base_url,
@@ -60,6 +64,10 @@ module PactBroker
60
64
  "#{pactigration_base_url(base_url, pact)}/pact-version/#{pact.pact_version_sha}"
61
65
  end
62
66
 
67
+ def pact_version_with_consumer_version_metadata_url pact, base_url = ""
68
+ "#{pactigration_base_url(base_url, pact)}/pact-version/#{pact.pact_version_sha}/metadata/#{encode_metadata(build_metadata_for_consumer_version_number(pact.consumer_version_number))}"
69
+ end
70
+
63
71
  def pact_version_url_with_metadata pact, metadata, base_url = ""
64
72
  if metadata && metadata.any?
65
73
  "#{pact_version_url(pact, base_url)}/metadata/#{encode_metadata(metadata)}"
@@ -162,12 +170,28 @@ module PactBroker
162
170
  end
163
171
 
164
172
  def verification_url_from_params params, base_url = ""
165
- [ base_url, "pacts",
166
- "provider", url_encode(params.fetch(:provider_name)),
167
- "consumer", url_encode(params.fetch(:consumer_name)),
168
- "pact-version", params.fetch(:pact_version_sha),
169
- "verification-results", params.fetch(:verification_number)
170
- ].join("/")
173
+ if params[:consumer_version_number]
174
+ metadata = encode_metadata(build_metadata_for_consumer_version_number(params[:consumer_version_number]))
175
+
176
+ [
177
+ base_url,
178
+ "pacts",
179
+ "provider", url_encode(params.fetch(:provider_name)),
180
+ "consumer", url_encode(params.fetch(:consumer_name)),
181
+ "pact-version", params.fetch(:pact_version_sha),
182
+ "metadata", metadata,
183
+ "verification-results", params.fetch(:verification_number)
184
+ ].join("/")
185
+ else
186
+ [
187
+ base_url,
188
+ "pacts",
189
+ "provider", url_encode(params.fetch(:provider_name)),
190
+ "consumer", url_encode(params.fetch(:consumer_name)),
191
+ "pact-version", params.fetch(:pact_version_sha),
192
+ "verification-results", params.fetch(:verification_number)
193
+ ].join("/")
194
+ end
171
195
  end
172
196
 
173
197
  def latest_verifications_for_consumer_version_url version, base_url
@@ -70,11 +70,11 @@ module PactBroker
70
70
  end
71
71
 
72
72
  def consumer
73
- webhook.consumer ? pacticipant_service.find_pacticipant_by_name(webhook.consumer.name) : nil
73
+ webhook.consumer&.name ? pacticipant_service.find_pacticipant_by_name(webhook.consumer.name) : nil
74
74
  end
75
75
 
76
76
  def provider
77
- webhook.provider ? pacticipant_service.find_pacticipant_by_name(webhook.provider.name) : nil
77
+ webhook.provider&.name ? pacticipant_service.find_pacticipant_by_name(webhook.provider.name) : nil
78
78
  end
79
79
 
80
80
  def webhooks
@@ -134,7 +134,7 @@ module PactBroker
134
134
  end
135
135
 
136
136
  def pact_params
137
- @pact_params ||= PactBroker::Pacts::PactParams.from_request request, path_info
137
+ @pact_params ||= PactBroker::Pacts::PactParams.from_request request, identifier_from_path
138
138
  end
139
139
 
140
140
  def set_json_error_message message
@@ -254,6 +254,10 @@ module PactBroker
254
254
  application_context.decorator_configuration.class_for(name)
255
255
  end
256
256
 
257
+ def api_contract_class(name)
258
+ application_context.api_contract_configuration.class_for(name)
259
+ end
260
+
257
261
  def schema
258
262
  nil
259
263
  end
@@ -31,7 +31,7 @@ module PactBroker
31
31
 
32
32
  def from_json
33
33
  if environment
34
- @environment = update_environment
34
+ @environment = replace_environment
35
35
  response.body = to_json
36
36
  else
37
37
  response.code = 404
@@ -63,12 +63,12 @@ module PactBroker
63
63
  identifier_from_path[:environment_uuid]
64
64
  end
65
65
 
66
- def update_environment
67
- environment_service.update(uuid, parsed_environment)
66
+ def replace_environment
67
+ environment_service.replace(uuid, parsed_environment)
68
68
  end
69
69
 
70
70
  def schema
71
- PactBroker::Api::Contracts::EnvironmentSchema
71
+ api_contract_class(:environment_schema)
72
72
  end
73
73
  end
74
74
  end
@@ -71,7 +71,7 @@ module PactBroker
71
71
  end
72
72
 
73
73
  def schema
74
- PactBroker::Api::Contracts::EnvironmentSchema
74
+ api_contract_class(:environment_schema)
75
75
  end
76
76
  end
77
77
  end
@@ -136,7 +136,13 @@ module PactBroker
136
136
  "pb:can-i-deploy-pacticipant-version-to-tag" =>
137
137
  {
138
138
  href: base_url + "/can-i-deploy?pacticipant={pacticipant}&version={version}&to={tag}",
139
- title: "Determine if an application can be safely deployed to an environment identified by the given tag",
139
+ title: "Determine if an application version can be safely deployed to an environment identified by the given tag",
140
+ templated: true
141
+ },
142
+ "pb:can-i-deploy-pacticipant-version-to-environment" =>
143
+ {
144
+ href: base_url + "/can-i-deploy?pacticipant={pacticipant}&version={version}&environment={environment}",
145
+ title: "Determine if an application version can be safely deployed to an environment",
140
146
  templated: true
141
147
  },
142
148
  "pb:provider-pacts-for-verification" => {
@@ -8,16 +8,46 @@ module PactBroker
8
8
  using PactBroker::HashRefinements
9
9
 
10
10
  def pact_params
11
- @pact_params ||= PactBroker::Pacts::PactParams.from_request(request, maybe_params_with_consumer_version_number.merge(path_info))
11
+ @pact_params ||= PactBroker::Pacts::PactParams.from_request(request, maybe_consumer_version_number_param.merge(identifier_from_path))
12
12
  end
13
13
 
14
- def maybe_params_with_consumer_version_number
15
- metadata.slice(:consumer_version_number)
14
+ def maybe_consumer_version_number_param
15
+ if metadata[:consumer_version_number]
16
+ metadata.slice(:consumer_version_number)
17
+ elsif metadata_consumer_version_numbers&.any?
18
+ {
19
+ consumer_version_number: consumer_versions_from_metadata.last&.number
20
+ }
21
+ else
22
+ {}
23
+ end
16
24
  end
17
25
 
18
26
  def metadata
19
27
  @metadata ||= PactBroker::Pacts::Metadata.parse_metadata(PactBrokerUrls.decode_pact_metadata(identifier_from_path[:metadata]))
20
28
  end
29
+
30
+ def metadata_consumer_version_numbers
31
+ @metadata_consumer_version_numbers ||= begin
32
+ if metadata[:consumer_version_selectors].is_a?(Array)
33
+ metadata[:consumer_version_selectors].collect{ | selector | selector[:consumer_version_number] }.compact.uniq
34
+ elsif metadata[:consumer_version_number]
35
+ [metadata[:consumer_version_number]]
36
+ else
37
+ nil
38
+ end
39
+ end
40
+ end
41
+
42
+ def consumer_versions_from_metadata
43
+ @consumer_versions_from_metadata ||= begin
44
+ if metadata_consumer_version_numbers
45
+ metadata_consumer_version_numbers.collect do | consumer_version_number |
46
+ version_service.find_by_pacticipant_name_and_number(pacticipant_name: identifier_from_path[:consumer_name], pacticipant_version_number: consumer_version_number)
47
+ end.compact.sort_by(&:order)
48
+ end
49
+ end
50
+ end
21
51
  end
22
52
  end
23
53
  end
@@ -10,6 +10,10 @@ module PactBroker
10
10
  def allowed_methods
11
11
  ["GET", "OPTIONS"]
12
12
  end
13
+
14
+ def decorator_options(options)
15
+ super(options.merge(consumer_versions: consumer_versions_from_metadata&.reverse))
16
+ end
13
17
  end
14
18
  end
15
19
  end
@@ -29,7 +29,7 @@ module PactBroker
29
29
  end
30
30
 
31
31
  def pact_params
32
- @pact_params ||= PactBroker::Pacts::PactParams.from_request request, path_info
32
+ @pact_params ||= PactBroker::Pacts::PactParams.from_request request, identifier_from_path
33
33
  end
34
34
 
35
35
  def policy_name
@@ -31,7 +31,7 @@ module PactBroker
31
31
  end
32
32
 
33
33
  def process_post
34
- handle_webhook_events do
34
+ handle_webhook_events(consumer_version_branch: parsed_contracts.branch, build_url: parsed_contracts.build_url) do
35
35
  results = contract_service.publish(parsed_contracts, base_url: base_url)
36
36
  response.body = decorator_class(:publish_contracts_results_decorator).new(results).to_json(decorator_options)
37
37
  end
@@ -4,11 +4,14 @@ require "pact_broker/domain/verification"
4
4
  require "pact_broker/api/contracts/verification_contract"
5
5
  require "pact_broker/api/decorators/verification_decorator"
6
6
  require "pact_broker/api/decorators/extended_verification_decorator"
7
+ require "pact_broker/api/resources/metadata_resource_methods"
7
8
 
8
9
  module PactBroker
9
10
  module Api
10
11
  module Resources
11
12
  class Verification < BaseResource
13
+ include MetadataResourceMethods
14
+
12
15
  def content_types_provided
13
16
  [
14
17
  ["application/hal+json", :to_json],
@@ -35,11 +38,11 @@ module PactBroker
35
38
  end
36
39
 
37
40
  def to_json
38
- decorator_for(verification).to_json(decorator_options)
41
+ decorator_for(verification).to_json(decorator_options(pact: pact))
39
42
  end
40
43
 
41
44
  def to_extended_json
42
- extended_decorator_for(verification).to_json(decorator_options)
45
+ extended_decorator_for(verification).to_json(decorator_options(pact: pact))
43
46
  end
44
47
 
45
48
  def delete_resource
@@ -37,10 +37,14 @@ module PactBroker
37
37
  end
38
38
 
39
39
  def malformed_request?
40
- if uuid
41
- false
40
+ if request.post?
41
+ if uuid
42
+ false
43
+ else
44
+ webhook_validation_errors?(webhook)
45
+ end
42
46
  else
43
- webhook_validation_errors?(webhook)
47
+ super
44
48
  end
45
49
  end
46
50
 
@@ -5,29 +5,15 @@ module PactBroker
5
5
  module Api
6
6
  module Resources
7
7
  module WebhookExecutionMethods
8
- def webhook_execution_configuration
9
- application_context.webhook_execution_configuration_creator.call(self)
10
- end
11
-
12
- def webhook_options
13
- {
14
- database_connector: database_connector,
15
- webhook_execution_configuration: webhook_execution_configuration
16
- }
17
- end
18
-
19
- def webhook_event_listener
20
- @webhook_event_listener ||= PactBroker::Webhooks::EventListener.new(webhook_options)
21
- end
22
-
23
- def handle_webhook_events
8
+ def handle_webhook_events(event_context = {})
9
+ @webhook_event_listener = PactBroker::Webhooks::EventListener.new(webhook_options(event_context))
24
10
  PactBroker::Events.subscribe(webhook_event_listener) do
25
11
  yield
26
12
  end
27
13
  end
28
14
 
29
15
  def schedule_triggered_webhooks
30
- webhook_event_listener.schedule_triggered_webhooks
16
+ webhook_event_listener&.schedule_triggered_webhooks
31
17
  end
32
18
 
33
19
  def finish_request
@@ -36,6 +22,26 @@ module PactBroker
36
22
  end
37
23
  super
38
24
  end
25
+
26
+
27
+ def webhook_options(event_context = {})
28
+ {
29
+ database_connector: database_connector,
30
+ webhook_execution_configuration: webhook_execution_configuration.with_webhook_context(event_context)
31
+ }
32
+ end
33
+ private :webhook_options
34
+
35
+ def webhook_execution_configuration
36
+ application_context.webhook_execution_configuration_creator.call(self)
37
+ end
38
+ private :webhook_execution_configuration
39
+
40
+ def webhook_event_listener
41
+ @webhook_event_listener
42
+ end
43
+
44
+ private :webhook_event_listener
39
45
  end
40
46
  end
41
47
  end
@@ -49,6 +49,7 @@ module PactBroker
49
49
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "version", :consumer_version_number, "verification-results", "latest"], Api::Resources::LatestVerificationForPact, {resource_name: "latest_verification_results_for_pact_publication"}
50
50
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "pact-version", :pact_version_sha, "verification-results", "latest"], Api::Resources::LatestVerificationForPact, {resource_name: "latest_verification_results_for_pact_version"}
51
51
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "pact-version", :pact_version_sha, "verification-results", :verification_number], Api::Resources::Verification, {resource_name: "verification_result"}
52
+ add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "pact-version", :pact_version_sha, "metadata", :metadata, "verification-results", :verification_number], Api::Resources::Verification, {resource_name: "verification_result"}
52
53
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "pact-version", :pact_version_sha, "verification-results", :verification_number, "triggered-webhooks"], Api::Resources::VerificationTriggeredWebhooks, {resource_name: "verification_result_triggered_webhooks"}
53
54
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "latest", "verification-results","latest"], Api::Resources::LatestVerificationForLatestPact, {resource_name: "latest_verification_results_for_latest_pact_publication"}
54
55
  add ["pacts", "provider", :provider_name, "consumer", :consumer_name, "latest", :tag, "verification-results","latest"], Api::Resources::LatestVerificationForLatestPact, {resource_name: "latest_verification_results_for_latest_tagged_pact_publication"}
@@ -151,5 +152,10 @@ module PactBroker
151
152
  API ||= begin
152
153
  build_api
153
154
  end
155
+
156
+ def self.routes
157
+ require "webmachine/describe_routes"
158
+ @routes ||= Webmachine::DescribeRoutes.call([API.application])
159
+ end
154
160
  # rubocop: enable Metrics/MethodLength
155
161
  end
@@ -1,4 +1,5 @@
1
1
  require "pact_broker/api/decorators/configuration"
2
+ require "pact_broker/api/contracts/configuration"
2
3
  require "pact_broker/api/decorators/decorator_context_creator"
3
4
  require "pact_broker/webhooks/execution_configuration_creator"
4
5
  require "pact_broker/errors/error_logger"
@@ -7,6 +8,7 @@ require "pact_broker/api/resources/error_response_body_generator"
7
8
  module PactBroker
8
9
  class ApplicationContext
9
10
  attr_reader :decorator_configuration,
11
+ :api_contract_configuration,
10
12
  :decorator_context_creator,
11
13
  :webhook_execution_configuration_creator,
12
14
  :resource_authorizer,
@@ -18,6 +20,7 @@ module PactBroker
18
20
  def initialize(params = {})
19
21
  params_with_defaults = {
20
22
  decorator_configuration: PactBroker::Api::Decorators::Configuration.default_configuration,
23
+ api_contract_configuration: PactBroker::Api::Contracts::Configuration.default_configuration,
21
24
  decorator_context_creator: PactBroker::Api::Decorators::DecoratorContextCreator,
22
25
  webhook_execution_configuration_creator: PactBroker::Webhooks::ExecutionConfigurationCreator,
23
26
  error_logger: PactBroker::Errors::ErrorLogger,
@@ -25,6 +28,7 @@ module PactBroker
25
28
  }.merge(params)
26
29
 
27
30
  @decorator_configuration = params_with_defaults[:decorator_configuration]
31
+ @api_contract_configuration = params_with_defaults[:api_contract_configuration]
28
32
  @decorator_context_creator = params_with_defaults[:decorator_context_creator]
29
33
  @webhook_execution_configuration_creator = params_with_defaults[:webhook_execution_configuration_creator]
30
34
  @resource_authorizer = params_with_defaults[:resource_authorizer]
@@ -32,6 +36,7 @@ module PactBroker
32
36
  @after_resource = params_with_defaults[:after_resource]
33
37
  @error_logger = params_with_defaults[:error_logger]
34
38
  @error_response_body_generator = params_with_defaults[:error_response_body_generator]
39
+
35
40
  end
36
41
 
37
42
  def self.default_application_context(overrides = {})
@@ -166,6 +166,10 @@ module PactBroker
166
166
  super(value_to_string_array(webhook_host_whitelist, "webhook_host_whitelist"))
167
167
  end
168
168
 
169
+ def main_branch_candidates= main_branch_candidates
170
+ super(value_to_string_array(main_branch_candidates, "main_branch_candidates"))
171
+ end
172
+
169
173
  def features= features
170
174
  super(value_to_string_array(features, "features").collect(&:downcase))
171
175
  end
@@ -27,7 +27,7 @@ module PactBroker
27
27
  validate_database_connection_config: true,
28
28
  database_statement_timeout: 15,
29
29
  metrics_sql_statement_timeout: 30,
30
- database_connection_validation_timeout: -1
30
+ database_connection_validation_timeout: nil
31
31
  )
32
32
 
33
33
  def database_configuration
@@ -1,6 +1,5 @@
1
1
  require "sequel"
2
2
  require "pact_broker/project_root"
3
- require "pact_broker/pacts/latest_tagged_pact_publications"
4
3
  require "pact_broker/logging"
5
4
  require "pact_broker/db/clean/selector"
6
5
 
@@ -50,7 +49,7 @@ module PactBroker
50
49
 
51
50
  def latest_tagged_pact_publications_ids_to_keep
52
51
  @latest_tagged_pact_publications_ids_to_keep ||= resolve_ids(keep.select(&:tag).select(&:latest).collect do | selector |
53
- PactBroker::Pacts::LatestTaggedPactPublications.select(:id).for_selector(selector)
52
+ PactBroker::Pacts::PactPublication.select(:id).latest_by_consumer_tag_for_clean_selector(selector)
54
53
  end.reduce(&:union) || [])
55
54
  end
56
55
 
@@ -51,13 +51,17 @@ module PactBroker
51
51
  end
52
52
 
53
53
  def delete_webhook_data
54
- ids_to_keep = db[:latest_triggered_webhooks].select(:id)
55
- resolved_ids_to_delete = db[:triggered_webhooks]
56
- .where(id: ids_to_keep)
57
- .invert
58
- .where(Sequel.lit("created_at < ?", cut_off_date))
59
- .limit(limit)
60
- .collect{ |row| row[:id] }
54
+ ltw_join = {
55
+ Sequel[:triggered_webhooks][:id] => Sequel[:ltw][:id]
56
+ }
57
+ resolved_ids_to_delete = db[:triggered_webhooks]
58
+ .select(Sequel[:triggered_webhooks][:id])
59
+ .left_join(:latest_triggered_webhooks, ltw_join, { table_alias: :ltw })
60
+ .where(Sequel[:ltw][:id] => nil)
61
+ .where(Sequel.lit("triggered_webhooks.created_at < ?", cut_off_date))
62
+ .order(Sequel[:triggered_webhooks][:id])
63
+ .limit(limit)
64
+ .collect{ |row| row[:id] }
61
65
 
62
66
  PactBroker::Webhooks::TriggeredWebhook.where(id: resolved_ids_to_delete).delete unless dry_run?
63
67
  { triggered_webhooks: resolved_ids_to_delete.count }
@@ -65,36 +69,50 @@ module PactBroker
65
69
 
66
70
  def delete_orphan_pact_versions
67
71
  referenced_pact_version_ids = db[:pact_publications].select(:pact_version_id).union(db[:verifications].select(:pact_version_id))
68
- pact_version_ids_to_delete = db[:pact_versions].where(id: referenced_pact_version_ids).invert.order(:id).limit(limit).collect{ |row| row[:id] }
72
+ rpv_join = {
73
+ Sequel[:pact_versions][:id] => Sequel[:rpv][:pact_version_id]
74
+ }
75
+ pact_version_ids_to_delete = db[:pact_versions]
76
+ .select(Sequel[:pact_versions][:id])
77
+ .left_join(referenced_pact_version_ids, rpv_join, { table_alias: :rpv })
78
+ .where(Sequel[:rpv][:pact_version_id] => nil)
79
+ .order(Sequel[:pact_versions][:id])
80
+ .limit(limit)
81
+ .collect{ |row| row[:id] }
69
82
  db[:pact_versions].where(id: pact_version_ids_to_delete).delete unless dry_run?
70
83
  { pact_versions: pact_version_ids_to_delete.count }
71
84
  end
72
85
 
73
86
  def delete_overwritten_pact_publications
74
- ids_to_keep = db[:latest_pact_publication_ids_for_consumer_versions].select(:pact_publication_id)
87
+ lp_join = {
88
+ Sequel[:pact_publications][:id] => Sequel[:lp][:pact_publication_id]
89
+ }
75
90
 
76
91
  resolved_ids_to_delete = db[:pact_publications]
77
- .where(id: ids_to_keep)
78
- .invert
79
- .where(Sequel.lit("created_at < ?", cut_off_date))
80
- .order(:id)
81
- .limit(limit)
82
- .collect{ |row| row[:id] }
92
+ .select(Sequel[:pact_publications][:id])
93
+ .left_join(:latest_pact_publication_ids_for_consumer_versions, lp_join, { table_alias: :lp })
94
+ .where(Sequel[:lp][:pact_publication_id] => nil)
95
+ .where(Sequel.lit("pact_publications.created_at < ?", cut_off_date))
96
+ .order(:id)
97
+ .limit(limit)
98
+ .collect{ |row| row[:id] }
83
99
 
84
100
  PactBroker::Pacts::PactPublication.where(id: resolved_ids_to_delete).delete unless dry_run?
85
-
86
101
  { pact_publications: resolved_ids_to_delete.count }
87
102
  end
88
103
 
89
104
  def delete_overwritten_verifications
90
- ids_to_keep = db[:latest_verification_id_for_pact_version_and_provider_version].select(:verification_id)
105
+ lv_join = {
106
+ Sequel[:verifications][:id] => Sequel[:lv][:verification_id]
107
+ }
91
108
  resolved_ids_to_delete = db[:verifications]
92
- .where(id: ids_to_keep)
93
- .invert
94
- .where(Sequel.lit("created_at < ?", cut_off_date))
95
- .order(:id)
96
- .limit(limit)
97
- .collect{ |row| row[:id] }
109
+ .select(Sequel[:verifications][:id])
110
+ .left_join(:latest_verification_id_for_pact_version_and_provider_version, lv_join, { table_alias: :lv})
111
+ .where(Sequel[:lv][:verification_id] => nil)
112
+ .where(Sequel.lit("verifications.created_at < ?", cut_off_date))
113
+ .order(Sequel[:verifications][:id])
114
+ .limit(limit)
115
+ .collect{ |row| row[:id] }
98
116
 
99
117
  PactBroker::Domain::Verification.where(id: resolved_ids_to_delete).delete unless dry_run?
100
118
  { verification_results: resolved_ids_to_delete.count }
@@ -117,6 +117,7 @@ end
117
117
  # undeployed_at | timestamp without time zone |
118
118
  # target | text |
119
119
  # target_for_index | text | NOT NULL DEFAULT ''::text
120
+ # auto_created | boolean | DEFAULT false
120
121
  # Indexes:
121
122
  # deployed_versions_pkey | PRIMARY KEY btree (id)
122
123
  # deployed_versions_uuid_index | UNIQUE btree (uuid)
@@ -65,6 +65,7 @@ module PactBroker
65
65
  .where(pacticipant_id: pacticipant.id)
66
66
  .eager(:version)
67
67
  .eager(:environment)
68
+ .order(:created_at, :id)
68
69
  .all
69
70
  end
70
71