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.
Files changed (191) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -0
  3. data/Gemfile +5 -4
  4. data/README.md +1 -0
  5. data/db/migrations/20230615_add_integrations_contract_data_updated_at.rb +13 -0
  6. data/db/migrations/20230616_set_integrations_contract_data_updated_at.rb +11 -0
  7. data/db/migrations/20231002_add_version_id_index_to_released_version.rb +21 -0
  8. data/db/migrations/20231003_add_version_id_index_to_deployed_version.rb +21 -0
  9. data/docs/CONFIGURATION.md +10 -0
  10. data/lib/pact_broker/api/contracts/base_contract.rb +2 -1
  11. data/lib/pact_broker/api/contracts/dry_validation_errors_formatter.rb +2 -0
  12. data/lib/pact_broker/api/contracts/pagination_query_params_schema.rb +19 -0
  13. data/lib/pact_broker/api/contracts/publish_contracts_contract_contract.rb +29 -18
  14. data/lib/pact_broker/api/decorators/base_decorator.rb +40 -1
  15. data/lib/pact_broker/api/decorators/branch_decorator.rb +35 -0
  16. data/lib/pact_broker/api/decorators/branch_version_decorator.rb +16 -0
  17. data/lib/pact_broker/api/decorators/configuration.rb +19 -0
  18. data/lib/pact_broker/api/decorators/custom_error_problem_json_decorator.rb +1 -1
  19. data/lib/pact_broker/api/decorators/decorator_context_creator.rb +47 -2
  20. data/lib/pact_broker/api/decorators/deployed_version_decorator.rb +2 -1
  21. data/lib/pact_broker/api/decorators/deployed_versions_decorator.rb +2 -2
  22. data/lib/pact_broker/api/decorators/dry_validation_errors_decorator.rb +32 -0
  23. data/lib/pact_broker/api/decorators/dry_validation_errors_problem_json_decorator.rb +24 -0
  24. data/lib/pact_broker/api/decorators/embedded_branch_version_decorator.rb +2 -2
  25. data/lib/pact_broker/api/decorators/embedded_deployed_version_decorator.rb +30 -0
  26. data/lib/pact_broker/api/decorators/embedded_error_problem_json_decorator.rb +84 -0
  27. data/lib/pact_broker/api/decorators/embedded_released_version_decorator.rb +27 -0
  28. data/lib/pact_broker/api/decorators/embedded_version_decorator.rb +0 -3
  29. data/lib/pact_broker/api/decorators/error_decorator.rb +30 -0
  30. data/lib/pact_broker/api/decorators/extended_pact_decorator.rb +6 -1
  31. data/lib/pact_broker/api/decorators/integration_decorator.rb +3 -2
  32. data/lib/pact_broker/api/decorators/integrations_decorator.rb +3 -0
  33. data/lib/pact_broker/api/decorators/notices_decorator.rb +11 -0
  34. data/lib/pact_broker/api/decorators/pact_pacticipant_decorator.rb +1 -5
  35. data/lib/pact_broker/api/decorators/pact_versions_decorator.rb +0 -1
  36. data/lib/pact_broker/api/decorators/pact_webhooks_status_decorator.rb +0 -1
  37. data/lib/pact_broker/api/decorators/pacticipant_branches_decorator.rb +32 -0
  38. data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +11 -1
  39. data/lib/pact_broker/api/decorators/{pacticipant_collection_decorator.rb → pacticipants_decorator.rb} +8 -4
  40. data/lib/pact_broker/api/decorators/pagination_links.rb +2 -2
  41. data/lib/pact_broker/api/decorators/released_versions_decorator.rb +2 -2
  42. data/lib/pact_broker/api/decorators/runtime_error_problem_json_decorator.rb +2 -2
  43. data/lib/pact_broker/api/decorators/validation_errors_decorator.rb +30 -0
  44. data/lib/pact_broker/api/decorators/validation_errors_problem_json_decorator.rb +4 -6
  45. data/lib/pact_broker/api/decorators/version_decorator.rb +5 -3
  46. data/lib/pact_broker/api/decorators/versions_decorator.rb +24 -14
  47. data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +2 -0
  48. data/lib/pact_broker/api/middleware/configuration.rb +2 -0
  49. data/lib/pact_broker/api/pact_broker_urls.rb +18 -2
  50. data/lib/pact_broker/api/resources/after_reply.rb +15 -0
  51. data/lib/pact_broker/api/resources/all_webhooks.rb +3 -3
  52. data/lib/pact_broker/api/resources/badge_methods.rb +2 -1
  53. data/lib/pact_broker/api/resources/base_resource.rb +6 -4
  54. data/lib/pact_broker/api/resources/branch.rb +40 -0
  55. data/lib/pact_broker/api/resources/branch_versions.rb +59 -0
  56. data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_branch_to_environment_badge.rb +1 -1
  57. data/lib/pact_broker/api/resources/currently_deployed_versions_for_environment.rb +1 -1
  58. data/lib/pact_broker/api/resources/currently_supported_versions_for_environment.rb +1 -1
  59. data/lib/pact_broker/api/resources/dashboard.rb +10 -0
  60. data/lib/pact_broker/api/resources/deployed_versions_for_version_and_environment.rb +1 -1
  61. data/lib/pact_broker/api/resources/environments.rb +1 -1
  62. data/lib/pact_broker/api/resources/error_handler.rb +18 -52
  63. data/lib/pact_broker/api/resources/error_handling_methods.rb +40 -14
  64. data/lib/pact_broker/api/resources/error_response_generator.rb +23 -6
  65. data/lib/pact_broker/api/resources/event_methods.rb +15 -0
  66. data/lib/pact_broker/api/resources/filter_methods.rb +15 -0
  67. data/lib/pact_broker/api/resources/group.rb +11 -2
  68. data/lib/pact_broker/api/resources/index.rb +6 -0
  69. data/lib/pact_broker/api/resources/integrations.rb +18 -4
  70. data/lib/pact_broker/api/resources/latest_version.rb +2 -0
  71. data/lib/pact_broker/api/resources/pact.rb +11 -6
  72. data/lib/pact_broker/api/resources/pacticipant_branches.rb +67 -0
  73. data/lib/pact_broker/api/resources/pacticipants.rb +26 -7
  74. data/lib/pact_broker/api/resources/pacticipants_for_label.rb +2 -2
  75. data/lib/pact_broker/api/resources/pagination_methods.rb +11 -1
  76. data/lib/pact_broker/api/resources/verifications.rb +9 -4
  77. data/lib/pact_broker/api/resources/versions.rb +12 -0
  78. data/lib/pact_broker/api.rb +5 -0
  79. data/lib/pact_broker/app.rb +10 -4
  80. data/lib/pact_broker/application_context.rb +29 -25
  81. data/lib/pact_broker/async/after_reply.rb +30 -0
  82. data/lib/pact_broker/config/runtime_configuration.rb +9 -21
  83. data/lib/pact_broker/config/runtime_configuration_coercion_methods.rb +32 -2
  84. data/lib/pact_broker/config/runtime_configuration_database_methods.rb +1 -1
  85. data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +15 -5
  86. data/lib/pact_broker/configuration.rb +29 -12
  87. data/lib/pact_broker/contracts/contracts_to_publish.rb +8 -0
  88. data/lib/pact_broker/contracts/service.rb +7 -1
  89. data/lib/pact_broker/dataset/page.rb +22 -0
  90. data/lib/pact_broker/dataset.rb +122 -0
  91. data/lib/pact_broker/db/data_migrations/set_contract_data_updated_at_for_integrations.rb +47 -0
  92. data/lib/pact_broker/db/migrate_data.rb +1 -0
  93. data/lib/pact_broker/db/models.rb +1 -1
  94. data/lib/pact_broker/deployments/currently_deployed_version_id.rb +2 -5
  95. data/lib/pact_broker/deployments/deployed_version.rb +3 -3
  96. data/lib/pact_broker/deployments/environment.rb +0 -2
  97. data/lib/pact_broker/deployments/released_version.rb +4 -5
  98. data/lib/pact_broker/doc/views/index/pacticipant-branch.markdown +25 -0
  99. data/lib/pact_broker/domain/label.rb +6 -3
  100. data/lib/pact_broker/domain/pact.rb +10 -5
  101. data/lib/pact_broker/domain/pacticipant.rb +4 -34
  102. data/lib/pact_broker/domain/tag.rb +4 -5
  103. data/lib/pact_broker/domain/verification.rb +2 -4
  104. data/lib/pact_broker/domain/version.rb +12 -19
  105. data/lib/pact_broker/errors/error_reporter.rb +30 -0
  106. data/lib/pact_broker/errors.rb +2 -15
  107. data/lib/pact_broker/events/subscriber.rb +12 -4
  108. data/lib/pact_broker/feature_toggle.rb +1 -1
  109. data/lib/pact_broker/groups/service.rb +38 -5
  110. data/lib/pact_broker/index/service.rb +1 -2
  111. data/lib/pact_broker/integrations/event_listener.rb +23 -0
  112. data/lib/pact_broker/integrations/integration.rb +24 -2
  113. data/lib/pact_broker/integrations/repository.rb +34 -1
  114. data/lib/pact_broker/integrations/service.rb +17 -18
  115. data/lib/pact_broker/labels/repository.rb +4 -8
  116. data/lib/pact_broker/locale/en.yml +5 -0
  117. data/lib/pact_broker/matrix/every_row.rb +58 -40
  118. data/lib/pact_broker/matrix/integration_row.rb +95 -0
  119. data/lib/pact_broker/matrix/integrations_repository.rb +133 -0
  120. data/lib/pact_broker/matrix/matrix_row.rb +88 -0
  121. data/lib/pact_broker/matrix/matrix_row_dataset_module.rb +185 -0
  122. data/lib/pact_broker/matrix/matrix_row_instance_methods.rb +150 -0
  123. data/lib/pact_broker/matrix/matrix_row_verification_dataset_module.rb +83 -0
  124. data/lib/pact_broker/matrix/parse_query.rb +1 -0
  125. data/lib/pact_broker/matrix/repository.rb +62 -285
  126. data/lib/pact_broker/matrix/resolved_selector.rb +13 -4
  127. data/lib/pact_broker/matrix/resolved_selector_builder.rb +84 -0
  128. data/lib/pact_broker/matrix/resolved_selectors_builder.rb +39 -0
  129. data/lib/pact_broker/matrix/row_ignorer.rb +36 -0
  130. data/lib/pact_broker/matrix/selector_ignorer.rb +59 -0
  131. data/lib/pact_broker/matrix/selector_resolver.rb +130 -0
  132. data/lib/pact_broker/metrics/service.rb +4 -9
  133. data/lib/pact_broker/pacticipants/latest_version_for_pacticipant_eager_loader.rb +33 -0
  134. data/lib/pact_broker/pacticipants/repository.rb +7 -9
  135. data/lib/pact_broker/pacticipants/service.rb +2 -2
  136. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +2 -4
  137. data/lib/pact_broker/pacts/metadata.rb +3 -1
  138. data/lib/pact_broker/pacts/pact_publication.rb +23 -5
  139. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +5 -1
  140. data/lib/pact_broker/pacts/pact_version.rb +2 -3
  141. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +2 -5
  142. data/lib/pact_broker/pacts/placeholder_pact.rb +3 -1
  143. data/lib/pact_broker/pacts/repository.rb +12 -12
  144. data/lib/pact_broker/pacts/service.rb +1 -1
  145. data/lib/pact_broker/repositories.rb +9 -1
  146. data/lib/pact_broker/string_refinements.rb +4 -0
  147. data/lib/pact_broker/tags/head_pact_tags.rb +2 -5
  148. data/lib/pact_broker/tags/repository.rb +3 -7
  149. data/lib/pact_broker/test/test_data_builder.rb +50 -1
  150. data/lib/pact_broker/ui/controllers/groups.rb +2 -1
  151. data/lib/pact_broker/ui/view_models/matrix_line.rb +4 -4
  152. data/lib/pact_broker/ui/views/groups/show.html.erb +2 -1
  153. data/lib/pact_broker/verifications/latest_verification_for_consumer_and_provider.rb +0 -3
  154. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +2 -4
  155. data/lib/pact_broker/verifications/repository.rb +2 -5
  156. data/lib/pact_broker/verifications/sequence.rb +1 -4
  157. data/lib/pact_broker/verifications/service.rb +4 -0
  158. data/lib/pact_broker/version.rb +1 -1
  159. data/lib/pact_broker/versions/branch.rb +2 -5
  160. data/lib/pact_broker/versions/branch_head.rb +0 -3
  161. data/lib/pact_broker/versions/branch_repository.rb +76 -0
  162. data/lib/pact_broker/versions/branch_service.rb +13 -25
  163. data/lib/pact_broker/versions/branch_version.rb +0 -3
  164. data/lib/pact_broker/versions/branch_version_repository.rb +17 -0
  165. data/lib/pact_broker/versions/repository.rb +19 -2
  166. data/lib/pact_broker/versions/sequence.rb +1 -3
  167. data/lib/pact_broker/versions/service.rb +4 -0
  168. data/lib/pact_broker/webhooks/execution.rb +3 -7
  169. data/lib/pact_broker/webhooks/job.rb +16 -7
  170. data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +2 -2
  171. data/lib/pact_broker/webhooks/repository.rb +0 -1
  172. data/lib/pact_broker/webhooks/trigger_service.rb +11 -12
  173. data/lib/pact_broker/webhooks/triggered_webhook.rb +3 -4
  174. data/lib/pact_broker/webhooks/webhook.rb +2 -2
  175. data/lib/pact_broker/webhooks/webhook_event.rb +2 -5
  176. data/lib/rack/pact_broker/add_cache_header.rb +14 -0
  177. data/lib/rack/pact_broker/application_context.rb +16 -0
  178. data/lib/rack/pact_broker/configurable_make_it_later.rb +1 -1
  179. data/lib/rack/pact_broker/invalid_uri_protection.rb +19 -3
  180. data/lib/webmachine/describe_routes.rb +55 -39
  181. data/lib/webmachine/render_error_monkey_patch.rb +13 -4
  182. data/pact_broker.gemspec +4 -4
  183. metadata +52 -29
  184. data/lib/pact_broker/api/decorators/decorator_context.rb +0 -22
  185. data/lib/pact_broker/matrix/query_builder.rb +0 -90
  186. data/lib/pact_broker/matrix/query_ids.rb +0 -40
  187. data/lib/pact_broker/matrix/quick_row.rb +0 -458
  188. data/lib/pact_broker/relationships/groupify.rb +0 -45
  189. data/lib/pact_broker/repositories/helpers.rb +0 -96
  190. data/lib/pact_broker/repositories/page.rb +0 -24
  191. data/lib/pact_broker/tags/tag_with_latest_flag.rb +0 -28
@@ -1,458 +0,0 @@
1
- require "pact_broker/repositories/helpers"
2
- require "pact_broker/matrix/query_builder"
3
- require "sequel"
4
- require "pact_broker/repositories/helpers"
5
- require "pact_broker/logging"
6
- require "pact_broker/pacts/pact_version"
7
- require "pact_broker/domain/pacticipant"
8
- require "pact_broker/domain/version"
9
- require "pact_broker/domain/verification"
10
- require "pact_broker/pacts/pact_publication"
11
- require "pact_broker/tags/tag_with_latest_flag"
12
- require "pact_broker/matrix/query_ids"
13
-
14
- # The PactBroker::Matrix::QuickRow represents a row in the table that is created when
15
- # the consumer versions are joined to the provider versions via the pacts and verifications tables,
16
- # aka "The Matrix". The difference between this class and the EveryRow class is that
17
- # the EveryRow class includes results for overridden pact verisons and verifications (used only when there is no latestby
18
- # set in the matrix query), where as the QuickRow class does not.
19
- # It is called the QuickRow because the initial implementation was called the Row, and this is an optimised
20
- # version. It needs to be renamed back to Row now that the old Row class has been deleted.
21
-
22
- # The difference between `join_verifications_for` and `join_verifications` is that
23
- # the left outer join is done on a pre-filtered dataset in `join_verifications_for`,
24
- # so that we get a row with null verification fields for a pact that has been verified
25
- # by a *different* version of the provider we're interested in,
26
- # rather than being excluded from the dataset altogether.
27
-
28
- module PactBroker
29
- module Matrix
30
- # TODO rename this to just Row
31
- # rubocop: disable Metrics/ClassLength
32
- class QuickRow < Sequel::Model(Sequel.as(:latest_pact_publication_ids_for_consumer_versions, :p))
33
-
34
- # Tables
35
- LV = :latest_verification_id_for_pact_version_and_provider_version
36
- LP = :latest_pact_publication_ids_for_consumer_versions
37
-
38
- # Joins
39
- LP_LV_JOIN = { Sequel[:p][:pact_version_id] => Sequel[:v][:pact_version_id] }
40
- CONSUMER_VERSION_JOIN = { Sequel[:p][:consumer_version_id] => Sequel[:cv][:id] }
41
- PROVIDER_VERSION_JOIN = { Sequel[:v][:provider_version_id] => Sequel[:pv][:id] }
42
-
43
- PACT_COLUMNS = [
44
- Sequel[:p][:consumer_id],
45
- Sequel[:p][:provider_id],
46
- Sequel[:p][:consumer_version_id],
47
- Sequel[:p][:pact_publication_id],
48
- Sequel[:p][:pact_version_id],
49
- Sequel[:p][:created_at].as(:consumer_version_created_at),
50
- Sequel[:p][:pact_publication_id].as(:pact_order)
51
- ]
52
- VERIFICATION_COLUMNS = [
53
- Sequel[:v][:provider_version_id],
54
- Sequel[:v][:verification_id],
55
- Sequel[:v][:created_at].as(:provider_version_created_at)
56
- ]
57
-
58
- JOINED_VERIFICATION_COLUMNS = [
59
- :verification_id,
60
- :provider_version_id,
61
- :pact_version_id,
62
- :provider_id,
63
- :created_at
64
- ]
65
-
66
- 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)
67
-
68
- ALL_COLUMNS = PACT_COLUMNS + VERIFICATION_COLUMNS
69
-
70
-
71
- # cachable select arguments
72
- SELECT_ALL_COLUMN_ARGS = [:select_all_columns] + ALL_COLUMNS
73
- SELECT_PACTICIPANT_IDS_ARGS = [:select_pacticipant_ids, Sequel[:p][:consumer_id], Sequel[:p][:provider_id]]
74
-
75
- EAGER_LOADED_RELATIONSHIPS_FOR_VERSION = { current_deployed_versions: :environment, current_supported_released_versions: :environment, branch_versions: [:branch_head, :version, branch: :pacticipant] }
76
-
77
- associate(:many_to_one, :pact_publication, :class => "PactBroker::Pacts::PactPublication", :key => :pact_publication_id, :primary_key => :id)
78
- associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
79
- associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
80
- associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id)
81
- associate(:many_to_one, :provider_version, :class => "PactBroker::Domain::Version", :key => :provider_version_id, :primary_key => :id)
82
- associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id)
83
- associate(:many_to_one, :verification, class: "PactBroker::Domain::Verification", :key => :verification_id, :primary_key => :id)
84
- associate(:one_to_many, :consumer_version_tags, :class => "PactBroker::Tags::TagWithLatestFlag", primary_key: :consumer_version_id, key: :version_id)
85
- associate(:one_to_many, :provider_version_tags, :class => "PactBroker::Tags::TagWithLatestFlag", primary_key: :provider_version_id, key: :version_id)
86
-
87
- dataset_module do
88
- include PactBroker::Repositories::Helpers
89
-
90
- select(*SELECT_ALL_COLUMN_ARGS)
91
- select(*SELECT_PACTICIPANT_IDS_ARGS)
92
-
93
- def distinct_integrations_for_selector_as_consumer(selector)
94
- select(:consumer_id, :provider_id)
95
- .distinct
96
- .where({ consumer_id: selector.pacticipant_id, consumer_version_id: selector.pacticipant_version_id }.compact)
97
- .from_self(alias: :integrations)
98
- .select(:consumer_id, :provider_id, Sequel[:consumers][:name].as(:consumer_name), Sequel[:providers][:name].as(:provider_name))
99
- .join_consumers(:integrations, :consumers)
100
- .join_providers(:integrations, :providers)
101
- end
102
-
103
- def distinct_integrations selectors, infer_integrations
104
- query = if selectors.size == 1
105
- pacticipant_ids_matching_one_selector_optimised(selectors)
106
- else
107
- query = select_pacticipant_ids.distinct
108
- if infer_integrations
109
- query.matching_any_of_multiple_selectors(selectors)
110
- else
111
- if selectors.all?(&:only_pacticipant_name_specified?)
112
- query.matching_multiple_selectors_without_joining_verifications(selectors)
113
- else
114
- query.matching_multiple_selectors_joining_verifications(selectors)
115
- end
116
- end
117
- end
118
-
119
- query.from_self(alias: :pacticipant_ids)
120
- .select(
121
- :consumer_id,
122
- Sequel[:c][:name].as(:consumer_name),
123
- :provider_id,
124
- Sequel[:p][:name].as(:provider_name)
125
- )
126
- .join_consumers(:pacticipant_ids, :c)
127
- .join_providers(:pacticipant_ids, :p)
128
- end
129
-
130
- def matching_selectors selectors
131
- if selectors.size == 1
132
- matching_one_selector(selectors)
133
- else
134
- matching_multiple_selectors_joining_verifications(selectors)
135
- end
136
- end
137
-
138
- def order_by_last_action_date
139
- 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))
140
- end
141
-
142
- def order_by_pact_publication_created_at
143
- order(Sequel.desc(:consumer_version_created_at), Sequel.desc(:pact_order))
144
- end
145
-
146
- # eager load tags?
147
- def eager_all_the_things
148
- eager(
149
- :consumer,
150
- :provider,
151
- :verification,
152
- :pact_publication,
153
- :pact_version,
154
- consumer_version: EAGER_LOADED_RELATIONSHIPS_FOR_VERSION,
155
- provider_version: EAGER_LOADED_RELATIONSHIPS_FOR_VERSION,
156
- consumer_version_tags: { version: :pacticipant },
157
- provider_version_tags: { version: :pacticipant }
158
- )
159
- end
160
-
161
- def default_scope
162
- select_all_columns.join_verifications.from_self
163
- end
164
-
165
- # PRIVATE METHODS
166
-
167
- # When we have one selector, we need to join ALL the verifications to find out
168
- # what integrations exist
169
- def matching_one_selector(selectors)
170
- query_ids = QueryIds.from_selectors(selectors)
171
- rows_where_selector_matches_consumer_cols = join_verifications
172
- .where {
173
- QueryBuilder.consumer_or_consumer_version_matches(query_ids, :p)
174
- }
175
-
176
- rows_where_selector_matches_provider_cols = inner_join_verifications_matching_one_selector_provider_or_provider_version(query_ids)
177
-
178
- rows_where_selector_matches_consumer_cols.union(rows_where_selector_matches_provider_cols)
179
- end
180
-
181
- def pacticipant_ids_matching_one_selector_optimised(selectors)
182
- query_ids = QueryIds.from_selectors(selectors)
183
- distinct_pacticipant_ids_where_consumer_or_consumer_version_matches(query_ids)
184
- .union(distinct_pacticipant_ids_where_provider_or_provider_version_matches(query_ids), all: true)
185
- end
186
-
187
- def distinct_pacticipant_ids_where_consumer_or_consumer_version_matches(query_ids)
188
- select_pacticipant_ids
189
- .distinct
190
- .where {
191
- QueryBuilder.consumer_or_consumer_version_matches(query_ids, :p)
192
- }
193
- end
194
-
195
- def distinct_pacticipant_ids_where_provider_or_provider_version_matches(query_ids)
196
- select_pacticipant_ids
197
- .distinct
198
- .inner_join_verifications
199
- .where {
200
- QueryBuilder.provider_or_provider_version_matches(query_ids, :v, :v)
201
- }
202
- end
203
-
204
- # When the user has specified multiple selectors, we only want to join the verifications for
205
- # the specified selectors. This is because of the behaviour of the left outer join.
206
- # Imagine a pact has been verified by a provider version that was NOT specified in the selectors.
207
- # If we join all the verifications and THEN filter the rows to only show the versions specified
208
- # in the selectors, we won't get a row for that pact, and hence, we won't
209
- # know that it hasn't been verified by the provider version we're interested in.
210
- # Instead, we need to filter the verifications dataset down to only the ones specified in the selectors first,
211
- # and THEN join them to the pacts, so that we get a row for the pact with null provider version
212
- # and verification fields.
213
-
214
- def matching_multiple_selectors_joining_verifications(selectors)
215
- query_ids = QueryIds.from_selectors(selectors)
216
- join_verifications_for(query_ids)
217
- .where {
218
- Sequel.&(
219
- QueryBuilder.consumer_or_consumer_version_matches(query_ids, :p),
220
- QueryBuilder.provider_or_provider_version_matches_or_pact_unverified(query_ids, :v, :p),
221
- QueryBuilder.either_consumer_or_provider_was_specified_in_query(query_ids, :p)
222
- )
223
- }
224
- end
225
-
226
- def matching_multiple_selectors_without_joining_verifications(selectors)
227
- # There are no versions specified in these selectors, so we can do the whole
228
- # query based on the consumer/provider IDs, which we have in the pact_publication
229
- # table without having to do a join.
230
- query_ids = QueryIds.from_selectors(selectors)
231
- where {
232
- Sequel.&(
233
- QueryBuilder.consumer_or_consumer_version_matches(query_ids, :p),
234
- QueryBuilder.provider_matches(query_ids, :p),
235
- QueryBuilder.either_consumer_or_provider_was_specified_in_query(query_ids, :p)
236
- )
237
- }
238
- end
239
-
240
- def matching_any_of_multiple_selectors(selectors)
241
- query_ids = QueryIds.from_selectors(selectors)
242
- join_verifications_for(query_ids)
243
- .where {
244
- Sequel.&(
245
- Sequel.|(
246
- QueryBuilder.consumer_or_consumer_version_matches(query_ids, :p),
247
- QueryBuilder.provider_or_provider_version_matches_or_pact_unverified(query_ids, :v, :p),
248
- ),
249
- QueryBuilder.either_consumer_or_provider_was_specified_in_query(query_ids, :p)
250
- )
251
- }
252
- end
253
-
254
- def join_verifications_for(query_ids)
255
- left_outer_join(verifications_for(query_ids), LP_LV_JOIN, { table_alias: :v } )
256
- end
257
-
258
- def inner_join_verifications_matching_one_selector_provider_or_provider_version(query_ids)
259
- verifications = db[LV]
260
- .select(*JOINED_VERIFICATION_COLUMNS)
261
- .where {
262
- QueryBuilder.provider_or_provider_version_matches(query_ids)
263
- }
264
-
265
- join(verifications, LP_LV_JOIN, { table_alias: :v } )
266
- end
267
-
268
- def verifications_for(query_ids)
269
- db[LV]
270
- .select(*JOINED_VERIFICATION_COLUMNS)
271
- .where {
272
- Sequel.&(
273
- QueryBuilder.consumer_in_pacticipant_ids(query_ids),
274
- QueryBuilder.provider_or_provider_version_matches(query_ids)
275
- )
276
- }
277
- end
278
-
279
- def join_consumers qualifier = :p, table_alias = :consumers
280
- join(
281
- :pacticipants,
282
- { Sequel[qualifier][:consumer_id] => Sequel[table_alias][:id] },
283
- { table_alias: table_alias }
284
- )
285
- end
286
-
287
- def join_providers qualifier = :p, table_alias = :providers
288
- join(
289
- :pacticipants,
290
- { Sequel[qualifier][:provider_id] => Sequel[table_alias][:id] },
291
- { table_alias: table_alias }
292
- )
293
- end
294
-
295
- def join_consumer_versions
296
- join(:versions, CONSUMER_VERSION_JOIN, { table_alias: :cv })
297
- end
298
-
299
- def join_provider_versions
300
- left_outer_join(:versions, PROVIDER_VERSION_JOIN, { table_alias: :pv } )
301
- end
302
-
303
- def join_verifications
304
- left_outer_join(LV, LP_LV_JOIN, { table_alias: :v } )
305
- end
306
-
307
- def inner_join_verifications
308
- join(LV, LP_LV_JOIN, { table_alias: :v } )
309
- end
310
- end # end dataset_module
311
-
312
- def pact_version_sha
313
- pact_version.sha
314
- end
315
-
316
- def pact_revision_number
317
- pact_publication.revision_number
318
- end
319
-
320
- def verification_number
321
- verification&.number
322
- end
323
-
324
- def success
325
- verification&.success
326
- end
327
-
328
- def pact_created_at
329
- pact_publication.created_at
330
- end
331
-
332
- def verification_executed_at
333
- verification&.execution_date
334
- end
335
-
336
- # Add logic for ignoring case
337
- def <=> other
338
- comparisons = [
339
- compare_name_asc(consumer_name, other.consumer_name),
340
- compare_number_desc(consumer_version_order, other.consumer_version_order),
341
- compare_number_desc(pact_revision_number, other.pact_revision_number),
342
- compare_name_asc(provider_name, other.provider_name),
343
- compare_number_desc(provider_version_order, other.provider_version_order),
344
- compare_number_desc(verification_id, other.verification_id)
345
- ]
346
-
347
- comparisons.find{|c| c != 0 } || 0
348
- end
349
-
350
- def compare_name_asc name1, name2
351
- name1 <=> name2
352
- end
353
-
354
- def to_s
355
- "#{consumer_name} v#{consumer_version_number} #{provider_name} #{provider_version_number} #{success}"
356
- end
357
-
358
- def compare_number_desc number1, number2
359
- if number1 && number2
360
- number2 <=> number1
361
- elsif number1
362
- 1
363
- else
364
- -1
365
- end
366
- end
367
-
368
- def eql?(obj)
369
- (obj.class == model) && (obj.values == values)
370
- end
371
-
372
- def pacticipant_names
373
- [consumer_name, provider_name]
374
- end
375
-
376
- def involves_pacticipant_with_name?(pacticipant_name)
377
- pacticipant_name.include?(pacticipant_name)
378
- end
379
-
380
- def provider_version_id
381
- # null when not verified
382
- values[:provider_version_id]
383
- end
384
-
385
- def verification_id
386
- # null when not verified
387
- return_or_raise_if_not_set(:verification_id)
388
- end
389
-
390
- def consumer_name
391
- consumer.name
392
- end
393
-
394
- def consumer_version_number
395
- consumer_version.number
396
- end
397
-
398
- def consumer_version_branch_versions
399
- consumer_version.branch_versions
400
- end
401
-
402
- def consumer_version_deployed_versions
403
- consumer_version.current_deployed_versions
404
- end
405
-
406
- def consumer_version_released_versions
407
- consumer_version.current_supported_released_versions
408
- end
409
-
410
- def consumer_version_order
411
- consumer_version.order
412
- end
413
-
414
- def provider_name
415
- provider.name
416
- end
417
-
418
- def provider_version_number
419
- provider_version&.number
420
- end
421
-
422
- def provider_version_branch_versions
423
- provider_version&.branch_versions || []
424
- end
425
-
426
- def provider_version_deployed_versions
427
- provider_version&.current_deployed_versions || []
428
- end
429
-
430
- def provider_version_released_versions
431
- provider_version&.current_supported_released_versions || []
432
- end
433
-
434
- def provider_version_order
435
- provider_version&.order
436
- end
437
-
438
- def last_action_date
439
- return_or_raise_if_not_set(:last_action_date)
440
- end
441
-
442
- def has_verification?
443
- !!verification_id
444
- end
445
-
446
- # This model needs the verifications and pacticipants joined to it
447
- # before it can be used, as it's not a "real" model.
448
- def return_or_raise_if_not_set(key)
449
- if values.key?(key)
450
- values[key]
451
- else
452
- raise "Required table not joined"
453
- end
454
- end
455
- end
456
- # rubocop: enable Metrics/ClassLength
457
- end
458
- end
@@ -1,45 +0,0 @@
1
- require "pact_broker/domain/group"
2
-
3
- =begin
4
- Splits all index_items up into groups of non-connecting index_items.
5
- =end
6
-
7
- module PactBroker
8
-
9
- module Relationships
10
-
11
- class Groupify
12
-
13
- def self.call index_items
14
- recurse_groups([], index_items.dup).collect { |group| Domain::Group.new(group) }
15
- end
16
-
17
- def self.recurse_groups groups, index_item_pool
18
- if index_item_pool.empty?
19
- groups
20
- else
21
- first, *rest = index_item_pool
22
- group = [first]
23
- new_connections = true
24
- while new_connections
25
- new_connections = false
26
- group = rest.inject(group) do |connected, candidate|
27
- if connected.select { |index_item| index_item.connected?(candidate) }.any?
28
- new_connections = true
29
- connected + [candidate]
30
- else
31
- connected
32
- end
33
- end
34
-
35
- rest = rest - group
36
- group.uniq
37
- end
38
-
39
- recurse_groups(groups + [group], index_item_pool - group)
40
- end
41
- end
42
- end
43
-
44
- end
45
- end
@@ -1,96 +0,0 @@
1
- require "pact_broker/repositories/page"
2
-
3
- Sequel.extension :escaped_like
4
-
5
- module PactBroker
6
- module Repositories
7
- module Helpers
8
-
9
- extend self
10
-
11
- def all_with_pagination_options(pagination_options)
12
- if pagination_options&.any?
13
- query = paginate(pagination_options[:page_number], pagination_options[:page_size])
14
- Page.new(query.all, query)
15
- else
16
- all
17
- end
18
- end
19
-
20
- def all_forbidding_lazy_load
21
- all.each{ | row | row.forbid_lazy_load if row.respond_to?(:forbid_lazy_load) }
22
- end
23
-
24
- def all_allowing_lazy_load
25
- all.each{ | row | row.allow_lazy_load if row.respond_to?(:allow_lazy_load) }
26
- end
27
-
28
- def name_like column_name, value
29
- if PactBroker.configuration.use_case_sensitive_resource_names
30
- if mysql?
31
- # sigh, mysql, this is the only way to perform a case sensitive search
32
- Sequel.like(column_name, value.gsub("_", "\\_"), { case_insensitive: false })
33
- else
34
- { column_name => value }
35
- end
36
- else
37
- Sequel.like(column_name, value.gsub("_", "\\_"), { case_insensitive: true })
38
- end
39
- end
40
-
41
- def pacticipant_id_for_name pacticipant_name
42
- Sequel::Model.db[:pacticipants].select(:id).where(name_like(:name, pacticipant_name)).limit(1)
43
- end
44
-
45
- def order_ignore_case column_name = :name
46
- order(Sequel.function(:lower, column_name))
47
- end
48
-
49
- def order_append_ignore_case column_name = :name
50
- order_append(Sequel.function(:lower, column_name))
51
- end
52
-
53
- def mysql?
54
- Sequel::Model.db.adapter_scheme.to_s =~ /mysql/
55
- end
56
-
57
- def postgres?
58
- Sequel::Model.db.adapter_scheme.to_s =~ /postgres/
59
- end
60
-
61
- def select_all_qualified
62
- select(Sequel[model.table_name].*)
63
- end
64
-
65
- def select_append_all_qualified
66
- select_append(Sequel[model.table_name].*)
67
- end
68
-
69
- # @param [Symbol] max_column the name of the column of which to calculate the maxiumum
70
- # @param [Array<Symbol>] group_by_columns the names of the columns by which to group
71
- def max_group_by(max_column, group_by_columns, &extra_criteria_block)
72
- maximums_base_query = extra_criteria_block ? extra_criteria_block.call(self) : self
73
- maximums = maximums_base_query.select_group(*group_by_columns).select_append(Sequel.function(:max, max_column).as(:max_value))
74
-
75
- max_join = group_by_columns.each_with_object({ Sequel[:maximums][:max_value] => max_column }) do | column_name, joins |
76
- joins[Sequel[:maximums][column_name]] = column_name
77
- end
78
-
79
- join(maximums, max_join, table_alias: :maximums)
80
- end
81
-
82
- def select_for_subquery column
83
- if mysql? #stoopid mysql doesn't allow you to modify datasets with subqueries
84
- column_name = column.respond_to?(:alias) ? column.alias : column
85
- select(column).collect{ | it | it[column_name] }
86
- else
87
- select(column)
88
- end
89
- end
90
-
91
- def no_columns_selected?
92
- opts[:select].nil?
93
- end
94
- end
95
- end
96
- end
@@ -1,24 +0,0 @@
1
- require "forwardable"
2
-
3
- # An array that provides the pagination details
4
-
5
- module PactBroker
6
- module Repositories
7
- module Helpers
8
- class Page < Array
9
- extend Forwardable
10
-
11
- attr_reader :query
12
-
13
- PAGE_PROPERTIES = [:page_size, :page_count, :page_range, :current_page, :next_page, :prev_page, :first_page?, :last_page?, :pagination_record_count, :current_page_record_count, :current_page_record_range]
14
-
15
- delegate PAGE_PROPERTIES => :query
16
-
17
- def initialize(array, query)
18
- super(array)
19
- @query = query
20
- end
21
- end
22
- end
23
- end
24
- end
@@ -1,28 +0,0 @@
1
- require "pact_broker/db"
2
- require "pact_broker/repositories/helpers"
3
-
4
- module PactBroker
5
- module Tags
6
- # The tag associated with the latest verification for a given tag
7
- # TODO remove this class now we have eager loaders for head_tag
8
- class TagWithLatestFlag < Sequel::Model(:tags_with_latest_flag)
9
- associate(:many_to_one, :version, :class => "PactBroker::Domain::Version", :key => :version_id, :primary_key => :id)
10
-
11
- dataset_module do
12
- include PactBroker::Repositories::Helpers
13
- end
14
-
15
- def latest?
16
- !values[:latest].nil?
17
- end
18
- end
19
- end
20
- end
21
-
22
- # Table: tags_with_latest_flag
23
- # Columns:
24
- # name | text |
25
- # version_id | integer |
26
- # created_at | timestamp without time zone |
27
- # updated_at | timestamp without time zone |
28
- # latest | integer |