pact_broker 2.107.1 → 2.109.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +68 -0
- data/Gemfile +5 -6
- data/README.md +1 -0
- data/db/migrations/20230615_add_integrations_contract_data_updated_at.rb +13 -0
- data/db/migrations/20230616_set_integrations_contract_data_updated_at.rb +11 -0
- data/db/migrations/20231002_add_version_id_index_to_released_version.rb +21 -0
- data/db/migrations/20231003_add_version_id_index_to_deployed_version.rb +21 -0
- data/docs/CONFIGURATION.md +10 -0
- data/lib/pact_broker/api/contracts/base_contract.rb +2 -1
- data/lib/pact_broker/api/contracts/dry_validation_errors_formatter.rb +2 -0
- data/lib/pact_broker/api/contracts/pagination_query_params_schema.rb +19 -0
- data/lib/pact_broker/api/contracts/publish_contracts_contract_contract.rb +29 -18
- data/lib/pact_broker/api/decorators/base_decorator.rb +40 -1
- data/lib/pact_broker/api/decorators/branch_decorator.rb +35 -0
- data/lib/pact_broker/api/decorators/branch_version_decorator.rb +16 -0
- data/lib/pact_broker/api/decorators/configuration.rb +19 -0
- data/lib/pact_broker/api/decorators/custom_error_problem_json_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/decorator_context_creator.rb +47 -2
- data/lib/pact_broker/api/decorators/deployed_version_decorator.rb +2 -1
- data/lib/pact_broker/api/decorators/deployed_versions_decorator.rb +2 -2
- data/lib/pact_broker/api/decorators/dry_validation_errors_decorator.rb +32 -0
- data/lib/pact_broker/api/decorators/dry_validation_errors_problem_json_decorator.rb +24 -0
- data/lib/pact_broker/api/decorators/embedded_branch_version_decorator.rb +2 -2
- data/lib/pact_broker/api/decorators/embedded_deployed_version_decorator.rb +30 -0
- data/lib/pact_broker/api/decorators/embedded_error_problem_json_decorator.rb +84 -0
- data/lib/pact_broker/api/decorators/embedded_released_version_decorator.rb +27 -0
- data/lib/pact_broker/api/decorators/embedded_version_decorator.rb +0 -3
- data/lib/pact_broker/api/decorators/error_decorator.rb +30 -0
- data/lib/pact_broker/api/decorators/extended_pact_decorator.rb +6 -1
- data/lib/pact_broker/api/decorators/integration_decorator.rb +3 -2
- data/lib/pact_broker/api/decorators/integrations_decorator.rb +3 -0
- data/lib/pact_broker/api/decorators/notices_decorator.rb +11 -0
- data/lib/pact_broker/api/decorators/pact_pacticipant_decorator.rb +1 -5
- data/lib/pact_broker/api/decorators/pact_versions_decorator.rb +0 -1
- data/lib/pact_broker/api/decorators/pact_webhooks_status_decorator.rb +0 -1
- data/lib/pact_broker/api/decorators/pacticipant_branches_decorator.rb +32 -0
- data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +11 -1
- data/lib/pact_broker/api/decorators/{pacticipant_collection_decorator.rb → pacticipants_decorator.rb} +8 -4
- data/lib/pact_broker/api/decorators/pagination_links.rb +2 -2
- data/lib/pact_broker/api/decorators/publish_contract_decorator.rb +6 -1
- data/lib/pact_broker/api/decorators/released_versions_decorator.rb +2 -2
- data/lib/pact_broker/api/decorators/runtime_error_problem_json_decorator.rb +2 -2
- data/lib/pact_broker/api/decorators/validation_errors_decorator.rb +30 -0
- data/lib/pact_broker/api/decorators/validation_errors_problem_json_decorator.rb +4 -6
- data/lib/pact_broker/api/decorators/version_decorator.rb +5 -3
- data/lib/pact_broker/api/decorators/versions_decorator.rb +24 -14
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +2 -0
- data/lib/pact_broker/api/middleware/configuration.rb +2 -0
- data/lib/pact_broker/api/pact_broker_urls.rb +18 -2
- data/lib/pact_broker/api/resources/after_reply.rb +15 -0
- data/lib/pact_broker/api/resources/all_webhooks.rb +3 -3
- data/lib/pact_broker/api/resources/badge_methods.rb +2 -1
- data/lib/pact_broker/api/resources/base_resource.rb +6 -4
- data/lib/pact_broker/api/resources/branch.rb +40 -0
- data/lib/pact_broker/api/resources/branch_versions.rb +59 -0
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_branch_to_environment_badge.rb +1 -1
- data/lib/pact_broker/api/resources/currently_deployed_versions_for_environment.rb +1 -1
- data/lib/pact_broker/api/resources/currently_supported_versions_for_environment.rb +1 -1
- data/lib/pact_broker/api/resources/dashboard.rb +10 -0
- data/lib/pact_broker/api/resources/deployed_versions_for_version_and_environment.rb +1 -1
- data/lib/pact_broker/api/resources/environment.rb +4 -0
- data/lib/pact_broker/api/resources/environments.rb +1 -1
- data/lib/pact_broker/api/resources/error_handler.rb +18 -52
- data/lib/pact_broker/api/resources/error_handling_methods.rb +40 -14
- data/lib/pact_broker/api/resources/error_response_generator.rb +23 -6
- data/lib/pact_broker/api/resources/event_methods.rb +15 -0
- data/lib/pact_broker/api/resources/filter_methods.rb +15 -0
- data/lib/pact_broker/api/resources/group.rb +11 -2
- data/lib/pact_broker/api/resources/index.rb +6 -0
- data/lib/pact_broker/api/resources/integrations.rb +18 -4
- data/lib/pact_broker/api/resources/latest_version.rb +2 -0
- data/lib/pact_broker/api/resources/pact.rb +16 -7
- data/lib/pact_broker/api/resources/pacticipant_branches.rb +67 -0
- data/lib/pact_broker/api/resources/pacticipants.rb +26 -7
- data/lib/pact_broker/api/resources/pacticipants_for_label.rb +2 -2
- data/lib/pact_broker/api/resources/pagination_methods.rb +11 -1
- data/lib/pact_broker/api/resources/publish_contracts.rb +1 -1
- data/lib/pact_broker/api/resources/verifications.rb +9 -4
- data/lib/pact_broker/api/resources/versions.rb +12 -0
- data/lib/pact_broker/api.rb +5 -0
- data/lib/pact_broker/app.rb +10 -9
- data/lib/pact_broker/application_context.rb +29 -25
- data/lib/pact_broker/async/after_reply.rb +30 -0
- data/lib/pact_broker/config/runtime_configuration.rb +9 -21
- data/lib/pact_broker/config/runtime_configuration_coercion_methods.rb +32 -2
- data/lib/pact_broker/config/runtime_configuration_database_methods.rb +1 -1
- data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +15 -5
- data/lib/pact_broker/configuration.rb +29 -12
- data/lib/pact_broker/contracts/contract_to_publish.rb +4 -5
- data/lib/pact_broker/contracts/contracts_to_publish.rb +8 -0
- data/lib/pact_broker/contracts/service.rb +9 -3
- data/lib/pact_broker/dataset/page.rb +22 -0
- data/lib/pact_broker/dataset.rb +122 -0
- data/lib/pact_broker/db/data_migrations/set_contract_data_updated_at_for_integrations.rb +47 -0
- data/lib/pact_broker/db/migrate_data.rb +1 -0
- data/lib/pact_broker/db/models.rb +1 -1
- data/lib/pact_broker/deployments/currently_deployed_version_id.rb +2 -5
- data/lib/pact_broker/deployments/deployed_version.rb +3 -3
- data/lib/pact_broker/deployments/environment.rb +0 -2
- data/lib/pact_broker/deployments/released_version.rb +4 -5
- data/lib/pact_broker/doc/views/index/pacticipant-branch.markdown +25 -0
- data/lib/pact_broker/domain/label.rb +6 -3
- data/lib/pact_broker/domain/pact.rb +10 -5
- data/lib/pact_broker/domain/pacticipant.rb +4 -34
- data/lib/pact_broker/domain/tag.rb +4 -5
- data/lib/pact_broker/domain/verification.rb +2 -4
- data/lib/pact_broker/domain/version.rb +12 -19
- data/lib/pact_broker/errors/error_reporter.rb +30 -0
- data/lib/pact_broker/errors.rb +2 -15
- data/lib/pact_broker/events/subscriber.rb +12 -4
- data/lib/pact_broker/feature_toggle.rb +1 -1
- data/lib/pact_broker/groups/service.rb +38 -5
- data/lib/pact_broker/index/service.rb +1 -2
- data/lib/pact_broker/integrations/event_listener.rb +23 -0
- data/lib/pact_broker/integrations/integration.rb +24 -2
- data/lib/pact_broker/integrations/repository.rb +34 -1
- data/lib/pact_broker/integrations/service.rb +17 -18
- data/lib/pact_broker/labels/repository.rb +4 -8
- data/lib/pact_broker/locale/en.yml +5 -0
- data/lib/pact_broker/logging.rb +10 -0
- data/lib/pact_broker/matrix/every_row.rb +58 -40
- data/lib/pact_broker/matrix/integration_row.rb +95 -0
- data/lib/pact_broker/matrix/integrations_repository.rb +133 -0
- data/lib/pact_broker/matrix/matrix_row.rb +88 -0
- data/lib/pact_broker/matrix/matrix_row_dataset_module.rb +185 -0
- data/lib/pact_broker/matrix/matrix_row_instance_methods.rb +150 -0
- data/lib/pact_broker/matrix/matrix_row_verification_dataset_module.rb +83 -0
- data/lib/pact_broker/matrix/parse_query.rb +1 -0
- data/lib/pact_broker/matrix/repository.rb +62 -285
- data/lib/pact_broker/matrix/resolved_selector.rb +13 -4
- data/lib/pact_broker/matrix/resolved_selector_builder.rb +84 -0
- data/lib/pact_broker/matrix/resolved_selectors_builder.rb +39 -0
- data/lib/pact_broker/matrix/row_ignorer.rb +36 -0
- data/lib/pact_broker/matrix/selector_ignorer.rb +59 -0
- data/lib/pact_broker/matrix/selector_resolver.rb +130 -0
- data/lib/pact_broker/metrics/service.rb +4 -9
- data/lib/pact_broker/pacticipants/latest_version_for_pacticipant_eager_loader.rb +33 -0
- data/lib/pact_broker/pacticipants/repository.rb +7 -9
- data/lib/pact_broker/pacticipants/service.rb +2 -2
- data/lib/pact_broker/pacts/generate_sha.rb +9 -4
- data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +2 -4
- data/lib/pact_broker/pacts/metadata.rb +3 -1
- data/lib/pact_broker/pacts/pact_params.rb +1 -1
- data/lib/pact_broker/pacts/pact_publication.rb +23 -5
- data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +5 -1
- data/lib/pact_broker/pacts/pact_version.rb +2 -3
- data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +2 -5
- data/lib/pact_broker/pacts/placeholder_pact.rb +3 -1
- data/lib/pact_broker/pacts/repository.rb +12 -12
- data/lib/pact_broker/pacts/service.rb +12 -13
- data/lib/pact_broker/repositories.rb +9 -1
- data/lib/pact_broker/string_refinements.rb +4 -0
- data/lib/pact_broker/tags/head_pact_tags.rb +2 -5
- data/lib/pact_broker/tags/repository.rb +3 -7
- data/lib/pact_broker/test/test_data_builder.rb +57 -2
- data/lib/pact_broker/ui/controllers/base_controller.rb +4 -2
- data/lib/pact_broker/ui/controllers/groups.rb +2 -1
- data/lib/pact_broker/ui/view_models/matrix_line.rb +4 -4
- data/lib/pact_broker/ui/views/groups/show.html.erb +2 -1
- data/lib/pact_broker/ui.rb +20 -9
- data/lib/pact_broker/verifications/latest_verification_for_consumer_and_provider.rb +0 -3
- data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +2 -4
- data/lib/pact_broker/verifications/repository.rb +2 -5
- data/lib/pact_broker/verifications/sequence.rb +1 -4
- data/lib/pact_broker/verifications/service.rb +4 -0
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/branch.rb +2 -5
- data/lib/pact_broker/versions/branch_head.rb +0 -3
- data/lib/pact_broker/versions/branch_repository.rb +76 -0
- data/lib/pact_broker/versions/branch_service.rb +13 -25
- data/lib/pact_broker/versions/branch_version.rb +0 -3
- data/lib/pact_broker/versions/branch_version_repository.rb +17 -0
- data/lib/pact_broker/versions/repository.rb +19 -2
- data/lib/pact_broker/versions/sequence.rb +1 -3
- data/lib/pact_broker/versions/service.rb +4 -0
- data/lib/pact_broker/webhooks/execution.rb +3 -7
- data/lib/pact_broker/webhooks/job.rb +16 -7
- data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +2 -2
- data/lib/pact_broker/webhooks/repository.rb +0 -1
- data/lib/pact_broker/webhooks/trigger_service.rb +11 -12
- data/lib/pact_broker/webhooks/triggered_webhook.rb +3 -4
- data/lib/pact_broker/webhooks/webhook.rb +2 -2
- data/lib/pact_broker/webhooks/webhook_event.rb +2 -5
- data/lib/rack/pact_broker/add_cache_header.rb +14 -0
- data/lib/rack/pact_broker/application_context.rb +16 -0
- data/lib/rack/pact_broker/configurable_make_it_later.rb +1 -1
- data/lib/rack/pact_broker/invalid_uri_protection.rb +19 -3
- data/lib/webmachine/describe_routes.rb +55 -39
- data/lib/webmachine/render_error_monkey_patch.rb +13 -4
- data/pact_broker.gemspec +5 -5
- metadata +54 -31
- data/lib/pact_broker/api/decorators/decorator_context.rb +0 -22
- data/lib/pact_broker/matrix/query_builder.rb +0 -90
- data/lib/pact_broker/matrix/query_ids.rb +0 -40
- data/lib/pact_broker/matrix/quick_row.rb +0 -458
- data/lib/pact_broker/relationships/groupify.rb +0 -45
- data/lib/pact_broker/repositories/helpers.rb +0 -96
- data/lib/pact_broker/repositories/page.rb +0 -24
- data/lib/pact_broker/tags/tag_with_latest_flag.rb +0 -28
@@ -227,8 +227,24 @@ module PactBroker
|
|
227
227
|
"#{tags_url(base_url, tag.version)}/#{url_encode(tag.name)}"
|
228
228
|
end
|
229
229
|
|
230
|
+
def branch_url(branch, base_url = "")
|
231
|
+
"#{pacticipant_branches_url(branch.pacticipant, base_url)}/#{url_encode(branch.name)}"
|
232
|
+
end
|
233
|
+
|
234
|
+
def pacticipant_branches_url(pacticipant, base_url = "")
|
235
|
+
"#{pacticipant_url(base_url, pacticipant)}/branches"
|
236
|
+
end
|
237
|
+
|
238
|
+
def branch_versions_url(branch, base_url = "")
|
239
|
+
"#{branch_url(branch, base_url)}/versions"
|
240
|
+
end
|
241
|
+
|
230
242
|
def branch_version_url(branch_version, base_url = "")
|
231
|
-
"#{
|
243
|
+
"#{branch_versions_url(branch_version.branch, base_url)}/#{url_encode(branch_version.version_number)}"
|
244
|
+
end
|
245
|
+
|
246
|
+
def latest_version_for_branch_url(branch, base_url = "")
|
247
|
+
"#{branch_url(branch, base_url)}/latest-version"
|
232
248
|
end
|
233
249
|
|
234
250
|
def templated_tag_url_for_pacticipant pacticipant_name, base_url = ""
|
@@ -271,7 +287,7 @@ module PactBroker
|
|
271
287
|
"#{base_url}/webhooks"
|
272
288
|
end
|
273
289
|
|
274
|
-
def webhook_url uuid, base_url
|
290
|
+
def webhook_url uuid, base_url = ""
|
275
291
|
"#{base_url}/webhooks/#{uuid}"
|
276
292
|
end
|
277
293
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "pact_broker/async/after_reply"
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Resources
|
6
|
+
module AfterReply
|
7
|
+
|
8
|
+
# @param [Callable] block the block to execute after the response has been sent to the user.
|
9
|
+
def after_reply(&block)
|
10
|
+
PactBroker::Async::AfterReply.new(request.env).execute(&block)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -38,7 +38,7 @@ module PactBroker
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def from_json
|
41
|
-
saved_webhook = webhook_service.create(next_uuid, webhook,
|
41
|
+
saved_webhook = webhook_service.create(next_uuid, webhook, webhook_consumer, webhook_provider)
|
42
42
|
response.body = decorator_class(:webhook_decorator).new(saved_webhook).to_json(**decorator_options)
|
43
43
|
end
|
44
44
|
|
@@ -60,11 +60,11 @@ module PactBroker
|
|
60
60
|
api_contract_class(:webhook_contract)
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
63
|
+
def webhook_consumer
|
64
64
|
webhook.consumer&.name ? pacticipant_service.find_pacticipant_by_name(webhook.consumer.name) : nil
|
65
65
|
end
|
66
66
|
|
67
|
-
def
|
67
|
+
def webhook_provider
|
68
68
|
webhook.provider&.name ? pacticipant_service.find_pacticipant_by_name(webhook.provider.name) : nil
|
69
69
|
end
|
70
70
|
|
@@ -37,7 +37,8 @@ module PactBroker
|
|
37
37
|
badge_url
|
38
38
|
rescue StandardError => e
|
39
39
|
# Want to render a badge, even if there's an error
|
40
|
-
|
40
|
+
error_reference = log_and_report_error(e)
|
41
|
+
badge_service.error_badge_url("error", "reference: #{error_reference}")
|
41
42
|
end
|
42
43
|
end
|
43
44
|
|
@@ -10,6 +10,7 @@ require "pact_broker/pacts/pact_params"
|
|
10
10
|
require "pact_broker/api/resources/authentication"
|
11
11
|
require "pact_broker/api/resources/authorization"
|
12
12
|
require "pact_broker/errors"
|
13
|
+
require "pact_broker/messages"
|
13
14
|
require "pact_broker/api/resources/error_handling_methods"
|
14
15
|
require "pact_broker/api/contracts/utf_8_validation"
|
15
16
|
|
@@ -26,7 +27,7 @@ module PactBroker
|
|
26
27
|
include PactBroker::Api::Resources::Authorization
|
27
28
|
include PactBroker::Api::Resources::ErrorHandlingMethods
|
28
29
|
include PactBroker::Api::Contracts::UTF8Validation
|
29
|
-
|
30
|
+
include PactBroker::Messages
|
30
31
|
include PactBroker::Logging
|
31
32
|
|
32
33
|
attr_accessor :user
|
@@ -206,7 +207,7 @@ module PactBroker
|
|
206
207
|
def find_pacticipant name, role
|
207
208
|
pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
|
208
209
|
if pacticipant.nil?
|
209
|
-
set_json_error_message("No #{role} with name '#{name}' found", title: "Not found", type: "
|
210
|
+
set_json_error_message("No #{role} with name '#{name}' found", title: "Not found", type: "not-found", status: 404)
|
210
211
|
end
|
211
212
|
end
|
212
213
|
end
|
@@ -257,8 +258,9 @@ module PactBroker
|
|
257
258
|
end
|
258
259
|
|
259
260
|
def validation_errors_for_schema?(schema_to_use = schema, params_to_validate = params)
|
260
|
-
|
261
|
-
|
261
|
+
result = schema_to_use.call(params_to_validate)
|
262
|
+
if result.errors.any?
|
263
|
+
set_json_validation_error_messages(result.errors)
|
262
264
|
true
|
263
265
|
else
|
264
266
|
false
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "pact_broker/api/resources/base_resource"
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Resources
|
6
|
+
class Branch < BaseResource
|
7
|
+
def content_types_provided
|
8
|
+
[["application/hal+json", :to_json]]
|
9
|
+
end
|
10
|
+
|
11
|
+
def allowed_methods
|
12
|
+
["GET", "DELETE", "OPTIONS"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def resource_exists?
|
16
|
+
!!branch
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_json
|
20
|
+
decorator_class(:branch_decorator).new(branch).to_json(**decorator_options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def delete_resource
|
24
|
+
branch_service.delete_branch(branch)
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
def policy_name
|
29
|
+
:'versions::branch'
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def branch
|
35
|
+
@branch_version ||= branch_service.find_branch(**identifier_from_path.slice(:pacticipant_name, :branch_name))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require "pact_broker/api/resources/base_resource"
|
2
|
+
require "pact_broker/configuration"
|
3
|
+
require "pact_broker/api/decorators/versions_decorator"
|
4
|
+
require "pact_broker/api/resources/pagination_methods"
|
5
|
+
|
6
|
+
|
7
|
+
module PactBroker
|
8
|
+
module Api
|
9
|
+
module Resources
|
10
|
+
class BranchVersions < BaseResource
|
11
|
+
include PaginationMethods
|
12
|
+
|
13
|
+
def content_types_provided
|
14
|
+
[["application/hal+json", :to_json]]
|
15
|
+
end
|
16
|
+
|
17
|
+
def allowed_methods
|
18
|
+
["GET", "OPTIONS"]
|
19
|
+
end
|
20
|
+
|
21
|
+
def malformed_request?
|
22
|
+
super || request.get? && validation_errors_for_schema?(schema, request.query)
|
23
|
+
end
|
24
|
+
|
25
|
+
def resource_exists?
|
26
|
+
!!branch
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_json
|
30
|
+
decorator_class(:versions_decorator).new(versions).to_json(**decorator_options(identifier_from_path.merge(resource_title: resource_title)))
|
31
|
+
end
|
32
|
+
|
33
|
+
def versions
|
34
|
+
@versions ||= version_service.find_pacticipant_versions_in_reverse_order(pacticipant_name, { branch_name: identifier_from_path[:branch_name] }, pagination_options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def policy_name
|
38
|
+
:'versions::versions'
|
39
|
+
end
|
40
|
+
|
41
|
+
def branch
|
42
|
+
@branch ||= branch_service.find_branch(**identifier_from_path.slice(:pacticipant_name, :branch_name))
|
43
|
+
end
|
44
|
+
|
45
|
+
def resource_title
|
46
|
+
"Versions for branch #{branch.name} of #{branch.pacticipant.name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def schema
|
52
|
+
if request.get?
|
53
|
+
PactBroker::Api::Contracts::PaginationQueryParamsSchema
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -14,7 +14,7 @@ module PactBroker
|
|
14
14
|
elsif pacticipant.nil?
|
15
15
|
badge_service.error_badge_url("pacticipant", "not found")
|
16
16
|
elsif version.nil?
|
17
|
-
if branch_service.find_branch(identifier_from_path.slice(:pacticipant_name, :branch_name)).nil?
|
17
|
+
if branch_service.find_branch(**identifier_from_path.slice(:pacticipant_name, :branch_name)).nil?
|
18
18
|
badge_service.error_badge_url("branch", "not found")
|
19
19
|
else
|
20
20
|
badge_service.error_badge_url("version", "not found")
|
@@ -21,7 +21,7 @@ module PactBroker
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def to_json
|
24
|
-
decorator_class(decorator_name).new(deployed_versions).to_json(**decorator_options(title: title))
|
24
|
+
decorator_class(decorator_name).new(deployed_versions).to_json(**decorator_options(title: title, expand: [:pacticipant, :version]))
|
25
25
|
end
|
26
26
|
|
27
27
|
def policy_name
|
@@ -21,7 +21,7 @@ module PactBroker
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def to_json
|
24
|
-
decorator_class(decorator_name).new(released_versions).to_json(**decorator_options(title: title))
|
24
|
+
decorator_class(decorator_name).new(released_versions).to_json(**decorator_options(title: title, expand: [:pacticipant, :version]))
|
25
25
|
end
|
26
26
|
|
27
27
|
def policy_name
|
@@ -20,6 +20,10 @@ module PactBroker
|
|
20
20
|
["GET", "OPTIONS"]
|
21
21
|
end
|
22
22
|
|
23
|
+
def malformed_request?
|
24
|
+
super || (request.get? && validation_errors_for_schema?(schema, request.query))
|
25
|
+
end
|
26
|
+
|
23
27
|
def to_json
|
24
28
|
decorator_class(:dashboard_decorator).new(index_items).to_json(**decorator_options)
|
25
29
|
end
|
@@ -34,6 +38,12 @@ module PactBroker
|
|
34
38
|
|
35
39
|
private
|
36
40
|
|
41
|
+
def schema
|
42
|
+
if request.get?
|
43
|
+
PactBroker::Api::Contracts::PaginationQueryParamsSchema
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
37
47
|
def index_items
|
38
48
|
index_service.find_index_items_for_api(**identifier_from_path.merge(pagination_options))
|
39
49
|
end
|
@@ -78,7 +78,7 @@ module PactBroker
|
|
78
78
|
end
|
79
79
|
|
80
80
|
def title
|
81
|
-
"Deployed versions for #{pacticipant_name} version #{pacticipant_version_number}"
|
81
|
+
"Deployed versions for #{pacticipant_name} version #{pacticipant_version_number} in environment #{environment.display_name}"
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
@@ -60,7 +60,7 @@ module PactBroker
|
|
60
60
|
|
61
61
|
def environments
|
62
62
|
@environments ||= if request.query["name"]
|
63
|
-
[environment_service.find_by_name(request.query["name"])]
|
63
|
+
[environment_service.find_by_name(request.query["name"])].compact
|
64
64
|
else
|
65
65
|
environment_service.find_all
|
66
66
|
end
|
@@ -1,70 +1,36 @@
|
|
1
1
|
require "pact_broker/configuration"
|
2
2
|
require "securerandom"
|
3
3
|
|
4
|
+
# Logs the error
|
5
|
+
# Reports the error
|
6
|
+
# Generates and returns response headers and response body
|
7
|
+
|
4
8
|
module PactBroker
|
5
9
|
module Api
|
6
10
|
module Resources
|
7
11
|
class ErrorHandler
|
8
12
|
include PactBroker::Logging
|
9
13
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
elsif reportable?(e)
|
15
|
-
log_error(e, "Error reference #{error_reference}")
|
16
|
-
report(e, error_reference, request)
|
17
|
-
else
|
18
|
-
logger.info("Error reference #{error_reference}", e)
|
19
|
-
end
|
20
|
-
response.body = response_body_hash(e, error_reference).to_json
|
14
|
+
def initialize(error_logger, error_response_generator, error_reporter)
|
15
|
+
@error_logger = error_logger
|
16
|
+
@error_response_generator = error_response_generator
|
17
|
+
@error_reporter = error_reporter
|
21
18
|
end
|
22
19
|
|
23
|
-
def
|
24
|
-
|
25
|
-
end
|
20
|
+
def call(error, env, message = nil)
|
21
|
+
error_reference = PactBroker::Errors.generate_error_reference
|
26
22
|
|
27
|
-
|
28
|
-
|
29
|
-
end
|
23
|
+
# log error
|
24
|
+
error_logger.call(error, error_reference, env)
|
30
25
|
|
31
|
-
|
32
|
-
|
33
|
-
end
|
26
|
+
# report error
|
27
|
+
error_reporter.call(error, error_reference, env)
|
34
28
|
|
35
|
-
def self.display_message(e, obfuscated_message)
|
36
|
-
if PactBroker.configuration.show_backtrace_in_error_response?
|
37
|
-
e.message || obfuscated_message
|
38
|
-
else
|
39
|
-
reportable?(e) ? obfuscated_message : e.message
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.obfuscated_error_message error_reference
|
44
|
-
"An error has occurred. The details have been logged with the reference #{error_reference}"
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.response_body_hash e, error_reference
|
48
|
-
response_body = {
|
49
|
-
error: {
|
50
|
-
message: display_message(e, obfuscated_error_message(error_reference)),
|
51
|
-
reference: error_reference
|
52
|
-
}
|
53
|
-
}
|
54
|
-
if PactBroker.configuration.show_backtrace_in_error_response?
|
55
|
-
response_body[:error][:backtrace] = e.backtrace
|
56
|
-
end
|
57
|
-
response_body
|
58
|
-
end
|
59
29
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
rescue StandardError => e
|
65
|
-
log_error(e, "Error executing api_error_reporter")
|
66
|
-
end
|
67
|
-
end
|
30
|
+
# generate response
|
31
|
+
headers, body = error_response_generator.call(error, error_reference, env, message: message)
|
32
|
+
headers.each { | key, value | response.headers[key] = value }
|
33
|
+
return headers, body
|
68
34
|
end
|
69
35
|
end
|
70
36
|
end
|
@@ -7,29 +7,39 @@ module PactBroker
|
|
7
7
|
module ErrorHandlingMethods
|
8
8
|
|
9
9
|
# @override
|
10
|
+
# @param [StandardError] error
|
10
11
|
def handle_exception(error)
|
11
|
-
error_reference =
|
12
|
-
application_context.error_logger.call(error, error_reference, request.env)
|
13
|
-
if PactBroker::Errors.reportable_error?(error)
|
14
|
-
PactBroker::Errors.report(error, error_reference, request.env)
|
15
|
-
end
|
12
|
+
error_reference = log_and_report_error(error)
|
16
13
|
headers, body = application_context.error_response_generator.call(error, error_reference, request.env)
|
17
14
|
headers.each { | key, value | response.headers[key] = value }
|
18
15
|
response.body = body
|
19
16
|
end
|
20
17
|
|
21
|
-
|
18
|
+
# @param [StandardError] error
|
19
|
+
def log_and_report_error(error)
|
20
|
+
# generate reference
|
21
|
+
error_reference = PactBroker::Errors.generate_error_reference
|
22
|
+
# log error
|
23
|
+
application_context.error_logger.call(error, error_reference, request.env)
|
24
|
+
# report error
|
25
|
+
application_context.error_reporter.call(error, error_reference, request.env)
|
26
|
+
# generate response
|
27
|
+
error_reference
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param [String] detail
|
31
|
+
# @param [String] title
|
32
|
+
# @param [String] type
|
33
|
+
# @param [Integer] status
|
34
|
+
def set_json_error_message(detail, title: "Server error", type: "server-error", status: 500)
|
22
35
|
response.headers["Content-Type"] = error_response_content_type
|
23
36
|
response.body = error_response_body(detail, title, type, status)
|
24
37
|
end
|
25
38
|
|
26
|
-
|
39
|
+
# @param [Hash,Dry::Validation::MessageSet] errors
|
40
|
+
def set_json_validation_error_messages(errors)
|
27
41
|
response.headers["Content-Type"] = error_response_content_type
|
28
|
-
|
29
|
-
response.body = PactBroker::Api::Decorators::ValidationErrorsProblemJSONDecorator.new(errors).to_json(**decorator_options)
|
30
|
-
else
|
31
|
-
response.body = { errors: errors }.to_json
|
32
|
-
end
|
42
|
+
response.body = validation_errors_response_body(errors)
|
33
43
|
end
|
34
44
|
|
35
45
|
def error_response_content_type
|
@@ -42,15 +52,31 @@ module PactBroker
|
|
42
52
|
|
43
53
|
def error_response_body(detail, title, type, status)
|
44
54
|
if problem_json_error_content_type?
|
45
|
-
|
55
|
+
decorator_class(:custom_error_problem_json_decorator).new(detail: detail, title: title, type: type, status: status).to_json(**decorator_options_for_error)
|
46
56
|
else
|
47
|
-
|
57
|
+
decorator_class(:error_decorator).new(detail).to_json
|
48
58
|
end
|
49
59
|
end
|
50
60
|
|
61
|
+
# @param [Hash,Dry::Validation::MessageSet] errors
|
62
|
+
def validation_errors_response_body(errors)
|
63
|
+
validation_errors_decorator_class(errors).new(errors).to_json(**decorator_options_for_error)
|
64
|
+
end
|
65
|
+
|
66
|
+
# @param [Hash,Dry::Validation::MessageSet] errors
|
67
|
+
def validation_errors_decorator_class(errors)
|
68
|
+
application_context.decorator_configuration.validation_error_decorator_class_for(errors.class, request.headers["Accept"])
|
69
|
+
end
|
70
|
+
|
51
71
|
def problem_json_error_content_type?
|
52
72
|
request.headers["Accept"]&.include?("application/problem+json")
|
53
73
|
end
|
74
|
+
|
75
|
+
# If we use the normal decorator options that have policy objects we can get into recursive loops in Pactflow, so just make a simple variant of the
|
76
|
+
# decorator options here
|
77
|
+
def decorator_options_for_error
|
78
|
+
{ user_options: { base_url: base_url } }
|
79
|
+
end
|
54
80
|
end
|
55
81
|
end
|
56
82
|
end
|
@@ -1,23 +1,36 @@
|
|
1
1
|
require "pact_broker/configuration"
|
2
2
|
require "pact_broker/api/decorators/runtime_error_problem_json_decorator"
|
3
|
+
require "pact_broker/errors"
|
4
|
+
require "pact_broker/messages"
|
5
|
+
|
6
|
+
# Generates the response headers and body for use when there is a runtime
|
7
|
+
# error in the business logic (services and repositories) when executing a Webmachine resource request.
|
8
|
+
# Obfuscates any exception messages that might expose vulnerablities in production.
|
9
|
+
# Uses the Accept header to determine whether to return application/problem+json
|
10
|
+
# or application/hal+json, for backwards compatibility.
|
11
|
+
# In the next major version of the Pact Broker, all error responses
|
12
|
+
# should use problem+json, regardless of Accept headers.
|
3
13
|
|
4
14
|
module PactBroker
|
5
15
|
module Api
|
6
16
|
module Resources
|
7
17
|
class ErrorResponseGenerator
|
8
18
|
include PactBroker::Logging
|
19
|
+
extend PactBroker::Messages
|
9
20
|
|
10
21
|
# @param error [StandardError]
|
11
22
|
# @param error_reference [String] an error reference to display to the user
|
12
23
|
# @param env [Hash] the rack env
|
13
24
|
# @return [Hash, String] the response headers to set, the response body to set
|
14
|
-
def self.call
|
15
|
-
body = response_body_hash(error, error_reference, env, display_message(error, obfuscated_error_message(error_reference)))
|
25
|
+
def self.call(error, error_reference, env, message: nil)
|
26
|
+
body = response_body_hash(error, error_reference, env, display_message(error, message, obfuscated_error_message(error_reference)))
|
16
27
|
return headers(env), body.to_json
|
17
28
|
end
|
18
29
|
|
19
|
-
def self.display_message(error, obfuscated_message)
|
20
|
-
if
|
30
|
+
def self.display_message(error, message, obfuscated_message)
|
31
|
+
if message
|
32
|
+
message
|
33
|
+
elsif PactBroker.configuration.show_backtrace_in_error_response?
|
21
34
|
error.message || obfuscated_message
|
22
35
|
else
|
23
36
|
PactBroker::Errors.reportable_error?(error) ? obfuscated_message : error.message
|
@@ -46,11 +59,11 @@ module PactBroker
|
|
46
59
|
end
|
47
60
|
|
48
61
|
private_class_method def self.problem_json_response_body(message, env)
|
49
|
-
|
62
|
+
error_decorator_class(env).new(message).to_hash(user_options: { base_url: env["pactbroker.base_url" ] })
|
50
63
|
end
|
51
64
|
|
52
65
|
private_class_method def self.obfuscated_error_message(error_reference)
|
53
|
-
"
|
66
|
+
message("errors.runtime.with_error_reference", error_reference: error_reference)
|
54
67
|
end
|
55
68
|
|
56
69
|
private_class_method def self.headers(env)
|
@@ -64,6 +77,10 @@ module PactBroker
|
|
64
77
|
private_class_method def self.problem_json?(env)
|
65
78
|
env["HTTP_ACCEPT"]&.include?("application/problem+json")
|
66
79
|
end
|
80
|
+
|
81
|
+
private_class_method def self.error_decorator_class(env)
|
82
|
+
env["pactbroker.application_context"].decorator_configuration.class_for(:runtime_error_problem_json_decorator)
|
83
|
+
end
|
67
84
|
end
|
68
85
|
end
|
69
86
|
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require "pact_broker/string_refinements"
|
1
2
|
require "pact_broker/api/resources/base_resource"
|
2
3
|
require "pact_broker/api/decorators/relationships_csv_decorator"
|
3
4
|
|
@@ -5,6 +6,8 @@ module PactBroker
|
|
5
6
|
module Api
|
6
7
|
module Resources
|
7
8
|
class Group < BaseResource
|
9
|
+
using PactBroker::StringRefinements
|
10
|
+
|
8
11
|
def content_types_provided
|
9
12
|
[["text/csv", :to_csv]]
|
10
13
|
end
|
@@ -32,9 +35,15 @@ module PactBroker
|
|
32
35
|
private
|
33
36
|
|
34
37
|
def group
|
35
|
-
@group ||= group_service.find_group_containing(pacticipant)
|
38
|
+
@group ||= group_service.find_group_containing(pacticipant, max_pacticipants: max_pacticipants)
|
39
|
+
end
|
40
|
+
|
41
|
+
def max_pacticipants
|
42
|
+
if request.query["maxPacticipants"]&.integer?
|
43
|
+
request.query["maxPacticipants"].to_i
|
44
|
+
end
|
36
45
|
end
|
37
46
|
end
|
38
47
|
end
|
39
48
|
end
|
40
|
-
end
|
49
|
+
end
|
@@ -116,6 +116,12 @@ module PactBroker
|
|
116
116
|
title: "Get, create or delete a tag for a pacticipant version",
|
117
117
|
templated: true
|
118
118
|
},
|
119
|
+
"pb:pacticipant-branch" =>
|
120
|
+
{
|
121
|
+
href: base_url + "/pacticipants/{pacticipant}/branches/{branch}",
|
122
|
+
title: "Get or delete a pacticipant branch",
|
123
|
+
templated: true
|
124
|
+
},
|
119
125
|
"pb:pacticipant-branch-version" =>
|
120
126
|
{
|
121
127
|
href: base_url + "/pacticipants/{pacticipant}/branches/{branch}/versions/{version}",
|