pact_broker 2.95.0 → 2.95.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e077e361037618a0d58670de46b25753d8755cb1e21ef58e9f73a8fe5705cd7f
4
- data.tar.gz: 0e64d6fee6eb4cf36f69dea5bf94c432c088c93984ca51783e68f20b7b2e3130
3
+ metadata.gz: f65cf2bd6eb2b3f0f7fd727e61fc73005817200f8e72bbab574493e4ea9b9ba3
4
+ data.tar.gz: aac1fb501fc5624227e63d424c8982f266fa0a9a2d80b1184844193347ba6724
5
5
  SHA512:
6
- metadata.gz: 8c7bbae3ff3736576977f15aaef79a3d6635667de76b994a83c8c4613ce7fa9999808af70838014f7b5d7c26e7ffbda5da5e5813b1394dd6c4557fe597c9a11f
7
- data.tar.gz: 4783820b31a355a9c2bf9a36151cc0730dba2a1424a1c68b8da39ac1f658cec3334b18c406b58d1b211cb0a5f3cc72b14a619066ca9d0c2daca828720f144d08
6
+ metadata.gz: 8272759e5880069606e56bea3893055df49543b76b237d7511ce8fa21c0414f1a0e593e98ed1f9e67c4b9048b4da1c2d3ef938b0dfea182406cda696111c2bc4
7
+ data.tar.gz: 426a032f0016c8952934fbf630420be42accf192baeaff3bd2651aefa75170d055d8a4ed125640a7b3cad124cf5a461d7c930e5d289f4a6e5bd666366661940a
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ <a name="v2.95.1"></a>
2
+ ### v2.95.1 (2022-03-18)
3
+
4
+ #### Bug Fixes
5
+
6
+ * **can-i-deploy**
7
+ * allow new provider to be introduced to existing consumer without can-i-deploy having circular dependency issues ([e43974ca](/../../commit/e43974ca))
8
+
1
9
  <a name="v2.95.0"></a>
2
10
  ### v2.95.0 (2022-03-16)
3
11
 
data/lib/db.rb CHANGED
@@ -38,6 +38,7 @@ module DB
38
38
  con.extension(:connection_validator)
39
39
  con.extension(:pagination)
40
40
  con.extension(:statement_timeout)
41
+ #con.extension(:caller_logging)
41
42
  con.extend_datasets do
42
43
  # rubocop: disable Lint/NestedMethodDefinition
43
44
  def any?
@@ -1,9 +1,281 @@
1
+ # frozen_string_literal: true
1
2
  require "pact_broker/configuration"
3
+ require "webmachine"
4
+ require "pact_broker/services"
5
+ require "pact_broker/api/decorators"
6
+ require "pact_broker/logging"
7
+ require "pact_broker/api/pact_broker_urls"
8
+ require "pact_broker/json"
9
+ require "pact_broker/pacts/pact_params"
10
+ require "pact_broker/api/resources/authentication"
11
+ require "pact_broker/api/resources/authorization"
12
+ require "pact_broker/errors"
2
13
 
3
14
  module PactBroker
4
15
  module Api
5
16
  module Resources
6
- BaseResource = PactBroker.configuration.base_resource_class_factory.call
17
+ class InvalidJsonError < PactBroker::Error ; end
18
+
19
+ class BaseResource < Webmachine::Resource
20
+ include PactBroker::Services
21
+ include PactBroker::Api::PactBrokerUrls
22
+ include PactBroker::Api::Resources::Authentication
23
+ include PactBroker::Api::Resources::Authorization
24
+
25
+ include PactBroker::Logging
26
+
27
+ attr_accessor :user
28
+
29
+ def initialize
30
+ PactBroker.configuration.before_resource.call(self)
31
+ application_context.before_resource&.call(self)
32
+ end
33
+
34
+ def options
35
+ { "Access-Control-Allow-Methods" => allowed_methods.join(", ")}
36
+ end
37
+
38
+ def known_methods
39
+ super + ["PATCH"]
40
+ end
41
+
42
+ def finish_request
43
+ application_context.after_resource&.call(self)
44
+ PactBroker.configuration.after_resource.call(self)
45
+ end
46
+
47
+ def is_authorized?(authorization_header)
48
+ authenticated?(self, authorization_header)
49
+ end
50
+
51
+ def forbidden?
52
+ if application_context.resource_authorizer
53
+ !application_context.resource_authorizer.call(self)
54
+ elsif PactBroker.configuration.authorize
55
+ !PactBroker.configuration.authorize.call(self, {})
56
+ else
57
+ false
58
+ end
59
+ end
60
+
61
+ # The path_info segments aren't URL decoded
62
+ def identifier_from_path
63
+ @identifier_from_path ||= request.path_info.each_with_object({}) do | (key, value), hash|
64
+ if value.is_a?(String)
65
+ hash[key] = URI.decode(value)
66
+ elsif value.is_a?(Symbol) || value.is_a?(Numeric)
67
+ hash[key] = value
68
+ end
69
+ end
70
+ end
71
+
72
+ alias_method :path_info, :identifier_from_path
73
+
74
+ def base_url
75
+ # Have to use something for the base URL here - we can't use an empty string as we can in the UI.
76
+ # Can't work out if cache poisoning is a vulnerability for APIs or not.
77
+ # Using the request base URI as a fallback if the base_url is not configured may be a vulnerability,
78
+ # but the documentation recommends that the
79
+ # base_url should be set in the configuration to mitigate this.
80
+ request.env["pactbroker.base_url"] || request.base_uri.to_s.chomp("/")
81
+ end
82
+
83
+ # See comments for base_url in lib/pact_broker/doc/controllers/app.rb
84
+ def ui_base_url
85
+ request.env["pactbroker.base_url"] || ""
86
+ end
87
+
88
+ def charsets_provided
89
+ [["utf-8", :encode]]
90
+ end
91
+
92
+ # We only use utf-8 so leave encoding as it is
93
+ def encode(body)
94
+ body
95
+ end
96
+
97
+ def resource_url
98
+ request.uri.to_s.gsub(/\?.*/, "").chomp("/")
99
+ end
100
+
101
+ def decorator_context options = {}
102
+ application_context.decorator_context_creator.call(self, options)
103
+ end
104
+
105
+ def decorator_options options = {}
106
+ { user_options: decorator_context(options) }
107
+ end
108
+
109
+ def handle_exception(error)
110
+ error_reference = PactBroker::Errors.generate_error_reference
111
+ application_context.error_logger.call(error, error_reference, request.env)
112
+ if PactBroker::Errors.reportable_error?(error)
113
+ PactBroker::Errors.report(error, error_reference, request.env)
114
+ end
115
+ response.body = application_context.error_response_body_generator.call(error, error_reference, request.env)
116
+ end
117
+
118
+ # rubocop: disable Metrics/CyclomaticComplexity
119
+ def params(options = {})
120
+ return options[:default] if options.key?(:default) && request_body.empty?
121
+
122
+ symbolize_names = !options.key?(:symbolize_names) || options[:symbolize_names]
123
+ if symbolize_names
124
+ @params_with_symbol_keys ||= JSON.parse(request_body, { symbolize_names: true }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
125
+ else
126
+ @params_with_string_keys ||= JSON.parse(request_body, { symbolize_names: false }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
127
+ end
128
+ rescue JSON::JSONError => e
129
+ raise InvalidJsonError.new("Error parsing JSON - #{e.message}")
130
+ end
131
+ # rubocop: enable Metrics/CyclomaticComplexity
132
+
133
+ def params_with_string_keys
134
+ params(symbolize_names: false)
135
+ end
136
+
137
+ def pact_params
138
+ @pact_params ||= PactBroker::Pacts::PactParams.from_request request, identifier_from_path
139
+ end
140
+
141
+ def set_json_error_message message
142
+ response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
143
+ response.body = { error: message }.to_json
144
+ end
145
+
146
+ def set_json_validation_error_messages errors
147
+ response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
148
+ response.body = { errors: errors }.to_json
149
+ end
150
+
151
+ def request_body
152
+ @request_body ||= request.body.to_s
153
+ end
154
+
155
+ def consumer_name
156
+ identifier_from_path[:consumer_name]
157
+ end
158
+
159
+ def consumer_version_number
160
+ identifier_from_path[:consumer_version_number]
161
+ end
162
+
163
+ def pacticipant_version_number
164
+ identifier_from_path[:pacticipant_version_number]
165
+ end
166
+
167
+ def consumer_specified?
168
+ identifier_from_path.key?(:consumer_name)
169
+ end
170
+
171
+ def provider_specified?
172
+ identifier_from_path.key?(:provider_name)
173
+ end
174
+
175
+ def provider_name
176
+ identifier_from_path[:provider_name]
177
+ end
178
+
179
+ def pacticipant_name
180
+ identifier_from_path[:pacticipant_name]
181
+ end
182
+
183
+ def pacticipant_specified?
184
+ identifier_from_path.key?(:pacticipant_name)
185
+ end
186
+
187
+ def invalid_json?
188
+ begin
189
+ params
190
+ false
191
+ rescue StandardError => e
192
+ logger.info "Error parsing JSON #{e} - #{request_body}"
193
+ set_json_error_message "Error parsing JSON - #{e.message}"
194
+ response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
195
+ true
196
+ end
197
+ end
198
+
199
+ def validation_errors? model
200
+ if (errors = model.validate).any?
201
+ set_json_validation_error_messages errors
202
+ true
203
+ else
204
+ false
205
+ end
206
+ end
207
+
208
+ def contract_validation_errors? contract, params
209
+ if (invalid = !contract.validate(params))
210
+ set_json_validation_error_messages contract.errors.messages
211
+ end
212
+ invalid
213
+ end
214
+
215
+ def find_pacticipant name, role
216
+ pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
217
+ set_json_error_message("No #{role} with name '#{name}' found") if pacticipant.nil?
218
+ end
219
+ end
220
+
221
+ def consumer
222
+ @consumer ||= identifier_from_path[:consumer_name] && find_pacticipant(identifier_from_path[:consumer_name], "consumer")
223
+ end
224
+
225
+ def provider
226
+ @provider ||= identifier_from_path[:provider_name] && find_pacticipant(identifier_from_path[:provider_name], "provider")
227
+ end
228
+
229
+ def pacticipant
230
+ @pacticipant ||= identifier_from_path[:pacticipant_name] && find_pacticipant(identifier_from_path[:pacticipant_name], "pacticipant")
231
+ end
232
+
233
+ def pact
234
+ @pact ||= pact_service.find_pact(pact_params)
235
+ end
236
+
237
+ # Not necessarily an existing integration
238
+ def integration
239
+ if consumer_specified? && provider_specified?
240
+ OpenStruct.new(consumer: consumer, provider: provider)
241
+ else
242
+ nil
243
+ end
244
+ end
245
+
246
+ def database_connector
247
+ request.env["pactbroker.database_connector"]
248
+ end
249
+
250
+ def application_context
251
+ request.path_info[:application_context]
252
+ end
253
+
254
+ def decorator_class(name)
255
+ application_context.decorator_configuration.class_for(name)
256
+ end
257
+
258
+ def api_contract_class(name)
259
+ application_context.api_contract_configuration.class_for(name)
260
+ end
261
+
262
+ def schema
263
+ nil
264
+ end
265
+
266
+ def validation_errors_for_schema?(schema_to_use = schema, params_to_validate = params)
267
+ if (errors = schema_to_use.call(params_to_validate)).any?
268
+ set_json_validation_error_messages(errors)
269
+ true
270
+ else
271
+ false
272
+ end
273
+ end
274
+
275
+ def malformed_request_for_json_with_schema?(schema_to_use = schema, params_to_validate = params)
276
+ invalid_json? || validation_errors_for_schema?(schema_to_use, params_to_validate)
277
+ end
278
+ end
7
279
  end
8
280
  end
9
281
  end
@@ -1,280 +0,0 @@
1
- # frozen_string_literal: true
2
- require "webmachine"
3
- require "pact_broker/services"
4
- require "pact_broker/api/decorators"
5
- require "pact_broker/logging"
6
- require "pact_broker/api/pact_broker_urls"
7
- require "pact_broker/json"
8
- require "pact_broker/pacts/pact_params"
9
- require "pact_broker/api/resources/authentication"
10
- require "pact_broker/api/resources/authorization"
11
- require "pact_broker/errors"
12
-
13
- module PactBroker
14
- module Api
15
- module Resources
16
- class InvalidJsonError < PactBroker::Error ; end
17
-
18
- class DefaultBaseResource < Webmachine::Resource
19
- include PactBroker::Services
20
- include PactBroker::Api::PactBrokerUrls
21
- include PactBroker::Api::Resources::Authentication
22
- include PactBroker::Api::Resources::Authorization
23
-
24
- include PactBroker::Logging
25
-
26
- attr_accessor :user
27
-
28
- def initialize
29
- PactBroker.configuration.before_resource.call(self)
30
- application_context.before_resource&.call(self)
31
- end
32
-
33
- def options
34
- { "Access-Control-Allow-Methods" => allowed_methods.join(", ")}
35
- end
36
-
37
- def known_methods
38
- super + ["PATCH"]
39
- end
40
-
41
- def finish_request
42
- application_context.after_resource&.call(self)
43
- PactBroker.configuration.after_resource.call(self)
44
- end
45
-
46
- def is_authorized?(authorization_header)
47
- authenticated?(self, authorization_header)
48
- end
49
-
50
- def forbidden?
51
- if application_context.resource_authorizer
52
- !application_context.resource_authorizer.call(self)
53
- elsif PactBroker.configuration.authorize
54
- !PactBroker.configuration.authorize.call(self, {})
55
- else
56
- false
57
- end
58
- end
59
-
60
- # The path_info segments aren't URL decoded
61
- def identifier_from_path
62
- @identifier_from_path ||= request.path_info.each_with_object({}) do | (key, value), hash|
63
- if value.is_a?(String)
64
- hash[key] = URI.decode(value)
65
- elsif value.is_a?(Symbol) || value.is_a?(Numeric)
66
- hash[key] = value
67
- end
68
- end
69
- end
70
-
71
- alias_method :path_info, :identifier_from_path
72
-
73
- def base_url
74
- # Have to use something for the base URL here - we can't use an empty string as we can in the UI.
75
- # Can't work out if cache poisoning is a vulnerability for APIs or not.
76
- # Using the request base URI as a fallback if the base_url is not configured may be a vulnerability,
77
- # but the documentation recommends that the
78
- # base_url should be set in the configuration to mitigate this.
79
- request.env["pactbroker.base_url"] || request.base_uri.to_s.chomp("/")
80
- end
81
-
82
- # See comments for base_url in lib/pact_broker/doc/controllers/app.rb
83
- def ui_base_url
84
- request.env["pactbroker.base_url"] || ""
85
- end
86
-
87
- def charsets_provided
88
- [["utf-8", :encode]]
89
- end
90
-
91
- # We only use utf-8 so leave encoding as it is
92
- def encode(body)
93
- body
94
- end
95
-
96
- def resource_url
97
- request.uri.to_s.gsub(/\?.*/, "").chomp("/")
98
- end
99
-
100
- def decorator_context options = {}
101
- application_context.decorator_context_creator.call(self, options)
102
- end
103
-
104
- def decorator_options options = {}
105
- { user_options: decorator_context(options) }
106
- end
107
-
108
- def handle_exception(error)
109
- error_reference = PactBroker::Errors.generate_error_reference
110
- application_context.error_logger.call(error, error_reference, request.env)
111
- if PactBroker::Errors.reportable_error?(error)
112
- PactBroker::Errors.report(error, error_reference, request.env)
113
- end
114
- response.body = application_context.error_response_body_generator.call(error, error_reference, request.env)
115
- end
116
-
117
- # rubocop: disable Metrics/CyclomaticComplexity
118
- def params(options = {})
119
- return options[:default] if options.key?(:default) && request_body.empty?
120
-
121
- symbolize_names = !options.key?(:symbolize_names) || options[:symbolize_names]
122
- if symbolize_names
123
- @params_with_symbol_keys ||= JSON.parse(request_body, { symbolize_names: true }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
124
- else
125
- @params_with_string_keys ||= JSON.parse(request_body, { symbolize_names: false }.merge(PACT_PARSING_OPTIONS)) #Not load! Otherwise it will try to load Ruby classes.
126
- end
127
- rescue JSON::JSONError => e
128
- raise InvalidJsonError.new("Error parsing JSON - #{e.message}")
129
- end
130
- # rubocop: enable Metrics/CyclomaticComplexity
131
-
132
- def params_with_string_keys
133
- params(symbolize_names: false)
134
- end
135
-
136
- def pact_params
137
- @pact_params ||= PactBroker::Pacts::PactParams.from_request request, identifier_from_path
138
- end
139
-
140
- def set_json_error_message message
141
- response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
142
- response.body = { error: message }.to_json
143
- end
144
-
145
- def set_json_validation_error_messages errors
146
- response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
147
- response.body = { errors: errors }.to_json
148
- end
149
-
150
- def request_body
151
- @request_body ||= request.body.to_s
152
- end
153
-
154
- def consumer_name
155
- identifier_from_path[:consumer_name]
156
- end
157
-
158
- def consumer_version_number
159
- identifier_from_path[:consumer_version_number]
160
- end
161
-
162
- def pacticipant_version_number
163
- identifier_from_path[:pacticipant_version_number]
164
- end
165
-
166
- def consumer_specified?
167
- identifier_from_path.key?(:consumer_name)
168
- end
169
-
170
- def provider_specified?
171
- identifier_from_path.key?(:provider_name)
172
- end
173
-
174
- def provider_name
175
- identifier_from_path[:provider_name]
176
- end
177
-
178
- def pacticipant_name
179
- identifier_from_path[:pacticipant_name]
180
- end
181
-
182
- def pacticipant_specified?
183
- identifier_from_path.key?(:pacticipant_name)
184
- end
185
-
186
- def invalid_json?
187
- begin
188
- params
189
- false
190
- rescue StandardError => e
191
- logger.info "Error parsing JSON #{e} - #{request_body}"
192
- set_json_error_message "Error parsing JSON - #{e.message}"
193
- response.headers["Content-Type"] = "application/hal+json;charset=utf-8"
194
- true
195
- end
196
- end
197
-
198
- def validation_errors? model
199
- if (errors = model.validate).any?
200
- set_json_validation_error_messages errors
201
- true
202
- else
203
- false
204
- end
205
- end
206
-
207
- def contract_validation_errors? contract, params
208
- if (invalid = !contract.validate(params))
209
- set_json_validation_error_messages contract.errors.messages
210
- end
211
- invalid
212
- end
213
-
214
- def find_pacticipant name, role
215
- pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
216
- set_json_error_message("No #{role} with name '#{name}' found") if pacticipant.nil?
217
- end
218
- end
219
-
220
- def consumer
221
- @consumer ||= identifier_from_path[:consumer_name] && find_pacticipant(identifier_from_path[:consumer_name], "consumer")
222
- end
223
-
224
- def provider
225
- @provider ||= identifier_from_path[:provider_name] && find_pacticipant(identifier_from_path[:provider_name], "provider")
226
- end
227
-
228
- def pacticipant
229
- @pacticipant ||= identifier_from_path[:pacticipant_name] && find_pacticipant(identifier_from_path[:pacticipant_name], "pacticipant")
230
- end
231
-
232
- def pact
233
- @pact ||= pact_service.find_pact(pact_params)
234
- end
235
-
236
- # Not necessarily an existing integration
237
- def integration
238
- if consumer_specified? && provider_specified?
239
- OpenStruct.new(consumer: consumer, provider: provider)
240
- else
241
- nil
242
- end
243
- end
244
-
245
- def database_connector
246
- request.env["pactbroker.database_connector"]
247
- end
248
-
249
- def application_context
250
- request.path_info[:application_context]
251
- end
252
-
253
- def decorator_class(name)
254
- application_context.decorator_configuration.class_for(name)
255
- end
256
-
257
- def api_contract_class(name)
258
- application_context.api_contract_configuration.class_for(name)
259
- end
260
-
261
- def schema
262
- nil
263
- end
264
-
265
- def validation_errors_for_schema?(schema_to_use = schema, params_to_validate = params)
266
- if (errors = schema_to_use.call(params_to_validate)).any?
267
- set_json_validation_error_messages(errors)
268
- true
269
- else
270
- false
271
- end
272
- end
273
-
274
- def malformed_request_for_json_with_schema?(schema_to_use = schema, params_to_validate = params)
275
- invalid_json? || validation_errors_for_schema?(schema_to_use, params_to_validate)
276
- end
277
- end
278
- end
279
- end
280
- end
@@ -35,7 +35,7 @@ module PactBroker
35
35
  attr_accessor :content_security_policy, :hal_browser_content_security_policy_overrides
36
36
  attr_accessor :api_error_reporters
37
37
  attr_reader :custom_logger
38
- attr_accessor :policy_builder, :policy_scope_builder, :base_resource_class_factory
38
+ attr_accessor :policy_builder, :policy_scope_builder
39
39
  alias_method :policy_finder=, :policy_builder=
40
40
  alias_method :policy_scope_finder=, :policy_scope_builder=
41
41
 
@@ -79,10 +79,6 @@ module PactBroker
79
79
  }
80
80
  config.policy_builder = -> (object) { DefaultPolicy.new(nil, object) }
81
81
  config.policy_scope_builder = -> (scope) { scope }
82
- config.base_resource_class_factory = -> () {
83
- require "pact_broker/api/resources/default_base_resource"
84
- PactBroker::Api::Resources::DefaultBaseResource
85
- }
86
82
  config
87
83
  end
88
84
 
@@ -108,7 +108,7 @@ module PactBroker
108
108
  # rubocop: disable Metrics/CyclomaticComplexity
109
109
  def self.latest_verification_for_pseudo_branch(pact_publication, is_overall_latest, latest_verifications_for_cv_tags, tags_option, options)
110
110
  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
111
+ pact_publication.latest_verification || pact_publication.latest_verification_for_consumer_branches(forbid_lazy_load: false)
112
112
  elsif tags_option == true
113
113
  latest_verifications_for_cv_tags
114
114
  .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) }
@@ -84,7 +84,7 @@ module PactBroker
84
84
 
85
85
  def find_integrations_for_specified_selectors(resolved_specified_selectors, options)
86
86
  if infer_selectors_for_integrations?(options)
87
- find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors, options)
87
+ find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors)
88
88
  else
89
89
  find_integrations_for_specified_selectors_only(resolved_specified_selectors)
90
90
  end
@@ -101,9 +101,9 @@ module PactBroker
101
101
  end
102
102
  end
103
103
 
104
- def find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors, options)
104
+ def find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors)
105
105
  integrations = integrations_where_specified_selector_is_consumer(resolved_specified_selectors) +
106
- integrations_where_specified_selector_is_provider(resolved_specified_selectors, options)
106
+ integrations_where_specified_selector_is_provider(resolved_specified_selectors)
107
107
  deduplicate_integrations(integrations)
108
108
  end
109
109
 
@@ -118,28 +118,25 @@ module PactBroker
118
118
  consumer_name: integration[:consumer_name],
119
119
  provider_id: integration[:provider_id],
120
120
  provider_name: integration[:provider_name],
121
- required: true
121
+ required: true # synchronous consumer requires the provider to be present
122
122
  )
123
123
  end
124
124
  end
125
125
  end
126
126
 
127
- def integrations_where_specified_selector_is_provider(resolved_specified_selectors, options)
127
+ def integrations_where_specified_selector_is_provider(resolved_specified_selectors)
128
128
  integrations_involving_specified_providers = PactBroker::Integrations::Integration
129
129
  .where(provider_id: resolved_specified_selectors.collect(&:pacticipant_id))
130
130
  .eager(:consumer, :provider)
131
131
  .all
132
132
 
133
- destination_selector = PactBroker::Matrix::UnresolvedSelector.new(options.slice(:latest, :tag, :branch, :environment_name).compact)
134
- required = PactBroker::Domain::Version.for_selector(destination_selector).pacticipants_set
135
-
136
133
  integrations_involving_specified_providers.collect do | integration |
137
134
  Integration.from_hash(
138
135
  consumer_id: integration.consumer.id,
139
136
  consumer_name: integration.consumer.name,
140
137
  provider_id: integration.provider.id,
141
138
  provider_name: integration.provider.name,
142
- required: required.member?(integration.consumer.id)
139
+ required: false # synchronous provider does not require the consumer to be present
143
140
  )
144
141
  end
145
142
  end
@@ -263,6 +260,9 @@ module PactBroker
263
260
  end
264
261
  end
265
262
 
263
+ # The user has specified --to TAG or --to-environment ENVIRONMENT in the CLI
264
+ # (or nothing, which to defaults to "with the latest version of the other integrated applications")
265
+ # The branch isn't implemented in the CLI yet (March 2022), but the API supports it.
266
266
  def infer_selectors_for_integrations?(options)
267
267
  options[:latest] || options[:tag] || options[:branch] || options[:environment_name]
268
268
  end
@@ -20,11 +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)
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])
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
28
 
29
29
  # TODO rename to consumer_version_tags
30
30
  associate(:one_to_many, :tags, :class => "PactBroker::Domain::Tag", :key => :version_id, :primary_key => :consumer_version_id)
@@ -105,8 +105,14 @@ module PactBroker
105
105
  .collect { | head_pact_publication| head_pact_publication.values.fetch(:tag_name) }
106
106
  end
107
107
 
108
+ # If the consumer_version is already loaded, and it already has tags, use those
109
+ # otherwise, load them directly.
108
110
  def consumer_version_tags
109
- tags
111
+ if associations[:consumer_version] && associations[:consumer_version].associations[:tags]
112
+ consumer_version.tags
113
+ else
114
+ tags
115
+ end
110
116
  end
111
117
 
112
118
  def latest_verification
@@ -299,7 +299,15 @@ module PactBroker
299
299
  end
300
300
 
301
301
  def collect_consumer_name_and_version_number(pact_publications_query)
302
- pact_publications_query.eager(:provider).eager(:consumer).eager(:consumer_version).order(:consumer_version_order).all.sort.collect do |p|
302
+ pact_publications = pact_publications_query
303
+ .eager(:provider)
304
+ .eager(:consumer)
305
+ .eager(:consumer_version)
306
+ .order(:consumer_version_order)
307
+ .all_forbidding_lazy_load
308
+ .sort
309
+
310
+ pact_publications.collect do |p|
303
311
  suffix = if p.values[:tag_name]
304
312
  " (tag #{p.values[:tag_name]})"
305
313
  elsif p.values[:branch_name]
@@ -308,7 +316,7 @@ module PactBroker
308
316
  ""
309
317
  end
310
318
 
311
- "#{p.consumer_name} #{p.consumer_version_number}" + suffix
319
+ "#{p.consumer.name} #{p.consumer_version.number}" + suffix
312
320
  end
313
321
  end
314
322
 
@@ -257,6 +257,7 @@ module PactBroker
257
257
  .collect(&:to_domain_with_content).first
258
258
  elsif consumer_version_number && pact_version_sha
259
259
  pact_publication = pact_publication_by_consumer_version.all.first
260
+ pact_publication&.allow_lazy_load
260
261
  if pact_publication && pact_publication.pact_version.sha == pact_version_sha
261
262
  pact_publication.tags
262
263
  pact_publication.to_domain_with_content
@@ -6,6 +6,10 @@ module PactBroker
6
6
 
7
7
  extend self
8
8
 
9
+ def all_forbidding_lazy_load
10
+ all.each{ | row | row.forbid_lazy_load if row.respond_to?(:forbid_lazy_load) }
11
+ end
12
+
9
13
  def name_like column_name, value
10
14
  if PactBroker.configuration.use_case_sensitive_resource_names
11
15
  if mysql?
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = "2.95.0"
2
+ VERSION = "2.95.1"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pact_broker
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.95.0
4
+ version: 2.95.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bethany Skurrie
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-03-16 00:00:00.000000000 Z
13
+ date: 2022-03-21 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: httparty