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
data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require "pact_broker/
|
1
|
+
require "pact_broker/dataset"
|
2
2
|
|
3
3
|
module PactBroker
|
4
4
|
module Verifications
|
@@ -8,9 +8,7 @@ module PactBroker
|
|
8
8
|
|
9
9
|
plugin :upsert, identifying_columns: [:pact_version_id, :provider_version_id]
|
10
10
|
|
11
|
-
dataset_module
|
12
|
-
include PactBroker::Repositories::Helpers
|
13
|
-
end
|
11
|
+
dataset_module(PactBroker::Dataset)
|
14
12
|
end
|
15
13
|
end
|
16
14
|
end
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "sequel"
|
2
1
|
require "pact_broker/domain/verification"
|
3
2
|
require "pact_broker/verifications/sequence"
|
4
3
|
require "pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version"
|
@@ -8,8 +7,6 @@ require "pact_broker/repositories/scopes"
|
|
8
7
|
module PactBroker
|
9
8
|
module Verifications
|
10
9
|
class Repository
|
11
|
-
|
12
|
-
include PactBroker::Repositories::Helpers
|
13
10
|
include PactBroker::Repositories
|
14
11
|
include PactBroker::Repositories::Scopes
|
15
12
|
|
@@ -140,8 +137,8 @@ module PactBroker
|
|
140
137
|
consumer = pacticipant_repository.find_by_name!(consumer_name)
|
141
138
|
provider = pacticipant_repository.find_by_name!(provider_name)
|
142
139
|
|
143
|
-
consumer_tag_filter =
|
144
|
-
provider_tag_filter =
|
140
|
+
consumer_tag_filter = Sequel.name_like(Sequel.qualify(:consumer_tags, :name), consumer_version_tag)
|
141
|
+
provider_tag_filter = Sequel.name_like(Sequel.qualify(:provider_tags, :name), provider_version_tag)
|
145
142
|
|
146
143
|
query = scope_for(PactBroker::Domain::Verification)
|
147
144
|
.select_all_qualified
|
@@ -1,6 +1,3 @@
|
|
1
|
-
require "sequel"
|
2
|
-
require "pact_broker/repositories/helpers"
|
3
|
-
|
4
1
|
module PactBroker
|
5
2
|
module Verifications
|
6
3
|
class Sequence < Sequel::Model(:verification_sequence_number)
|
@@ -8,7 +5,7 @@ module PactBroker
|
|
8
5
|
# The easiest way to implement a cross database compatible sequence.
|
9
6
|
# Sad, I know.
|
10
7
|
def next_val
|
11
|
-
if PactBroker::
|
8
|
+
if PactBroker::Dataset::Helpers.postgres?
|
12
9
|
db.execute("SELECT nextval('verification_number_sequence') as val") { |v| v.first["val"].to_i }
|
13
10
|
else
|
14
11
|
db.transaction do
|
@@ -31,6 +31,10 @@ module PactBroker
|
|
31
31
|
|
32
32
|
# TODO use a decorator instead of passing in params, srsly, Beth
|
33
33
|
# verified_pacts is an array of SelectedPact objects
|
34
|
+
# @param [Integer] next_verification_number
|
35
|
+
# @param [Hash] params the verification params
|
36
|
+
# @param [Array<SelectedPact>] verified_pacts
|
37
|
+
# @param [Hash] event_context
|
34
38
|
def create next_verification_number, params, verified_pacts, event_context
|
35
39
|
first_verified_pact = verified_pacts.first
|
36
40
|
logger.info("Creating verification #{next_verification_number} for pact_version_sha=#{first_verified_pact.pact_version_sha}", params.without("testResults"))
|
data/lib/pact_broker/version.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
require "pact_broker/
|
2
|
-
require "pact_broker/repositories/helpers"
|
1
|
+
require "pact_broker/dataset"
|
3
2
|
|
4
3
|
module PactBroker
|
5
4
|
module Versions
|
@@ -11,9 +10,7 @@ module PactBroker
|
|
11
10
|
associate(:many_to_one, :pacticipant, :class => "PactBroker::Domain::Pacticipant", :key => :pacticipant_id, :primary_key => :id)
|
12
11
|
associate(:one_to_many, :branch_versions, :class => "PactBroker::Versions::BranchVersion", :key => :branch_id, :primary_key => :id)
|
13
12
|
|
14
|
-
dataset_module
|
15
|
-
include PactBroker::Repositories::Helpers
|
16
|
-
end
|
13
|
+
dataset_module(PactBroker::Dataset)
|
17
14
|
end
|
18
15
|
end
|
19
16
|
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require "pact_broker/repositories/scopes"
|
2
|
+
module PactBroker
|
3
|
+
module Versions
|
4
|
+
class BranchRepository
|
5
|
+
include PactBroker::Services
|
6
|
+
include PactBroker::Repositories::Scopes
|
7
|
+
|
8
|
+
# @param [PactBroker::Domain::Pacticipant] pacticipant
|
9
|
+
# @param [Hash] filter_options with key :query_string
|
10
|
+
# @param [Hash] pagination_options with keys :page_size and :page_number
|
11
|
+
# @param [Array] eager_load_associations the associations to eager load
|
12
|
+
def find_all_branches_for_pacticipant(pacticipant, filter_options = {}, pagination_options = {}, eager_load_associations = [])
|
13
|
+
query = scope_for(Branch).where(pacticipant_id: pacticipant.id).select_all_qualified
|
14
|
+
query = query.filter(:name, filter_options[:query_string]) if filter_options[:query_string]
|
15
|
+
query
|
16
|
+
.order(Sequel.desc(:created_at), Sequel.desc(:id))
|
17
|
+
.eager(*eager_load_associations)
|
18
|
+
.all_with_pagination_options(pagination_options)
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param [String] pacticipant_name
|
22
|
+
# @param [String] branch_name
|
23
|
+
# @return [PactBroker::Versions::Branch, nil]
|
24
|
+
def find_branch(pacticipant_name:, branch_name:)
|
25
|
+
Branch
|
26
|
+
.select_all_qualified
|
27
|
+
.join(:pacticipants, { Sequel[:branches][:pacticipant_id] => Sequel[:pacticipants][:id] }) do
|
28
|
+
Sequel.name_like(Sequel[:pacticipants][:name], pacticipant_name)
|
29
|
+
end
|
30
|
+
.where(Sequel[:branches][:name] => branch_name)
|
31
|
+
.single_record
|
32
|
+
end
|
33
|
+
|
34
|
+
# Deletes a branch, its branch head and branch_version objects, without deleting the
|
35
|
+
# pacticipant version objects
|
36
|
+
#
|
37
|
+
# @param [PactBroker::Versions::Branch] the branch to delete
|
38
|
+
def delete_branch(branch)
|
39
|
+
branch.delete
|
40
|
+
end
|
41
|
+
|
42
|
+
# @param [PactBroker::Domain::Pacticipant] pacticipant
|
43
|
+
# @params [Array<String>] exclude the names of the branches to NOT delete
|
44
|
+
# @param [Integer] the number of branches that will be deleted
|
45
|
+
def count_branches_to_delete(pacticipant, exclude: )
|
46
|
+
build_query_for_pacticipant_branches(pacticipant, exclude: exclude).count
|
47
|
+
end
|
48
|
+
|
49
|
+
# Returns the list of branches which will NOT be deleted (the bulk delete is executed async after the request has finished)
|
50
|
+
# @param [PactBroker::Domain::Pacticipant] pacticipant
|
51
|
+
# @params [Array<String>] exclude the names of the branches to NOT delete
|
52
|
+
# @return [Array<PactBroker::Versions::Branch>]
|
53
|
+
def remaining_branches_after_future_deletion(pacticipant, exclude: )
|
54
|
+
exclude_dup = exclude.dup
|
55
|
+
if pacticipant.main_branch
|
56
|
+
exclude_dup << pacticipant.main_branch
|
57
|
+
end
|
58
|
+
Branch.where(pacticipant_id: pacticipant.id).where(name: exclude_dup)
|
59
|
+
end
|
60
|
+
|
61
|
+
# @param [PactBroker::Domain::Pacticipant] pacticipant
|
62
|
+
# @params [Array<String>] exclude the names of the branches to NOT delete
|
63
|
+
def delete_branches_for_pacticipant(pacticipant, exclude:)
|
64
|
+
build_query_for_pacticipant_branches(pacticipant, exclude: exclude).delete
|
65
|
+
end
|
66
|
+
|
67
|
+
def build_query_for_pacticipant_branches(pacticipant, exclude: )
|
68
|
+
exclude_dup = exclude.dup
|
69
|
+
if pacticipant.main_branch
|
70
|
+
exclude_dup << pacticipant.main_branch
|
71
|
+
end
|
72
|
+
Branch.where(pacticipant_id: pacticipant.id).exclude(name: exclude_dup)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -1,40 +1,28 @@
|
|
1
|
+
require "forwardable"
|
1
2
|
require "pact_broker/logging"
|
2
3
|
require "pact_broker/repositories"
|
3
4
|
require "pact_broker/messages"
|
4
|
-
require "forwardable"
|
5
5
|
|
6
6
|
module PactBroker
|
7
7
|
module Versions
|
8
8
|
class BranchService
|
9
9
|
extend PactBroker::Repositories
|
10
|
+
extend PactBroker::Messages
|
10
11
|
|
11
12
|
class << self
|
12
13
|
extend Forwardable
|
13
|
-
delegate [:delete_branch_version] => :branch_version_repository
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
def self.find_branch_version(pacticipant_name:, branch_name:, version_number:, **)
|
18
|
-
BranchVersion.where(
|
19
|
-
version: PactBroker::Domain::Version.where_pacticipant_name_and_version_number(pacticipant_name, version_number),
|
20
|
-
branch: Branch.where(name: branch_name)
|
21
|
-
).single_record
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.find_or_create_branch_version(pacticipant_name:, branch_name:, version_number:, **)
|
25
|
-
pacticipant = pacticipant_repository.find_by_name_or_create(pacticipant_name)
|
26
|
-
version = version_repository.find_by_pacticipant_id_and_number_or_create(pacticipant.id, version_number)
|
27
|
-
branch_version_repository.add_branch(version, branch_name)
|
28
|
-
end
|
14
|
+
delegate [:find_branch_version, :find_or_create_branch_version, :delete_branch_version] => :branch_version_repository
|
15
|
+
delegate [:find_branch, :delete_branch, :find_all_branches_for_pacticipant, :delete_branches_for_pacticipant] => :branch_repository
|
29
16
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
.
|
37
|
-
.
|
17
|
+
# Returns a list of notices to display to the user in the terminal
|
18
|
+
# @param [PactBroker::Domain::Pacticipant] pacticipant
|
19
|
+
# @param [Array<String>] exclude the list of branches to NOT delete
|
20
|
+
# @return [Array<PactBroker::Contracts::Notice>]
|
21
|
+
def branch_deletion_notices(pacticipant, exclude:)
|
22
|
+
count = branch_repository.count_branches_to_delete(pacticipant, exclude: exclude)
|
23
|
+
remaining = branch_repository.remaining_branches_after_future_deletion(pacticipant, exclude: exclude).sort_by(&:created_at).collect(&:name).join(", ")
|
24
|
+
[PactBroker::Contracts::Notice.success(message("messages.branch.bulk_delete", count: count, pacticipant_name: pacticipant.name, remaining: remaining))]
|
25
|
+
end
|
38
26
|
end
|
39
27
|
end
|
40
28
|
end
|
@@ -1,7 +1,24 @@
|
|
1
|
+
require "pact_broker/versions/branch_version"
|
2
|
+
require "pact_broker/services"
|
3
|
+
|
1
4
|
module PactBroker
|
2
5
|
module Versions
|
3
6
|
class BranchVersionRepository
|
4
7
|
include PactBroker::Services
|
8
|
+
include PactBroker::Repositories
|
9
|
+
|
10
|
+
def find_branch_version(pacticipant_name:, branch_name:, version_number:, **)
|
11
|
+
BranchVersion.where(
|
12
|
+
version: PactBroker::Domain::Version.where_pacticipant_name_and_version_number(pacticipant_name, version_number),
|
13
|
+
branch: Branch.where(name: branch_name)
|
14
|
+
).single_record
|
15
|
+
end
|
16
|
+
|
17
|
+
def find_or_create_branch_version(pacticipant_name:, branch_name:, version_number:, **)
|
18
|
+
pacticipant = pacticipant_repository.find_by_name_or_create(pacticipant_name)
|
19
|
+
version = version_repository.find_by_pacticipant_id_and_number_or_create(pacticipant.id, version_number)
|
20
|
+
branch_version_repository.add_branch(version, branch_name)
|
21
|
+
end
|
5
22
|
|
6
23
|
def add_branch(version, branch_name, auto_created: false)
|
7
24
|
branch = find_or_create_branch(version.pacticipant, branch_name)
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require "sequel"
|
2
1
|
require "pact_broker/logging"
|
3
2
|
require "pact_broker/domain/version"
|
4
3
|
require "pact_broker/tags/repository"
|
@@ -11,7 +10,6 @@ module PactBroker
|
|
11
10
|
class Repository
|
12
11
|
|
13
12
|
include PactBroker::Logging
|
14
|
-
include PactBroker::Repositories::Helpers
|
15
13
|
include PactBroker::Repositories
|
16
14
|
|
17
15
|
def find_by_pacticipant_id_and_number pacticipant_id, number
|
@@ -59,6 +57,9 @@ module PactBroker
|
|
59
57
|
.single_record
|
60
58
|
end
|
61
59
|
|
60
|
+
# The eager loaded relations are hardcoded here to support the PactBroker::Api::Decorators::VersionDecorator
|
61
|
+
# Newer "find all" implementations for other models pass the relations to eager load in
|
62
|
+
# from the decorator via the resource.
|
62
63
|
def find_all_pacticipant_versions_in_reverse_order name, pagination_options = {}
|
63
64
|
pacticipant = pacticipant_repository.find_by_name!(name)
|
64
65
|
query = PactBroker::Domain::Version
|
@@ -71,6 +72,22 @@ module PactBroker
|
|
71
72
|
query.all_with_pagination_options(pagination_options)
|
72
73
|
end
|
73
74
|
|
75
|
+
def find_pacticipant_versions_in_reverse_order(pacticipant_name, options = {}, pagination_options = {})
|
76
|
+
pacticipant = pacticipant_repository.find_by_name!(pacticipant_name)
|
77
|
+
query = PactBroker::Domain::Version
|
78
|
+
.where(pacticipant: pacticipant)
|
79
|
+
.eager(:pacticipant)
|
80
|
+
.eager(branch_versions: [:version, :branch_head, { branch: :pacticipant }])
|
81
|
+
.eager(tags: :head_tag)
|
82
|
+
.eager(:pact_publications)
|
83
|
+
.reverse_order(:order)
|
84
|
+
|
85
|
+
if options[:branch_name]
|
86
|
+
query = query.where_branch_name(options[:branch_name])
|
87
|
+
end
|
88
|
+
query.all_with_pagination_options(pagination_options)
|
89
|
+
end
|
90
|
+
|
74
91
|
# There may be a race condition if two simultaneous requests come in to create the same version
|
75
92
|
def create(args)
|
76
93
|
version_params = {
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require "sequel"
|
2
|
-
|
3
1
|
module PactBroker
|
4
2
|
module Versions
|
5
3
|
class Sequence < Sequel::Model(:version_sequence_number)
|
@@ -8,7 +6,7 @@ module PactBroker
|
|
8
6
|
# The easiest way to implement a cross database compatible sequence.
|
9
7
|
# Sad, I know.
|
10
8
|
def next_val
|
11
|
-
if PactBroker::
|
9
|
+
if PactBroker::Dataset::Helpers.postgres?
|
12
10
|
db.execute("SELECT nextval('version_order_sequence') as val") { |v| v.first["val"].to_i }
|
13
11
|
else
|
14
12
|
db.transaction do
|
@@ -30,6 +30,10 @@ module PactBroker
|
|
30
30
|
version_repository.find_all_pacticipant_versions_in_reverse_order(name, pagination_options)
|
31
31
|
end
|
32
32
|
|
33
|
+
def self.find_pacticipant_versions_in_reverse_order(pacticipant_name, options, pagination_options = {})
|
34
|
+
version_repository.find_pacticipant_versions_in_reverse_order(pacticipant_name, options, pagination_options)
|
35
|
+
end
|
36
|
+
|
33
37
|
def self.create_or_overwrite(pacticipant_name, version_number, version)
|
34
38
|
pacticipant = pacticipant_repository.find_by_name_or_create(pacticipant_name)
|
35
39
|
version = version_repository.create_or_overwrite(pacticipant, version_number, version)
|
@@ -1,6 +1,4 @@
|
|
1
|
-
require "
|
2
|
-
require "pact_broker/db"
|
3
|
-
require "pact_broker/repositories/helpers"
|
1
|
+
require "pact_broker/dataset"
|
4
2
|
|
5
3
|
module PactBroker
|
6
4
|
module Webhooks
|
@@ -15,12 +13,10 @@ module PactBroker
|
|
15
13
|
set_primary_key :id
|
16
14
|
plugin :timestamps
|
17
15
|
|
18
|
-
dataset_module do
|
19
|
-
include PactBroker::Repositories::Helpers
|
20
|
-
end
|
21
|
-
|
22
16
|
associate(:many_to_one, :triggered_webhook, :class => "PactBroker::Webhooks::TriggeredWebhook", :key => :triggered_webhook_id, :primary_key => :id)
|
23
17
|
|
18
|
+
dataset_module(PactBroker::Dataset)
|
19
|
+
|
24
20
|
def <=> other
|
25
21
|
comp = created_date <=> other.created_date
|
26
22
|
comp = id <=> other.id if comp == 0
|
@@ -36,11 +36,15 @@ module PactBroker
|
|
36
36
|
def perform_with_triggered_webhook
|
37
37
|
@error_count = data[:error_count] || 0
|
38
38
|
begin
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
if triggered_webhook.webhook
|
40
|
+
webhook_execution_result = PactBroker::Webhooks::TriggerService.execute_triggered_webhook_now(triggered_webhook, webhook_options(data))
|
41
|
+
if webhook_execution_result.success?
|
42
|
+
handle_success
|
43
|
+
else
|
44
|
+
handle_failure
|
45
|
+
end
|
42
46
|
else
|
43
|
-
|
47
|
+
handle_webhook_deleted
|
44
48
|
end
|
45
49
|
rescue StandardError => e
|
46
50
|
handle_error e
|
@@ -73,19 +77,24 @@ module PactBroker
|
|
73
77
|
end
|
74
78
|
|
75
79
|
def handle_success
|
76
|
-
update_triggered_webhook_status
|
80
|
+
update_triggered_webhook_status(TriggeredWebhook::STATUS_SUCCESS)
|
77
81
|
end
|
78
82
|
|
79
83
|
def handle_failure
|
80
84
|
if reschedule_job?
|
81
85
|
reschedule_job
|
82
|
-
update_triggered_webhook_status
|
86
|
+
update_triggered_webhook_status(TriggeredWebhook::STATUS_RETRYING)
|
83
87
|
else
|
84
88
|
logger.info "Failed to execute webhook #{triggered_webhook.webhook_uuid} after #{retry_schedule.size + 1} attempts."
|
85
|
-
update_triggered_webhook_status
|
89
|
+
update_triggered_webhook_status(TriggeredWebhook::STATUS_FAILURE)
|
86
90
|
end
|
87
91
|
end
|
88
92
|
|
93
|
+
def handle_webhook_deleted
|
94
|
+
logger.info("Webhook with uuid #{triggered_webhook.webhook_uuid} cannot be executed it has been deleted. Marking triggered webhook as failed.")
|
95
|
+
update_triggered_webhook_status(TriggeredWebhook::STATUS_FAILURE)
|
96
|
+
end
|
97
|
+
|
89
98
|
def reschedule_job?
|
90
99
|
error_count < retry_schedule.size
|
91
100
|
end
|
@@ -134,7 +134,7 @@ module PactBroker
|
|
134
134
|
webhook_context[:consumer_version_tags].join(", ")
|
135
135
|
else
|
136
136
|
if pact
|
137
|
-
pact.
|
137
|
+
pact.consumer_version_tag_names.join(", ")
|
138
138
|
else
|
139
139
|
""
|
140
140
|
end
|
@@ -145,7 +145,7 @@ module PactBroker
|
|
145
145
|
if webhook_context.key?(:consumer_version_branch)
|
146
146
|
webhook_context[:consumer_version_branch] || ""
|
147
147
|
else
|
148
|
-
pact&.
|
148
|
+
pact&.consumer_version_branch_names&.last || ""
|
149
149
|
end
|
150
150
|
end
|
151
151
|
|
@@ -13,11 +13,21 @@ module PactBroker
|
|
13
13
|
include PactBroker::Logging
|
14
14
|
using PactBroker::HashRefinements
|
15
15
|
|
16
|
+
# the main entry point
|
17
|
+
def create_triggered_webhooks_for_event pact, verification, event_name, event_context
|
18
|
+
webhooks = webhook_repository.find_webhooks_to_trigger(consumer: pact.consumer, provider: pact.provider, event_name: event_name)
|
19
|
+
|
20
|
+
if webhooks.any?
|
21
|
+
create_triggered_webhooks_for_webhooks(webhooks, pact, verification, event_name, event_context.merge(event_name: event_name))
|
22
|
+
else
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
16
27
|
def next_uuid
|
17
28
|
SecureRandom.uuid
|
18
29
|
end
|
19
30
|
|
20
|
-
# TODO support currently deployed
|
21
31
|
def test_execution webhook, event_context, execution_configuration
|
22
32
|
merged_options = execution_configuration.with_failure_log_message("Webhook execution failed").to_hash
|
23
33
|
|
@@ -36,17 +46,6 @@ module PactBroker
|
|
36
46
|
webhook_execution_result
|
37
47
|
end
|
38
48
|
|
39
|
-
# the main entry point
|
40
|
-
def create_triggered_webhooks_for_event pact, verification, event_name, event_context
|
41
|
-
webhooks = webhook_repository.find_webhooks_to_trigger(consumer: pact.consumer, provider: pact.provider, event_name: event_name)
|
42
|
-
|
43
|
-
if webhooks.any?
|
44
|
-
create_triggered_webhooks_for_webhooks(webhooks, pact, verification, event_name, event_context.merge(event_name: event_name))
|
45
|
-
else
|
46
|
-
[]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
49
|
def schedule_webhooks(triggered_webhooks, options)
|
51
50
|
triggered_webhooks.each_with_index do | triggered_webhook, i |
|
52
51
|
logger.info "Scheduling job for webhook with uuid #{triggered_webhook.webhook.uuid}, context: #{triggered_webhook.event_context}"
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require "
|
2
|
-
require "pact_broker/repositories/helpers"
|
1
|
+
require "pact_broker/dataset"
|
3
2
|
require "pact_broker/webhooks/execution"
|
4
3
|
require "pact_broker/hash_refinements"
|
5
4
|
|
@@ -23,7 +22,7 @@ module PactBroker
|
|
23
22
|
STATUS_FAILURE = "failure".freeze
|
24
23
|
|
25
24
|
dataset_module do
|
26
|
-
include PactBroker::
|
25
|
+
include PactBroker::Dataset
|
27
26
|
|
28
27
|
def delete
|
29
28
|
require "pact_broker/webhooks/execution"
|
@@ -70,7 +69,7 @@ module PactBroker
|
|
70
69
|
def execute options
|
71
70
|
# getting a random 'no method to_domain for null' error
|
72
71
|
# not sure on which object, so splitting this out into two lines
|
73
|
-
pact = pact_publication.to_domain
|
72
|
+
pact = pact_publication.with_version_branches_and_tags.to_domain
|
74
73
|
webhook.to_domain.execute(pact, verification, event_context.symbolize_keys, options)
|
75
74
|
end
|
76
75
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require "
|
1
|
+
require "pact_broker/dataset"
|
2
2
|
require "pact_broker/domain/webhook"
|
3
3
|
require "pact_broker/webhooks/webhook_request_template"
|
4
4
|
require "pact_broker/domain/pacticipant"
|
@@ -15,7 +15,7 @@ module PactBroker
|
|
15
15
|
one_to_many :events, :class => "PactBroker::Webhooks::WebhookEvent", :reciprocal => :webhook
|
16
16
|
|
17
17
|
dataset_module do
|
18
|
-
include PactBroker::
|
18
|
+
include PactBroker::Dataset
|
19
19
|
|
20
20
|
# Keep the triggered webhooks after the webhook has been deleted
|
21
21
|
def delete
|
@@ -1,5 +1,4 @@
|
|
1
|
-
require "
|
2
|
-
require "pact_broker/repositories/helpers"
|
1
|
+
require "pact_broker/dataset"
|
3
2
|
|
4
3
|
module PactBroker
|
5
4
|
module Webhooks
|
@@ -17,9 +16,7 @@ module PactBroker
|
|
17
16
|
|
18
17
|
EVENT_NAMES = [CONTRACT_PUBLISHED, CONTRACT_CONTENT_CHANGED, VERIFICATION_PUBLISHED, VERIFICATION_SUCCEEDED, VERIFICATION_FAILED, CONTRACT_REQUIRING_VERIFICATION_PUBLISHED]
|
19
18
|
|
20
|
-
dataset_module
|
21
|
-
include PactBroker::Repositories::Helpers
|
22
|
-
end
|
19
|
+
dataset_module(PactBroker::Dataset)
|
23
20
|
|
24
21
|
def contract_published?
|
25
22
|
name == CONTRACT_PUBLISHED
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Rack
|
2
|
+
module PactBroker
|
3
|
+
class AddCacheHeader
|
4
|
+
def initialize app
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
status, headers, body = @app.call(env)
|
10
|
+
[status, { "Cache-Control" => "no-cache" }.merge(headers || {}), body]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Sets the PactBroker::ApplicationContext on the rack env if it is not already set.
|
2
|
+
|
3
|
+
module Rack
|
4
|
+
module PactBroker
|
5
|
+
class ApplicationContext
|
6
|
+
def initialize(app, application_context)
|
7
|
+
@app = app
|
8
|
+
@application_context = application_context
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
@app.call({ "pactbroker.application_context" => @application_context }.merge(env))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
# Allows a default Rack
|
2
|
+
# Allows a default Rack middleware implementation to be set,
|
3
3
|
# and then be optionally changed out for a different implementation
|
4
4
|
# after the app has been built.
|
5
5
|
# Used for allowing the authorization code to set after the
|
@@ -12,6 +12,8 @@ module Rack
|
|
12
12
|
class InvalidUriProtection
|
13
13
|
include ::PactBroker::Messages
|
14
14
|
|
15
|
+
CONSECUTIVE_SLASH = /\/{2,}/
|
16
|
+
|
15
17
|
def initialize app
|
16
18
|
@app = app
|
17
19
|
end
|
@@ -19,12 +21,12 @@ module Rack
|
|
19
21
|
def call env
|
20
22
|
if (uri = valid_uri?(env))
|
21
23
|
if (error_message = validate(uri))
|
22
|
-
[422,
|
24
|
+
[422, headers, [body(env, error_message, "Unprocessable", "invalid-request-parameter-value", 422)]]
|
23
25
|
else
|
24
26
|
app.call(env)
|
25
27
|
end
|
26
28
|
else
|
27
|
-
[404,
|
29
|
+
[404, headers, [body(env, "Empty path component found", "Not Found", "not-found", 404)]]
|
28
30
|
end
|
29
31
|
end
|
30
32
|
|
@@ -34,7 +36,9 @@ module Rack
|
|
34
36
|
|
35
37
|
def valid_uri? env
|
36
38
|
begin
|
37
|
-
parse(::Rack::Request.new(env).url)
|
39
|
+
uri = parse(::Rack::Request.new(env).url)
|
40
|
+
return nil if CONSECUTIVE_SLASH.match(uri.path)
|
41
|
+
uri
|
38
42
|
rescue URI::InvalidURIError, ArgumentError
|
39
43
|
nil
|
40
44
|
end
|
@@ -52,6 +56,18 @@ module Rack
|
|
52
56
|
message("errors.tab_in_url_path")
|
53
57
|
end
|
54
58
|
end
|
59
|
+
|
60
|
+
def headers
|
61
|
+
{"Content-Type" => "application/problem+json"}
|
62
|
+
end
|
63
|
+
|
64
|
+
def body(env, detail, title, type, status)
|
65
|
+
env["pactbroker.application_context"]
|
66
|
+
.decorator_configuration
|
67
|
+
.class_for(:custom_error_problem_json_decorator)
|
68
|
+
.new(detail: detail, title: title, type: type, status: status)
|
69
|
+
.to_json(user_options: { base_url: env["pactbroker.base_url"] })
|
70
|
+
end
|
55
71
|
end
|
56
72
|
end
|
57
73
|
end
|