pact_broker 2.95.1 → 2.98.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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/Gemfile +1 -0
  4. data/docs/CONFIGURATION.md +120 -66
  5. data/lib/db.rb +1 -7
  6. data/lib/pact_broker/api/middleware/http_debug_logs.rb +36 -0
  7. data/lib/pact_broker/app.rb +3 -7
  8. data/lib/pact_broker/config/basic_auth_configuration.rb +7 -0
  9. data/lib/pact_broker/config/runtime_configuration.rb +22 -4
  10. data/lib/pact_broker/config/runtime_configuration_coercion_methods.rb +11 -0
  11. data/lib/pact_broker/config/runtime_configuration_database_methods.rb +6 -1
  12. data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +13 -2
  13. data/lib/pact_broker/configuration.rb +2 -12
  14. data/lib/pact_broker/db/models.rb +2 -2
  15. data/lib/pact_broker/index/service.rb +2 -3
  16. data/lib/pact_broker/integrations/integration.rb +21 -6
  17. data/lib/pact_broker/integrations/service.rb +1 -1
  18. data/lib/pact_broker/matrix/repository.rb +2 -3
  19. data/lib/pact_broker/matrix/service.rb +0 -1
  20. data/lib/pact_broker/metrics/service.rb +2 -2
  21. data/lib/pact_broker/pacts/lazy_loaders.rb +26 -0
  22. data/lib/pact_broker/pacts/pact_publication.rb +13 -34
  23. data/lib/pact_broker/pacts/pact_version.rb +24 -28
  24. data/lib/pact_broker/pacts/pact_version_association_loaders.rb +36 -0
  25. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +9 -13
  26. data/lib/pact_broker/pacts/repository.rb +29 -25
  27. data/lib/pact_broker/repositories/helpers.rb +4 -0
  28. data/lib/pact_broker/test/http_test_data_builder.rb +8 -1
  29. data/lib/pact_broker/test/test_data_builder.rb +2 -1
  30. data/lib/pact_broker/ui/controllers/matrix.rb +14 -11
  31. data/lib/pact_broker/version.rb +1 -1
  32. data/pact_broker.gemspec +1 -1
  33. metadata +9 -16
  34. data/lib/pact_broker/matrix/aggregated_row.rb +0 -79
  35. data/lib/pact_broker/matrix/head_row.rb +0 -80
  36. data/lib/pact_broker/matrix/row.rb +0 -287
@@ -0,0 +1,36 @@
1
+ require "pact_broker/logging"
2
+
3
+ module PactBroker
4
+ module Api
5
+ module Middleware
6
+ class HttpDebugLogs
7
+ include PactBroker::Logging
8
+
9
+ EXCLUDE_HEADERS = ["puma.", "rack.", "pactbroker."]
10
+ RACK_SESSION = "rack.session"
11
+
12
+ def initialize(app)
13
+ @app = app
14
+ @logger = logger
15
+ end
16
+
17
+ def call(env)
18
+ env_to_log = env.reject { | header, _ | header.start_with?(*EXCLUDE_HEADERS) }
19
+ env_to_log["rack.session"] = env["rack.session"].to_hash if env["rack.session"]
20
+ env_to_log["rack.input"] = request_body(env) if env["rack.input"]
21
+ logger.debug("env", payload: env_to_log)
22
+ status, headers, body = @app.call(env)
23
+ logger.debug("response", payload: { "status" => status, "headers" => headers, "body" => body })
24
+ [status, headers, body]
25
+ end
26
+
27
+ def request_body(env)
28
+ buffer = env["rack.input"]
29
+ request_body = buffer.read
30
+ buffer.respond_to?(:rewind) && buffer.rewind
31
+ JSON.parse(request_body) rescue request_body
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -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
@@ -20,6 +20,13 @@ module PactBroker
20
20
 
21
21
  sensitive_values(:basic_auth_password, :basic_auth_read_only_password)
22
22
 
23
+ coerce_types(
24
+ basic_auth_username: :string,
25
+ basic_auth_password: :string,
26
+ basic_auth_read_only_username: :string,
27
+ basic_auth_read_only_password: :string
28
+ )
29
+
23
30
  def basic_auth_credentials_provided?
24
31
  basic_auth_username&.not_blank? && basic_auth_password&.not_blank?
25
32
  end
@@ -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(
@@ -178,8 +182,14 @@ module PactBroker
178
182
  def webhook_certificates= webhook_certificates
179
183
  if webhook_certificates.is_a?(Array)
180
184
  super(webhook_certificates.collect(&:symbolize_keys))
185
+ elsif webhook_certificates.is_a?(Hash)
186
+ if all_keys_are_number_strings?(webhook_certificates)
187
+ super(convert_hash_with_number_string_keys_to_array(webhook_certificates).collect(&:symbolize_keys))
188
+ else
189
+ raise_validation_error("webhook_certificates must be an array, or a hash where each key is an integer in string format.")
190
+ end
181
191
  elsif !webhook_certificates.nil?
182
- raise_validation_error("webhook_certificates must be an array")
192
+ raise_validation_error("webhook_certificates cannot be set using a #{webhook_certificates.class}")
183
193
  end
184
194
  end
185
195
 
@@ -208,6 +218,14 @@ module PactBroker
208
218
  def raise_validation_error(msg)
209
219
  raise PactBroker::ConfigurationError, msg
210
220
  end
221
+
222
+ def set_webhook_attribute_defaults
223
+ # can't set a default on this, or anyway config blows up when trying to merge the
224
+ # hash from the env vars into an array/nil.
225
+ if webhook_certificates.nil?
226
+ self.webhook_certificates = []
227
+ end
228
+ end
211
229
  end
212
230
  end
213
231
  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)
@@ -31,6 +31,11 @@ module PactBroker
31
31
  database_connection_validation_timeout: nil
32
32
  )
33
33
 
34
+ coerce_types(
35
+ database_username: :string,
36
+ database_password: :string
37
+ )
38
+
34
39
  def database_configuration
35
40
  database_credentials
36
41
  .merge(
@@ -77,7 +82,7 @@ module PactBroker
77
82
  private :postgres?
78
83
 
79
84
  def driver_options
80
- if postgres?
85
+ if postgres? && database_statement_timeout
81
86
  { options: "-c statement_timeout=#{database_statement_timeout}s" }
82
87
  end
83
88
  end
@@ -1,8 +1,11 @@
1
1
  require "uri"
2
+ require "pact_broker/hash_refinements"
2
3
 
3
4
  module PactBroker
4
5
  module Config
5
6
  module RuntimeConfigurationLoggingMethods
7
+ using PactBroker::HashRefinements
8
+
6
9
  module ClassMethods
7
10
  def sensitive_values(*values)
8
11
  @sensitive_values ||= []
@@ -19,17 +22,25 @@ module PactBroker
19
22
  end
20
23
 
21
24
  module InstanceMethods
25
+ # base_url raises a not implemented error
22
26
  def log_configuration(logger)
23
- to_source_trace.sort_by { |key, _| key }.each { |key, value| log_config_inner(key, value, logger) }
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
+ }
33
+ end.sort_by { |key, _| key }.each { |key, value| log_config_inner(key, value, logger) }
24
34
  end
25
35
 
26
36
  def log_config_inner(key, value, logger)
37
+ # TODO fix the source display for webhook_certificates set by environment variables
27
38
  if !value.has_key? :value
28
39
  value.sort_by { |inner_key, _| inner_key }.each { |inner_key, inner_value| log_config_inner("#{key}.#{inner_key}", inner_value, logger) }
29
40
  elsif self.class.sensitive_value?(key)
30
41
  logger.info "#{key}=#{redact(key, value[:value])} source=#{value[:source]}"
31
42
  else
32
- logger.info "#{key}=#{value[:value]} source=#{value[:source]}"
43
+ logger.info "#{key}=#{value[:value].inspect} source=#{value[:source]}"
33
44
  end
34
45
  end
35
46
  private :log_config_inner
@@ -15,10 +15,6 @@ module PactBroker
15
15
  RequestStore.store[:pact_broker_configuration] = configuration
16
16
  end
17
17
 
18
- def self.with_runtime_configuration_overrides(overrides, &block)
19
- self.configuration.with_runtime_configuration_overrides(overrides, &block)
20
- end
21
-
22
18
  # @private, for testing only
23
19
  def self.reset_configuration
24
20
  RequestStore.store[:pact_broker_configuration] = Configuration.default_configuration
@@ -59,6 +55,8 @@ module PactBroker
59
55
  config.version_parser = PactBroker::Versions::ParseSemanticVersion
60
56
  config.sha_generator = PactBroker::Pacts::GenerateSha
61
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.
62
60
  require "pact_broker/db/seed_example_data"
63
61
  PactBroker::DB::SeedExampleData.call
64
62
  end
@@ -82,14 +80,6 @@ module PactBroker
82
80
  config
83
81
  end
84
82
 
85
- def with_runtime_configuration_overrides(overrides)
86
- original_runtime_configuration = runtime_configuration
87
- self.runtime_configuration = override_runtime_configuration!(overrides)
88
- yield
89
- ensure
90
- self.runtime_configuration = original_runtime_configuration
91
- end
92
-
93
83
  def override_runtime_configuration!(overrides)
94
84
  new_runtime_configuration = runtime_configuration.dup
95
85
  valid_overrides = {}
@@ -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
@@ -108,7 +107,7 @@ module PactBroker
108
107
  # rubocop: disable Metrics/CyclomaticComplexity
109
108
  def self.latest_verification_for_pseudo_branch(pact_publication, is_overall_latest, latest_verifications_for_cv_tags, tags_option, options)
110
109
  if options[:view] == "branch" || (options[:view] == "all" && pact_publication.consumer_version.branch_heads.any?)
111
- pact_publication.latest_verification || pact_publication.latest_verification_for_consumer_branches(forbid_lazy_load: false)
110
+ pact_publication.latest_verification || pact_publication.latest_verification_for_consumer_branches
112
111
  elsif tags_option == true
113
112
  latest_verifications_for_cv_tags
114
113
  .select{ | v | v.consumer_id == pact_publication.consumer_id && v.provider_id == pact_publication.provider_id && pact_publication.head_pact_tags.collect(&:name).include?(v.consumer_version_tag_name) }
@@ -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) }
@@ -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]
@@ -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
@@ -9,6 +9,32 @@ module PactBroker
9
9
  .latest_for_consumer_tag(consumer_version_tag_names)
10
10
  .from_self.order_by(:tag_name)
11
11
  }
12
+
13
+ LATEST_VERIFICATION_FOR_CONSUMER_BRANCHES = lambda {
14
+ bv_pp_join = {
15
+ Sequel[:branch_versions][:version_id] => Sequel[:pact_publications][:consumer_version_id],
16
+ Sequel[:pact_publications][:provider_id] => provider_id
17
+ }
18
+
19
+ verifications_join = {
20
+ Sequel[:verifications][:pact_version_id] => Sequel[:pact_publications][:pact_version_id]
21
+ }
22
+
23
+ branch_ids = PactBroker::Versions::BranchVersion
24
+ .select(:branch_id)
25
+ .where(version_id: consumer_version_id)
26
+
27
+
28
+ latest_verification_id = PactBroker::Versions::BranchVersion
29
+ .select(Sequel[:verifications][:id])
30
+ .where(Sequel[:branch_versions][:branch_id] => branch_ids)
31
+ .join(:pact_publications, bv_pp_join)
32
+ .join(:verifications, verifications_join)
33
+ .order(Sequel.desc(Sequel[:verifications][:id]))
34
+ .limit(1)
35
+
36
+ PactBroker::Domain::Verification.where(id: latest_verification_id)
37
+ }
12
38
  end
13
39
  end
14
40
  end
@@ -20,12 +20,11 @@ module PactBroker
20
20
  delegate [:consumer_version_number, :name, :provider_name, :consumer_name] => :cached_domain_for_delegation
21
21
 
22
22
  set_primary_key :id
23
- associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id, forbid_lazy_load: false)
24
- associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id, forbid_lazy_load: false)
25
- associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id, forbid_lazy_load: false)
26
- associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id, forbid_lazy_load: false)
27
- associate(:many_to_one, :integration, class: "PactBroker::Integrations::Integration", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id], forbid_lazy_load: false)
28
-
23
+ associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
24
+ associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
25
+ associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id)
26
+ associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id)
27
+ associate(:many_to_one, :integration, class: "PactBroker::Integrations::Integration", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id], read_only: true, forbid_lazy_load: false)
29
28
  # TODO rename to consumer_version_tags
30
29
  associate(:one_to_many, :tags, :class => "PactBroker::Domain::Tag", :key => :version_id, :primary_key => :consumer_version_id)
31
30
 
@@ -34,43 +33,19 @@ module PactBroker
34
33
  read_only: true,
35
34
  key: :id,
36
35
  primary_key: :id,
37
- dataset: lambda {
38
-
39
- bv_pp_join = {
40
- Sequel[:branch_versions][:version_id] => Sequel[:pact_publications][:consumer_version_id],
41
- Sequel[:pact_publications][:provider_id] => provider_id
42
- }
43
-
44
- verifications_join = {
45
- Sequel[:verifications][:pact_version_id] => Sequel[:pact_publications][:pact_version_id]
46
- }
47
-
48
- branch_ids = PactBroker::Versions::BranchVersion
49
- .select(:branch_id)
50
- .where(version_id: consumer_version_id)
51
-
52
-
53
- latest_verification_id = PactBroker::Versions::BranchVersion
54
- .select(Sequel[:verifications][:id])
55
- .where(Sequel[:branch_versions][:branch_id] => branch_ids)
56
- .join(:pact_publications, bv_pp_join)
57
- .join(:verifications, verifications_join)
58
- .order(Sequel.desc(Sequel[:verifications][:id]))
59
- .limit(1)
60
-
61
- PactBroker::Domain::Verification.where(id: latest_verification_id)
62
- },
36
+ forbid_lazy_load: false,
37
+ dataset: PactBroker::Pacts::LazyLoaders::LATEST_VERIFICATION_FOR_CONSUMER_BRANCHES,
63
38
  eager_loader: proc do | _ |
64
39
  raise NotImplementedError
65
40
  end
66
41
  )
67
42
 
68
-
69
43
  one_to_many(:head_pact_publications_for_tags,
70
44
  class: PactPublication,
71
45
  read_only: true,
72
46
  dataset: PactBroker::Pacts::LazyLoaders::HEAD_PACT_PUBLICATIONS_FOR_TAGS,
73
- eager_loader: PactBroker::Pacts::EagerLoaders::HeadPactPublicationsForTags
47
+ eager_loader: PactBroker::Pacts::EagerLoaders::HeadPactPublicationsForTags,
48
+ forbid_lazy_load: false
74
49
  )
75
50
 
76
51
  plugin :upsert, identifying_columns: [:consumer_version_id, :provider_id, :revision_number]
@@ -81,6 +56,10 @@ module PactBroker
81
56
  include PactPublicationDatasetModule
82
57
  include PactPublicationCleanSelectorDatasetModule
83
58
  include PactPublicationWipDatasetModule
59
+
60
+ def eager_for_domain_with_content
61
+ eager(:tags, :consumer, :provider, :consumer_version, :pact_version)
62
+ end
84
63
  end
85
64
 
86
65
  def self.subtract(a, *b)
@@ -1,39 +1,32 @@
1
1
  require "sequel"
2
2
  require "pact_broker/repositories/helpers"
3
- require "pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version"
4
3
  require "pact_broker/pacts/content"
4
+ require "pact_broker/pacts/pact_version_association_loaders"
5
5
 
6
6
  module PactBroker
7
7
  module Pacts
8
8
  class PactVersion < Sequel::Model(:pact_versions)
9
+ include PactVersionAssociationLoaders
10
+
9
11
  plugin :timestamps
10
12
  plugin :upsert, identifying_columns: [:consumer_id, :provider_id, :sha]
11
13
 
12
- one_to_many :pact_publications, reciprocal: :pact_version
13
- one_to_many :verifications, reciprocal: :verification, order: :id, class: "PactBroker::Domain::Verification"
14
- associate(:many_to_one, :provider, class: "PactBroker::Domain::Pacticipant", key: :provider_id, primary_key: :id)
15
- associate(:many_to_one, :consumer, class: "PactBroker::Domain::Pacticipant", key: :consumer_id, primary_key: :id)
16
- associate(:many_to_many, :consumer_versions, class: "PactBroker::Domain::Version", join_table: :pact_publications, left_key: :pact_version_id, right_key: :consumer_version_id, order: :order)
14
+ one_to_many(:pact_publications, reciprocal: :pact_version)
15
+ one_to_many(:verifications, reciprocal: :verification, order: :id, class: "PactBroker::Domain::Verification")
16
+ many_to_one(:provider, class: "PactBroker::Domain::Pacticipant", key: :provider_id, primary_key: :id)
17
+ many_to_one(:consumer, class: "PactBroker::Domain::Pacticipant", key: :consumer_id, primary_key: :id)
18
+ many_to_many(:consumer_versions,
19
+ class: "PactBroker::Domain::Version",
20
+ join_table: :pact_publications,
21
+ left_key: :pact_version_id,
22
+ right_key: :consumer_version_id,
23
+ order: :order
24
+ )
17
25
 
18
26
  one_to_one(:latest_main_branch_verification,
19
27
  class: "PactBroker::Domain::Verification",
20
28
  read_only: true,
21
- dataset: lambda {
22
- providers_join = {
23
- Sequel[:providers][:id] => Sequel[:latest_verification_id_for_pact_version_and_provider_version][:provider_id]
24
- }
25
-
26
- branch_versions_join = {
27
- Sequel[:latest_verification_id_for_pact_version_and_provider_version][:provider_version_id] => Sequel[:branch_versions][:version_id],
28
- Sequel[:providers][:main_branch] => Sequel[:branch_versions][:branch_name]
29
- }
30
- max_verification_id_for_pact_version = PactBroker::Verifications::LatestVerificationIdForPactVersionAndProviderVersion
31
- .join(:pacticipants, providers_join, { table_alias: :providers })
32
- .join(:branch_versions, branch_versions_join)
33
- .select(Sequel.function(:max, :verification_id))
34
- .where(pact_version_id: id)
35
- PactBroker::Domain::Verification.where(id: max_verification_id_for_pact_version)
36
- },
29
+ dataset: LATEST_MAIN_BRANCH_VERIFICATION,
37
30
  key: :pact_version_id,
38
31
  primary_key: :id,
39
32
  eager_block: lambda { | ds | ds.from_provider_main_branch.latest_by_pact_version }
@@ -42,15 +35,18 @@ module PactBroker
42
35
  one_to_one(:latest_verification,
43
36
  class: "PactBroker::Domain::Verification",
44
37
  read_only: true,
45
- dataset: lambda { PactBroker::Domain::Verification.where(id: PactBroker::Verifications::LatestVerificationIdForPactVersionAndProviderVersion.select(Sequel.function(:max, :verification_id)).where(pact_version_id: id)) },
38
+ dataset: LATEST_VERIFICATION_DATASET,
46
39
  key: :pact_version_id, primary_key: :id,
47
40
  eager_block: lambda { | ds | ds.latest_by_pact_version }
48
41
  )
49
42
 
50
43
  # do not eager load this - it won't work because of the limit(1)
51
- one_through_one(:latest_consumer_version, class: "PactBroker::Domain::Version", join_table: :pact_publications, left_key: :pact_version_id, right_key: :consumer_version_id) do | ds |
52
- ds.unlimited.order(Sequel.desc(:order)).limit(1)
53
- end
44
+ one_through_one(:latest_consumer_version,
45
+ class: "PactBroker::Domain::Version",
46
+ join_table: :pact_publications,
47
+ left_key: :pact_version_id,
48
+ right_key: :consumer_version_id, &LATEST_CONSUMER_VERSION_LAZY_LOADER
49
+ )
54
50
 
55
51
  dataset_module do
56
52
  include PactBroker::Repositories::Helpers
@@ -89,11 +85,11 @@ module PactBroker
89
85
  end
90
86
 
91
87
  def provider_name
92
- pact_publications.last.provider.name
88
+ provider.name
93
89
  end
94
90
 
95
91
  def consumer_name
96
- pact_publications.last.consumer.name
92
+ consumer.name
97
93
  end
98
94
 
99
95
  def latest_pact_publication
@@ -0,0 +1,36 @@
1
+ require "pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version"
2
+
3
+ module PactBroker
4
+ module Pacts
5
+ module PactVersionAssociationLoaders
6
+
7
+ LATEST_MAIN_BRANCH_VERIFICATION = lambda {
8
+ providers_join = {
9
+ Sequel[:providers][:id] => Sequel[:latest_verification_id_for_pact_version_and_provider_version][:provider_id]
10
+ }
11
+
12
+ branch_versions_join = {
13
+ Sequel[:latest_verification_id_for_pact_version_and_provider_version][:provider_version_id] => Sequel[:branch_versions][:version_id],
14
+ Sequel[:providers][:main_branch] => Sequel[:branch_versions][:branch_name]
15
+ }
16
+ max_verification_id_for_pact_version = PactBroker::Verifications::LatestVerificationIdForPactVersionAndProviderVersion
17
+ .join(:pacticipants, providers_join, { table_alias: :providers })
18
+ .join(:branch_versions, branch_versions_join)
19
+ .select(Sequel.function(:max, :verification_id))
20
+ .where(pact_version_id: id)
21
+ PactBroker::Domain::Verification.where(id: max_verification_id_for_pact_version)
22
+ }
23
+
24
+ LATEST_VERIFICATION_DATASET = lambda {
25
+ PactBroker::Domain::Verification
26
+ .where(
27
+ id: PactBroker::Verifications::LatestVerificationIdForPactVersionAndProviderVersion.select(
28
+ Sequel.function(:max, :verification_id)
29
+ ).where(pact_version_id: id)
30
+ )
31
+ }
32
+
33
+ LATEST_CONSUMER_VERSION_LAZY_LOADER = lambda { | ds | ds.unlimited.order(Sequel.desc(:order)).limit(1) }
34
+ end
35
+ end
36
+ end