pact_broker 2.72.0 → 2.76.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (173) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/.optic/.gitignore +2 -0
  4. data/.optic/api/specification.json +1 -0
  5. data/.optic/ignore +14 -0
  6. data/CHANGELOG.md +66 -0
  7. data/DEVELOPER_SETUP.md +9 -0
  8. data/Dockerfile +1 -0
  9. data/ISSUES.md +3 -3
  10. data/README.md +1 -1
  11. data/config/database.yml +1 -1
  12. data/db/migrations/20210115_add_webhook_foreign_key_indexes.rb +49 -0
  13. data/db/migrations/20210116_add_context_to_triggered_webhook.rb +11 -0
  14. data/db/migrations/migration_helper.rb +8 -0
  15. data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +33 -0
  16. data/docker-compose-test.yml +4 -4
  17. data/lib/db.rb +1 -0
  18. data/lib/pact_broker/api.rb +13 -2
  19. data/lib/pact_broker/api/decorators.rb +3 -7
  20. data/lib/pact_broker/api/decorators/configuration.rb +33 -0
  21. data/lib/pact_broker/api/decorators/decorator_context_creator.rb +13 -0
  22. data/lib/pact_broker/api/decorators/extended_pact_decorator.rb +9 -1
  23. data/lib/pact_broker/api/decorators/extended_verification_decorator.rb +8 -0
  24. data/lib/pact_broker/api/decorators/matrix_decorator.rb +9 -4
  25. data/lib/pact_broker/api/decorators/pact_collection_decorator.rb +1 -0
  26. data/lib/pact_broker/api/decorators/pacticipant_collection_decorator.rb +2 -3
  27. data/lib/pact_broker/api/decorators/reason_decorator.rb +2 -0
  28. data/lib/pact_broker/api/decorators/tag_decorator.rb +0 -3
  29. data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +3 -1
  30. data/lib/pact_broker/api/pact_broker_urls.rb +4 -4
  31. data/lib/pact_broker/api/paths.rb +5 -0
  32. data/lib/pact_broker/api/renderers/html_pact_renderer.rb +2 -2
  33. data/lib/pact_broker/api/resources/all_webhooks.rb +3 -3
  34. data/lib/pact_broker/api/resources/can_i_deploy_badge.rb +1 -1
  35. data/lib/pact_broker/api/resources/dashboard.rb +2 -2
  36. data/lib/pact_broker/api/resources/default_base_resource.rb +37 -12
  37. data/lib/pact_broker/api/resources/error_handler.rb +1 -1
  38. data/lib/pact_broker/api/resources/error_response_body_generator.rb +41 -0
  39. data/lib/pact_broker/api/resources/group.rb +1 -1
  40. data/lib/pact_broker/api/resources/integrations.rb +1 -1
  41. data/lib/pact_broker/api/resources/label.rb +1 -1
  42. data/lib/pact_broker/api/resources/latest_pact.rb +2 -2
  43. data/lib/pact_broker/api/resources/latest_pacts.rb +1 -1
  44. data/lib/pact_broker/api/resources/latest_verifications_for_consumer_version.rb +2 -2
  45. data/lib/pact_broker/api/resources/matrix.rb +2 -2
  46. data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +1 -1
  47. data/lib/pact_broker/api/resources/metadata_resource_methods.rb +2 -1
  48. data/lib/pact_broker/api/resources/pact.rb +2 -2
  49. data/lib/pact_broker/api/resources/pact_triggered_webhooks.rb +1 -1
  50. data/lib/pact_broker/api/resources/pact_versions.rb +1 -1
  51. data/lib/pact_broker/api/resources/pact_webhooks.rb +3 -3
  52. data/lib/pact_broker/api/resources/pact_webhooks_status.rb +2 -2
  53. data/lib/pact_broker/api/resources/pacticipant.rb +1 -1
  54. data/lib/pact_broker/api/resources/pacticipants.rb +3 -3
  55. data/lib/pact_broker/api/resources/pacticipants_for_label.rb +1 -1
  56. data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +1 -1
  57. data/lib/pact_broker/api/resources/provider_pacts.rb +1 -7
  58. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +2 -2
  59. data/lib/pact_broker/api/resources/relationships.rb +1 -1
  60. data/lib/pact_broker/api/resources/tag.rb +1 -1
  61. data/lib/pact_broker/api/resources/tagged_pact_versions.rb +1 -1
  62. data/lib/pact_broker/api/resources/verification.rb +2 -2
  63. data/lib/pact_broker/api/resources/verification_triggered_webhooks.rb +1 -1
  64. data/lib/pact_broker/api/resources/verifications.rb +1 -1
  65. data/lib/pact_broker/api/resources/version.rb +1 -1
  66. data/lib/pact_broker/api/resources/versions.rb +1 -1
  67. data/lib/pact_broker/api/resources/webhook.rb +2 -2
  68. data/lib/pact_broker/api/resources/webhook_execution.rb +4 -4
  69. data/lib/pact_broker/api/resources/webhook_execution_methods.rb +1 -3
  70. data/lib/pact_broker/api/resources/webhooks.rb +3 -3
  71. data/lib/pact_broker/app.rb +14 -3
  72. data/lib/pact_broker/application_context.rb +41 -0
  73. data/lib/pact_broker/configuration.rb +12 -4
  74. data/lib/pact_broker/doc/controllers/app.rb +3 -2
  75. data/lib/pact_broker/domain/version.rb +13 -6
  76. data/lib/pact_broker/domain/webhook_request.rb +1 -1
  77. data/lib/pact_broker/error.rb +0 -2
  78. data/lib/pact_broker/errors.rb +28 -0
  79. data/lib/pact_broker/errors/error_logger.rb +25 -0
  80. data/lib/pact_broker/metrics/service.rb +12 -1
  81. data/lib/pact_broker/pacts/metadata.rb +53 -8
  82. data/lib/pact_broker/pacts/repository.rb +10 -17
  83. data/lib/pact_broker/pacts/selector.rb +22 -0
  84. data/lib/pact_broker/pacts/selectors.rb +4 -0
  85. data/lib/pact_broker/services.rb +106 -31
  86. data/lib/pact_broker/tags/tag_with_latest_flag.rb +2 -0
  87. data/lib/pact_broker/test/http_test_data_builder.rb +83 -21
  88. data/lib/pact_broker/test/test_data_builder.rb +3 -2
  89. data/lib/pact_broker/ui/views/index/_getting-started.haml +1 -1
  90. data/lib/pact_broker/ui/views/index/show-with-tags.haml +16 -16
  91. data/lib/pact_broker/ui/views/index/show.haml +6 -6
  92. data/lib/pact_broker/ui/views/layouts/main.haml +2 -2
  93. data/lib/pact_broker/ui/views/matrix/show.haml +32 -33
  94. data/lib/pact_broker/version.rb +1 -1
  95. data/lib/pact_broker/webhooks/execution_configuration.rb +4 -0
  96. data/lib/pact_broker/webhooks/execution_configuration_creator.rb +14 -0
  97. data/lib/pact_broker/webhooks/repository.rb +3 -2
  98. data/lib/pact_broker/webhooks/service.rb +2 -1
  99. data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
  100. data/lib/rack/pact_broker/hal_browser_redirect.rb +42 -0
  101. data/lib/rack/pact_broker/set_base_url.rb +22 -0
  102. data/lib/sequel/extensions/statement_timeout.rb +22 -0
  103. data/optic.yml +5 -0
  104. data/pact_broker.gemspec +1 -1
  105. data/public/css/bootstrap-grid.css +3719 -0
  106. data/public/css/bootstrap-grid.css.map +1 -0
  107. data/public/css/bootstrap-grid.min.css +7 -0
  108. data/public/css/bootstrap-grid.min.css.map +1 -0
  109. data/public/css/bootstrap-reboot.css +331 -0
  110. data/public/css/bootstrap-reboot.css.map +1 -0
  111. data/public/css/bootstrap-reboot.min.css +8 -0
  112. data/public/css/bootstrap-reboot.min.css.map +1 -0
  113. data/public/css/bootstrap.css +8885 -5604
  114. data/public/css/bootstrap.css.map +1 -1
  115. data/public/css/bootstrap.min.css +4 -3
  116. data/public/css/bootstrap.min.css.map +1 -1
  117. data/public/images/alert.svg +1 -0
  118. data/public/images/arrow-switch.svg +1 -0
  119. data/public/images/check.svg +1 -0
  120. data/public/images/clock.svg +1 -0
  121. data/public/images/copy.svg +1 -0
  122. data/public/images/kebab-horizontal.svg +1 -0
  123. data/public/javascripts/clipboard.js +3 -3
  124. data/public/javascripts/{jquery-3.3.1.js → jquery-3.5.1.js} +1150 -642
  125. data/public/javascripts/jquery-3.5.1.min.js +2 -0
  126. data/public/javascripts/jquery-3.5.1.min.map +1 -0
  127. data/public/javascripts/matrix.js +2 -2
  128. data/public/js/bootstrap.bundle.js +7013 -0
  129. data/public/js/bootstrap.bundle.js.map +1 -0
  130. data/public/js/bootstrap.bundle.min.js +7 -0
  131. data/public/js/bootstrap.bundle.min.js.map +1 -0
  132. data/public/js/bootstrap.js +3862 -1804
  133. data/public/js/bootstrap.js.map +1 -0
  134. data/public/js/bootstrap.min.js +6 -6
  135. data/public/js/bootstrap.min.js.map +1 -0
  136. data/public/stylesheets/index.css +56 -3
  137. data/public/stylesheets/matrix.css +55 -5
  138. data/public/stylesheets/pact.css +14 -0
  139. data/regression/.gitignore +1 -0
  140. data/regression/can_i_deploy_spec.rb +42 -0
  141. data/regression/regression_helper.rb +37 -0
  142. data/regression/script/approval-all.sh +6 -0
  143. data/script/exercise-api-for-optic.sh +3 -0
  144. data/script/reproduce-issue-starting-up.rb +43 -0
  145. data/script/reproduce-issue.rb +9 -21
  146. data/spec/lib/pact_broker/api/decorators/extended_pact_decorator_spec.rb +1 -0
  147. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +20 -8
  148. data/spec/lib/pact_broker/api/decorators/verifiable_pact_decorator_spec.rb +5 -7
  149. data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +10 -6
  150. data/spec/lib/pact_broker/api/resources/can_i_deploy_badge_spec.rb +1 -1
  151. data/spec/lib/pact_broker/api/resources/default_base_resource_spec.rb +59 -10
  152. data/spec/lib/pact_broker/api/resources/error_response_body_generator_spec.rb +69 -0
  153. data/spec/lib/pact_broker/db/log_quietener_spec.rb +1 -1
  154. data/spec/lib/pact_broker/doc/controllers/app_spec.rb +3 -5
  155. data/spec/lib/pact_broker/errors/error_logger_spec.rb +62 -0
  156. data/spec/lib/pact_broker/errors_spec.rb +55 -0
  157. data/spec/lib/pact_broker/pacts/metadata_spec.rb +73 -0
  158. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +2 -2
  159. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +33 -13
  160. data/spec/lib/pact_broker/pacts/selected_pact_spec.rb +23 -0
  161. data/spec/lib/pact_broker/webhooks/repository_spec.rb +5 -2
  162. data/spec/lib/pact_broker/webhooks/service_spec.rb +2 -1
  163. data/spec/lib/rack/pact_broker/hal_browser_redirect_spec.rb +27 -0
  164. data/tasks/rspec.rake +6 -0
  165. metadata +65 -17
  166. data/public/css/bootstrap-theme.css +0 -587
  167. data/public/css/bootstrap-theme.css.map +0 -1
  168. data/public/css/bootstrap-theme.min.css +0 -6
  169. data/public/css/bootstrap-theme.min.css.map +0 -1
  170. data/public/fonts/glyphicons-halflings-regular.svg +0 -288
  171. data/public/javascripts/jquery-3.3.1.min.js +0 -2
  172. data/public/javascripts/jquery-3.3.1.min.map +0 -1
  173. data/spec/lib/pact_broker/api/resources/error_handler_spec.rb +0 -195
@@ -0,0 +1,41 @@
1
+ require 'pact_broker/api/decorators/configuration'
2
+ require 'pact_broker/api/decorators/decorator_context_creator'
3
+ require 'pact_broker/webhooks/execution_configuration_creator'
4
+ require 'pact_broker/errors/error_logger'
5
+ require 'pact_broker/api/resources/error_response_body_generator'
6
+
7
+ module PactBroker
8
+ class ApplicationContext
9
+ attr_reader :decorator_configuration,
10
+ :decorator_context_creator,
11
+ :webhook_execution_configuration_creator,
12
+ :resource_authorizer,
13
+ :before_resource,
14
+ :after_resource,
15
+ :error_logger,
16
+ :error_response_body_generator
17
+
18
+ def initialize(params = {})
19
+ params_with_defaults = {
20
+ decorator_configuration: PactBroker::Api::Decorators::Configuration.default_configuration,
21
+ decorator_context_creator: PactBroker::Api::Decorators::DecoratorContextCreator,
22
+ webhook_execution_configuration_creator: PactBroker::Webhooks::ExecutionConfigurationCreator,
23
+ error_logger: PactBroker::Errors::ErrorLogger,
24
+ error_response_body_generator: PactBroker::Api::Resources::ErrorResponseBodyGenerator
25
+ }.merge(params)
26
+
27
+ @decorator_configuration = params_with_defaults[:decorator_configuration]
28
+ @decorator_context_creator = params_with_defaults[:decorator_context_creator]
29
+ @webhook_execution_configuration_creator = params_with_defaults[:webhook_execution_configuration_creator]
30
+ @resource_authorizer = params_with_defaults[:resource_authorizer]
31
+ @before_resource = params_with_defaults[:before_resource]
32
+ @after_resource = params_with_defaults[:after_resource]
33
+ @error_logger = params_with_defaults[:error_logger]
34
+ @error_response_body_generator = params_with_defaults[:error_response_body_generator]
35
+ end
36
+
37
+ def self.default_application_context(overrides = {})
38
+ ApplicationContext.new(overrides)
39
+ end
40
+ end
41
+ end
@@ -38,7 +38,8 @@ module PactBroker
38
38
  :log_dir,
39
39
  :allow_missing_migration_files,
40
40
  :auto_migrate_db_data,
41
- :use_rack_protection
41
+ :use_rack_protection,
42
+ :metrics_sql_statement_timeout
42
43
  ]
43
44
 
44
45
  attr_accessor :base_url, :log_dir, :database_connection, :auto_migrate_db, :auto_migrate_db_data, :allow_missing_migration_files, :example_data_seeder, :seed_example_data, :use_hal_browser, :html_pact_renderer, :use_rack_protection
@@ -57,6 +58,7 @@ module PactBroker
57
58
  attr_reader :api_error_reporters
58
59
  attr_reader :custom_logger
59
60
  attr_accessor :policy_builder, :policy_scope_builder, :base_resource_class_factory
61
+ attr_accessor :metrics_sql_statement_timeout
60
62
 
61
63
  alias_method :policy_finder=, :policy_builder=
62
64
  alias_method :policy_scope_finder=, :policy_scope_builder=
@@ -125,7 +127,8 @@ module PactBroker
125
127
  require 'pact_broker/api/resources/default_base_resource'
126
128
  PactBroker::Api::Resources::DefaultBaseResource
127
129
  }
128
- config.warning_error_class_names = ['Sequel::ForeignKeyConstraintViolation']
130
+ config.warning_error_class_names = ['Sequel::ForeignKeyConstraintViolation', 'PG::QueryCanceled']
131
+ config.metrics_sql_statement_timeout = 30
129
132
  config
130
133
  end
131
134
 
@@ -247,8 +250,13 @@ module PactBroker
247
250
 
248
251
  def warning_error_classes
249
252
  warning_error_class_names.collect do | class_name |
250
- Object.const_get(class_name)
251
- end
253
+ begin
254
+ Object.const_get(class_name)
255
+ rescue NameError => e
256
+ logger.warn("Class #{class_name} couldn't be loaded as a warning error class (#{e.class} - #{e.message}). Ignoring.")
257
+ nil
258
+ end
259
+ end.compact
252
260
  end
253
261
 
254
262
  private
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'padrino-core'
2
3
  require 'redcarpet'
3
4
 
@@ -50,9 +51,9 @@ module PactBroker
50
51
  # https://www.acunetix.com/blog/articles/automated-detection-of-host-header-attacks/
51
52
  # Either use the explicitly configured base url or an empty string,
52
53
  # rather than request.base_url, which uses the X-Forwarded headers.
53
- PactBroker.configuration.base_url || ''
54
+ env["pactbroker.base_url"] || ''
54
55
  end
55
56
  end
56
57
  end
57
58
  end
58
- end
59
+ end
@@ -47,13 +47,20 @@ module PactBroker
47
47
  dataset_module do
48
48
  include PactBroker::Repositories::Helpers
49
49
 
50
+ def for(pacticipant_name, version_number)
51
+ where_pacticipant_name(pacticipant_name).where_number(version_number).single_record
52
+ end
53
+
50
54
  def where_pacticipant_name(pacticipant_name)
51
- join(:pacticipants) do | p |
52
- Sequel.&(
53
- { Sequel[first_source_alias][:pacticipant_id] => Sequel[p][:id] },
54
- name_like(Sequel[p][:name], pacticipant_name)
55
- )
56
- end
55
+ where(pacticipant_id: db[:pacticipants].select(:id).where(name_like(:name, pacticipant_name)))
56
+ # If we do a join, we get the extra columns from the pacticipant table that then
57
+ # make == not work
58
+ # join(:pacticipants) do | p |
59
+ # Sequel.&(
60
+ # { Sequel[first_source_alias][:pacticipant_id] => Sequel[p][:id] },
61
+ # name_like(Sequel[p][:name], pacticipant_name)
62
+ # )
63
+ # end
57
64
  end
58
65
 
59
66
  def where_tag(tag)
@@ -51,7 +51,7 @@ module PactBroker
51
51
  end
52
52
 
53
53
  def execute
54
- options = PactBroker::BuildHttpOptions.call(uri)
54
+ options = PactBroker::BuildHttpOptions.call(uri).merge(read_timeout: 15, open_timeout: 15)
55
55
  req = http_request
56
56
  Net::HTTP.start(uri.hostname, uri.port, :ENV, options) do |http|
57
57
  http.request req
@@ -1,6 +1,4 @@
1
1
  module PactBroker
2
-
3
2
  class Error < StandardError; end
4
3
  class TestError < StandardError; end
5
-
6
4
  end
@@ -0,0 +1,28 @@
1
+ require 'pact_broker/configuration'
2
+ require 'pact_broker/error'
3
+ require 'pact_broker/logging'
4
+ require 'securerandom'
5
+
6
+ module PactBroker
7
+ module Errors
8
+ include PactBroker::Logging
9
+
10
+ def self.generate_error_reference
11
+ SecureRandom.urlsafe_base64.gsub(/[^a-z]/i, '')[0,10]
12
+ end
13
+
14
+ def self.reportable_error?(error)
15
+ !error.is_a?(PactBroker::Error) && !error.is_a?(JSON::JSONError)
16
+ end
17
+
18
+ def self.report error, error_reference, request
19
+ PactBroker.configuration.api_error_reporters.each do | error_notifier |
20
+ begin
21
+ error_notifier.call(error, env: request.env, error_reference: error_reference)
22
+ rescue StandardError => e
23
+ log_error(e, "Error executing api_error_reporter")
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ require 'pact_broker/configuration'
2
+ require 'pact_broker/logging'
3
+
4
+ module PactBroker
5
+ module Errors
6
+ class ErrorLogger
7
+ include PactBroker::Logging
8
+
9
+ # don't need the env, just in case PF needs it
10
+ def self.call(error, error_reference, env = {})
11
+ if log_as_warning?(error)
12
+ logger.warn("Error reference #{error_reference}", error)
13
+ elsif PactBroker::Errors.reportable_error?(error)
14
+ log_error(error, "Error reference #{error_reference}")
15
+ else
16
+ logger.info("Error reference #{error_reference}", error)
17
+ end
18
+ end
19
+
20
+ def self.log_as_warning?(error)
21
+ PactBroker.configuration.warning_error_classes.any? { |clazz| error.is_a?(clazz) || error.cause&.is_a?(clazz) }
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,3 +1,4 @@
1
+ require 'pact_broker/configuration'
1
2
  require 'pact_broker/pacts/pact_publication'
2
3
  require 'pact_broker/pacts/pact_version'
3
4
  require 'pact_broker/domain/pacticipant'
@@ -66,7 +67,7 @@ module PactBroker
66
67
  count: PactBroker::Webhooks::Execution.count
67
68
  },
68
69
  matrix: {
69
- count: PactBroker::Matrix::Row.count
70
+ count: matrix_count
70
71
  }
71
72
  }
72
73
  end
@@ -87,6 +88,16 @@ module PactBroker
87
88
  order by 1"
88
89
  PactBroker::Pacts::PactPublication.db[query].all.each_with_object({}) { |row, hash| hash[row[:number_of_verifications]] = row[:pact_version_count] }
89
90
  end
91
+
92
+ def matrix_count
93
+ begin
94
+ PactBroker::Matrix::Row.db.with_statement_timeout(PactBroker.configuration.metrics_sql_statement_timeout) do
95
+ PactBroker::Matrix::Row.count
96
+ end
97
+ rescue Sequel::DatabaseError => e
98
+ -1
99
+ end
100
+ end
90
101
  end
91
102
  end
92
103
  end
@@ -1,10 +1,17 @@
1
- require 'pact_broker/feature_toggle'
2
-
3
1
  module PactBroker
4
2
  module Pacts
5
3
  module Metadata
6
4
  extend self
7
5
 
6
+ MAPPINGS = [
7
+ [:consumer_version_tags, "cvt"],
8
+ [:consumer_version_number, "cvn"],
9
+ [:wip, "w"],
10
+ [:consumer_version_selectors, "s"],
11
+ [:tag, "t"],
12
+ [:latest, "l"]
13
+ ]
14
+
8
15
  # When verifying a pact at /.../latest/TAG, this stores the
9
16
  # tag and the current consumer version number in the
10
17
  # metadata parameter of the URL for publishing the verification results.
@@ -13,12 +20,12 @@ module PactBroker
13
20
  def build_metadata_for_latest_pact(pact, selection_parameters)
14
21
  if selection_parameters[:tag]
15
22
  {
16
- consumer_version_tags: [selection_parameters[:tag]],
17
- consumer_version_number: pact.consumer_version_number
23
+ "cvt" => [selection_parameters[:tag]],
24
+ "cvn" => pact.consumer_version_number
18
25
  }
19
26
  else
20
27
  {
21
- consumer_version_number: pact.consumer_version_number
28
+ "cvn" => pact.consumer_version_number
22
29
  }
23
30
  end
24
31
  end
@@ -30,12 +37,50 @@ module PactBroker
30
37
  # go back to the correct consumer version number (eg for git statuses)
31
38
  def build_metadata_for_webhook_triggered_by_pact_publication(pact)
32
39
  metadata = {
33
- consumer_version_number: pact.consumer_version_number,
34
- consumer_version_tags: pact.consumer_version_tag_names
40
+ "cvn" => pact.consumer_version_number,
41
+ "cvt" => pact.consumer_version_tag_names
35
42
  }
36
- metadata[:wip] = "true" if PactBroker.feature_enabled?(:experimental_webhook_wip)
43
+ metadata["w"] = "true"
37
44
  metadata
38
45
  end
46
+
47
+ def build_metadata_for_pact_for_verification(verifiable_pact)
48
+ # todo put in tags
49
+ if verifiable_pact.wip
50
+ {
51
+ "w" => true
52
+ }
53
+ else
54
+ {
55
+ "s" => verifiable_pact.selectors.collect do | selector |
56
+ {
57
+ "t" => selector.tag,
58
+ "l" => selector.latest,
59
+ "cvn" => selector.consumer_version.number
60
+ }.compact
61
+ end
62
+ }
63
+ end
64
+ end
65
+
66
+ def parse_metadata(metadata)
67
+ parse_object(metadata)
68
+ end
69
+
70
+ def parse_object(object)
71
+ case object
72
+ when Hash then parse_hash(object)
73
+ when Array then object.collect{|i| parse_object(i) }
74
+ else object
75
+ end
76
+ end
77
+
78
+ def parse_hash(hash)
79
+ hash.each_with_object({}) do | (key, value), new_hash |
80
+ long_key = MAPPINGS.find{ |mapping| mapping.last == key }&.first
81
+ new_hash[long_key || key] = parse_object(value)
82
+ end
83
+ end
39
84
  end
40
85
  end
41
86
  end
@@ -168,7 +168,7 @@ module PactBroker
168
168
  .values
169
169
  .collect do | pact_publications |
170
170
  latest_pact_publication = pact_publications.sort_by{ |p| p.values.fetch(:consumer_version_order) }.last
171
- SelectedPact.new(latest_pact_publication.to_domain, Selectors.new(selector))
171
+ SelectedPact.new(latest_pact_publication.to_domain, Selectors.new(selector).resolve(latest_pact_publication.consumer_version))
172
172
  end
173
173
  end
174
174
 
@@ -428,7 +428,7 @@ module PactBroker
428
428
  .order_ignore_case(:consumer_name)
429
429
  .collect do | latest_pact_publication |
430
430
  pact_publication = PactPublication.find(id: latest_pact_publication.id)
431
- SelectedPact.new(pact_publication.to_domain, Selectors.create_for_overall_latest)
431
+ SelectedPact.new(pact_publication.to_domain, Selectors.create_for_overall_latest.resolve(pact_publication.consumer_version))
432
432
  end
433
433
  else
434
434
  selectors_for_overall_latest = consumer_version_selectors.select(&:overall_latest?)
@@ -438,7 +438,7 @@ module PactBroker
438
438
  query.collect do | latest_pact_publication |
439
439
  pact_publication = PactPublication.find(id: latest_pact_publication.id)
440
440
  resolved_selector = selector.consumer ? Selector.latest_for_consumer(selector.consumer) : Selector.overall_latest
441
- SelectedPact.new(pact_publication.to_domain, Selectors.new(resolved_selector))
441
+ SelectedPact.new(pact_publication.to_domain, Selectors.new(resolved_selector).resolve(pact_publication.consumer_version))
442
442
  end
443
443
  end
444
444
  end
@@ -453,26 +453,19 @@ module PactBroker
453
453
  query = query.consumer(selector.consumer) if selector.consumer
454
454
  query.all.collect do | latest_tagged_pact_publication |
455
455
  pact_publication = PactPublication.find(id: latest_tagged_pact_publication.id)
456
- resolved_pact = selector.consumer ? Selector.latest_for_tag_and_consumer(selector.tag, selector.consumer) : Selector.latest_for_tag(selector.tag)
456
+ resolved_selector = if selector.consumer
457
+ Selector.latest_for_tag_and_consumer(selector.tag, selector.consumer).resolve(pact_publication.consumer_version)
458
+ else
459
+ Selector.latest_for_tag(selector.tag).resolve(pact_publication.consumer_version)
460
+ end
457
461
  SelectedPact.new(
458
462
  pact_publication.to_domain,
459
- Selectors.new(resolved_pact)
463
+ Selectors.new(resolved_selector)
460
464
  )
461
465
  end
462
466
  end
463
467
  end
464
468
 
465
- def create_fallback_selected_pact(pact_publications, consumer_version_selectors)
466
- selector_tag_names = pact_publications.collect(&:tag_name)
467
- selectors = Selectors.create_for_latest_fallback_of_each_tag(selector_tag_names)
468
- last_pact_publication = pact_publications.sort_by(&:consumer_version_order).last
469
- pact_publication = unscoped(PactPublication).find(id: last_pact_publication.id)
470
- SelectedPact.new(
471
- pact_publication.to_domain,
472
- selectors
473
- )
474
- end
475
-
476
469
  def find_pacts_for_which_the_latest_version_for_the_fallback_tag_is_required(provider_name, selectors)
477
470
  selectors.collect do | selector |
478
471
  query = scope_for(LatestTaggedPactPublications).provider(provider_name).where(tag_name: selector.fallback_tag)
@@ -482,7 +475,7 @@ module PactBroker
482
475
  pact_publication = unscoped(PactPublication).find(id: latest_tagged_pact_publication.id)
483
476
  SelectedPact.new(
484
477
  pact_publication.to_domain,
485
- Selectors.new(selector)
478
+ Selectors.new(selector.resolve(pact_publication.consumer_version))
486
479
  )
487
480
  end
488
481
  end.flatten
@@ -5,6 +5,10 @@ module PactBroker
5
5
  merge!(options)
6
6
  end
7
7
 
8
+ def resolve(consumer_version)
9
+ ResolvedSelector.new(self.to_h, consumer_version)
10
+ end
11
+
8
12
  def tag= tag
9
13
  self[:tag] = tag
10
14
  end
@@ -94,6 +98,10 @@ module PactBroker
94
98
  !!(tag && !latest?)
95
99
  end
96
100
 
101
+ def == other
102
+ other.class == self.class && super
103
+ end
104
+
97
105
  def <=> other
98
106
  if overall_latest? || other.overall_latest?
99
107
  if overall_latest? == other.overall_latest?
@@ -124,5 +132,19 @@ module PactBroker
124
132
  !!self[:latest]
125
133
  end
126
134
  end
135
+
136
+ class ResolvedSelector < Selector
137
+ def initialize(options = {}, consumer_version)
138
+ super(options.merge(consumer_version: consumer_version))
139
+ end
140
+
141
+ def consumer_version
142
+ self[:consumer_version]
143
+ end
144
+
145
+ def == other
146
+ super && consumer_version == other.consumer_version
147
+ end
148
+ end
127
149
  end
128
150
  end
@@ -19,6 +19,10 @@ module PactBroker
19
19
  Selectors.new([Selector.overall_latest])
20
20
  end
21
21
 
22
+ def resolve(consumer_version)
23
+ Selectors.new(collect{ |selector| selector.resolve(consumer_version) })
24
+ end
25
+
22
26
  def + other
23
27
  Selectors.new(super)
24
28
  end
@@ -1,80 +1,155 @@
1
1
  module PactBroker
2
2
  module Services
3
3
 
4
+ FACTORIES = {}
5
+
6
+ extend self
7
+
8
+ def register_service(name, &block)
9
+ FACTORIES[name] = block
10
+ end
11
+
12
+ def get(name)
13
+ FACTORIES[name].call
14
+ end
15
+
4
16
  def index_service
5
- require 'pact_broker/index/service'
6
- Index::Service
17
+ get(:index_service)
7
18
  end
8
19
 
9
20
  def pact_service
10
- # TODO work out how to fix circular dependency
11
- require 'pact_broker/pacts/service'
12
- Pacts::Service
21
+ get(:pact_service)
13
22
  end
14
23
 
15
24
  def pacticipant_service
16
- require 'pact_broker/pacticipants/service'
17
- Pacticipants::Service
25
+ get(:pacticipant_service)
18
26
  end
19
27
 
20
28
  def tag_service
21
- require 'pact_broker/tags/service'
22
- Tags::Service
29
+ get(:tag_service)
23
30
  end
24
31
 
25
32
  def label_service
26
- require 'pact_broker/labels/service'
27
- Labels::Service
33
+ get(:label_service)
28
34
  end
29
35
 
30
36
  def group_service
31
- require 'pact_broker/groups/service'
32
- Groups::Service
37
+ get(:group_service)
33
38
  end
34
39
 
35
40
  def webhook_service
36
- require 'pact_broker/webhooks/service'
37
- Webhooks::Service
41
+ get(:webhook_service)
38
42
  end
39
43
 
40
44
  def version_service
41
- require 'pact_broker/versions/service'
42
- Versions::Service
45
+ get(:version_service)
43
46
  end
44
47
 
45
48
  def verification_service
46
- require 'pact_broker/verifications/service'
47
- Verifications::Service
49
+ get(:verification_service)
48
50
  end
49
51
 
50
52
  def badge_service
51
- require 'pact_broker/badges/service'
52
- Badges::Service
53
+ get(:badge_service)
53
54
  end
54
55
 
55
56
  def matrix_service
56
- require 'pact_broker/matrix/service'
57
- Matrix::Service
57
+ get(:matrix_service)
58
58
  end
59
59
 
60
60
  def certificate_service
61
- require 'pact_broker/certificates/service'
62
- Certificates::Service
61
+ get(:certificate_service)
63
62
  end
64
63
 
65
64
  def integration_service
66
- require 'pact_broker/integrations/service'
67
- Integrations::Service
65
+ get(:integration_service)
68
66
  end
69
67
 
70
68
  def webhook_trigger_service
71
- require 'pact_broker/webhooks/trigger_service'
72
- Webhooks::TriggerService
69
+ get(:webhook_trigger_service)
73
70
  end
74
71
 
75
72
  def metrics_service
76
- require 'pact_broker/metrics/service'
77
- Metrics::Service
73
+ get(:metrics_service)
74
+ end
75
+
76
+ def register_default_services
77
+ register_service(:index_service) do
78
+ require 'pact_broker/index/service'
79
+ Index::Service
80
+ end
81
+
82
+ register_service(:metrics_service) do
83
+ require 'pact_broker/metrics/service'
84
+ Metrics::Service
85
+ end
86
+
87
+ register_service(:matrix_service) do
88
+ require 'pact_broker/matrix/service'
89
+ Matrix::Service
90
+ end
91
+
92
+ register_service(:pact_service) do
93
+ require 'pact_broker/pacts/service'
94
+ Pacts::Service
95
+ end
96
+
97
+ register_service(:pacticipant_service) do
98
+ require 'pact_broker/pacticipants/service'
99
+ Pacticipants::Service
100
+ end
101
+
102
+ register_service(:tag_service) do
103
+ require 'pact_broker/tags/service'
104
+ Tags::Service
105
+ end
106
+
107
+ register_service(:label_service) do
108
+ require 'pact_broker/labels/service'
109
+ Labels::Service
110
+ end
111
+
112
+ register_service(:group_service) do
113
+ require 'pact_broker/groups/service'
114
+ Groups::Service
115
+ end
116
+
117
+ register_service(:webhook_service) do
118
+ require 'pact_broker/webhooks/service'
119
+ Webhooks::Service
120
+ end
121
+
122
+ register_service(:version_service) do
123
+ require 'pact_broker/versions/service'
124
+ Versions::Service
125
+ end
126
+
127
+ register_service(:verification_service) do
128
+ require 'pact_broker/verifications/service'
129
+ Verifications::Service
130
+ end
131
+
132
+ register_service(:badge_service) do
133
+ require 'pact_broker/badges/service'
134
+ Badges::Service
135
+ end
136
+
137
+ register_service(:certificate_service) do
138
+ require 'pact_broker/certificates/service'
139
+ Certificates::Service
140
+ end
141
+
142
+ register_service(:integration_service) do
143
+ require 'pact_broker/integrations/service'
144
+ Integrations::Service
145
+ end
146
+
147
+ register_service(:webhook_trigger_service) do
148
+ require 'pact_broker/webhooks/trigger_service'
149
+ Webhooks::TriggerService
150
+ end
78
151
  end
79
152
  end
80
153
  end
154
+
155
+ PactBroker::Services.register_default_services