pact_broker 2.104.0 → 2.105.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +18 -0
  3. data/lib/pact_broker/api/middleware/http_debug_logs.rb +2 -2
  4. data/lib/pact_broker/app.rb +1 -1
  5. data/lib/pact_broker/config/runtime_configuration.rb +1 -0
  6. data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +3 -0
  7. data/lib/pact_broker/configuration.rb +1 -1
  8. data/lib/pact_broker/db/data_migrations/set_pacticipant_main_branch.rb +2 -2
  9. data/lib/pact_broker/domain/pact.rb +7 -1
  10. data/lib/pact_broker/initializers/database_connection.rb +1 -1
  11. data/lib/pact_broker/locale/en.yml +1 -0
  12. data/lib/pact_broker/matrix/can_i_deploy_query_schema.rb +6 -0
  13. data/lib/pact_broker/matrix/deployment_status_summary.rb +1 -1
  14. data/lib/pact_broker/matrix/resolved_selector.rb +2 -2
  15. data/lib/pact_broker/pacts/pact_version.rb +39 -0
  16. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +74 -47
  17. data/lib/pact_broker/pacts/repository.rb +2 -2
  18. data/lib/pact_broker/pacts/service.rb +7 -8
  19. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +7 -4
  20. data/lib/pact_broker/tasks/clean_task.rb +1 -1
  21. data/lib/pact_broker/tasks/delete_overwritten_data_task.rb +1 -1
  22. data/lib/pact_broker/test/http_test_data_builder.rb +34 -26
  23. data/lib/pact_broker/test/test_data_builder.rb +28 -12
  24. data/lib/pact_broker/verifications/service.rb +1 -1
  25. data/lib/pact_broker/version.rb +1 -1
  26. data/lib/pact_broker/versions/branch.rb +1 -0
  27. data/lib/pact_broker/webhooks/event_listener.rb +2 -2
  28. data/lib/pact_broker/webhooks/execution_configuration.rb +4 -0
  29. data/lib/pact_broker/webhooks/execution_configuration_creator.rb +1 -0
  30. data/lib/pact_broker/webhooks/webhook_request_logger.rb +1 -1
  31. data/pact_broker.gemspec +1 -1
  32. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b2a928f323706d303796168aed1ec181dbf44be8156fc54010357a26771cffd2
4
- data.tar.gz: b6e9ab38c908cd2263e51e16816f1b4ad8950151cf033ce5009c33022bd1ca59
3
+ metadata.gz: c43c0dbf719c9e927fad6ffcee28b559036726a61a41813a3451554e5f1db087
4
+ data.tar.gz: '0964dcfea819d1ccc1c1ccc15d8a7493670dfbefbde75aedb63ac9405c7c764d'
5
5
  SHA512:
6
- metadata.gz: 9e43a6235c4a0a1cfdb8dacd8b83eca7f11e76c1ec40510207b7a904b72d2d1895878fdbbc1e249454c1b3fa5a814bb764bf747ae76b0f0f0f180da096f1d056
7
- data.tar.gz: 77c95170acc6e136e177d27baaa65f2f668b5085789ebfafde5552983d83a3c42e25b21ee558faf19263d364ae9526350424d32312fb3a6db5d9dcb38e7521a4
6
+ metadata.gz: 12f323b624a2ff4dcc7827e254ec71c83a1d3ffe89532746feb67e360aa5fda938927f43176b86ea08b7b3fddf66d4ef0a5c8cf9ec6b4190332e572a2fd4ad0a
7
+ data.tar.gz: a3a5aed03639c5ef8ab602da938e502e4b0434248c99de262bac7a1d6a09e42e4991d32748ae542bfdf1376db133957ff69652b99e49cc1fdfc22f0845907f22
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ <a name="v2.105.0"></a>
2
+ ### v2.105.0 (2022-10-19)
3
+
4
+ #### Features
5
+
6
+ * update wording of version description for version in environment ([d122fa68](/../../commit/d122fa68))
7
+
8
+ * **webhooks**
9
+ * allow auth headers to be logged for debugging purposes (#575) ([102b1930](/../../commit/102b1930))
10
+
11
+ #### Bug Fixes
12
+
13
+ * add validation to ensure an environment or to tag is specified for the /can-i-deploy endpoint ([e9d772eb](/../../commit/e9d772eb))
14
+ * implement pending logic for provider branches ([7cdf1a7c](/../../commit/7cdf1a7c))
15
+
16
+ * **wip pacts**
17
+ * fix performance issue encountered when removing explicitly specified pacts from the list of potential WIP pacts (#573) ([757f0301](/../../commit/757f0301))
18
+
1
19
  <a name="v2.104.0"></a>
2
20
  ### v2.104.0 (2022-09-17)
3
21
 
@@ -21,9 +21,9 @@ module PactBroker
21
21
  env_to_log = env.reject { | header, _ | header.start_with?(*EXCLUDE_HEADERS) }
22
22
  env_to_log["rack.session"] = env["rack.session"].to_hash if env["rack.session"]
23
23
  env_to_log["rack.input"] = request_body(env) if env["rack.input"]
24
- logger.debug("env", payload: env_to_log)
24
+ logger.debug("env", env_to_log)
25
25
  status, headers, body = @app.call(env)
26
- logger.debug("response", payload: { "status" => status, "headers" => headers, "body" => body })
26
+ logger.debug("response", "status" => status, "headers" => headers, "body" => body)
27
27
  [status, headers, body]
28
28
  else
29
29
  @app.call(env)
@@ -223,7 +223,7 @@ module PactBroker
223
223
  except: configuration.rack_protection_except
224
224
  }.compact
225
225
 
226
- logger.info("Configuring Rack::Protection", payload: rack_protection_options)
226
+ logger.info("Configuring Rack::Protection", rack_protection_options)
227
227
  @app_builder.use Rack::Protection, rack_protection_options
228
228
 
229
229
  is_hal_browser = ->(env) { env["PATH_INFO"] == "/hal-browser/browser.html" }
@@ -52,6 +52,7 @@ module PactBroker
52
52
  webhook_http_code_success: [200, 201, 202, 203, 204, 205, 206],
53
53
  webhook_scheme_whitelist: ["https"],
54
54
  webhook_host_whitelist: [],
55
+ webhook_redact_sensitive_data: true,
55
56
  disable_ssl_verification: false,
56
57
  user_agent: "Pact Broker v#{PactBroker::VERSION}"
57
58
  )
@@ -31,6 +31,9 @@ module PactBroker
31
31
  source: source_info.dig(key, :source) || {:type=>:defaults}
32
32
  }
33
33
  end.sort_by { |key, _| key }.each { |key, value| log_config_inner(key, value, logger) }
34
+ if self.webhook_redact_sensitive_data == false
35
+ logger.warn("WARNING!!! webhook_redact_sensitive_data is set to false. This will allow authentication information to be included in the webhook logs. This should only be used for debugging purposes. Do not run the application permanently in production with this value.")
36
+ end
34
37
  end
35
38
 
36
39
  def log_config_inner(key, value, logger)
@@ -94,7 +94,7 @@ module PactBroker
94
94
  end
95
95
 
96
96
  if logger.debug?
97
- logger.debug("Overridding runtime configuration", payload: { overrides: valid_overrides, ignoring: invalid_overrides })
97
+ logger.debug("Overridding runtime configuration", overrides: valid_overrides, ignoring: invalid_overrides)
98
98
  end
99
99
 
100
100
  valid_overrides.each do | key, value |
@@ -23,9 +23,9 @@ module PactBroker
23
23
 
24
24
  if main_branch_name
25
25
  connection[:pacticipants].where(id: pacticipant_row[:id], main_branch: nil).update(main_branch: main_branch_name)
26
- logger.info("Setting main branch for pacticipant", payload: { branch: main_branch_name, pacticipant_name: pacticipant_row[:name] })
26
+ logger.info("Setting main branch for pacticipant", branch: main_branch_name, pacticipant_name: pacticipant_row[:name])
27
27
  else
28
- logger.info("Cannot determine main branch for pacticipant", payload: { branch: nil, pacticipant_name: pacticipant_row[:name] })
28
+ logger.info("Cannot determine main branch for pacticipant", branch: nil, pacticipant_name: pacticipant_row[:name])
29
29
  end
30
30
  end
31
31
 
@@ -94,7 +94,13 @@ module PactBroker
94
94
  provider_version_tags - tags_with_successful_verifications_from_that_branch - tags_with_previous_successful_verifications_from_other_branches
95
95
  end
96
96
 
97
- def pending?
97
+ # @param [String] branch_name the name of the provider branch that will be verifying the pacts
98
+ # @return Boolean whether or not the pact is in pending state (ie. the build should not fail if the verification fails)
99
+ def pending_for_provider_branch?(branch_name)
100
+ pact_version.pending_for_provider_branch?(branch_name)
101
+ end
102
+
103
+ def pending_for_any_provider_branch?
98
104
  !pact_version.verified_successfully_by_any_provider_version?
99
105
  end
100
106
 
@@ -4,7 +4,7 @@ require "fileutils"
4
4
 
5
5
  module PactBroker
6
6
  def self.create_database_connection(config, logger = nil)
7
- logger&.info "Connecting to database:", payload: "#{config.merge(password: "*****")}"
7
+ logger&.info("Connecting to database:", config.merge(password: "*****"))
8
8
 
9
9
  sequel_config = config.dup
10
10
  max_retries = sequel_config.delete(:connect_max_retries) || 0
@@ -85,6 +85,7 @@ en:
85
85
  invalid_webhook_uuid: The UUID can only contain the characters A-Z, a-z, 0-9, _ and -, and must be 16 or more characters.
86
86
  pacticipant_not_found: No pacticipant with name '%{name}' found
87
87
  environment_name_must_be_unique: Another environment with name '%{name}' already exists.
88
+ must_specify_environment_or_tag: Must specify either an environment or a 'to' tag.
88
89
  cannot_specify_tag_and_environment: Cannot specify both a 'to' tag and an environment.
89
90
  cannot_specify_latest_and_environment: Cannot specify both latest=true and an environment.
90
91
  cannot_specify_more_than_one_destination_identifier: Cannot specify more than one of tag, environment and mainBranch.
@@ -2,12 +2,14 @@ require "dry-validation"
2
2
  require "pact_broker/messages"
3
3
  require "pact_broker/api/contracts/dry_validation_predicates"
4
4
  require "pact_broker/project_root"
5
+ require "pact_broker/string_refinements"
5
6
 
6
7
  module PactBroker
7
8
  module Api
8
9
  module Contracts
9
10
  class CanIDeployQuerySchema
10
11
  extend PactBroker::Messages
12
+ using PactBroker::StringRefinements
11
13
 
12
14
  SCHEMA = Dry::Validation.Schema do
13
15
  configure do
@@ -26,6 +28,10 @@ module PactBroker
26
28
  result[:to] ||= []
27
29
  result[:to] << message("errors.validation.cannot_specify_tag_and_environment")
28
30
  end
31
+ if params[:to].blank? && params[:environment].blank?
32
+ result[:environment] ||= []
33
+ result[:environment] << message("errors.validation.must_specify_environment_or_tag")
34
+ end
29
35
  result
30
36
  end
31
37
 
@@ -161,7 +161,7 @@ module PactBroker
161
161
  end
162
162
 
163
163
  def log_required_integrations_without_a_row_occurred integrations
164
- logger.info("required_integrations_without_a_row returned non empty", payload: { integrations: integrations, considered_rows: considered_rows })
164
+ logger.info("required_integrations_without_a_row returned non empty", integrations: integrations, considered_rows: considered_rows)
165
165
  end
166
166
 
167
167
  def row_exists_for_integration(integration)
@@ -211,9 +211,9 @@ module PactBroker
211
211
  "a version of #{pacticipant_name} with tag #{tag} (no such version exists)"
212
212
  elsif environment_name && pacticipant_version_number
213
213
  prefix = one_of_many? ? "one of the versions" : "the version"
214
- "#{prefix} of #{pacticipant_name} currently deployed or released to #{environment_name} (#{pacticipant_version_number})"
214
+ "#{prefix} of #{pacticipant_name} currently in #{environment_name} (#{pacticipant_version_number})"
215
215
  elsif environment_name
216
- "a version of #{pacticipant_name} currently deployed or released to #{environment_name} (no version is currently recorded as deployed/released in this environment)"
216
+ "a version of #{pacticipant_name} currently in #{environment_name} (no version is currently recorded as deployed/released in this environment)"
217
217
  elsif pacticipant_version_number && version_does_not_exist?
218
218
  "version #{pacticipant_version_number} of #{pacticipant_name} (no such version exists)"
219
219
  elsif pacticipant_version_number
@@ -80,6 +80,14 @@ module PactBroker
80
80
  }
81
81
  join(:tags, tags_join)
82
82
  end
83
+
84
+ def join_branch_versions_for_branch_name_to_verifications(branch_name)
85
+ branch_versions_join = {
86
+ Sequel[:branch_versions][:version_id] => Sequel[:verifications][:provider_version_id],
87
+ Sequel[:branch_versions][:branch_name] => branch_name
88
+ }
89
+ join(:branch_versions, branch_versions_join)
90
+ end
83
91
  end
84
92
 
85
93
  def name
@@ -106,6 +114,10 @@ module PactBroker
106
114
  latest_consumer_version.number
107
115
  end
108
116
 
117
+ def pending_for_provider_branch?(branch_name)
118
+ !any_successful_verifications_from_provider_branch?(branch_name) && !any_successful_verifications_from_another_branch_from_before_this_branch_created?(branch_name)
119
+ end
120
+
109
121
  def select_provider_tags_with_successful_verifications_from_another_branch_from_before_this_branch_created(tags)
110
122
  tags.select do | tag |
111
123
  first_tag_with_name = PactBroker::Domain::Tag.where(pacticipant_id: provider_id, name: tag).order(:created_at).first
@@ -157,6 +169,33 @@ module PactBroker
157
169
  )
158
170
  end
159
171
  end
172
+
173
+ def any_successful_verifications_from_provider_branch?(branch_name)
174
+ PactVersion.where(Sequel[:pact_versions][:id] => id)
175
+ .join_successful_verifications
176
+ .join_branch_versions_for_branch_name_to_verifications(branch_name)
177
+ .any?
178
+ end
179
+
180
+ def any_successful_verifications_from_another_branch_from_before_this_branch_created?(branch_name)
181
+ branch = PactBroker::Versions::Branch.where(pacticipant_id: provider_id, name: branch_name).single_record
182
+
183
+ verifications_join = {
184
+ Sequel[:verifications][:pact_version_id] => Sequel[:pact_versions][:id],
185
+ Sequel[:verifications][:success] => true
186
+ }
187
+ query = PactVersion.where(Sequel[:pact_versions][:id] => id)
188
+ .join(:verifications, verifications_join)
189
+ .join(:branch_versions, Sequel[:branch_versions][:version_id] => Sequel[:verifications][:provider_version_id]) do
190
+ Sequel.lit("branch_versions.branch_name != ?", branch_name)
191
+ end
192
+
193
+ if branch
194
+ query = query.where { Sequel[:verifications][:created_at] < branch.created_at }
195
+ end
196
+
197
+ query.any?
198
+ end
160
199
  end
161
200
  end
162
201
  end
@@ -12,6 +12,7 @@ require "pact_broker/repositories/scopes"
12
12
 
13
13
  module PactBroker
14
14
  module Pacts
15
+ # rubocop: disable Metrics/ClassLength
15
16
  class PactsForVerificationRepository
16
17
  include PactBroker::Logging
17
18
  include PactBroker::Repositories
@@ -26,6 +27,7 @@ module PactBroker
26
27
  :pact_version
27
28
  ]
28
29
 
30
+ # @return [VerifiablePact] an array of VerifiablePact objects
29
31
  def find(provider_name, consumer_version_selectors)
30
32
  selected_pacts = find_pacts_by_selector(provider_name, consumer_version_selectors)
31
33
  selected_pacts = selected_pacts + find_pacts_for_fallback_tags(selected_pacts, provider_name, consumer_version_selectors)
@@ -43,7 +45,7 @@ module PactBroker
43
45
  # provider tags they are pending for.
44
46
  # Don't include pact publications that were created before the provider tag was first used
45
47
  # (that is, before the provider's git branch was created).
46
- def find_wip provider_name, provider_version_branch, provider_tags_names, specified_pact_version_shas, options = {}
48
+ def find_wip(provider_name, provider_version_branch, provider_tags_names, explicitly_specified_verifiable_pacts, options = {})
47
49
  # TODO not sure about this
48
50
  if provider_tags_names.empty? && provider_version_branch == nil
49
51
  log_debug_for_wip do
@@ -53,7 +55,7 @@ module PactBroker
53
55
  end
54
56
 
55
57
  if provider_version_branch
56
- return find_wip_pact_versions_for_provider_by_provider_branch(provider_name, provider_version_branch, specified_pact_version_shas, options)
58
+ return find_wip_pact_versions_for_provider_by_provider_branch(provider_name, provider_version_branch, explicitly_specified_verifiable_pacts, options)
57
59
  end
58
60
 
59
61
  provider = pacticipant_repository.find_by_name(provider_name)
@@ -63,7 +65,7 @@ module PactBroker
63
65
  provider,
64
66
  provider_tags_names,
65
67
  wip_start_date,
66
- specified_pact_version_shas,
68
+ explicitly_specified_verifiable_pacts,
67
69
  :latest_by_consumer_tag
68
70
  )
69
71
 
@@ -71,7 +73,7 @@ module PactBroker
71
73
  provider,
72
74
  provider_tags_names,
73
75
  wip_start_date,
74
- specified_pact_version_shas,
76
+ explicitly_specified_verifiable_pacts,
75
77
  :latest_by_consumer_branch
76
78
  )
77
79
 
@@ -139,7 +141,7 @@ module PactBroker
139
141
  selectors = selector_for_latest_main_version_or_overall_latest(provider)
140
142
  selectors << Selector.for_currently_deployed
141
143
  selectors << Selector.for_currently_supported
142
- logger.debug("Default selectors", payload: selectors)
144
+ logger.debug("Default selectors", selectors)
143
145
  selectors
144
146
  end
145
147
 
@@ -193,11 +195,11 @@ module PactBroker
193
195
  end
194
196
 
195
197
  # TODO ? find the WIP pacts by consumer branch
196
- def find_wip_pact_versions_for_provider_by_provider_tags(provider, provider_tags_names, wip_start_date, specified_pact_version_shas, pact_publication_scope)
198
+ def find_wip_pact_versions_for_provider_by_provider_tags(provider, provider_tags_names, wip_start_date, explicitly_specified_verifiable_pacts, pact_publication_scope)
197
199
  potential_wip_pacts_by_consumer_tag_query = PactPublication.for_provider(provider).created_after(wip_start_date).send(pact_publication_scope)
198
200
 
199
201
  log_debug_for_wip do
200
- log_pact_publications("Potential WIP pacts for provider tag(s) #{provider_tags_names.join(", ")} created after #{wip_start_date} by #{pact_publication_scope}", potential_wip_pacts_by_consumer_tag_query)
202
+ log_pact_publications_from_query("Potential WIP pacts for provider tag(s) #{provider_tags_names.join(", ")} created after #{wip_start_date} by #{pact_publication_scope}", potential_wip_pacts_by_consumer_tag_query)
201
203
  end
202
204
 
203
205
  tag_to_pact_publications = provider_tags_names.each_with_object({}) do | provider_tag_name, tag_to_pact_publication |
@@ -205,7 +207,7 @@ module PactBroker
205
207
  potential_wip_pacts_by_consumer_tag_query,
206
208
  provider,
207
209
  provider_tag_name,
208
- specified_pact_version_shas
210
+ explicitly_specified_verifiable_pacts
209
211
  )
210
212
  end
211
213
 
@@ -225,7 +227,7 @@ module PactBroker
225
227
  end
226
228
  end
227
229
 
228
- def find_wip_pact_versions_for_provider_by_provider_branch(provider_name, provider_version_branch, specified_pact_version_shas, options)
230
+ def find_wip_pact_versions_for_provider_by_provider_branch(provider_name, provider_version_branch, explicitly_specified_verifiable_pacts, options)
229
231
  provider = pacticipant_repository.find_by_name(provider_name)
230
232
  wip_start_date = options.fetch(:include_wip_pacts_since)
231
233
 
@@ -233,22 +235,22 @@ module PactBroker
233
235
  potential_wip_by_consumer_tag = PactPublication.for_provider(provider).created_after(wip_start_date).latest_by_consumer_tag
234
236
 
235
237
  log_debug_for_wip do
236
- log_pact_publications("Potential WIP pacts for provider branch #{provider_version_branch} created after #{wip_start_date} by consumer branch", potential_wip_by_consumer_branch)
237
- log_pact_publications("Potential WIP pacts for provider branch #{provider_version_branch} created after #{wip_start_date} by consumer tag", potential_wip_by_consumer_tag)
238
+ log_pact_publications_from_query("Potential WIP pacts for provider branch #{provider_version_branch} created after #{wip_start_date} by consumer branch", potential_wip_by_consumer_branch)
239
+ log_pact_publications_from_query("Potential WIP pacts for provider branch #{provider_version_branch} created after #{wip_start_date} by consumer tag", potential_wip_by_consumer_tag)
238
240
  end
239
241
 
240
242
  wip_pact_publications_by_branch = remove_non_wip_for_branch(
241
243
  potential_wip_by_consumer_branch,
242
244
  provider,
243
245
  provider_version_branch,
244
- specified_pact_version_shas
246
+ explicitly_specified_verifiable_pacts
245
247
  )
246
248
 
247
249
  wip_pact_publications_by_tag = remove_non_wip_for_branch(
248
250
  potential_wip_by_consumer_tag,
249
251
  provider,
250
252
  provider_version_branch,
251
- specified_pact_version_shas
253
+ explicitly_specified_verifiable_pacts
252
254
  )
253
255
 
254
256
  verifiable_pacts = (wip_pact_publications_by_branch + wip_pact_publications_by_tag).collect do | pact_publication |
@@ -259,55 +261,61 @@ module PactBroker
259
261
  deduplicate_verifiable_pacts(verifiable_pacts).sort
260
262
  end
261
263
 
262
- def remove_non_wip_for_branch(pact_publications_query, provider, provider_version_branch, specified_pact_version_shas)
263
- specified_explicitly = pact_publications_query.for_pact_version_sha(specified_pact_version_shas)
264
+ def remove_non_wip_for_branch(pact_publications_query, provider, provider_version_branch, explicitly_specified_verifiable_pacts)
264
265
  verified_by_this_branch = pact_publications_query.successfully_verified_by_provider_branch_when_not_wip(provider.id, provider_version_branch)
265
266
  verified_by_other_branch = pact_publications_query.successfully_verified_by_provider_another_branch_before_this_branch_first_created(provider.id, provider_version_branch)
266
267
 
267
268
  log_debug_for_wip do
268
- log_pact_publications("Ignoring pacts explicitly specified in the selectors", specified_explicitly)
269
- log_pact_publications("Ignoring pacts successfully verified by this provider branch when not WIP", verified_by_this_branch)
270
- log_pact_publications("Ignoring pacts successfully verified by another provider branch when not WIP", verified_by_other_branch)
269
+ log_pact_publications("Ignoring pacts explicitly specified in the selectors", explicitly_specified_verifiable_pacts)
270
+ log_pact_publications_from_query("Ignoring pacts successfully verified by this provider branch when not WIP", verified_by_this_branch)
271
+ log_pact_publications_from_query("Ignoring pacts successfully verified by another provider branch when not WIP", verified_by_other_branch)
271
272
  end
272
273
 
273
- PactPublication.subtract(
274
- pact_publications_query.eager(*PUBLICATION_ASSOCIATIONS_FOR_EAGER_LOAD).all,
275
- specified_explicitly.all,
276
- verified_by_this_branch.all,
277
- verified_by_other_branch.all
278
- )
274
+ remove_explicitly_specified_verifiable_pacts(PactPublication.subtract(
275
+ pact_publications_query.eager(*PUBLICATION_ASSOCIATIONS_FOR_EAGER_LOAD).all,
276
+ verified_by_this_branch.all,
277
+ verified_by_other_branch.all),
278
+ explicitly_specified_verifiable_pacts)
279
279
  end
280
280
 
281
- def remove_non_wip_for_tag(pact_publications_query, provider, tag, specified_pact_version_shas)
282
- specified_explicitly = pact_publications_query.for_pact_version_sha(specified_pact_version_shas)
281
+ def remove_non_wip_for_tag(pact_publications_query, provider, tag, explicitly_specified_verifiable_pacts)
283
282
  verified_by_this_tag = pact_publications_query.successfully_verified_by_provider_tag_when_not_wip(tag)
284
283
  verified_by_another_tag = pact_publications_query.successfully_verified_by_provider_another_tag_before_this_tag_first_created(provider.id, tag)
285
284
 
286
285
  log_debug_for_wip do
287
- log_pact_publications("Ignoring pacts explicitly specified in the selectors", specified_explicitly)
288
- log_pact_publications("Ignoring pacts successfully verified by this provider tag when not WIP", verified_by_this_tag)
289
- log_pact_publications("Ignoring pacts successfully verified by another provider tag when not WIP", verified_by_another_tag)
286
+ log_pact_publications("Ignoring pacts explicitly specified in the selectors", explicitly_specified_verifiable_pacts)
287
+ log_pact_publications_from_query("Ignoring pacts successfully verified by this provider tag when not WIP", verified_by_this_tag)
288
+ log_pact_publications_from_query("Ignoring pacts successfully verified by another provider tag when not WIP", verified_by_another_tag)
290
289
  end
291
290
 
292
- PactPublication.subtract(
293
- pact_publications_query.eager(*PUBLICATION_ASSOCIATIONS_FOR_EAGER_LOAD).all,
294
- specified_explicitly.all,
295
- verified_by_this_tag.all,
296
- verified_by_another_tag.all)
291
+ remove_explicitly_specified_verifiable_pacts(
292
+ PactPublication.subtract(
293
+ pact_publications_query.eager(*PUBLICATION_ASSOCIATIONS_FOR_EAGER_LOAD).all,
294
+ verified_by_this_tag.all,
295
+ verified_by_another_tag.all),
296
+ explicitly_specified_verifiable_pacts)
297
297
  end
298
298
 
299
- def collect_consumer_name_and_version_number(pact_publications_query)
300
- pact_publications = pact_publications_query
301
- .eager(:consumer, :consumer_version)
302
- .order(:consumer_version_order)
303
- .all_forbidding_lazy_load
304
- .sort
299
+ def remove_explicitly_specified_verifiable_pacts(pact_publications, explicitly_specified_verifiable_pacts)
300
+ pact_publications.reject do | pact_publication |
301
+ explicitly_specified_verifiable_pacts.find{ | explict_pact |
302
+ explict_pact.consumer.id == pact_publication.consumer_id &&
303
+ explict_pact.provider.id == pact_publication.provider_id &&
304
+ explict_pact.pact_version_sha == pact_publication.pact_version_sha
305
+ }
306
+ end
307
+ end
305
308
 
309
+ def collect_consumer_name_and_version_number(pact_publications)
306
310
  pact_publications.collect do |p|
307
- suffix = if p.values[:tag_name]
308
- " (tag #{p.values[:tag_name]})"
309
- elsif p.values[:branch_name]
310
- " (branch #{p.values[:branch_name]})"
311
+ suffix = if p.respond_to?(:values)
312
+ if p.values[:tag_name]
313
+ " (tag #{p.values[:tag_name]})"
314
+ elsif p.values[:branch_name]
315
+ " (branch #{p.values[:branch_name]})"
316
+ else
317
+ ""
318
+ end
311
319
  else
312
320
  ""
313
321
  end
@@ -316,10 +324,28 @@ module PactBroker
316
324
  end
317
325
  end
318
326
 
319
- def log_pact_publications(message, pact_publications_query)
320
- pact_publication_descriptions = collect_consumer_name_and_version_number(pact_publications_query)
327
+ def with_sorted_eager_fields(pact_publications_query)
328
+ pact_publications_query
329
+ .eager(:provider)
330
+ .eager(:consumer, :consumer_version)
331
+ .order(:consumer_version_order)
332
+ .all_forbidding_lazy_load
333
+ .sort
334
+ end
335
+
336
+ def log_pact_publications_from_query(message, pact_publications_query)
337
+ pact_publication_descriptions = collect_consumer_name_and_version_number(with_sorted_eager_fields(pact_publications_query))
338
+ if pact_publication_descriptions.any?
339
+ logger.debug("#{message}", pact_publication_descriptions)
340
+ else
341
+ logger.debug("#{message} (none)")
342
+ end
343
+ end
344
+
345
+ def log_pact_publications(message, pact_publications)
346
+ pact_publication_descriptions = collect_consumer_name_and_version_number(pact_publications)
321
347
  if pact_publication_descriptions.any?
322
- logger.debug("#{message}", payload: pact_publication_descriptions)
348
+ logger.debug("#{message}", pact_publication_descriptions)
323
349
  else
324
350
  logger.debug("#{message} (none)")
325
351
  end
@@ -333,5 +359,6 @@ module PactBroker
333
359
  end
334
360
  end
335
361
  end
362
+ # rubocop: enable Metrics/ClassLength
336
363
  end
337
364
  end
@@ -158,8 +158,8 @@ module PactBroker
158
158
  PactsForVerificationRepository.new.find(provider_name, consumer_version_selectors)
159
159
  end
160
160
 
161
- def find_wip_pact_versions_for_provider provider_name, provider_version_branch, provider_tags_names, specified_pact_version_shas, options = {}
162
- PactsForVerificationRepository.new.find_wip(provider_name, provider_version_branch, provider_tags_names, specified_pact_version_shas, options)
161
+ def find_wip_pact_versions_for_provider provider_name, provider_version_branch, provider_tags_names, explicitly_specified_verifiable_pacts, options = {}
162
+ PactsForVerificationRepository.new.find_wip(provider_name, provider_version_branch, provider_tags_names, explicitly_specified_verifiable_pacts, options)
163
163
  end
164
164
 
165
165
  def find_pact_versions_for_provider provider_name, tag = nil
@@ -43,7 +43,7 @@ module PactBroker
43
43
  end
44
44
 
45
45
  def delete params
46
- logger.info "Deleting pact version", payload: params
46
+ logger.info("Deleting pact version", params)
47
47
  pacts = pact_repository.find_all_revisions(params[:consumer_name], params[:consumer_version_number], params[:provider_name])
48
48
  webhook_service.delete_all_webhook_related_objects_by_pact_publication_ids(pacts.collect(&:id))
49
49
  pact_repository.delete(params)
@@ -122,12 +122,11 @@ module PactBroker
122
122
  .find_for_verification(provider_name, consumer_version_selectors)
123
123
  .collect do | selected_pact |
124
124
  # Todo move this into the repository
125
- squash_pacts_for_verification(provider_version_tags, selected_pact, options[:include_pending_status])
125
+ squash_pacts_for_verification(provider_version_tags, provider_version_branch, selected_pact, options[:include_pending_status])
126
126
  end
127
127
 
128
128
  verifiable_wip_pacts = if options[:include_wip_pacts_since]
129
- specified_pact_version_shas = explicitly_specified_verifiable_pacts.collect(&:pact_version_sha)
130
- pact_repository.find_wip_pact_versions_for_provider(provider_name, provider_version_branch, provider_version_tags, specified_pact_version_shas, options)
129
+ pact_repository.find_wip_pact_versions_for_provider(provider_name, provider_version_branch, provider_version_tags, explicitly_specified_verifiable_pacts, options)
131
130
  else
132
131
  []
133
132
  end
@@ -156,8 +155,8 @@ module PactBroker
156
155
 
157
156
  # Overwriting an existing pact with the same consumer/provider/consumer version number
158
157
  def create_pact_revision params, existing_pact
159
- logger.info "Updating existing pact publication", payload: params.without(:json_content)
160
- logger.debug "Content #{params[:json_content]}"
158
+ logger.info("Updating existing pact publication", params.without(:json_content))
159
+ logger.debug("Content #{params[:json_content]}")
161
160
  pact_version_sha = generate_sha(params[:json_content])
162
161
  json_content = add_interaction_ids(params[:json_content])
163
162
  update_params = { pact_version_sha: pact_version_sha, json_content: json_content }
@@ -185,8 +184,8 @@ module PactBroker
185
184
 
186
185
  # When no publication for the given consumer/provider/consumer version number exists
187
186
  def create_pact params, version, provider
188
- logger.info "Creating new pact publication", payload: params.without(:json_content)
189
- logger.debug "Content #{params[:json_content]}"
187
+ logger.info("Creating new pact publication", params.without(:json_content))
188
+ logger.debug("Content #{params[:json_content]}")
190
189
  pact_version_sha = generate_sha(params[:json_content])
191
190
  json_content = add_interaction_ids(params[:json_content])
192
191
  pact = pact_repository.create(
@@ -5,17 +5,19 @@
5
5
  module PactBroker
6
6
  module Pacts
7
7
  module SquashPactsForVerification
8
- def self.call(provider_version_tags, selected_pact, include_pending_status = false)
8
+ def self.call(provider_version_tags, provider_version_branch, selected_pact, include_pending_status = false)
9
9
  domain_pact = selected_pact.pact
10
10
 
11
11
  if include_pending_status
12
12
  pending_provider_tags = []
13
13
  pending = nil
14
- if provider_version_tags.any?
14
+ if provider_version_branch
15
+ pending = domain_pact.pending_for_provider_branch?(provider_version_branch)
16
+ elsif provider_version_tags.any?
15
17
  pending_provider_tags = domain_pact.select_pending_provider_version_tags(provider_version_tags)
16
18
  pending = pending_provider_tags.any?
17
19
  else
18
- pending = domain_pact.pending?
20
+ pending = domain_pact.pending_for_any_provider_branch?
19
21
  end
20
22
  non_pending_provider_tags = provider_version_tags - pending_provider_tags
21
23
  VerifiablePact.new(
@@ -23,7 +25,8 @@ module PactBroker
23
25
  selected_pact.selectors,
24
26
  pending,
25
27
  pending_provider_tags,
26
- non_pending_provider_tags
28
+ non_pending_provider_tags,
29
+ provider_version_branch
27
30
  )
28
31
  else
29
32
  VerifiablePact.new(
@@ -63,7 +63,7 @@ module PactBroker
63
63
  end
64
64
 
65
65
  def output string, payload = {}
66
- logger ? logger.info(string, payload: payload) : puts("#{string} #{payload.to_json}")
66
+ logger ? logger.info(string, payload) : puts("#{string} #{payload.to_json}")
67
67
  end
68
68
 
69
69
  def add_defaults_to_keep_selectors
@@ -46,7 +46,7 @@ module PactBroker
46
46
  end
47
47
 
48
48
  def output string, payload = {}
49
- logger ? logger.info(string, payload: payload) : puts("#{string} #{payload.to_json}")
49
+ logger ? logger.info(string, payload) : puts("#{string} #{payload.to_json}")
50
50
  end
51
51
  end
52
52
  end
@@ -265,7 +265,9 @@ module PactBroker
265
265
  "request" => {
266
266
  "method" => "POST",
267
267
  "url" => url,
268
- "body" => body || default_body
268
+ "body" => body || default_body,
269
+ "username" => "user",
270
+ "password" => "pass"
269
271
  }
270
272
  }.compact
271
273
  path = "webhooks/#{uuid}"
@@ -286,32 +288,9 @@ module PactBroker
286
288
  def create_global_webhook_for_anything_published(uuid: nil, url: "https://postman-echo.com/post")
287
289
  puts "Creating global webhook for contract changed event with uuid #{uuid}"
288
290
  uuid ||= SecureRandom.uuid
289
- request_body = {
290
- "description" => "A webhook for all consumers and providers",
291
- "events" => [{
292
- "name" => "contract_published"
293
- },{
294
- "name" => "provider_verification_published"
295
- }],
296
- "request" => {
297
- "method" => "POST",
298
- "url" => url,
299
- "headers" => { "Content-Type" => "application/json"},
300
- "body" => {
301
- "eventName" => "${pactbroker.eventName}",
302
- "consumerVersionNumber" => "${pactbroker.consumerVersionNumber}",
303
- "consumerVersionTags" => "${pactbroker.consumerVersionTags}",
304
- "consumerVersionBranch" => "${pactbroker.consumerVersionBranch}",
305
- "githubVerificationStatus" => "${pactbroker.githubVerificationStatus}",
306
- "providerVersionNumber" => "${pactbroker.providerVersionNumber}",
307
- "providerVersionTags" => "${pactbroker.providerVersionTags}",
308
- "providerVersionBranch" => "${pactbroker.providerVersionBranch}",
309
- "canIMerge" => "${pactbroker.providerMainBranchGithubVerificationStatus}"
310
- }
311
- }
312
- }
291
+
313
292
  path = "webhooks/#{uuid}"
314
- client.put(path, request_body.to_json).tap { |response| check_for_error(response) }
293
+ client.put(path, webhook_body_with_all_parameters(url).to_json).tap { |response| check_for_error(response) }
315
294
  separate
316
295
  self
317
296
  end
@@ -438,6 +417,35 @@ module PactBroker
438
417
  puts response.body
439
418
  end
440
419
  end
420
+
421
+ def webhook_body_with_all_parameters(url)
422
+ {
423
+ "description" => "A webhook for all consumers and providers",
424
+ "events" => [{
425
+ "name" => "contract_published"
426
+ },{
427
+ "name" => "provider_verification_published"
428
+ }],
429
+ "request" => {
430
+ "method" => "POST",
431
+ "url" => url,
432
+ "headers" => { "Content-Type" => "application/json"},
433
+ "username" => "user",
434
+ "password" => "pass",
435
+ "body" => {
436
+ "eventName" => "${pactbroker.eventName}",
437
+ "consumerVersionNumber" => "${pactbroker.consumerVersionNumber}",
438
+ "consumerVersionTags" => "${pactbroker.consumerVersionTags}",
439
+ "consumerVersionBranch" => "${pactbroker.consumerVersionBranch}",
440
+ "githubVerificationStatus" => "${pactbroker.githubVerificationStatus}",
441
+ "providerVersionNumber" => "${pactbroker.providerVersionNumber}",
442
+ "providerVersionTags" => "${pactbroker.providerVersionTags}",
443
+ "providerVersionBranch" => "${pactbroker.providerVersionBranch}",
444
+ "canIMerge" => "${pactbroker.providerMainBranchGithubVerificationStatus}"
445
+ }
446
+ }
447
+ }
448
+ end
441
449
  end
442
450
  end
443
451
  end
@@ -399,22 +399,13 @@ module PactBroker
399
399
  verification = PactBroker::Domain::Verification.new(parameters)
400
400
  pact_version = PactBroker::Pacts::Repository.new.find_pact_version(@consumer, @provider, pact.pact_version_sha)
401
401
  @provider_version = version_repository.find_by_pacticipant_id_and_number_or_create(provider.id, provider_version_number)
402
- PactBroker::Versions::BranchVersionRepository.new.add_branch(@provider_version, branch) if branch
402
+ branch_version = PactBroker::Versions::BranchVersionRepository.new.add_branch(@provider_version, branch) if branch
403
403
 
404
- if tag_names.any?
405
- tag_names.each do | tag_name |
406
- PactBroker::Domain::Tag.new(name: tag_name, version: @provider_version, version_order: @provider_version.order).insert_ignore
407
- set_created_at_if_set(parameters[:created_at], :tags, version_id: @provider_version.id, name: tag_name)
408
- end
409
- end
404
+ set_created_at_for_provider_tags(parameters, tag_names)
410
405
 
411
406
  @verification = PactBroker::Verifications::Repository.new.create(verification, provider_version_number, pact_version)
412
407
 
413
- set_created_at_if_set(parameters[:created_at], :verifications, id: @verification.id)
414
- set_created_at_if_set(parameters[:created_at], :versions, id: @provider_version.id)
415
- set_created_at_if_set(parameters[:created_at], :latest_verification_id_for_pact_version_and_provider_version, pact_version_id: pact_version_id, provider_version_id: @provider_version.id)
416
- set_created_at_if_set(parameters[:created_at], :pact_version_provider_tag_successful_verifications, { verification_id: @verification.id }, :execution_date)
417
-
408
+ set_created_at_for_verification_resources(parameters, pact_version.id, branch, branch_version)
418
409
  self
419
410
  end
420
411
 
@@ -674,6 +665,31 @@ module PactBroker
674
665
  [nil, Domain::WebhookPacticipant.new(label: label)]
675
666
  end
676
667
  end
668
+
669
+ def set_created_at_for_provider_tags(parameters, tag_names)
670
+ if tag_names.any?
671
+ tag_names.each do | tag_name |
672
+ PactBroker::Domain::Tag.new(name: tag_name, version: @provider_version, version_order: @provider_version.order).insert_ignore
673
+ set_created_at_if_set(parameters[:created_at], :tags, version_id: @provider_version.id, name: tag_name)
674
+ end
675
+ end
676
+ end
677
+
678
+ def set_created_at_for_verification_resources(parameters, pact_version_id, branch, branch_version)
679
+ if branch
680
+ set_created_at_if_set(parameters[:created_at], :branch_versions, id: branch_version.id)
681
+
682
+ # if the branch has just been created...
683
+ if branch_version.branch.branch_versions.size == 1
684
+ set_created_at_if_set(parameters[:created_at], :branches, id: branch_version.branch.id)
685
+ end
686
+ end
687
+
688
+ set_created_at_if_set(parameters[:created_at], :verifications, id: @verification.id)
689
+ set_created_at_if_set(parameters[:created_at], :versions, id: @provider_version.id)
690
+ set_created_at_if_set(parameters[:created_at], :latest_verification_id_for_pact_version_and_provider_version, pact_version_id: pact_version_id, provider_version_id: @provider_version.id)
691
+ set_created_at_if_set(parameters[:created_at], :pact_version_provider_tag_successful_verifications, { verification_id: @verification.id }, :execution_date)
692
+ end
677
693
  end
678
694
  end
679
695
  end
@@ -33,7 +33,7 @@ module PactBroker
33
33
  # verified_pacts is an array of SelectedPact objects
34
34
  def create next_verification_number, params, verified_pacts, event_context
35
35
  first_verified_pact = verified_pacts.first
36
- logger.info "Creating verification #{next_verification_number} for pact_version_sha=#{first_verified_pact.pact_version_sha}", payload: params.reject{ |k,_| k == "testResults"}
36
+ logger.info("Creating verification #{next_verification_number} for pact_version_sha=#{first_verified_pact.pact_version_sha}", params.without("testResults"))
37
37
  verification = PactBroker::Domain::Verification.new
38
38
  provider_version_number = params.fetch("providerApplicationVersion")
39
39
  PactBroker::Api::Decorators::VerificationDecorator.new(verification).from_hash(params)
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = "2.104.0"
2
+ VERSION = "2.105.0"
3
3
  end
@@ -8,6 +8,7 @@ module PactBroker
8
8
  plugin :insert_ignore, identifying_columns: [:name, :pacticipant_id]
9
9
 
10
10
  associate(:many_to_one, :pacticipant, :class => "PactBroker::Domain::Pacticipant", :key => :pacticipant_id, :primary_key => :id)
11
+ associate(:one_to_many, :branch_versions, :class => "PactBroker::Versions::BranchVersion", :key => :branch_id, :primary_key => :id)
11
12
 
12
13
  dataset_module do
13
14
  include PactBroker::Repositories::Helpers
@@ -53,10 +53,10 @@ module PactBroker
53
53
 
54
54
  def log_detected_event
55
55
  event = detected_events.last
56
- logger.debug "Event detected", payload: { event_name: event.name, event_comment: event.comment }
56
+ logger.debug("Event detected", event_name: event.name, event_comment: event.comment)
57
57
  if event.triggered_webhooks&.any?
58
58
  triggered_webhook_descriptions = event.triggered_webhooks.collect{ |tw| { event_name: event.name, webhook_uuid: tw.webhook_uuid, triggered_webhook_uuid: tw.uuid, webhook_description: tw.webhook.description } }
59
- logger.info "Triggered webhooks for #{event.name}", payload: { triggered_webhooks: triggered_webhook_descriptions }
59
+ logger.info("Triggered webhooks for #{event.name}", triggered_webhooks: triggered_webhook_descriptions)
60
60
  else
61
61
  logger.debug "No enabled webhooks found for event #{event.name}"
62
62
  end
@@ -25,6 +25,10 @@ module PactBroker
25
25
  with_updated_attribute(logging_options: { failure_log_message: value })
26
26
  end
27
27
 
28
+ def with_redact_sensitive_data(value)
29
+ with_updated_attribute(logging_options: { redact_sensitive_data: value })
30
+ end
31
+
28
32
  def with_retry_schedule(value)
29
33
  with_updated_attribute(retry_schedule: value)
30
34
  end
@@ -10,6 +10,7 @@ module PactBroker
10
10
  def self.call(resource)
11
11
  PactBroker::Webhooks::ExecutionConfiguration.new
12
12
  .with_show_response(PactBroker.configuration.show_webhook_response?)
13
+ .with_redact_sensitive_data(PactBroker.configuration.webhook_redact_sensitive_data)
13
14
  .with_retry_schedule(PactBroker.configuration.webhook_retry_schedule)
14
15
  .with_http_success_codes(PactBroker.configuration.webhook_http_code_success)
15
16
  .with_user_agent(PactBroker.configuration.user_agent)
@@ -51,7 +51,7 @@ module PactBroker
51
51
  end
52
52
 
53
53
  def log_request(webhook_request)
54
- http_request = HttpRequestWithRedactedHeaders.new(webhook_request.http_request)
54
+ http_request = options[:redact_sensitive_data] ? HttpRequestWithRedactedHeaders.new(webhook_request.http_request) : webhook_request.http_request
55
55
  logger.info "Making webhook #{webhook_request.uuid} request #{http_request.method.upcase} URI=#{webhook_request.url} (headers and body in debug logs)"
56
56
  logger.debug "Webhook #{webhook_request.uuid} request headers=#{http_request.to_hash}"
57
57
  logger.debug "Webhook #{webhook_request.uuid} request body=#{http_request.body}"
data/pact_broker.gemspec CHANGED
@@ -78,7 +78,7 @@ Gem::Specification.new do |gem|
78
78
  gem.add_runtime_dependency "dry-types", "~> 0.10.3" # https://travis-ci.org/pact-foundation/pact_broker/jobs/249448621
79
79
  gem.add_runtime_dependency "dry-logic", "0.4.2" # Later version cases ArgumentError: wrong number of arguments
80
80
  gem.add_runtime_dependency "table_print", "~> 1.5"
81
- gem.add_runtime_dependency "semantic_logger", "~> 4.3"
81
+ gem.add_runtime_dependency "semantic_logger", "~> 4.11"
82
82
  gem.add_runtime_dependency "sanitize", "6.0"
83
83
  gem.add_runtime_dependency "wisper", "~> 2.0"
84
84
  gem.add_runtime_dependency "anyway_config", "~> 2.1"
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.104.0
4
+ version: 2.105.0
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-09-17 00:00:00.000000000 Z
13
+ date: 2022-10-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: json
@@ -334,14 +334,14 @@ dependencies:
334
334
  requirements:
335
335
  - - "~>"
336
336
  - !ruby/object:Gem::Version
337
- version: '4.3'
337
+ version: '4.11'
338
338
  type: :runtime
339
339
  prerelease: false
340
340
  version_requirements: !ruby/object:Gem::Requirement
341
341
  requirements:
342
342
  - - "~>"
343
343
  - !ruby/object:Gem::Version
344
- version: '4.3'
344
+ version: '4.11'
345
345
  - !ruby/object:Gem::Dependency
346
346
  name: sanitize
347
347
  requirement: !ruby/object:Gem::Requirement
@@ -1227,7 +1227,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1227
1227
  - !ruby/object:Gem::Version
1228
1228
  version: '0'
1229
1229
  requirements: []
1230
- rubygems_version: 3.3.22
1230
+ rubygems_version: 3.3.24
1231
1231
  signing_key:
1232
1232
  specification_version: 4
1233
1233
  summary: See description