pact_broker 2.107.1 → 2.108.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 +55 -0
- data/Gemfile +5 -4
- 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/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_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/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 +11 -6
- 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/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 -4
- 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/contracts_to_publish.rb +8 -0
- data/lib/pact_broker/contracts/service.rb +7 -1
- 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/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/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_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 +1 -1
- 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 +50 -1
- 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/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 +4 -4
- metadata +52 -29
- 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
@@ -1,26 +1,9 @@
|
|
1
|
-
require "pact_broker/
|
1
|
+
require "pact_broker/dataset"
|
2
2
|
require "pact_broker/domain/order_versions"
|
3
|
-
require "pact_broker/repositories/helpers"
|
4
|
-
require "pact_broker/tags/tag_with_latest_flag"
|
5
3
|
require "pact_broker/versions/eager_loaders"
|
6
4
|
|
7
5
|
module PactBroker
|
8
6
|
module Domain
|
9
|
-
|
10
|
-
# Same attributes as PactBroker::Tags::TagWithLatestFlag
|
11
|
-
class EagerTagWithLatestFlag < SimpleDelegator
|
12
|
-
attr_reader :latest
|
13
|
-
|
14
|
-
def initialize(tag, latest)
|
15
|
-
super(tag)
|
16
|
-
@latest = latest
|
17
|
-
end
|
18
|
-
|
19
|
-
def latest?
|
20
|
-
latest
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
7
|
VERSION_COLUMNS = [:id, :number, :repository_ref, :pacticipant_id, :order, :created_at, :updated_at, :build_url]
|
25
8
|
|
26
9
|
class Version < Sequel::Model(Sequel::Model.db[:versions].select(*VERSION_COLUMNS.collect{ | column | Sequel.qualify(:versions, column) }))
|
@@ -51,7 +34,7 @@ module PactBroker
|
|
51
34
|
eager_loader: PactBroker::Versions::EagerLoaders::LatestVersionForPacticipant
|
52
35
|
|
53
36
|
dataset_module do
|
54
|
-
include PactBroker::
|
37
|
+
include PactBroker::Dataset
|
55
38
|
|
56
39
|
def with_branch
|
57
40
|
where(id: PactBroker::Versions::BranchVersion.select(:version_id))
|
@@ -214,6 +197,7 @@ module PactBroker
|
|
214
197
|
end
|
215
198
|
|
216
199
|
# rubocop: disable Metrics/CyclomaticComplexity
|
200
|
+
# @param [PactBroker::Matrix::UnresolvedSelector] selector
|
217
201
|
def for_selector(selector)
|
218
202
|
query = self
|
219
203
|
query = query.where_pacticipant_name(selector.pacticipant_name) if selector.pacticipant_name
|
@@ -252,6 +236,15 @@ module PactBroker
|
|
252
236
|
end
|
253
237
|
# rubocop: enable Metrics/CyclomaticComplexity
|
254
238
|
|
239
|
+
# Return the IDs of the versions described by the given unresolved selectors
|
240
|
+
# @return Sequel::Dataset<PactBroker::Domain::Version>
|
241
|
+
def ids_for_selectors(unresolved_selectors)
|
242
|
+
# Need the select at the start and at the end to stop extra columns being returned (eg. branch name, environment name)
|
243
|
+
unresolved_selectors
|
244
|
+
.collect{ |selector| self.select(Sequel[:versions][:id]).for_selector(selector).select(:id) }
|
245
|
+
.reduce(&:union)
|
246
|
+
end
|
247
|
+
|
255
248
|
def pacticipants_set
|
256
249
|
from_self(alias: :v)
|
257
250
|
.select_group(Sequel[:v][:pacticipant_id])
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require "pact_broker/logging"
|
2
|
+
require "pact_broker/errors"
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Errors
|
6
|
+
class ErrorReporter
|
7
|
+
include PactBroker::Logging
|
8
|
+
|
9
|
+
def initialize(api_error_reporters)
|
10
|
+
@api_error_reporters = api_error_reporters
|
11
|
+
end
|
12
|
+
|
13
|
+
def call error, error_reference, env
|
14
|
+
if PactBroker::Errors.reportable_error?(error)
|
15
|
+
api_error_reporters.each do | error_reporter |
|
16
|
+
begin
|
17
|
+
error_reporter.call(error, env: env, error_reference: error_reference)
|
18
|
+
rescue StandardError => e
|
19
|
+
log_error(e, "Error executing api_error_reporter")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :api_error_reporters
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/pact_broker/errors.rb
CHANGED
@@ -1,28 +1,15 @@
|
|
1
|
-
require "pact_broker/configuration"
|
2
|
-
require "pact_broker/error"
|
3
|
-
require "pact_broker/logging"
|
4
1
|
require "securerandom"
|
5
2
|
|
6
3
|
module PactBroker
|
7
4
|
module Errors
|
8
|
-
include PactBroker::Logging
|
9
|
-
|
10
5
|
def self.generate_error_reference
|
11
6
|
SecureRandom.urlsafe_base64.gsub(/[^a-z]/i, "")[0,10]
|
12
7
|
end
|
13
8
|
|
9
|
+
# Return true if the error is one that should be reported to an external bug tracking system
|
10
|
+
# @return [Boolean]
|
14
11
|
def self.reportable_error?(error)
|
15
12
|
error.is_a?(PactBroker::TestError) || (!error.is_a?(PactBroker::Error) && !error.is_a?(JSON::JSONError))
|
16
13
|
end
|
17
|
-
|
18
|
-
def self.report error, error_reference, env
|
19
|
-
PactBroker.configuration.api_error_reporters.each do | error_notifier |
|
20
|
-
begin
|
21
|
-
error_notifier.call(error, env: env, error_reference: error_reference)
|
22
|
-
rescue StandardError => e
|
23
|
-
log_error(e, "Error executing api_error_reporter")
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
14
|
end
|
28
15
|
end
|
@@ -32,11 +32,19 @@ module PactBroker
|
|
32
32
|
extend self
|
33
33
|
|
34
34
|
def subscribe(*args)
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
if block_given?
|
36
|
+
result = nil
|
37
|
+
TemporaryListeners.subscribe(*args) do
|
38
|
+
result = yield
|
39
|
+
end
|
40
|
+
result
|
41
|
+
else
|
42
|
+
Wisper.subscribe(*args)
|
38
43
|
end
|
39
|
-
|
44
|
+
end
|
45
|
+
|
46
|
+
def unsubscribe(*args)
|
47
|
+
Wisper.unsubscribe(*args)
|
40
48
|
end
|
41
49
|
end
|
42
50
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require "pact_broker/repositories"
|
2
|
-
require "pact_broker/
|
2
|
+
require "pact_broker/domain/index_item"
|
3
3
|
|
4
4
|
module PactBroker
|
5
5
|
module Groups
|
@@ -8,13 +8,46 @@ module PactBroker
|
|
8
8
|
extend PactBroker::Repositories
|
9
9
|
extend PactBroker::Services
|
10
10
|
|
11
|
-
|
12
|
-
|
11
|
+
# Returns a list of all the integrations (PactBroker::Domain::IndexItem) that are connected to the given pacticipant.
|
12
|
+
# @param pacticipant [PactBroker::Domain::Pacticipant] the pacticipant for which to return the connected pacticipants
|
13
|
+
# @option max_pacticipants [Integer] the maximum number of pacticipants to return, or nil for no maximum. 40 is about the most applications you can meaningfully show in the circle network diagram.
|
14
|
+
# @return [PactBroker::Domain::Group]
|
15
|
+
def find_group_containing(pacticipant, max_pacticipants: nil)
|
16
|
+
PactBroker::Domain::Group.new(build_index_items(integrations_connected_to(pacticipant, max_pacticipants)))
|
13
17
|
end
|
14
18
|
|
15
|
-
def
|
16
|
-
|
19
|
+
def integrations_connected_to(pacticipant, max_pacticipants)
|
20
|
+
PactBroker::Integrations::Integration
|
21
|
+
.eager(:consumer, :provider)
|
22
|
+
.where(id: ids_of_integrations_connected_to(pacticipant, max_pacticipants))
|
23
|
+
.all
|
17
24
|
end
|
25
|
+
private_class_method :integrations_connected_to
|
26
|
+
|
27
|
+
def build_index_items(integrations)
|
28
|
+
integrations.collect do | integration |
|
29
|
+
PactBroker::Domain::IndexItem.new(integration.consumer, integration.provider)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
private_class_method :build_index_items
|
33
|
+
|
34
|
+
def ids_of_integrations_connected_to(pacticipant, max_pacticipants)
|
35
|
+
integrations = []
|
36
|
+
connected_pacticipants = Set.new([pacticipant.id])
|
37
|
+
new_connected_pacticipants = Set.new([pacticipant.id])
|
38
|
+
|
39
|
+
loop do
|
40
|
+
new_integrations = PactBroker::Integrations::Integration.including_pacticipant_id(new_connected_pacticipants.to_a).exclude(id: integrations.collect(&:id)).all
|
41
|
+
integrations.concat(new_integrations)
|
42
|
+
pacticipant_ids_for_new_integrations = Set.new(new_integrations.flat_map(&:pacticipant_ids))
|
43
|
+
new_connected_pacticipants = pacticipant_ids_for_new_integrations - connected_pacticipants
|
44
|
+
connected_pacticipants.merge(pacticipant_ids_for_new_integrations)
|
45
|
+
break if new_connected_pacticipants.empty? || (max_pacticipants && connected_pacticipants.size >= max_pacticipants)
|
46
|
+
end
|
47
|
+
|
48
|
+
integrations.collect(&:id).uniq
|
49
|
+
end
|
50
|
+
private_class_method :ids_of_integrations_connected_to
|
18
51
|
end
|
19
52
|
end
|
20
53
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require "pact_broker/repositories"
|
2
2
|
require "pact_broker/logging"
|
3
3
|
require "pact_broker/domain/index_item"
|
4
|
-
require "pact_broker/repositories/helpers"
|
5
4
|
require "pact_broker/index/page"
|
6
5
|
require "pact_broker/verifications/latest_verification_for_consumer_version_tag"
|
7
6
|
require "pact_broker/string_refinements"
|
@@ -74,7 +73,7 @@ module PactBroker
|
|
74
73
|
.eager(:provider)
|
75
74
|
.eager(pact_version: { latest_verification: { provider_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, :branch_heads, { tags: :head_tag } ] } })
|
76
75
|
.eager(integration: [{latest_verification: :provider_version}, :latest_triggered_webhooks])
|
77
|
-
.eager(consumer_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, :branch_heads, { tags: :head_tag }])
|
76
|
+
.eager(consumer_version: [{ current_deployed_versions: :environment }, { current_supported_released_versions: :environment }, :branch_versions, :branch_heads, { tags: :head_tag }])
|
78
77
|
.eager(:head_pact_publications_for_tags)
|
79
78
|
|
80
79
|
index_items = pact_publications.all.collect do | pact_publication |
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "pact_broker/services"
|
2
|
+
|
3
|
+
# Listens for events that happen in the Pact Broker that are relevant to the Integrations objects.
|
4
|
+
|
5
|
+
module PactBroker
|
6
|
+
module Integrations
|
7
|
+
class EventListener
|
8
|
+
include PactBroker::Services
|
9
|
+
|
10
|
+
# @param [Hash] params the params from the broadcast event
|
11
|
+
# @option params [PactBroker::Domain::Pact] :pact the newly published pact
|
12
|
+
def contract_published(params)
|
13
|
+
integration_service.handle_contract_data_published(params.fetch(:pact).consumer, params.fetch(:pact).provider)
|
14
|
+
end
|
15
|
+
|
16
|
+
# @param [Hash] params the params from the broadcast event
|
17
|
+
# @option params [PactBroker::Domain::Verification] :verification the newly published verification
|
18
|
+
def provider_verification_published(params)
|
19
|
+
integration_service.handle_contract_data_published(params.fetch(:verification).consumer, params.fetch(:verification).provider)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require "pact_broker/
|
1
|
+
require "pact_broker/dataset"
|
2
2
|
require "pact_broker/verifications/pseudo_branch_status"
|
3
3
|
require "pact_broker/domain/verification"
|
4
4
|
require "pact_broker/webhooks/latest_triggered_webhook"
|
@@ -7,7 +7,7 @@ require "pact_broker/verifications/latest_verification_for_consumer_and_provider
|
|
7
7
|
|
8
8
|
module PactBroker
|
9
9
|
module Integrations
|
10
|
-
class Integration < Sequel::Model(Sequel::Model.db[:integrations].select(:id, :consumer_id, :provider_id))
|
10
|
+
class Integration < Sequel::Model(Sequel::Model.db[:integrations].select(:id, :consumer_id, :provider_id, :contract_data_updated_at))
|
11
11
|
set_primary_key :id
|
12
12
|
plugin :insert_ignore, identifying_columns: [:consumer_id, :provider_id]
|
13
13
|
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
|
@@ -75,6 +75,20 @@ module PactBroker
|
|
75
75
|
end
|
76
76
|
end)
|
77
77
|
|
78
|
+
dataset_module do
|
79
|
+
include PactBroker::Dataset
|
80
|
+
|
81
|
+
def filter_by_pacticipant(query_string)
|
82
|
+
matching_pacticipants = PactBroker::Domain::Pacticipant.filter(:name, query_string)
|
83
|
+
pacticipants_join = Sequel.|({ Sequel[:integrations][:consumer_id] => Sequel[:p][:id] }, { Sequel[:integrations][:provider_id] => Sequel[:p][:id] })
|
84
|
+
join(matching_pacticipants, pacticipants_join, table_alias: :p)
|
85
|
+
end
|
86
|
+
|
87
|
+
def including_pacticipant_id(pacticipant_id)
|
88
|
+
where(consumer_id: pacticipant_id).or(provider_id: pacticipant_id)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
78
92
|
def self.compare_by_last_action_date a, b
|
79
93
|
if b.latest_pact_or_verification_publication_date && a.latest_pact_or_verification_publication_date
|
80
94
|
b.latest_pact_or_verification_publication_date <=> a.latest_pact_or_verification_publication_date
|
@@ -111,6 +125,14 @@ module PactBroker
|
|
111
125
|
def provider_name
|
112
126
|
provider.name
|
113
127
|
end
|
128
|
+
|
129
|
+
def pacticipant_ids
|
130
|
+
[consumer_id, provider_id]
|
131
|
+
end
|
132
|
+
|
133
|
+
def to_s
|
134
|
+
"Integration: consumer #{associations[:consumer]&.name || consumer_id}/provider #{associations[:provider]&.name || provider_id}"
|
135
|
+
end
|
114
136
|
end
|
115
137
|
end
|
116
138
|
end
|
@@ -1,14 +1,28 @@
|
|
1
1
|
require "pact_broker/integrations/integration"
|
2
|
+
require "pact_broker/repositories/scopes"
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Integrations
|
5
6
|
class Repository
|
7
|
+
|
8
|
+
include PactBroker::Repositories::Scopes
|
9
|
+
|
10
|
+
def find(filter_options = {}, pagination_options = {}, eager_load_associations = [])
|
11
|
+
query = scope_for(PactBroker::Integrations::Integration).select_all_qualified
|
12
|
+
query = query.filter_by_pacticipant(filter_options[:query_string]) if filter_options[:query_string]
|
13
|
+
query
|
14
|
+
.eager(*eager_load_associations)
|
15
|
+
.order(Sequel.desc(:contract_data_updated_at, nulls: :last))
|
16
|
+
.all_with_pagination_options(pagination_options)
|
17
|
+
end
|
18
|
+
|
6
19
|
def create_for_pact(consumer_id, provider_id)
|
7
20
|
if Integration.where(consumer_id: consumer_id, provider_id: provider_id).empty?
|
8
21
|
Integration.new(
|
9
22
|
consumer_id: consumer_id,
|
10
23
|
provider_id: provider_id,
|
11
|
-
created_at: Sequel.datetime_class.now
|
24
|
+
created_at: Sequel.datetime_class.now,
|
25
|
+
contract_data_updated_at: Sequel.datetime_class.now
|
12
26
|
).insert_ignore
|
13
27
|
end
|
14
28
|
nil
|
@@ -17,6 +31,25 @@ module PactBroker
|
|
17
31
|
def delete(consumer_id, provider_id)
|
18
32
|
Integration.where(consumer_id: consumer_id, provider_id: provider_id).delete
|
19
33
|
end
|
34
|
+
|
35
|
+
# Sets the contract_data_updated_at for the integration(s) as specified by the consumer and provider
|
36
|
+
# @param [PactBroker::Domain::Pacticipant, nil] consumer the consumer for the integration, or nil if for a provider-only event (eg. Pactflow provider contract published)
|
37
|
+
# @param [PactBroker::Domain::Pacticipant] provider the provider for the integration
|
38
|
+
def set_contract_data_updated_at(consumer, provider)
|
39
|
+
Integration
|
40
|
+
.where({ consumer_id: consumer&.id, provider_id: provider.id }.compact )
|
41
|
+
.update(contract_data_updated_at: Sequel.datetime_class.now)
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
# Sets the contract_data_updated_at for the integrations as specified by an array of objects which each have a consumer and provider
|
46
|
+
# @param [Array<Object>] where each object has a consumer and a provider
|
47
|
+
def set_contract_data_updated_at_for_multiple_integrations(objects_with_consumer_and_provider)
|
48
|
+
consumer_and_provider_ids = objects_with_consumer_and_provider.collect{ | object | [object.consumer.id, object.provider.id] }.uniq
|
49
|
+
Integration
|
50
|
+
.where([:consumer_id, :provider_id] => consumer_and_provider_ids)
|
51
|
+
.update(contract_data_updated_at: Sequel.datetime_class.now)
|
52
|
+
end
|
20
53
|
end
|
21
54
|
end
|
22
55
|
end
|
@@ -3,7 +3,6 @@ require "pact_broker/repositories"
|
|
3
3
|
require "pact_broker/logging"
|
4
4
|
require "pact_broker/integrations/integration"
|
5
5
|
require "pact_broker/db/models"
|
6
|
-
require "pact_broker/repositories/helpers"
|
7
6
|
require "pact_broker/repositories/scopes"
|
8
7
|
|
9
8
|
module PactBroker
|
@@ -14,22 +13,22 @@ module PactBroker
|
|
14
13
|
include PactBroker::Logging
|
15
14
|
extend PactBroker::Repositories::Scopes
|
16
15
|
|
17
|
-
def self.find_all
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
16
|
+
def self.find_all(filter_options = {}, pagination_options = {}, eager_load_associations = [])
|
17
|
+
integration_repository.find(filter_options, pagination_options, eager_load_associations)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Callback to invoke when a consumer contract, verification result (or provider contract in Pactflow) is published
|
21
|
+
# @param [PactBroker::Domain::Pacticipant] consumer or nil
|
22
|
+
# @param [PactBroker::Domain::Pacticipant] provider
|
23
|
+
def self.handle_contract_data_published(consumer, provider)
|
24
|
+
integration_repository.set_contract_data_updated_at(consumer, provider)
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
# Callback to invoke when a batch of contract data is published (eg. the publish contracts endpoint)
|
29
|
+
# @param [Array<Object>] where each object has a consumer and a provider
|
30
|
+
def self.handle_bulk_contract_data_published(objects_with_consumer_and_provider)
|
31
|
+
integration_repository.set_contract_data_updated_at_for_multiple_integrations(objects_with_consumer_and_provider)
|
33
32
|
end
|
34
33
|
|
35
34
|
def self.delete(consumer_name, provider_name)
|
@@ -49,7 +48,7 @@ module PactBroker
|
|
49
48
|
def self.delete_all
|
50
49
|
# TODO move all these into their own repositories
|
51
50
|
PactBroker::DB.each_integration_model do | model |
|
52
|
-
if PactBroker::
|
51
|
+
if PactBroker::Dataset::Helpers.postgres?
|
53
52
|
logger.info("Truncating ", model.table_name)
|
54
53
|
model.truncate(cascade: true)
|
55
54
|
else
|
@@ -1,22 +1,18 @@
|
|
1
1
|
require "pact_broker/domain/label"
|
2
|
-
require "pact_broker/repositories/helpers"
|
3
2
|
|
4
3
|
module PactBroker
|
5
4
|
module Labels
|
6
5
|
class Repository
|
7
|
-
|
8
|
-
include PactBroker::Repositories::Helpers
|
9
|
-
|
10
6
|
def create args
|
11
7
|
Domain::Label.new(name: args.fetch(:name), pacticipant: args.fetch(:pacticipant)).save
|
12
8
|
end
|
13
9
|
|
14
10
|
def find args
|
15
11
|
PactBroker::Domain::Label
|
16
|
-
.
|
17
|
-
.join(:pacticipants, {id: :pacticipant_id})
|
18
|
-
.where(name_like(Sequel.qualify("labels", "name"), args.fetch(:label_name)))
|
19
|
-
.where(name_like(Sequel.qualify("pacticipants", "name"), args.fetch(:pacticipant_name)))
|
12
|
+
.select_all_qualified
|
13
|
+
.join(:pacticipants, { id: :pacticipant_id })
|
14
|
+
.where(Sequel.name_like(Sequel.qualify("labels", "name"), args.fetch(:label_name)))
|
15
|
+
.where(Sequel.name_like(Sequel.qualify("pacticipants", "name"), args.fetch(:pacticipant_name)))
|
20
16
|
.single_record
|
21
17
|
end
|
22
18
|
|
@@ -59,7 +59,11 @@ en:
|
|
59
59
|
verifications: Add Pact verification tests to the %{provider_name} build. See https://docs.pact.io/go/provider_verification
|
60
60
|
webhooks: Configure separate %{provider_name} pact verification build and webhook to trigger it when the pact content changes. See https://docs.pact.io/go/webhooks
|
61
61
|
version_branch: Configure the version branch to be the value of your repository branch.
|
62
|
+
branch:
|
63
|
+
bulk_delete: "Scheduled deletion of %{count} branches for pacticipant %{pacticipant_name}. Remaining branches are: %{remaining}"
|
62
64
|
errors:
|
65
|
+
runtime:
|
66
|
+
with_error_reference: "An error has occurred. The details have been logged with the reference %{error_reference}"
|
63
67
|
validation:
|
64
68
|
no_spaces: "cannot contain spaces"
|
65
69
|
single_line: "cannot contain multiple lines"
|
@@ -89,6 +93,7 @@ en:
|
|
89
93
|
environment_with_name_not_found: "Environment with name '%{name}' does not exist"
|
90
94
|
cannot_modify_version_branch: "The branch for a pacticipant version cannot be changed once set (currently '%{old_branch}', proposed value '%{new_branch}'). Your pact publication/verification publication configurations may be in conflict with each other if you are seeing this error. If the current branch value is incorrect, you must delete the pacticipant version resource at %{version_url} and publish the pacts/verification results again with a consistent branch name."
|
91
95
|
invalid_content_for_content_type: "content could not be parsed as %{content_type}"
|
96
|
+
invalid_parsed_contract_class: "parsed content was expected to be a Hash but was a %{actual_class}"
|
92
97
|
cannot_set_currently_deployed_true: The currentlyDeployed property cannot be set back to true. Please record a new deployment.
|
93
98
|
cannot_set_currently_supported_true: The currentlySupported property cannot be set back to true. Please record a new deployment.
|
94
99
|
invalid_limit: The limit must be 1 or greater.
|
@@ -1,13 +1,45 @@
|
|
1
|
-
require "pact_broker/matrix/
|
1
|
+
require "pact_broker/matrix/matrix_row"
|
2
|
+
require "pact_broker/matrix/matrix_row_dataset_module"
|
3
|
+
require "pact_broker/matrix/matrix_row_instance_methods"
|
4
|
+
require "pact_broker/matrix/matrix_row_verification_dataset_module"
|
2
5
|
|
6
|
+
# Same as PactBroker::Matrix::MatrixRow
|
7
|
+
# except the data is sourced from the pact_publications table, and contains
|
8
|
+
# every pact publication, not just the latest publication for the consumer version.
|
9
|
+
# This is used when there is no "latestby" in the matrix query.
|
3
10
|
module PactBroker
|
4
11
|
module Matrix
|
5
|
-
class EveryRow <
|
6
|
-
set_dataset(Sequel.as(:pact_publications, :p))
|
12
|
+
class EveryRow < Sequel::Model(Sequel.as(:pact_publications, :p))
|
7
13
|
|
8
|
-
|
14
|
+
# Same as PactBroker::Matrix::MatrixRow::Verification
|
15
|
+
# except the data is sourced from the verifications table, and contains
|
16
|
+
# every verification, not just the latest verification for the pact version and the provider version.
|
17
|
+
# This is used when there is no "latestby" in the matrix query.
|
18
|
+
class Verification < Sequel::Model(:verifications)
|
19
|
+
dataset_module do
|
20
|
+
select(:select_verification_columns_with_aliases,
|
21
|
+
Sequel[:verifications][:id].as(:verification_id),
|
22
|
+
Sequel[:verifications][:provider_version_id],
|
23
|
+
Sequel[:verifications][:created_at].as(:provider_version_created_at),
|
24
|
+
Sequel[:verifications][:pact_version_id]
|
25
|
+
)
|
9
26
|
|
10
|
-
|
27
|
+
include PactBroker::Matrix::MatrixRowVerificationDatasetModule
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Must be kept in sync with PactBroker::Matrix::MatrixRow
|
32
|
+
associate(:many_to_one, :pact_publication, :class => "PactBroker::Pacts::PactPublication", :key => :pact_publication_id, :primary_key => :id)
|
33
|
+
associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
|
34
|
+
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
|
35
|
+
associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id)
|
36
|
+
associate(:many_to_one, :provider_version, :class => "PactBroker::Domain::Version", :key => :provider_version_id, :primary_key => :id)
|
37
|
+
associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id)
|
38
|
+
associate(:many_to_one, :verification, class: "PactBroker::Domain::Verification", :key => :verification_id, :primary_key => :id)
|
39
|
+
associate(:one_to_many, :consumer_version_tags, :class => "PactBroker::Domain::Tag", primary_key: :consumer_version_id, key: :version_id)
|
40
|
+
associate(:one_to_many, :provider_version_tags, :class => "PactBroker::Domain::Tag", primary_key: :provider_version_id, key: :version_id)
|
41
|
+
|
42
|
+
PACT_COLUMNS_WITH_ALIASES = [
|
11
43
|
Sequel[:p][:consumer_id],
|
12
44
|
Sequel[:p][:provider_id],
|
13
45
|
Sequel[:p][:consumer_version_id],
|
@@ -18,50 +50,36 @@ module PactBroker
|
|
18
50
|
Sequel[:p][:id].as(:pact_order)
|
19
51
|
]
|
20
52
|
|
21
|
-
|
22
|
-
Sequel[:
|
53
|
+
ALL_COLUMNS_AFTER_JOIN = [
|
54
|
+
Sequel[:p][:consumer_id],
|
55
|
+
Sequel[:p][:provider_id],
|
56
|
+
Sequel[:p][:consumer_version_id],
|
57
|
+
Sequel[:p][:pact_publication_id],
|
58
|
+
Sequel[:p][:pact_version_id],
|
59
|
+
Sequel[:p][:pact_revision_number],
|
60
|
+
Sequel[:p][:consumer_version_created_at],
|
61
|
+
Sequel[:p][:pact_order],
|
62
|
+
Sequel[:v][:verification_id],
|
23
63
|
Sequel[:v][:provider_version_id],
|
24
|
-
Sequel[:v][:
|
64
|
+
Sequel[:v][:provider_version_created_at]
|
25
65
|
]
|
26
66
|
|
27
|
-
JOINED_VERIFICATION_COLUMNS = [:id, :pact_version_id, :provider_id, :provider_version_id, :created_at]
|
28
|
-
|
29
|
-
ALL_COLUMNS = PACT_COLUMNS + VERIFICATION_COLUMNS
|
30
|
-
|
31
|
-
SELECT_ALL_COLUMN_ARGS = [:select_all_columns] + ALL_COLUMNS
|
32
|
-
|
33
67
|
dataset_module do
|
34
|
-
|
68
|
+
include PactBroker::Matrix::MatrixRowDatasetModule
|
35
69
|
|
36
|
-
|
37
|
-
|
38
|
-
end
|
70
|
+
select(:select_pact_columns_with_aliases, *PACT_COLUMNS_WITH_ALIASES)
|
71
|
+
select(:select_all_columns_after_join, *ALL_COLUMNS_AFTER_JOIN)
|
39
72
|
|
40
|
-
def
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
def inner_join_verifications_matching_one_selector_provider_or_provider_version(query_ids)
|
45
|
-
verifications = db[:verifications]
|
46
|
-
.select(*JOINED_VERIFICATION_COLUMNS)
|
47
|
-
.where {
|
48
|
-
QueryBuilder.provider_or_provider_version_matches(query_ids)
|
49
|
-
}
|
50
|
-
|
51
|
-
join(verifications, P_V_JOIN, { table_alias: :v } )
|
73
|
+
def verification_dataset
|
74
|
+
EveryRow::Verification
|
52
75
|
end
|
76
|
+
end
|
53
77
|
|
54
|
-
|
55
|
-
|
56
|
-
.select(*JOINED_VERIFICATION_COLUMNS)
|
57
|
-
.where {
|
58
|
-
Sequel.&(
|
59
|
-
QueryBuilder.consumer_in_pacticipant_ids(query_ids),
|
60
|
-
QueryBuilder.provider_or_provider_version_matches(query_ids)
|
61
|
-
)
|
62
|
-
}
|
63
|
-
end
|
78
|
+
def pact_publication_id
|
79
|
+
return_or_raise_if_not_set(:pact_publication_id)
|
64
80
|
end
|
81
|
+
|
82
|
+
include PactBroker::Matrix::MatrixRowInstanceMethods
|
65
83
|
end
|
66
84
|
end
|
67
85
|
end
|