pact_broker 2.107.1 → 2.109.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
@@ -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
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# A Sequel model used for identifying potential and required integrations
|
|
2
|
+
# between the versions described by the specified selectors
|
|
3
|
+
# and other applications.
|
|
4
|
+
# It is only meant to be used via the public dataset methods.
|
|
5
|
+
|
|
6
|
+
module PactBroker
|
|
7
|
+
module Matrix
|
|
8
|
+
class IntegrationRow < Sequel::Model(Sequel.as(:latest_pact_publication_ids_for_consumer_versions, :p))
|
|
9
|
+
dataset_module do
|
|
10
|
+
select(:select_pacticipant_ids, Sequel[:p][:consumer_id], Sequel[:p][:provider_id])
|
|
11
|
+
|
|
12
|
+
# Return the distinct consumer/provider ids and names for the integrations which involve the given resolved selector
|
|
13
|
+
# in the role of consumer. The resolved selector must have a pacticipant_id, and may or may not have a pacticipant_version_id.
|
|
14
|
+
# @public
|
|
15
|
+
# @param [PactBroker::Matrix::ResolvedSelector] resolved_selector
|
|
16
|
+
# @return [Sequel::Dataset] for rows with consumer_id, consumer_name, provider_id and provider_name
|
|
17
|
+
def integrations_for_selector_as_consumer(resolved_selector)
|
|
18
|
+
select(:consumer_id, :provider_id)
|
|
19
|
+
.distinct
|
|
20
|
+
.where({ consumer_id: resolved_selector.pacticipant_id, consumer_version_id: resolved_selector.pacticipant_version_id }.compact)
|
|
21
|
+
.from_self(alias: :integrations)
|
|
22
|
+
.select(:consumer_id, :provider_id, Sequel[:consumers][:name].as(:consumer_name), Sequel[:providers][:name].as(:provider_name))
|
|
23
|
+
.join_consumers(:integrations, :consumers)
|
|
24
|
+
.join_providers(:integrations, :providers)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Find all the integrations (consumer/provider pairs) that involve ONLY the given selectors.
|
|
28
|
+
# @public
|
|
29
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
|
|
30
|
+
# @return [Sequel::Dataset] for rows with consumer_id, consumer_name, provider_id and provider_name
|
|
31
|
+
def distinct_integrations_between_given_selectors(resolved_selectors)
|
|
32
|
+
if resolved_selectors.size == 1
|
|
33
|
+
raise ArgumentError.new("Expected multiple selectors to be provided, but only received one #{selectors}")
|
|
34
|
+
end
|
|
35
|
+
query = pact_publications_matching_selectors_as_consumer(resolved_selectors)
|
|
36
|
+
.select_pacticipant_ids
|
|
37
|
+
.distinct
|
|
38
|
+
|
|
39
|
+
query.from_self(alias: :pacticipant_ids)
|
|
40
|
+
.select(
|
|
41
|
+
:consumer_id,
|
|
42
|
+
Sequel[:c][:name].as(:consumer_name),
|
|
43
|
+
:provider_id,
|
|
44
|
+
Sequel[:p][:name].as(:provider_name)
|
|
45
|
+
)
|
|
46
|
+
.join_consumers(:pacticipant_ids, :c)
|
|
47
|
+
.join_providers(:pacticipant_ids, :p)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @public
|
|
51
|
+
def join_consumers qualifier = :p, table_alias = :consumers
|
|
52
|
+
join(
|
|
53
|
+
:pacticipants,
|
|
54
|
+
{ Sequel[qualifier][:consumer_id] => Sequel[table_alias][:id] },
|
|
55
|
+
{ table_alias: table_alias }
|
|
56
|
+
)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @public
|
|
60
|
+
def join_providers qualifier = :p, table_alias = :providers
|
|
61
|
+
join(
|
|
62
|
+
:pacticipants,
|
|
63
|
+
{ Sequel[qualifier][:provider_id] => Sequel[table_alias][:id] },
|
|
64
|
+
{ table_alias: table_alias }
|
|
65
|
+
)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# @private
|
|
69
|
+
def pact_publications_matching_selectors_as_consumer(resolved_selectors)
|
|
70
|
+
pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
|
|
71
|
+
|
|
72
|
+
self
|
|
73
|
+
.select_pacticipant_ids
|
|
74
|
+
.distinct
|
|
75
|
+
.inner_join_versions_for_selectors_as_consumer(resolved_selectors)
|
|
76
|
+
.where(provider_id: pacticipant_ids)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# @private
|
|
80
|
+
def inner_join_versions_for_selectors_as_consumer(resolved_selectors)
|
|
81
|
+
# get the UnresolvedSelector objects back out of the resolved_selectors because the Version.for_selector() method uses the UnresolvedSelector
|
|
82
|
+
unresolved_selectors = resolved_selectors.collect(&:original_selector).uniq
|
|
83
|
+
versions = PactBroker::Domain::Version.ids_for_selectors(unresolved_selectors)
|
|
84
|
+
inner_join_versions_dataset(versions)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @private
|
|
88
|
+
def inner_join_versions_dataset(versions)
|
|
89
|
+
versions_join = { Sequel[:p][:consumer_version_id] => Sequel[:versions][:id] }
|
|
90
|
+
join(versions, versions_join, table_alias: :versions)
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
require "pact_broker/matrix/integration_row"
|
|
2
|
+
# A "find only" repository for the PactBroker::Matrix::Integration object.
|
|
3
|
+
# The PactBroker::Matrix::Integration object is not a Sequel Model like the PactBroker::Integrations::Integration - it is built from the
|
|
4
|
+
# matrix data specifically for a given matrix query, and as well as the consumer/provider attributes, it also
|
|
5
|
+
# knows whether or not that particular depdency is required in the context of the specific matrix query.
|
|
6
|
+
# eg. a HTTP consumer will always require that a provider is deployed, but a provider can be deployed if the consumer does not exist
|
|
7
|
+
# in the given environment yet.
|
|
8
|
+
# The "integrations for selectors" query is used to work out what what integrations are involved for a can-i-deploy query.
|
|
9
|
+
|
|
10
|
+
module PactBroker
|
|
11
|
+
module Matrix
|
|
12
|
+
class IntegrationsRepository
|
|
13
|
+
# Find all the Integrations required for this query, using the options to determine whether to find
|
|
14
|
+
# the inferred integrations or not.
|
|
15
|
+
# The infer_selectors_for_integrations only makes a difference when there are multiple selectors.
|
|
16
|
+
# When it is false, then only integrations are returned that exist *between* the versions of
|
|
17
|
+
# the selectors. When it is true, then all integrations that involve any of the versions of the selectors
|
|
18
|
+
# are returned.
|
|
19
|
+
#
|
|
20
|
+
# eg.
|
|
21
|
+
# Foo v1 has verified contract with Bar v2
|
|
22
|
+
# Waffle v3 has verified contract with Bar v2
|
|
23
|
+
# Foo v1 has unverified contract with Frog
|
|
24
|
+
#
|
|
25
|
+
# With selectors Foo v1 and Bar v2, and infer_selectors_for_integrations false, the returned integrations are Foo/Bar
|
|
26
|
+
# With the same selectors and infer_selectors_for_integrations true, the returned integrations are Foo/Bar, Waffle/Bar and Foo/Frog.
|
|
27
|
+
#
|
|
28
|
+
# When there is a single selector, the result is exactly the same whether infer_selectors_for_integrations is true or false.
|
|
29
|
+
#
|
|
30
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_specified_selectors
|
|
31
|
+
# @param [Boolean] infer_selectors_for_integrations
|
|
32
|
+
# @return [Array<PactBroker::Matrix::Integration>]
|
|
33
|
+
def find_integrations_for_specified_selectors(resolved_specified_selectors, infer_selectors_for_integrations)
|
|
34
|
+
if infer_selectors_for_integrations || resolved_specified_selectors.size == 1
|
|
35
|
+
find_integrations_involving_any_specfied_selectors(resolved_specified_selectors).sort_by(&:pacticipant_names)
|
|
36
|
+
else
|
|
37
|
+
find_integrations_between_specified_selectors(resolved_specified_selectors).sort_by(&:pacticipant_names)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# Find the Integrations that only involve the versions from the selectors specifed in the query.
|
|
44
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_specified_selectors
|
|
45
|
+
# @return [Array<PactBroker::Matrix::Integration>]
|
|
46
|
+
def find_integrations_between_specified_selectors(resolved_specified_selectors)
|
|
47
|
+
specified_pacticipant_names = resolved_specified_selectors.collect(&:pacticipant_name)
|
|
48
|
+
IntegrationRow
|
|
49
|
+
.distinct_integrations_between_given_selectors(resolved_specified_selectors)
|
|
50
|
+
.all
|
|
51
|
+
.collect(&:to_hash)
|
|
52
|
+
.collect do | integration_hash |
|
|
53
|
+
required = is_a_row_for_this_integration_required?(specified_pacticipant_names, integration_hash[:consumer_name])
|
|
54
|
+
Integration.from_hash(integration_hash.merge(required: required))
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Find all Integrations where any of the specified selectors are involved.
|
|
59
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_specified_selectors
|
|
60
|
+
# @return [Array<PactBroker::Matrix::Integration>]
|
|
61
|
+
def find_integrations_involving_any_specfied_selectors(resolved_specified_selectors)
|
|
62
|
+
integrations = integrations_where_specified_selector_is_consumer(resolved_specified_selectors) +
|
|
63
|
+
integrations_where_specified_selector_is_provider(resolved_specified_selectors)
|
|
64
|
+
deduplicate_integrations(integrations)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Find all the providers for the consumer versions specified in the query.
|
|
68
|
+
# We must identify the providers for the consumer *versions*, not just the *consumers* (via the integrations table)
|
|
69
|
+
# because the providers may change over time, as integrations get added and removed.
|
|
70
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] the resolved selectors that were specified in the query
|
|
71
|
+
# @return [Array<PactBroker::Matrix::Integration>]
|
|
72
|
+
def integrations_where_specified_selector_is_consumer(resolved_specified_selectors)
|
|
73
|
+
resolved_specified_selectors.flat_map do | selector |
|
|
74
|
+
# Could optimise this to all in one query, but it's a small gain
|
|
75
|
+
IntegrationRow
|
|
76
|
+
.integrations_for_selector_as_consumer(selector)
|
|
77
|
+
.all
|
|
78
|
+
.collect do | integration |
|
|
79
|
+
Integration.from_hash(
|
|
80
|
+
consumer_id: integration[:consumer_id],
|
|
81
|
+
consumer_name: integration[:consumer_name],
|
|
82
|
+
provider_id: integration[:provider_id],
|
|
83
|
+
provider_name: integration[:provider_name],
|
|
84
|
+
required: true # consumer requires the provider to be present
|
|
85
|
+
)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# Returns a list of *potential* integrations for the pacticipants in the selectors, where the pacticipant is a provider.
|
|
91
|
+
# Can't tell from the verifications table if a particular provider version has a consumer, as that is determined
|
|
92
|
+
# by what is deployed to the environment, not what is verified. By looking in the integration table, we can identify
|
|
93
|
+
# what consumers *may* be present in the target environment.
|
|
94
|
+
# Find all the consumers for the providers specified in the query. Does not take into consideration the provider version (not sure why).
|
|
95
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] the resolved selectors that were specified in the query
|
|
96
|
+
# @return [Array<PactBroker::Matrix::Integration>]
|
|
97
|
+
def integrations_where_specified_selector_is_provider(resolved_specified_selectors)
|
|
98
|
+
integrations_involving_specified_providers = PactBroker::Integrations::Integration
|
|
99
|
+
.where(provider_id: resolved_specified_selectors.collect(&:pacticipant_id))
|
|
100
|
+
.eager(:consumer, :provider)
|
|
101
|
+
.all
|
|
102
|
+
|
|
103
|
+
integrations_involving_specified_providers.collect do | integration |
|
|
104
|
+
Integration.from_hash(
|
|
105
|
+
consumer_id: integration.consumer.id,
|
|
106
|
+
consumer_name: integration.consumer.name,
|
|
107
|
+
provider_id: integration.provider.id,
|
|
108
|
+
provider_name: integration.provider.name,
|
|
109
|
+
required: false # provider does not require the consumer to be present
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# Deduplicate a list of Integrations
|
|
115
|
+
# @param [Array<PactBroker::Matrix::Integration>] integrations
|
|
116
|
+
# @return [Array<PactBroker::Matrix::Integration>]
|
|
117
|
+
def deduplicate_integrations(integrations)
|
|
118
|
+
integrations
|
|
119
|
+
.group_by{ | integration| [integration.consumer_id, integration.provider_id] }
|
|
120
|
+
.values
|
|
121
|
+
.collect { | duplicate_integrations | duplicate_integrations.find(&:required?) || duplicate_integrations.first }
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# If a specified pacticipant is a consumer, then its provider is required to be deployed
|
|
125
|
+
# to the same environment before the consumer can be deployed.
|
|
126
|
+
# If a specified pacticipant is a provider only, then it may be deployed
|
|
127
|
+
# without the consumer being present, but cannot break an existing consumer.
|
|
128
|
+
def is_a_row_for_this_integration_required?(specified_pacticipant_names, consumer_name)
|
|
129
|
+
specified_pacticipant_names.include?(consumer_name)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
require "pact_broker/dataset"
|
|
2
|
+
require "pact_broker/logging"
|
|
3
|
+
require "pact_broker/pacts/pact_version"
|
|
4
|
+
require "pact_broker/domain/pacticipant"
|
|
5
|
+
require "pact_broker/domain/version"
|
|
6
|
+
require "pact_broker/domain/verification"
|
|
7
|
+
require "pact_broker/domain/tag"
|
|
8
|
+
require "pact_broker/pacts/pact_publication"
|
|
9
|
+
require "pact_broker/matrix/matrix_row_dataset_module"
|
|
10
|
+
require "pact_broker/matrix/matrix_row_instance_methods"
|
|
11
|
+
require "pact_broker/matrix/matrix_row_verification_dataset_module"
|
|
12
|
+
|
|
13
|
+
# The PactBroker::Matrix::MatrixRow represents a row in the table that is created when
|
|
14
|
+
# the consumer versions are joined to the provider versions via the pacts and verifications tables,
|
|
15
|
+
# aka "The Matrix". The difference between this class and the EveryRow class is that
|
|
16
|
+
# the EveryRow class includes results for overridden pact verisons and verifications (used only when there is no latestby
|
|
17
|
+
# set in the matrix query), where as the MatrixRow class only includes the latest pact for each consumer version,
|
|
18
|
+
# and the latest verification for each provider version.
|
|
19
|
+
|
|
20
|
+
module PactBroker
|
|
21
|
+
module Matrix
|
|
22
|
+
class MatrixRow < Sequel::Model(Sequel.as(:latest_pact_publication_ids_for_consumer_versions, :p))
|
|
23
|
+
|
|
24
|
+
class Verification < Sequel::Model(Sequel.as(:latest_verification_id_for_pact_version_and_provider_version, :v))
|
|
25
|
+
dataset_module do
|
|
26
|
+
select(:select_verification_columns_with_aliases,
|
|
27
|
+
Sequel[:v][:provider_version_id],
|
|
28
|
+
Sequel[:v][:verification_id],
|
|
29
|
+
Sequel[:v][:created_at].as(:provider_version_created_at),
|
|
30
|
+
Sequel[:v][:pact_version_id]
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
include PactBroker::Matrix::MatrixRowVerificationDatasetModule
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
PACT_COLUMNS_WITH_ALIASES = [
|
|
38
|
+
Sequel[:p][:consumer_id],
|
|
39
|
+
Sequel[:p][:provider_id],
|
|
40
|
+
Sequel[:p][:consumer_version_id],
|
|
41
|
+
Sequel[:p][:pact_publication_id],
|
|
42
|
+
Sequel[:p][:pact_version_id],
|
|
43
|
+
Sequel[:p][:created_at].as(:consumer_version_created_at),
|
|
44
|
+
Sequel[:p][:pact_publication_id].as(:pact_order)
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
ALL_COLUMNS_AFTER_JOIN = [
|
|
48
|
+
Sequel[:p][:consumer_id],
|
|
49
|
+
Sequel[:p][:provider_id],
|
|
50
|
+
Sequel[:p][:consumer_version_id],
|
|
51
|
+
Sequel[:p][:pact_publication_id],
|
|
52
|
+
Sequel[:p][:pact_version_id],
|
|
53
|
+
Sequel[:p][:consumer_version_created_at],
|
|
54
|
+
Sequel[:p][:pact_order],
|
|
55
|
+
Sequel[:v][:verification_id],
|
|
56
|
+
Sequel[:v][:provider_version_id],
|
|
57
|
+
Sequel[:v][:provider_version_created_at]
|
|
58
|
+
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
# Must be kept in sync with PactBroker::Matrix::EveryRow
|
|
62
|
+
associate(:many_to_one, :pact_publication, :class => "PactBroker::Pacts::PactPublication", :key => :pact_publication_id, :primary_key => :id)
|
|
63
|
+
associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
|
|
64
|
+
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
|
|
65
|
+
associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id)
|
|
66
|
+
associate(:many_to_one, :provider_version, :class => "PactBroker::Domain::Version", :key => :provider_version_id, :primary_key => :id)
|
|
67
|
+
associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id)
|
|
68
|
+
associate(:many_to_one, :verification, class: "PactBroker::Domain::Verification", :key => :verification_id, :primary_key => :id)
|
|
69
|
+
associate(:one_to_many, :consumer_version_tags, :class => "PactBroker::Domain::Tag", primary_key: :consumer_version_id, key: :version_id)
|
|
70
|
+
associate(:one_to_many, :provider_version_tags, :class => "PactBroker::Domain::Tag", primary_key: :provider_version_id, key: :version_id)
|
|
71
|
+
|
|
72
|
+
dataset_module do
|
|
73
|
+
include PactBroker::Dataset
|
|
74
|
+
include PactBroker::Matrix::MatrixRowDatasetModule
|
|
75
|
+
|
|
76
|
+
select(:select_pact_columns_with_aliases, *PACT_COLUMNS_WITH_ALIASES)
|
|
77
|
+
select(:select_all_columns_after_join, *ALL_COLUMNS_AFTER_JOIN)
|
|
78
|
+
|
|
79
|
+
# @private
|
|
80
|
+
def verification_dataset
|
|
81
|
+
MatrixRow::Verification
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
include PactBroker::Matrix::MatrixRowInstanceMethods
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# The dataset methods used by both the MatrixRow and the EveryRow classes
|
|
2
|
+
# Requires the following methods to be defined on the model
|
|
3
|
+
# - verification_dataset
|
|
4
|
+
# - select_pact_columns_with_aliases
|
|
5
|
+
# - select_all_columns_after_join
|
|
6
|
+
|
|
7
|
+
module PactBroker
|
|
8
|
+
module Matrix
|
|
9
|
+
module MatrixRowDatasetModule
|
|
10
|
+
EAGER_LOADED_RELATIONSHIPS_FOR_VERSION = { current_deployed_versions: :environment, current_supported_released_versions: :environment, branch_versions: [:branch_head, :version, branch: :pacticipant] }
|
|
11
|
+
LAST_ACTION_DATE = Sequel.lit("CASE WHEN (provider_version_created_at IS NOT NULL AND provider_version_created_at > consumer_version_created_at) THEN provider_version_created_at ELSE consumer_version_created_at END").as(:last_action_date)
|
|
12
|
+
|
|
13
|
+
# The matrix query used to determine the final dataset
|
|
14
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
|
|
15
|
+
def matching_selectors(resolved_selectors, limit:)
|
|
16
|
+
if resolved_selectors.size == 1
|
|
17
|
+
matching_one_selector_for_either_consumer_or_provider(resolved_selectors, limit: limit)
|
|
18
|
+
else
|
|
19
|
+
matching_only_selectors_joining_verifications(resolved_selectors, limit: limit)
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# @public
|
|
24
|
+
def order_by_last_action_date
|
|
25
|
+
from_self(alias: :unordered_rows).select(LAST_ACTION_DATE, Sequel[:unordered_rows].* ).order(Sequel.desc(:last_action_date), Sequel.desc(:pact_order), Sequel.desc(:verification_id))
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# eager load tags?
|
|
29
|
+
# @public
|
|
30
|
+
def eager_all_the_things
|
|
31
|
+
eager(
|
|
32
|
+
:consumer,
|
|
33
|
+
:provider,
|
|
34
|
+
:verification,
|
|
35
|
+
:pact_publication,
|
|
36
|
+
:pact_version,
|
|
37
|
+
consumer_version: EAGER_LOADED_RELATIONSHIPS_FOR_VERSION,
|
|
38
|
+
provider_version: EAGER_LOADED_RELATIONSHIPS_FOR_VERSION,
|
|
39
|
+
consumer_version_tags: [:head_tag, { version: :pacticipant }],
|
|
40
|
+
provider_version_tags: [:head_tag, { version: :pacticipant }]
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Just for testing purposes
|
|
45
|
+
def default_scope
|
|
46
|
+
select_pact_columns_with_aliases
|
|
47
|
+
.from_self(alias: :p)
|
|
48
|
+
.left_outer_join_verifications
|
|
49
|
+
.select_all_columns_after_join
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# PRIVATE METHODS
|
|
53
|
+
|
|
54
|
+
# Final matrix query with one selector (not the normal use case)
|
|
55
|
+
# When we have one selector, we need to join ALL the verifications to find out
|
|
56
|
+
# what integrations exist
|
|
57
|
+
# @private
|
|
58
|
+
def matching_one_selector_for_either_consumer_or_provider(resolved_selectors, limit: )
|
|
59
|
+
if resolved_selectors.size != 1
|
|
60
|
+
raise ArgumentError.new("Expected one selector to be provided, but received #{resolved_selectors.size}: #{resolved_selectors}")
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# consumer
|
|
64
|
+
pact_publication_matching_consumer = select_pact_columns_with_aliases.most_recent(limit).from_self(alias: :p).inner_join_versions_for_selectors_as_consumer(resolved_selectors)
|
|
65
|
+
rows_where_selector_matches_consumer = pact_publication_matching_consumer.left_outer_join_verifications.select_all_columns_after_join
|
|
66
|
+
|
|
67
|
+
# provider
|
|
68
|
+
verifications_matching_provider = verification_dataset.matching_selectors_as_provider_for_any_consumer(resolved_selectors)
|
|
69
|
+
rows_where_selector_matches_provider = select_pact_columns_with_aliases.most_recent(limit).from_self(alias: :p).inner_join_verifications_dataset(verifications_matching_provider).select_all_columns_after_join
|
|
70
|
+
|
|
71
|
+
# union
|
|
72
|
+
rows_where_selector_matches_consumer.union(rows_where_selector_matches_provider)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Find the matrix rows
|
|
76
|
+
# When the user has specified multiple selectors, we only want to join the verifications for
|
|
77
|
+
# the specified selectors. This is because of the behaviour of the left outer join.
|
|
78
|
+
# Imagine a pact has been verified by a provider version that was NOT specified in the selectors.
|
|
79
|
+
# If we join all the verifications and THEN filter the rows to only show the versions specified
|
|
80
|
+
# in the selectors, we won't get a row for that pact, and hence, we won't
|
|
81
|
+
# know that it hasn't been verified by the provider version we're interested in.
|
|
82
|
+
# Instead, we need to filter the verifications dataset down to only the ones specified in the selectors first,
|
|
83
|
+
# and THEN join them to the pacts, so that we get a row for the pact with null provider version
|
|
84
|
+
# and verification fields.
|
|
85
|
+
# IDEA FOR OPTIMISATION - would it work to limit the pact_publications query and the verifications query to the limit of the overall query?
|
|
86
|
+
# @private
|
|
87
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
|
|
88
|
+
# @return [Sequel::Dataset<MatrixRow>]
|
|
89
|
+
def matching_only_selectors_joining_verifications(resolved_selectors, limit: )
|
|
90
|
+
pact_publications = matching_only_selectors_as_consumer(resolved_selectors, limit: limit)
|
|
91
|
+
verifications = verification_dataset.matching_only_selectors_as_provider(resolved_selectors)
|
|
92
|
+
|
|
93
|
+
specified_pacticipant_ids = resolved_selectors.select(&:specified?).collect(&:pacticipant_id).uniq
|
|
94
|
+
|
|
95
|
+
pact_publications
|
|
96
|
+
.from_self(alias: :p)
|
|
97
|
+
.select_all_columns_after_join
|
|
98
|
+
.left_outer_join_verifications_dataset(verifications)
|
|
99
|
+
.where(consumer_id: specified_pacticipant_ids).or(provider_id: specified_pacticipant_ids)
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
# Return pact publications where the consumer/consumer version is described by any of the resolved_selectors, AND the provider is described by any of the resolved selectors.
|
|
103
|
+
# @private
|
|
104
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
|
|
105
|
+
# @return [Sequel::Dataset<MatrixRow>]
|
|
106
|
+
def matching_only_selectors_as_consumer(resolved_selectors, limit: )
|
|
107
|
+
[
|
|
108
|
+
matching_only_selectors_as_consumer_where_only_pacticipant_name_in_selector(resolved_selectors, limit: limit),
|
|
109
|
+
matching_only_selectors_as_consumer_where_not_only_pacticipant_name_in_selector(resolved_selectors, limit: limit),
|
|
110
|
+
].compact.reduce(&:union)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
# Return pact publications where the consumer is described by any of the resolved_selectors *that only specify the pacticipant NAME*, AND the provider is described by any of the resolved selectors.
|
|
115
|
+
# If the original selector only specified the pacticipant name, we don't need to join to the versions table to identify the required pact_publications.
|
|
116
|
+
# Return nil if there are no resolved selectors where only the pacticipant name is specified.
|
|
117
|
+
# @private
|
|
118
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
|
|
119
|
+
# @return [Sequel::Dataset<MatrixRow>, nil]
|
|
120
|
+
def matching_only_selectors_as_consumer_where_only_pacticipant_name_in_selector(resolved_selectors, limit:)
|
|
121
|
+
all_pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
|
|
122
|
+
pacticipant_ids_for_pacticipant_only_selectors = resolved_selectors.select(&:only_pacticipant_name_specified?).collect(&:pacticipant_id).uniq
|
|
123
|
+
|
|
124
|
+
if pacticipant_ids_for_pacticipant_only_selectors.any?
|
|
125
|
+
select_pact_columns_with_aliases
|
|
126
|
+
.where(consumer_id: pacticipant_ids_for_pacticipant_only_selectors)
|
|
127
|
+
.where(provider_id: all_pacticipant_ids)
|
|
128
|
+
.most_recent(limit)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Return pact publications where the consumer *version* is described by any of the resolved_selectors
|
|
133
|
+
# *that specify more than just the pacticipant name*,
|
|
134
|
+
# AND the provider is described by any of the resolved selectors.
|
|
135
|
+
# If the selector uses any of the tag/branch/environment/latest attributes, we need to join to the versions table to identify the required pact_publications.
|
|
136
|
+
# Return nil if there are no resolved selectors where anything other than the pacticipant name is specified.
|
|
137
|
+
# @private
|
|
138
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
|
|
139
|
+
# @return [Sequel::Dataset<MatrixRow>, nil]
|
|
140
|
+
def matching_only_selectors_as_consumer_where_not_only_pacticipant_name_in_selector(resolved_selectors, limit:)
|
|
141
|
+
all_pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
|
|
142
|
+
resolved_selectors_with_versions_specified = resolved_selectors.reject(&:only_pacticipant_name_specified?)
|
|
143
|
+
|
|
144
|
+
if resolved_selectors_with_versions_specified.any?
|
|
145
|
+
select_pact_columns_with_aliases
|
|
146
|
+
.inner_join_versions_for_selectors_as_consumer(resolved_selectors_with_versions_specified)
|
|
147
|
+
.where(provider_id: all_pacticipant_ids)
|
|
148
|
+
.most_recent(limit)
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# @private
|
|
153
|
+
def inner_join_versions_for_selectors_as_consumer(resolved_selectors)
|
|
154
|
+
# get the UnresolvedSelector objects back out of the resolved_selectors because the Version.for_selector() method uses the UnresolvedSelector
|
|
155
|
+
unresolved_selectors = resolved_selectors.collect(&:original_selector).uniq
|
|
156
|
+
versions = PactBroker::Domain::Version.ids_for_selectors(unresolved_selectors)
|
|
157
|
+
inner_join_versions_dataset(versions)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# @private
|
|
161
|
+
def inner_join_versions_dataset(versions)
|
|
162
|
+
versions_join = { Sequel[:p][:consumer_version_id] => Sequel[:versions][:id] }
|
|
163
|
+
join(versions, versions_join, table_alias: :versions)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# @private
|
|
167
|
+
def left_outer_join_verifications
|
|
168
|
+
left_outer_join_verifications_dataset(verification_dataset.select_verification_columns_with_aliases)
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def left_outer_join_verifications_dataset(verifications)
|
|
172
|
+
left_outer_join(verifications, { Sequel[:p][:pact_version_id] => Sequel[:v][:pact_version_id] }, { table_alias: :v } )
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# @private
|
|
176
|
+
def inner_join_verifications_dataset(verifications_dataset)
|
|
177
|
+
join(verifications_dataset, { Sequel[:p][:pact_version_id] => Sequel[:v][:pact_version_id] }, { table_alias: :v } )
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def most_recent(limit)
|
|
181
|
+
order(Sequel.desc(:created_at)).limit(limit)
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|