pact_broker 2.96.0 → 2.99.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.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +43 -0
  3. data/Gemfile +1 -0
  4. data/docs/CONFIGURATION.md +131 -67
  5. data/lib/db.rb +1 -7
  6. data/lib/pact_broker/api/middleware/http_debug_logs.rb +42 -0
  7. data/lib/pact_broker/api/resources/base_resource.rb +4 -0
  8. data/lib/pact_broker/api/resources/latest_pacts.rb +1 -1
  9. data/lib/pact_broker/api/resources/pact.rb +0 -8
  10. data/lib/pact_broker/api/resources/pact_content_diff.rb +7 -2
  11. data/lib/pact_broker/api/resources/pact_versions.rb +1 -5
  12. data/lib/pact_broker/api/resources/pact_versions_for_branch.rb +1 -5
  13. data/lib/pact_broker/api/resources/provider_pacts.rb +1 -1
  14. data/lib/pact_broker/api/resources/tagged_pact_versions.rb +1 -5
  15. data/lib/pact_broker/api/resources/verification.rb +0 -4
  16. data/lib/pact_broker/api/resources/verifications.rb +0 -4
  17. data/lib/pact_broker/api/resources/version.rb +8 -0
  18. data/lib/pact_broker/app.rb +3 -7
  19. data/lib/pact_broker/config/runtime_configuration.rb +24 -5
  20. data/lib/pact_broker/config/runtime_configuration_coercion_methods.rb +11 -0
  21. data/lib/pact_broker/config/runtime_configuration_database_methods.rb +2 -2
  22. data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +7 -2
  23. data/lib/pact_broker/configuration.rb +2 -0
  24. data/lib/pact_broker/db/models.rb +2 -2
  25. data/lib/pact_broker/index/service.rb +1 -2
  26. data/lib/pact_broker/integrations/integration.rb +21 -6
  27. data/lib/pact_broker/integrations/service.rb +1 -1
  28. data/lib/pact_broker/matrix/every_row.rb +19 -1
  29. data/lib/pact_broker/matrix/integration.rb +5 -5
  30. data/lib/pact_broker/matrix/quick_row.rb +36 -3
  31. data/lib/pact_broker/matrix/repository.rb +4 -3
  32. data/lib/pact_broker/matrix/service.rb +0 -1
  33. data/lib/pact_broker/metrics/service.rb +2 -2
  34. data/lib/pact_broker/pacts/create_formatted_diff.rb +1 -0
  35. data/lib/pact_broker/pacts/eager_loaders.rb +4 -1
  36. data/lib/pact_broker/pacts/pact_publication.rb +9 -6
  37. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +25 -0
  38. data/lib/pact_broker/pacts/pact_publication_wip_dataset_module.rb +0 -15
  39. data/lib/pact_broker/pacts/pact_version.rb +24 -28
  40. data/lib/pact_broker/pacts/pact_version_association_loaders.rb +36 -0
  41. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +9 -13
  42. data/lib/pact_broker/pacts/repository.rb +29 -27
  43. data/lib/pact_broker/test/http_test_data_builder.rb +11 -2
  44. data/lib/pact_broker/test/test_data_builder.rb +2 -1
  45. data/lib/pact_broker/ui/controllers/matrix.rb +14 -11
  46. data/lib/pact_broker/ui/views/groups/show.html.erb +2 -2
  47. data/lib/pact_broker/version.rb +1 -1
  48. data/pact_broker.gemspec +1 -1
  49. metadata +9 -16
  50. data/lib/pact_broker/matrix/aggregated_row.rb +0 -79
  51. data/lib/pact_broker/matrix/head_row.rb +0 -80
  52. data/lib/pact_broker/matrix/row.rb +0 -287
@@ -152,6 +152,10 @@ module PactBroker
152
152
  @request_body ||= request.body.to_s
153
153
  end
154
154
 
155
+ def any_request_body?
156
+ request_body && request_body.size > 0
157
+ end
158
+
155
159
  def consumer_name
156
160
  identifier_from_path[:consumer_name]
157
161
  end
@@ -22,7 +22,7 @@ module PactBroker
22
22
  end
23
23
 
24
24
  def policy_name
25
- :'pacts::pacts'
25
+ :'pacts::latest_pacts'
26
26
  end
27
27
  end
28
28
  end
@@ -94,14 +94,6 @@ module PactBroker
94
94
  :'pacts::pact'
95
95
  end
96
96
 
97
- def policy_pacticipant
98
- if resource_exists?
99
- consumer
100
- else
101
- nil
102
- end
103
- end
104
-
105
97
  private
106
98
 
107
99
  def pact
@@ -1,6 +1,7 @@
1
1
  require "pact_broker/api/resources/base_resource"
2
2
  require "pact_broker/pacts/pact_params"
3
3
  require "pact_broker/pacts/diff"
4
+ require "timeout"
4
5
 
5
6
  module PactBroker
6
7
  module Api
@@ -19,8 +20,12 @@ module PactBroker
19
20
  end
20
21
 
21
22
  def to_text
22
- output = PactBroker::Pacts::Diff.new.process pact_params.merge(base_url: base_url), comparison_pact_params, raw: false
23
- response.body = output
23
+ Timeout::timeout(PactBroker.configuration.pact_content_diff_timeout) do
24
+ output = PactBroker::Pacts::Diff.new.process pact_params.merge(base_url: base_url), comparison_pact_params, raw: false
25
+ response.body = output
26
+ end
27
+ rescue Timeout::Error
28
+ 408
24
29
  end
25
30
 
26
31
  def pact
@@ -32,11 +32,7 @@ module PactBroker
32
32
  end
33
33
 
34
34
  def policy_name
35
- :'pacts::pacts'
36
- end
37
-
38
- def policy_pacticipant
39
- consumer
35
+ :'pacts::pact_versions'
40
36
  end
41
37
  end
42
38
  end
@@ -28,11 +28,7 @@ module PactBroker
28
28
  end
29
29
 
30
30
  def policy_name
31
- :'pacts::pacts'
32
- end
33
-
34
- def policy_pacticipant
35
- consumer
31
+ :'pacts::pact_versions'
36
32
  end
37
33
  end
38
34
  end
@@ -20,7 +20,7 @@ module PactBroker
20
20
  end
21
21
 
22
22
  def policy_name
23
- :'pacts::pacts'
23
+ :'pacts::provider_pacts'
24
24
  end
25
25
 
26
26
  def to_json
@@ -36,11 +36,7 @@ module PactBroker
36
36
  end
37
37
 
38
38
  def policy_name
39
- :'pacts::pacts'
40
- end
41
-
42
- def policy_pacticipant
43
- consumer
39
+ :'pacts::pact_versions'
44
40
  end
45
41
  end
46
42
  end
@@ -54,10 +54,6 @@ module PactBroker
54
54
  :'verifications::verification'
55
55
  end
56
56
 
57
- def policy_pacticipant
58
- provider
59
- end
60
-
61
57
  private
62
58
 
63
59
  def verification
@@ -62,10 +62,6 @@ module PactBroker
62
62
  :'verifications::verifications'
63
63
  end
64
64
 
65
- def policy_pacticipant
66
- provider
67
- end
68
-
69
65
  private
70
66
 
71
67
  def pact
@@ -25,6 +25,14 @@ module PactBroker
25
25
  !!version
26
26
  end
27
27
 
28
+ def malformed_request?
29
+ if request.put? && any_request_body?
30
+ invalid_json?
31
+ else
32
+ false
33
+ end
34
+ end
35
+
28
36
  def from_json
29
37
  if request.really_put?
30
38
  handle_request do
@@ -29,6 +29,7 @@ require "pact_broker/api/middleware/configuration"
29
29
  require "pact_broker/api/middleware/basic_auth"
30
30
  require "pact_broker/config/basic_auth_configuration"
31
31
  require "pact_broker/api/authorization/resource_access_policy"
32
+ require "pact_broker/api/middleware/http_debug_logs"
32
33
 
33
34
  module PactBroker
34
35
 
@@ -134,17 +135,11 @@ module PactBroker
134
135
  # Keep this configuration in sync with lib/db.rb
135
136
  configuration.database_connection ||= PactBroker.create_database_connection(configuration.database_configuration, configuration.logger)
136
137
  PactBroker::DB.connection = configuration.database_connection
137
- PactBroker::DB.connection.extend_datasets do
138
- # rubocop: disable Lint/NestedMethodDefinition
139
- def any?
140
- !empty?
141
- end
142
- # rubocop: enable Lint/NestedMethodDefinition
143
- end
144
138
  PactBroker::DB.validate_connection_config if configuration.validate_database_connection_config
145
139
  PactBroker::DB.set_mysql_strict_mode_if_mysql
146
140
  PactBroker::DB.connection.extension(:pagination)
147
141
  PactBroker::DB.connection.extension(:statement_timeout)
142
+ PactBroker::DB.connection.extension(:any_not_empty)
148
143
  PactBroker::DB.connection.timezone = :utc
149
144
  Sequel.datetime_class = DateTime
150
145
  Sequel.database_timezone = :utc # Store all dates in UTC, assume any date without a TZ is UTC
@@ -180,6 +175,7 @@ module PactBroker
180
175
  end
181
176
 
182
177
  def configure_middleware
178
+ @app_builder.use PactBroker::Api::Middleware::HttpDebugLogs if configuration.http_debug_logging_enabled
183
179
  configure_basic_auth
184
180
  configure_rack_protection
185
181
  @app_builder.use Rack::PactBroker::InvalidUriProtection
@@ -39,7 +39,8 @@ module PactBroker
39
39
  log_format: nil,
40
40
  warning_error_class_names: ["Sequel::ForeignKeyConstraintViolation"],
41
41
  hide_pactflow_messages: false,
42
- log_configuration_on_startup: true
42
+ log_configuration_on_startup: true,
43
+ http_debug_logging_enabled: false
43
44
  )
44
45
 
45
46
  on_load :validate_logging_attributes!
@@ -52,9 +53,12 @@ module PactBroker
52
53
  webhook_scheme_whitelist: ["https"],
53
54
  webhook_host_whitelist: [],
54
55
  disable_ssl_verification: false,
55
- webhook_certificates: [],
56
- user_agent: "Pact Broker v#{PactBroker::VERSION}",
56
+ user_agent: "Pact Broker v#{PactBroker::VERSION}"
57
57
  )
58
+ # no default, if you set it to [] or nil, then anyway config blows up when it tries to merge in the
59
+ # numerically indexed hash from the environment variables.
60
+ attr_config :webhook_certificates
61
+ on_load :set_webhook_attribute_defaults
58
62
 
59
63
  # resource attributes
60
64
  attr_config(
@@ -67,7 +71,8 @@ module PactBroker
67
71
  badge_provider_mode: :redirect,
68
72
  enable_public_badge_access: false,
69
73
  shields_io_base_url: "https://img.shields.io",
70
- use_case_sensitive_resource_names: true
74
+ use_case_sensitive_resource_names: true,
75
+ pact_content_diff_timeout: 15
71
76
  )
72
77
 
73
78
  # domain attributes
@@ -178,8 +183,14 @@ module PactBroker
178
183
  def webhook_certificates= webhook_certificates
179
184
  if webhook_certificates.is_a?(Array)
180
185
  super(webhook_certificates.collect(&:symbolize_keys))
186
+ elsif webhook_certificates.is_a?(Hash)
187
+ if all_keys_are_number_strings?(webhook_certificates)
188
+ super(convert_hash_with_number_string_keys_to_array(webhook_certificates).collect(&:symbolize_keys))
189
+ else
190
+ raise_validation_error("webhook_certificates must be an array, or a hash where each key is an integer in string format.")
191
+ end
181
192
  elsif !webhook_certificates.nil?
182
- raise_validation_error("webhook_certificates must be an array")
193
+ raise_validation_error("webhook_certificates cannot be set using a #{webhook_certificates.class}")
183
194
  end
184
195
  end
185
196
 
@@ -208,6 +219,14 @@ module PactBroker
208
219
  def raise_validation_error(msg)
209
220
  raise PactBroker::ConfigurationError, msg
210
221
  end
222
+
223
+ def set_webhook_attribute_defaults
224
+ # can't set a default on this, or anyway config blows up when trying to merge the
225
+ # hash from the env vars into an array/nil.
226
+ if webhook_certificates.nil?
227
+ self.webhook_certificates = []
228
+ end
229
+ end
211
230
  end
212
231
  end
213
232
  end
@@ -4,6 +4,17 @@ require "pact_broker/config/space_delimited_integer_list"
4
4
  module PactBroker
5
5
  module Config
6
6
  module RuntimeConfigurationCoercionMethods
7
+
8
+ def all_keys_are_number_strings?(hash)
9
+ hash.keys.all? { | k | k.to_s.to_i.to_s == k } # is an integer as a string
10
+ end
11
+
12
+ def convert_hash_with_number_string_keys_to_array(hash)
13
+ hash.keys.collect{ |k| [k, k.to_i]}.sort_by(&:last).collect(&:first).collect do | key |
14
+ hash[key]
15
+ end
16
+ end
17
+
7
18
  def value_to_string_array value, property_name
8
19
  if value.is_a?(String)
9
20
  PactBroker::Config::SpaceDelimitedStringList.parse(value)
@@ -16,7 +16,7 @@ module PactBroker
16
16
  database_port: nil,
17
17
  database_url: nil,
18
18
  database_sslmode: nil,
19
- sql_log_level: :debug,
19
+ sql_log_level: :none,
20
20
  sql_log_warn_duration: 5,
21
21
  sql_enable_caller_logging: false,
22
22
  database_max_connections: nil,
@@ -82,7 +82,7 @@ module PactBroker
82
82
  private :postgres?
83
83
 
84
84
  def driver_options
85
- if postgres?
85
+ if postgres? && database_statement_timeout
86
86
  { options: "-c statement_timeout=#{database_statement_timeout}s" }
87
87
  end
88
88
  end
@@ -24,12 +24,17 @@ module PactBroker
24
24
  module InstanceMethods
25
25
  # base_url raises a not implemented error
26
26
  def log_configuration(logger)
27
- to_source_trace.without("base_url").each_with_object({})do | (key, details), new_hash |
28
- new_hash[key] = details.merge(value: self.send(key.to_sym))
27
+ source_info = to_source_trace
28
+ (self.class.config_attributes - [:base_url]).collect(&:to_s).each_with_object({})do | key, new_hash |
29
+ new_hash[key] = {
30
+ value: self.send(key.to_sym),
31
+ source: source_info.dig(key, :source) || {:type=>:defaults}
32
+ }
29
33
  end.sort_by { |key, _| key }.each { |key, value| log_config_inner(key, value, logger) }
30
34
  end
31
35
 
32
36
  def log_config_inner(key, value, logger)
37
+ # TODO fix the source display for webhook_certificates set by environment variables
33
38
  if !value.has_key? :value
34
39
  value.sort_by { |inner_key, _| inner_key }.each { |inner_key, inner_value| log_config_inner("#{key}.#{inner_key}", inner_value, logger) }
35
40
  elsif self.class.sensitive_value?(key)
@@ -55,6 +55,8 @@ module PactBroker
55
55
  config.version_parser = PactBroker::Versions::ParseSemanticVersion
56
56
  config.sha_generator = PactBroker::Pacts::GenerateSha
57
57
  config.example_data_seeder = lambda do
58
+ # Do the require in the lambda, not at the top of the file, because we need
59
+ # the database connection to be made before loading any Sequel::Model classes.
58
60
  require "pact_broker/db/seed_example_data"
59
61
  PactBroker::DB::SeedExampleData.call
60
62
  end
@@ -14,11 +14,11 @@ require "pact_broker/domain/pacticipant"
14
14
  require "pact_broker/deployments/environment"
15
15
  require "pact_broker/deployments/deployed_version"
16
16
  require "pact_broker/deployments/released_version"
17
- require "pact_broker/matrix/row"
18
- require "pact_broker/matrix/head_row"
19
17
  require "pact_broker/versions/branch"
20
18
  require "pact_broker/versions/branch_version"
21
19
  require "pact_broker/versions/branch_head"
20
+ require "pact_broker/matrix/quick_row"
21
+ require "pact_broker/matrix/every_row"
22
22
 
23
23
  module PactBroker
24
24
  INTEGRATIONS_TABLES = [
@@ -1,10 +1,9 @@
1
1
  require "pact_broker/repositories"
2
2
  require "pact_broker/logging"
3
3
  require "pact_broker/domain/index_item"
4
- require "pact_broker/matrix/head_row"
5
- require "pact_broker/matrix/aggregated_row"
6
4
  require "pact_broker/repositories/helpers"
7
5
  require "pact_broker/index/page"
6
+ require "pact_broker/verifications/latest_verification_for_consumer_version_tag"
8
7
 
9
8
  module PactBroker
10
9
  module Index
@@ -3,6 +3,7 @@ require "pact_broker/verifications/pseudo_branch_status"
3
3
  require "pact_broker/domain/verification"
4
4
  require "pact_broker/webhooks/latest_triggered_webhook"
5
5
  require "pact_broker/webhooks/webhook"
6
+ require "pact_broker/verifications/latest_verification_for_consumer_and_provider"
6
7
 
7
8
  module PactBroker
8
9
  module Integrations
@@ -21,17 +22,30 @@ module PactBroker
21
22
  integration.associations[:latest_pact] = nil
22
23
  end
23
24
 
24
- PactBroker::Pacts::PactPublication.overall_latest.each do | pact |
25
- eo_opts[:rows].each do | integration |
26
- if integration.consumer_id == pact.consumer_id && integration.provider_id == pact.provider_id
27
- integration.associations[:latest_pact] = pact
28
- end
25
+
26
+ # Would prefer to be able to eager load only the fields specified in the original Integrations
27
+ # query, but we don't seem to have that information in this context.
28
+ # Need the latest verification for the verification status in the index response.
29
+ latest_pact_publications_query = PactBroker::Pacts::PactPublication
30
+ .eager_for_domain_with_content
31
+ .eager(pact_version: :latest_verification)
32
+ .overall_latest
33
+
34
+ latest_pact_publications_query.all.each do | pact |
35
+ eo_opts[:id_map][[pact.consumer_id, pact.provider_id]]&.each do | integration |
36
+ integration.associations[:latest_pact] = pact
29
37
  end
30
38
  end
31
39
  end
32
40
 
33
41
  one_to_one(:latest_pact, class: "PactBroker::Pacts::PactPublication", :key => [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id], :eager_loader=> LATEST_PACT_EAGER_LOADER) do | _ds |
34
- PactBroker::Pacts::PactPublication.overall_latest_for_consumer_id_and_provider_id(consumer_id, provider_id)
42
+ # Would prefer to be able to eager load only the fields specified in the original Integrations
43
+ # query, but we don't seem to have that information in this context.
44
+ # Need the latest verification for the verification status in the index response.
45
+ PactBroker::Pacts::PactPublication
46
+ .eager_for_domain_with_content
47
+ .eager(pact_version: :latest_verification)
48
+ .overall_latest_for_consumer_id_and_provider_id(consumer_id, provider_id)
35
49
  end
36
50
 
37
51
  # When viewing the index, every webhook in the database will match at least one of the rows, so
@@ -65,6 +79,7 @@ module PactBroker
65
79
  end
66
80
  end
67
81
 
82
+ # TODO make this the verification status for the latest from main branch
68
83
  def verification_status_for_latest_pact
69
84
  @verification_status_for_latest_pact ||= PactBroker::Verifications::PseudoBranchStatus.new(latest_pact, latest_pact&.latest_verification)
70
85
  end
@@ -26,7 +26,7 @@ module PactBroker
26
26
  scope_for(PactBroker::Integrations::Integration)
27
27
  .eager(:consumer)
28
28
  .eager(:provider)
29
- .eager(latest_pact: [:latest_verification, :pact_version])
29
+ .eager(:latest_pact) # latest_pact eager loader is custom, can't take any more options
30
30
  .eager(:latest_verification)
31
31
  .all
32
32
  .sort { | a, b| Integration.compare_by_last_action_date(a, b) }
@@ -17,15 +17,19 @@ module PactBroker
17
17
  Sequel[:p][:created_at].as(:consumer_version_created_at),
18
18
  Sequel[:p][:id].as(:pact_order)
19
19
  ]
20
+
20
21
  VERIFICATION_COLUMNS = [
21
22
  Sequel[:v][:id].as(:verification_id),
22
23
  Sequel[:v][:provider_version_id],
23
24
  Sequel[:v][:created_at].as(:provider_version_created_at)
24
25
  ]
25
26
 
27
+ JOINED_VERIFICATION_COLUMNS = [:id, :pact_version_id, :provider_id, :provider_version_id, :created_at]
28
+
26
29
  ALL_COLUMNS = PACT_COLUMNS + VERIFICATION_COLUMNS
27
30
 
28
31
  SELECT_ALL_COLUMN_ARGS = [:select_all_columns] + ALL_COLUMNS
32
+
29
33
  dataset_module do
30
34
  select(*SELECT_ALL_COLUMN_ARGS)
31
35
 
@@ -33,9 +37,23 @@ module PactBroker
33
37
  left_outer_join(:verifications, P_V_JOIN, { table_alias: :v } )
34
38
  end
35
39
 
40
+ def inner_join_verifications
41
+ join(:verifications, P_V_JOIN, { table_alias: :v } )
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 } )
52
+ end
53
+
36
54
  def verifications_for(query_ids)
37
55
  db[:verifications]
38
- .select(:id, :pact_version_id, :provider_id, :provider_version_id, :created_at)
56
+ .select(*JOINED_VERIFICATION_COLUMNS)
39
57
  .where {
40
58
  Sequel.&(
41
59
  QueryBuilder.consumer_in_pacticipant_ids(query_ids),
@@ -1,9 +1,9 @@
1
-
2
1
  # Represents the integration relationship between a consumer and a provider in the context
3
2
  # of a matrix or can-i-deploy query.
4
- # If the required flag is set, then one of the pacticipants (consumers) specified in the HTTP query
5
- # requires the provider. It would not be required if a provider was specified, and it had an
6
- # integration with a consumer.
3
+ # If the required flag is set, then one of the pacticipants specified in the matrix query
4
+ # is a consumer and it requires the provider to be already deployed. An integration would not be required if a provider
5
+ # was specified, and it had an integration with a consumer, but that consumer wasn't deployed yet.
6
+ #
7
7
 
8
8
  module PactBroker
9
9
  module Matrix
@@ -11,7 +11,7 @@ module PactBroker
11
11
 
12
12
  attr_reader :consumer_name, :consumer_id, :provider_name, :provider_id
13
13
 
14
- def initialize consumer_id, consumer_name, provider_id, provider_name, required
14
+ def initialize(consumer_id, consumer_name, provider_id, provider_name, required)
15
15
  @consumer_id = consumer_id
16
16
  @consumer_name = consumer_name
17
17
  @provider_id = provider_id
@@ -11,6 +11,14 @@ require "pact_broker/pacts/pact_publication"
11
11
  require "pact_broker/tags/tag_with_latest_flag"
12
12
  require "pact_broker/matrix/query_ids"
13
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
+
14
22
  # The difference between `join_verifications_for` and `join_verifications` is that
15
23
  # the left outer join is done on a pre-filtered dataset in `join_verifications_for`,
16
24
  # so that we get a row with null verification fields for a pact that has been verified
@@ -19,6 +27,7 @@ require "pact_broker/matrix/query_ids"
19
27
 
20
28
  module PactBroker
21
29
  module Matrix
30
+ # TODO rename this to just Row
22
31
  # rubocop: disable Metrics/ClassLength
23
32
  class QuickRow < Sequel::Model(Sequel.as(:latest_pact_publication_ids_for_consumer_versions, :p))
24
33
 
@@ -45,6 +54,15 @@ module PactBroker
45
54
  Sequel[:v][:verification_id],
46
55
  Sequel[:v][:created_at].as(:provider_version_created_at)
47
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
+
48
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)
49
67
 
50
68
  ALL_COLUMNS = PACT_COLUMNS + VERIFICATION_COLUMNS
@@ -146,10 +164,15 @@ module PactBroker
146
164
  # When we have one selector, we need to join ALL the verifications to find out
147
165
  # what integrations exist
148
166
  def matching_one_selector(selectors)
149
- join_verifications
167
+ query_ids = QueryIds.from_selectors(selectors)
168
+ rows_where_selector_matches_consumer_cols = join_verifications
150
169
  .where {
151
- QueryBuilder.consumer_or_consumer_version_or_provider_or_provider_or_provider_version_match(QueryIds.from_selectors(selectors), :p, :v)
170
+ QueryBuilder.consumer_or_consumer_version_matches(query_ids, :p)
152
171
  }
172
+
173
+ rows_where_selector_matches_provider_cols = inner_join_verifications_matching_one_selector_provider_or_provider_version(query_ids)
174
+
175
+ rows_where_selector_matches_consumer_cols.union(rows_where_selector_matches_provider_cols)
153
176
  end
154
177
 
155
178
  def pacticipant_ids_matching_one_selector_optimised(selectors)
@@ -229,9 +252,19 @@ module PactBroker
229
252
  left_outer_join(verifications_for(query_ids), LP_LV_JOIN, { table_alias: :v } )
230
253
  end
231
254
 
255
+ def inner_join_verifications_matching_one_selector_provider_or_provider_version(query_ids)
256
+ verifications = db[LV]
257
+ .select(*JOINED_VERIFICATION_COLUMNS)
258
+ .where {
259
+ QueryBuilder.provider_or_provider_version_matches(query_ids)
260
+ }
261
+
262
+ join(verifications, LP_LV_JOIN, { table_alias: :v } )
263
+ end
264
+
232
265
  def verifications_for(query_ids)
233
266
  db[LV]
234
- .select(:verification_id, :provider_version_id, :pact_version_id, :provider_id, :created_at)
267
+ .select(*JOINED_VERIFICATION_COLUMNS)
235
268
  .where {
236
269
  Sequel.&(
237
270
  QueryBuilder.consumer_in_pacticipant_ids(query_ids),
@@ -1,9 +1,7 @@
1
1
  require "pact_broker/logging"
2
2
  require "pact_broker/repositories/helpers"
3
- require "pact_broker/matrix/row"
4
3
  require "pact_broker/matrix/quick_row"
5
4
  require "pact_broker/matrix/every_row"
6
- require "pact_broker/matrix/head_row"
7
5
  require "pact_broker/error"
8
6
  require "pact_broker/matrix/query_results"
9
7
  require "pact_broker/matrix/integration"
@@ -24,7 +22,8 @@ module PactBroker
24
22
 
25
23
  # TODO move latest verification logic in to database
26
24
 
27
- TP_COLS = PactBroker::Matrix::Row::TP_COLS
25
+ # Used when using table_print to output query results
26
+ TP_COLS = [ :consumer_version_number, :pact_revision_number, :provider_version_number, :verification_number]
28
27
 
29
28
  GROUP_BY_PROVIDER_VERSION_NUMBER = [:consumer_name, :consumer_version_number, :provider_name, :provider_version_number]
30
29
  GROUP_BY_PROVIDER = [:consumer_name, :consumer_version_number, :provider_name]
@@ -124,6 +123,8 @@ module PactBroker
124
123
  end
125
124
  end
126
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?
127
128
  def integrations_where_specified_selector_is_provider(resolved_specified_selectors)
128
129
  integrations_involving_specified_providers = PactBroker::Integrations::Integration
129
130
  .where(provider_id: resolved_specified_selectors.collect(&:pacticipant_id))
@@ -1,6 +1,5 @@
1
1
  require "pact_broker/logging"
2
2
  require "pact_broker/repositories"
3
- require "pact_broker/matrix/row"
4
3
  require "pact_broker/matrix/deployment_status_summary"
5
4
  require "pact_broker/matrix/query_results_with_deployment_status_summary"
6
5
  require "pact_broker/messages"
@@ -118,8 +118,8 @@ module PactBroker
118
118
 
119
119
  def matrix_count
120
120
  begin
121
- PactBroker::Matrix::Row.db.with_statement_timeout(PactBroker.configuration.metrics_sql_statement_timeout) do
122
- PactBroker::Matrix::Row.count
121
+ PactBroker::Matrix::EveryRow.db.with_statement_timeout(PactBroker.configuration.metrics_sql_statement_timeout) do
122
+ PactBroker::Matrix::EveryRow.default_scope.count
123
123
  end
124
124
  rescue Sequel::DatabaseError => _ex
125
125
  -1
@@ -19,6 +19,7 @@ module PactBroker
19
19
  end
20
20
 
21
21
  difference = diff(previous_pact_hash, pact_hash)
22
+
22
23
  Pact::Matchers::UnixDiffFormatter.call(difference, colour: false, include_explanation: false)
23
24
  end
24
25
  end
@@ -32,7 +32,10 @@ module PactBroker
32
32
 
33
33
  pact_publications.each do | pact_publication |
34
34
  pact_publication.consumer_version_tags.collect(&:name).sort.each do | tag_name |
35
- pact_publication.associations[:head_pact_publications_for_tags] << head_pact_publications_by_tag[tag_name]
35
+ # Not sure how this can ever be nil, but a PF error suggests that it has happend. Maybe a timing issue?
36
+ if head_pact_publications_by_tag[tag_name]
37
+ pact_publication.associations[:head_pact_publications_for_tags] << head_pact_publications_by_tag[tag_name]
38
+ end
36
39
  end
37
40
  end
38
41
  end