pact_broker 2.95.0 → 2.95.1

Sign up to get free protection for your applications and to get access to all the features.
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