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
@@ -0,0 +1,150 @@
|
|
1
|
+
# The instance methods
|
2
|
+
module PactBroker
|
3
|
+
module Matrix
|
4
|
+
module MatrixRowInstanceMethods
|
5
|
+
def pact_version_sha
|
6
|
+
pact_version.sha
|
7
|
+
end
|
8
|
+
|
9
|
+
def pact_revision_number
|
10
|
+
pact_publication.revision_number
|
11
|
+
end
|
12
|
+
|
13
|
+
def verification_number
|
14
|
+
verification&.number
|
15
|
+
end
|
16
|
+
|
17
|
+
def success
|
18
|
+
verification&.success
|
19
|
+
end
|
20
|
+
|
21
|
+
def pact_created_at
|
22
|
+
pact_publication.created_at
|
23
|
+
end
|
24
|
+
|
25
|
+
def verification_executed_at
|
26
|
+
verification&.execution_date
|
27
|
+
end
|
28
|
+
|
29
|
+
# Add logic for ignoring case
|
30
|
+
def <=> other
|
31
|
+
comparisons = [
|
32
|
+
compare_name_asc(consumer_name, other.consumer_name),
|
33
|
+
compare_number_desc(consumer_version_order, other.consumer_version_order),
|
34
|
+
compare_number_desc(pact_revision_number, other.pact_revision_number),
|
35
|
+
compare_name_asc(provider_name, other.provider_name),
|
36
|
+
compare_number_desc(provider_version_order, other.provider_version_order),
|
37
|
+
compare_number_desc(verification_id, other.verification_id)
|
38
|
+
]
|
39
|
+
|
40
|
+
comparisons.find{|c| c != 0 } || 0
|
41
|
+
end
|
42
|
+
|
43
|
+
def compare_name_asc name1, name2
|
44
|
+
name1 <=> name2
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
"#{consumer_name} v#{consumer_version_number} #{provider_name} #{provider_version_number} #{success}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def compare_number_desc number1, number2
|
52
|
+
if number1 && number2
|
53
|
+
number2 <=> number1
|
54
|
+
elsif number1
|
55
|
+
1
|
56
|
+
else
|
57
|
+
-1
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def eql?(obj)
|
62
|
+
(obj.class == model) && (obj.values == values)
|
63
|
+
end
|
64
|
+
|
65
|
+
def pacticipant_names
|
66
|
+
[consumer_name, provider_name]
|
67
|
+
end
|
68
|
+
|
69
|
+
def involves_pacticipant_with_name?(pacticipant_name)
|
70
|
+
pacticipant_name.include?(pacticipant_name)
|
71
|
+
end
|
72
|
+
|
73
|
+
def provider_version_id
|
74
|
+
# null when not verified
|
75
|
+
values[:provider_version_id]
|
76
|
+
end
|
77
|
+
|
78
|
+
def verification_id
|
79
|
+
# null when not verified
|
80
|
+
return_or_raise_if_not_set(:verification_id)
|
81
|
+
end
|
82
|
+
|
83
|
+
def consumer_name
|
84
|
+
consumer.name
|
85
|
+
end
|
86
|
+
|
87
|
+
def consumer_version_number
|
88
|
+
consumer_version.number
|
89
|
+
end
|
90
|
+
|
91
|
+
def consumer_version_branch_versions
|
92
|
+
consumer_version.branch_versions
|
93
|
+
end
|
94
|
+
|
95
|
+
def consumer_version_deployed_versions
|
96
|
+
consumer_version.current_deployed_versions
|
97
|
+
end
|
98
|
+
|
99
|
+
def consumer_version_released_versions
|
100
|
+
consumer_version.current_supported_released_versions
|
101
|
+
end
|
102
|
+
|
103
|
+
def consumer_version_order
|
104
|
+
consumer_version.order
|
105
|
+
end
|
106
|
+
|
107
|
+
def provider_name
|
108
|
+
provider.name
|
109
|
+
end
|
110
|
+
|
111
|
+
def provider_version_number
|
112
|
+
provider_version&.number
|
113
|
+
end
|
114
|
+
|
115
|
+
def provider_version_branch_versions
|
116
|
+
provider_version&.branch_versions || []
|
117
|
+
end
|
118
|
+
|
119
|
+
def provider_version_deployed_versions
|
120
|
+
provider_version&.current_deployed_versions || []
|
121
|
+
end
|
122
|
+
|
123
|
+
def provider_version_released_versions
|
124
|
+
provider_version&.current_supported_released_versions || []
|
125
|
+
end
|
126
|
+
|
127
|
+
def provider_version_order
|
128
|
+
provider_version&.order
|
129
|
+
end
|
130
|
+
|
131
|
+
def last_action_date
|
132
|
+
return_or_raise_if_not_set(:last_action_date)
|
133
|
+
end
|
134
|
+
|
135
|
+
def has_verification?
|
136
|
+
!!verification_id
|
137
|
+
end
|
138
|
+
|
139
|
+
# This model needs the verifications and pacticipants joined to it
|
140
|
+
# before it can be used, as it's not a "real" model.
|
141
|
+
def return_or_raise_if_not_set(key)
|
142
|
+
if values.key?(key)
|
143
|
+
values[key]
|
144
|
+
else
|
145
|
+
raise "Required table not joined"
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
#
|
2
|
+
# The dataset methods to be included in the MatrixRow::Verification dataset module
|
3
|
+
# and the EveryRow::Verification dataset module.
|
4
|
+
# Expects the method `select_verification_columns_with_aliases` to be defined on the class
|
5
|
+
#
|
6
|
+
module PactBroker
|
7
|
+
module Matrix
|
8
|
+
module MatrixRowVerificationDatasetModule
|
9
|
+
# Verifications for the provider versions matching the given selectors, where the consumers match the pacticipants in the given selectors.
|
10
|
+
# @public
|
11
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] selectors
|
12
|
+
# @return [Sequel::Dataset<MatrixRow>]
|
13
|
+
def matching_only_selectors_as_provider(resolved_selectors)
|
14
|
+
[
|
15
|
+
matching_only_selectors_as_provider_where_only_pacticipant_name_in_selector(resolved_selectors),
|
16
|
+
matching_only_selectors_as_provider_where_not_only_pacticipant_name_in_selector(resolved_selectors)
|
17
|
+
].compact.reduce(&:union)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @public
|
21
|
+
# @return [Sequel::Dataset<Verification>, nil]
|
22
|
+
def matching_selectors_as_provider_for_any_consumer(resolved_selectors)
|
23
|
+
select_verification_columns_with_aliases
|
24
|
+
.inner_join_versions_for_selectors_as_provider(resolved_selectors)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Return verifications where the provider is described by any of the resolved_selectors *that only specify the pacticipant NAME*,
|
28
|
+
# AND the consumer is described by any of the resolved selectors.
|
29
|
+
# If the original selector only specified the pacticipant name, we don't need to join to the versions table to identify the required verifications.
|
30
|
+
# Return nil if there are no resolved selectors where only the pacticipant name is specified.
|
31
|
+
# @private
|
32
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
|
33
|
+
# @return [Sequel::Dataset<Verification>, nil]
|
34
|
+
def matching_only_selectors_as_provider_where_only_pacticipant_name_in_selector(resolved_selectors)
|
35
|
+
all_pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
|
36
|
+
pacticipant_ids_for_pacticipant_only_selectors = resolved_selectors.select(&:only_pacticipant_name_specified?).collect(&:pacticipant_id).uniq
|
37
|
+
|
38
|
+
if pacticipant_ids_for_pacticipant_only_selectors.any?
|
39
|
+
select_verification_columns_with_aliases
|
40
|
+
.where(provider_id: pacticipant_ids_for_pacticipant_only_selectors)
|
41
|
+
.where(consumer_id: all_pacticipant_ids)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# Return verifications where the provider *version* is described by any of the resolved_selectors
|
46
|
+
# *that specify more than just the pacticipant name*,
|
47
|
+
# AND the consumer is described by any of the resolved selectors.
|
48
|
+
# If the selector uses any of the tag/branch/environment/latest attributes, we need to join to the versions table to identify the required verifications.
|
49
|
+
# Return nil if there are no resolved selectors where anything other than the pacticipant name is specified.
|
50
|
+
# @private
|
51
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
|
52
|
+
# @return [Sequel::Dataset<Verification>, nil]
|
53
|
+
def matching_only_selectors_as_provider_where_not_only_pacticipant_name_in_selector(resolved_selectors)
|
54
|
+
# get the UnresolvedSelector objects back out of the resolved_selectors because the Version.for_selector() method uses the UnresolvedSelector
|
55
|
+
all_pacticipant_ids = resolved_selectors.collect(&:pacticipant_id).uniq
|
56
|
+
resolved_selectors_with_versions_specified = resolved_selectors.reject(&:only_pacticipant_name_specified?)
|
57
|
+
|
58
|
+
if resolved_selectors_with_versions_specified.any?
|
59
|
+
select_verification_columns_with_aliases
|
60
|
+
.inner_join_versions_for_selectors_as_provider(resolved_selectors_with_versions_specified)
|
61
|
+
.where(consumer_id: all_pacticipant_ids)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Don't think it's worth splitting this into 2 different queries for selectors with only pacticipant name/selectors with version properties,
|
66
|
+
# as it's unlikely for there ever to be a query through the UI or CLI that results in 1 selector which only has a pacticipant name in it.
|
67
|
+
# @private
|
68
|
+
# @param [Array<PactBroker::Matrix::ResolvedSelector>] resolved_selectors
|
69
|
+
# @return [Sequel::Dataset<Verification>]
|
70
|
+
def inner_join_versions_for_selectors_as_provider(resolved_selectors)
|
71
|
+
# get the UnresolvedSelector objects back out of the resolved_selectors because the Version.for_selector() method uses the UnresolvedSelector
|
72
|
+
unresolved_selectors = resolved_selectors.collect(&:original_selector).uniq
|
73
|
+
versions = PactBroker::Domain::Version.ids_for_selectors(unresolved_selectors)
|
74
|
+
join_versions_dataset(versions)
|
75
|
+
end
|
76
|
+
|
77
|
+
# @private
|
78
|
+
def join_versions_dataset(versions_dataset)
|
79
|
+
join(versions_dataset, { Sequel[self.model.table_name][:provider_version_id] => Sequel[:versions][:id] }, table_alias: :versions)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -1,71 +1,50 @@
|
|
1
|
-
require "pact_broker/
|
2
|
-
require "pact_broker/repositories/helpers"
|
3
|
-
require "pact_broker/matrix/quick_row"
|
1
|
+
require "pact_broker/matrix/matrix_row"
|
4
2
|
require "pact_broker/matrix/every_row"
|
5
|
-
require "pact_broker/error"
|
6
3
|
require "pact_broker/matrix/query_results"
|
7
4
|
require "pact_broker/matrix/integration"
|
8
5
|
require "pact_broker/matrix/query_results_with_deployment_status_summary"
|
9
|
-
require "pact_broker/matrix/resolved_selector"
|
10
6
|
require "pact_broker/matrix/unresolved_selector"
|
11
7
|
require "pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version"
|
8
|
+
require "pact_broker/matrix/integrations_repository"
|
9
|
+
require "pact_broker/matrix/resolved_selectors_builder"
|
10
|
+
require "pact_broker/matrix/row_ignorer"
|
11
|
+
require "pact_broker/matrix/integrations_repository"
|
12
12
|
|
13
13
|
module PactBroker
|
14
14
|
module Matrix
|
15
|
-
|
16
|
-
class Error < PactBroker::Error; end
|
17
|
-
|
18
15
|
class Repository
|
19
|
-
include PactBroker::Repositories::Helpers
|
20
16
|
include PactBroker::Repositories
|
21
|
-
include PactBroker::Logging
|
22
|
-
|
23
|
-
# TODO move latest verification logic in to database
|
24
17
|
|
25
18
|
# Used when using table_print to output query results
|
26
19
|
TP_COLS = [ :consumer_version_number, :pact_revision_number, :provider_version_number, :verification_number]
|
27
20
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
#
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
end
|
56
|
-
# rubocop: enable Metrics/CyclomaticComplexity
|
57
|
-
|
58
|
-
# Return the latest matrix row (pact/verification) for each consumer_version_number/provider_version_number
|
59
|
-
def find specified_selectors, options = {}
|
60
|
-
resolved_ignore_selectors = resolve_ignore_selectors(options)
|
61
|
-
resolved_specified_selectors = resolve_versions_and_add_ids(specified_selectors, :specified, resolved_ignore_selectors)
|
62
|
-
integrations = find_integrations_for_specified_selectors(resolved_specified_selectors, options)
|
63
|
-
resolved_selectors = add_any_inferred_selectors(resolved_specified_selectors, resolved_ignore_selectors, integrations, options)
|
64
|
-
considered_rows, ignored_rows = find_considered_and_ignored_rows(resolved_selectors, resolved_ignore_selectors, options)
|
65
|
-
QueryResults.new(considered_rows.sort, ignored_rows.sort, specified_selectors, options, resolved_selectors, resolved_ignore_selectors, integrations)
|
66
|
-
end
|
67
|
-
|
68
|
-
def find_for_consumer_and_provider pacticipant_1_name, pacticipant_2_name
|
21
|
+
GROUP_BY_CONSUMER_VERSION_AND_PROVIDER_VERSION = [:consumer_name, :consumer_version_number, :provider_name, :provider_version_number]
|
22
|
+
GROUP_BY_CONSUMER_VERSION_AND_PROVIDER = [:consumer_name, :consumer_version_number, :provider_name]
|
23
|
+
GROUP_BY_CONSUMER_AND_PROVIDER = [:consumer_name, :provider_name]
|
24
|
+
|
25
|
+
# THE METHOD for querying the Matrix
|
26
|
+
# @param [Array<PactBroker::Matrix::UnresolvedSelector>] unresolved_specified_selectors
|
27
|
+
# @param [Hash] options
|
28
|
+
def find(unresolved_specified_selectors, options = {})
|
29
|
+
infer_selectors = infer_selectors_for_integrations?(options)
|
30
|
+
resolved_selectors_builder = ResolvedSelectorsBuilder.new
|
31
|
+
resolved_selectors_builder.resolve_selectors(unresolved_specified_selectors, options.fetch(:ignore_selectors, []))
|
32
|
+
integrations = matrix_integration_repository.find_integrations_for_specified_selectors(resolved_selectors_builder.specified_selectors, infer_selectors)
|
33
|
+
resolved_selectors_builder.resolve_inferred_selectors(integrations, options) if infer_selectors
|
34
|
+
|
35
|
+
considered_rows, ignored_rows = find_considered_and_ignored_rows(resolved_selectors_builder.all_selectors, resolved_selectors_builder.ignore_selectors, options)
|
36
|
+
QueryResults.new(
|
37
|
+
considered_rows.sort,
|
38
|
+
ignored_rows.sort,
|
39
|
+
unresolved_specified_selectors,
|
40
|
+
options,
|
41
|
+
resolved_selectors_builder.all_selectors,
|
42
|
+
resolved_selectors_builder.ignore_selectors,
|
43
|
+
integrations
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
def find_for_consumer_and_provider(pacticipant_1_name, pacticipant_2_name)
|
69
48
|
selectors = [ UnresolvedSelector.new(pacticipant_name: pacticipant_1_name), UnresolvedSelector.new(pacticipant_name: pacticipant_2_name)]
|
70
49
|
options = { latestby: "cvpv" }
|
71
50
|
find(selectors, options)
|
@@ -73,88 +52,26 @@ module PactBroker
|
|
73
52
|
|
74
53
|
private
|
75
54
|
|
76
|
-
def
|
77
|
-
|
78
|
-
rows = apply_latestby(options, rows)
|
79
|
-
rows = apply_success_filter(rows, options)
|
80
|
-
considered_rows, ignored_rows = split_rows_into_considered_and_ignored(rows, resolved_ignore_selectors)
|
81
|
-
return considered_rows, ignored_rows
|
55
|
+
def matrix_integration_repository
|
56
|
+
PactBroker::Matrix::IntegrationsRepository.new
|
82
57
|
end
|
83
58
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
def find_integrations_for_specified_selectors_only(resolved_specified_selectors)
|
93
|
-
specified_pacticipant_names = resolved_specified_selectors.collect(&:pacticipant_name)
|
94
|
-
base_model_for_integrations
|
95
|
-
.distinct_integrations(resolved_specified_selectors, false)
|
96
|
-
.collect(&:to_hash)
|
97
|
-
.collect do | integration_hash |
|
98
|
-
required = is_a_row_for_this_integration_required?(specified_pacticipant_names, integration_hash[:consumer_name])
|
99
|
-
Integration.from_hash(integration_hash.merge(required: required))
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors)
|
104
|
-
integrations = integrations_where_specified_selector_is_consumer(resolved_specified_selectors) +
|
105
|
-
integrations_where_specified_selector_is_provider(resolved_specified_selectors)
|
106
|
-
deduplicate_integrations(integrations)
|
107
|
-
end
|
108
|
-
|
109
|
-
def integrations_where_specified_selector_is_consumer(resolved_specified_selectors)
|
110
|
-
resolved_specified_selectors.flat_map do | selector |
|
111
|
-
base_model_for_integrations
|
112
|
-
.distinct_integrations_for_selector_as_consumer(selector)
|
113
|
-
.all
|
114
|
-
.collect do | integration |
|
115
|
-
Integration.from_hash(
|
116
|
-
consumer_id: integration[:consumer_id],
|
117
|
-
consumer_name: integration[:consumer_name],
|
118
|
-
provider_id: integration[:provider_id],
|
119
|
-
provider_name: integration[:provider_name],
|
120
|
-
required: true # synchronous consumer requires the provider to be present
|
121
|
-
)
|
122
|
-
end
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# Why does the consumer equivalent of this method use the QuickRow distinct_integrations_for_selector_as_consumer
|
127
|
-
# while this method uses the Integration?
|
128
|
-
def integrations_where_specified_selector_is_provider(resolved_specified_selectors)
|
129
|
-
integrations_involving_specified_providers = PactBroker::Integrations::Integration
|
130
|
-
.where(provider_id: resolved_specified_selectors.collect(&:pacticipant_id))
|
131
|
-
.eager(:consumer, :provider)
|
132
|
-
.all
|
133
|
-
|
134
|
-
integrations_involving_specified_providers.collect do | integration |
|
135
|
-
Integration.from_hash(
|
136
|
-
consumer_id: integration.consumer.id,
|
137
|
-
consumer_name: integration.consumer.name,
|
138
|
-
provider_id: integration.provider.id,
|
139
|
-
provider_name: integration.provider.name,
|
140
|
-
required: false # synchronous provider does not require the consumer to be present
|
141
|
-
)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
def deduplicate_integrations(integrations)
|
146
|
-
integrations
|
147
|
-
.group_by{ | integration| [integration.consumer_id, integration.provider_id] }
|
148
|
-
.values
|
149
|
-
.collect { | duplicate_integrations | duplicate_integrations.find(&:required?) || duplicate_integrations.first }
|
59
|
+
# If the user has specified --to TAG or --to-environment ENVIRONMENT in the CLI
|
60
|
+
# (or nothing, which to defaults to latest=true - "with the latest version of the other integrated applications")
|
61
|
+
# we need to work out what the integrations are between the specified selectors and the other pacticipant versions
|
62
|
+
# in the target environment/branches/tags.
|
63
|
+
# @param [Hash] options the matrix options
|
64
|
+
# @return [Boolean]
|
65
|
+
def infer_selectors_for_integrations?(options)
|
66
|
+
options[:latest] || !!options[:tag] || !!options[:branch] || !!options[:environment_name] || options[:main_branch]
|
150
67
|
end
|
151
68
|
|
152
|
-
def
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
69
|
+
def find_considered_and_ignored_rows(all_resolved_selectors, resolved_ignore_selectors, options)
|
70
|
+
rows = query_matrix(all_resolved_selectors, options)
|
71
|
+
rows = apply_latestby(options, rows)
|
72
|
+
rows = apply_success_filter(rows, options)
|
73
|
+
considered_rows, ignored_rows = RowIgnorer.split_rows_into_considered_and_ignored(rows, resolved_ignore_selectors)
|
74
|
+
return considered_rows, ignored_rows
|
158
75
|
end
|
159
76
|
|
160
77
|
def apply_success_filter(rows_with_latest_by_applied, options)
|
@@ -167,36 +84,32 @@ module PactBroker
|
|
167
84
|
end
|
168
85
|
end
|
169
86
|
|
170
|
-
# If a specified pacticipant is a consumer, then its provider is required to be deployed
|
171
|
-
# to the same environment before the consumer can be deployed.
|
172
|
-
# If a specified pacticipant is a provider only, then it may be deployed
|
173
|
-
# without the consumer being present.
|
174
|
-
def is_a_row_for_this_integration_required?(specified_pacticipant_names, consumer_name)
|
175
|
-
specified_pacticipant_names.include?(consumer_name)
|
176
|
-
end
|
177
|
-
|
178
87
|
# rubocop: disable Metrics/CyclomaticComplexity
|
179
88
|
# It would be nicer to do this in the SQL, but it requires time that I don't have at the moment
|
180
|
-
def apply_latestby
|
89
|
+
def apply_latestby(options, lines)
|
181
90
|
return lines unless options[:latestby]
|
182
91
|
group_by_columns = case options[:latestby]
|
183
|
-
when "cvpv" then
|
184
|
-
when "cvp" then
|
185
|
-
when "cp" then
|
92
|
+
when "cvpv" then GROUP_BY_CONSUMER_VERSION_AND_PROVIDER_VERSION
|
93
|
+
when "cvp" then GROUP_BY_CONSUMER_VERSION_AND_PROVIDER
|
94
|
+
when "cp" then GROUP_BY_CONSUMER_AND_PROVIDER
|
186
95
|
end
|
187
96
|
|
188
97
|
# The group with the nil provider_version_numbers will be the results of the left outer join
|
189
98
|
# that don't have verifications, so we need to include them all.
|
190
|
-
|
99
|
+
|
100
|
+
lines
|
101
|
+
.group_by{ |line| group_by_columns.collect{ |key| line.send(key) } }
|
191
102
|
.values
|
192
|
-
.collect{ |
|
103
|
+
.collect { | grouped_lines |
|
104
|
+
grouped_lines.first.provider_version_number.nil? ? grouped_lines.first : grouped_lines.sort_by(&:provider_version_order).last
|
105
|
+
}
|
193
106
|
.flatten
|
194
107
|
end
|
195
108
|
# rubocop: enable Metrics/CyclomaticComplexity
|
196
109
|
|
197
|
-
def query_matrix
|
198
|
-
query = base_model(options)
|
199
|
-
.matching_selectors(
|
110
|
+
def query_matrix(all_resolved_selectors, options)
|
111
|
+
query = base_model(options)
|
112
|
+
.matching_selectors(all_resolved_selectors, limit: options[:limit])
|
200
113
|
.order_by_last_action_date
|
201
114
|
|
202
115
|
query = query.limit(options[:limit]) if options[:limit]
|
@@ -204,143 +117,7 @@ module PactBroker
|
|
204
117
|
end
|
205
118
|
|
206
119
|
def base_model(options = {})
|
207
|
-
options[:latestby] ?
|
208
|
-
end
|
209
|
-
|
210
|
-
def resolve_ignore_selectors(options)
|
211
|
-
resolve_versions_and_add_ids(options.fetch(:ignore_selectors, []), :ignored)
|
212
|
-
end
|
213
|
-
|
214
|
-
# To make it easy for pf to override
|
215
|
-
def base_model_for_integrations
|
216
|
-
QuickRow
|
217
|
-
end
|
218
|
-
|
219
|
-
# Find the version number for selectors with the latest and/or tag specified
|
220
|
-
def resolve_versions_and_add_ids(unresolved_selectors, selector_type, resolved_ignore_selectors = [])
|
221
|
-
names = unresolved_selectors.collect(&:pacticipant_name)
|
222
|
-
pacticipants = PactBroker::Domain::Pacticipant.where(name: names).to_a.group_by(&:name).transform_values(&:first)
|
223
|
-
unresolved_selectors.collect do | unresolved_selector |
|
224
|
-
pacticipant = pacticipants[unresolved_selector.pacticipant_name]
|
225
|
-
if pacticipant
|
226
|
-
versions = find_versions_for_selector(unresolved_selector)
|
227
|
-
build_resolved_selectors(pacticipant, versions, unresolved_selector, selector_type, resolved_ignore_selectors)
|
228
|
-
else
|
229
|
-
selector_for_non_existing_pacticipant(unresolved_selector, selector_type)
|
230
|
-
end
|
231
|
-
end.flatten
|
232
|
-
end
|
233
|
-
|
234
|
-
def find_versions_for_selector(selector)
|
235
|
-
# For selectors that just set the pacticipant name, there's no need to resolve the version -
|
236
|
-
# only the pacticipant ID will be used in the query
|
237
|
-
return nil if selector.all_for_pacticipant?
|
238
|
-
versions = version_repository.find_versions_for_selector(selector)
|
239
|
-
|
240
|
-
if selector.latest
|
241
|
-
[versions.first]
|
242
|
-
else
|
243
|
-
versions.empty? ? [nil] : versions
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
# When a single selector specifies multiple versions (eg. "all prod pacts"), this expands
|
248
|
-
# the single selector into one selector for each version.
|
249
|
-
def build_resolved_selectors(pacticipant, versions, unresolved_selector, selector_type, resolved_ignore_selectors)
|
250
|
-
if versions
|
251
|
-
one_of_many = versions.compact.size > 1
|
252
|
-
versions.collect do | version |
|
253
|
-
if version
|
254
|
-
selector_for_found_version(pacticipant, version, unresolved_selector, selector_type, one_of_many, resolved_ignore_selectors)
|
255
|
-
else
|
256
|
-
selector_for_non_existing_version(pacticipant, unresolved_selector, selector_type, resolved_ignore_selectors)
|
257
|
-
end
|
258
|
-
end
|
259
|
-
else
|
260
|
-
selector_for_all_versions_of_a_pacticipant(pacticipant, unresolved_selector, selector_type, resolved_ignore_selectors)
|
261
|
-
end
|
262
|
-
end
|
263
|
-
|
264
|
-
# The user has specified --to TAG or --to-environment ENVIRONMENT in the CLI
|
265
|
-
# (or nothing, which to defaults to latest=true - "with the latest version of the other integrated applications")
|
266
|
-
def infer_selectors_for_integrations?(options)
|
267
|
-
options[:latest] || options[:tag] || options[:branch] || options[:environment_name] || options[:main_branch]
|
268
|
-
end
|
269
|
-
|
270
|
-
# When only one selector is specified, (eg. checking to see if Foo version 2 can be deployed to prod),
|
271
|
-
# need to look up all integrated pacticipants, and determine their relevant (eg. latest prod) versions
|
272
|
-
def inferred_selectors(resolved_specified_selectors, resolved_ignore_selectors, integrations, options)
|
273
|
-
all_pacticipant_names = integrations.collect(&:pacticipant_names).flatten.uniq
|
274
|
-
specified_names = resolved_specified_selectors.collect{ |s| s[:pacticipant_name] }
|
275
|
-
inferred_pacticipant_names = all_pacticipant_names - specified_names
|
276
|
-
build_inferred_selectors(inferred_pacticipant_names, resolved_ignore_selectors, options)
|
277
|
-
end
|
278
|
-
|
279
|
-
def build_inferred_selectors(inferred_pacticipant_names, resolved_ignore_selectors, options)
|
280
|
-
selectors = inferred_pacticipant_names.collect do | pacticipant_name |
|
281
|
-
selector = UnresolvedSelector.new(pacticipant_name: pacticipant_name)
|
282
|
-
selector.tag = options[:tag] if options[:tag]
|
283
|
-
selector.branch = options[:branch] if options[:branch]
|
284
|
-
selector.main_branch = options[:main_branch] if options[:main_branch]
|
285
|
-
selector.latest = options[:latest] if options[:latest]
|
286
|
-
selector.environment_name = options[:environment_name] if options[:environment_name]
|
287
|
-
selector
|
288
|
-
end
|
289
|
-
resolve_versions_and_add_ids(selectors, :inferred, resolved_ignore_selectors)
|
290
|
-
end
|
291
|
-
|
292
|
-
def selector_for_non_existing_version(pacticipant, unresolved_selector, selector_type, resolved_ignore_selectors)
|
293
|
-
ignore = resolved_ignore_selectors.any? do | s |
|
294
|
-
s.pacticipant_id == pacticipant.id && s.only_pacticipant_name_specified?
|
295
|
-
end
|
296
|
-
ResolvedSelector.for_pacticipant_and_non_existing_version(pacticipant, unresolved_selector, selector_type, ignore)
|
297
|
-
end
|
298
|
-
|
299
|
-
# rubocop: disable Metrics/ParameterLists
|
300
|
-
def selector_for_found_version(pacticipant, version, unresolved_selector, selector_type, one_of_many, resolved_ignore_selectors)
|
301
|
-
ignore = resolved_ignore_selectors.any? do | s |
|
302
|
-
s.pacticipant_id == pacticipant.id && (s.only_pacticipant_name_specified? || s.pacticipant_version_id == version.id)
|
303
|
-
end
|
304
|
-
ResolvedSelector.for_pacticipant_and_version(pacticipant, version, unresolved_selector, selector_type, ignore, one_of_many)
|
305
|
-
end
|
306
|
-
# rubocop: enable Metrics/ParameterLists
|
307
|
-
|
308
|
-
def selector_for_all_versions_of_a_pacticipant(pacticipant, unresolved_selector, selector_type, resolved_ignore_selectors)
|
309
|
-
# Doesn't make sense to ignore this, as you can't have a can-i-deploy query
|
310
|
-
# for "all versions of a pacticipant". But whatever.
|
311
|
-
ignore = resolved_ignore_selectors.any? do | s |
|
312
|
-
s.pacticipant_id == pacticipant.id && s.only_pacticipant_name_specified?
|
313
|
-
end
|
314
|
-
ResolvedSelector.for_pacticipant(pacticipant, unresolved_selector, selector_type, ignore)
|
315
|
-
end
|
316
|
-
|
317
|
-
# only relevant for ignore selectors, validation stops this happening for the normal
|
318
|
-
# selectors
|
319
|
-
def selector_for_non_existing_pacticipant(unresolved_selector, selector_type)
|
320
|
-
ResolvedSelector.for_non_existing_pacticipant(unresolved_selector, selector_type, false)
|
321
|
-
end
|
322
|
-
|
323
|
-
def split_rows_into_considered_and_ignored(rows, resolved_ignore_selectors)
|
324
|
-
if resolved_ignore_selectors.any?
|
325
|
-
considered, ignored = [], []
|
326
|
-
rows.each do | row |
|
327
|
-
if ignore_row?(resolved_ignore_selectors, row)
|
328
|
-
ignored << row
|
329
|
-
else
|
330
|
-
considered << row
|
331
|
-
end
|
332
|
-
end
|
333
|
-
return considered, ignored
|
334
|
-
else
|
335
|
-
return rows, []
|
336
|
-
end
|
337
|
-
end
|
338
|
-
|
339
|
-
def ignore_row?(resolved_ignore_selectors, row)
|
340
|
-
resolved_ignore_selectors.any? do | s |
|
341
|
-
s.pacticipant_id == row.consumer_id && (s.only_pacticipant_name_specified? || s.pacticipant_version_id == row.consumer_version_id) ||
|
342
|
-
s.pacticipant_id == row.provider_id && (s.only_pacticipant_name_specified? || s.pacticipant_version_id == row.provider_version_id)
|
343
|
-
end
|
120
|
+
options[:latestby] ? MatrixRow : EveryRow
|
344
121
|
end
|
345
122
|
end
|
346
123
|
end
|