pact_broker 2.109.0 → 2.110.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -0
  3. data/README.md +1 -2
  4. data/docs/developer/design_pattern_for_eager_loading_collections.md +23 -0
  5. data/docs/developer/matrix.md +95 -0
  6. data/docs/developer/rack.md +11 -0
  7. data/lib/pact_broker/api/contracts/consumer_version_selector_contract.rb +1 -1
  8. data/lib/pact_broker/api/decorators/base_decorator.rb +10 -1
  9. data/lib/pact_broker/api/decorators/version_decorator.rb +14 -0
  10. data/lib/pact_broker/api/resources/branch_versions.rb +1 -1
  11. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +5 -0
  12. data/lib/pact_broker/api/resources/versions.rb +1 -1
  13. data/lib/pact_broker/app.rb +24 -9
  14. data/lib/pact_broker/contracts/service.rb +6 -2
  15. data/lib/pact_broker/db/advisory_lock.rb +58 -0
  16. data/lib/pact_broker/domain/version.rb +3 -2
  17. data/lib/pact_broker/integrations/integration.rb +11 -1
  18. data/lib/pact_broker/integrations/repository.rb +46 -7
  19. data/lib/pact_broker/integrations/service.rb +2 -0
  20. data/lib/pact_broker/locale/en.yml +1 -1
  21. data/lib/pact_broker/matrix/matrix_row.rb +0 -1
  22. data/lib/pact_broker/matrix/resolved_selector.rb +0 -1
  23. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +56 -2
  24. data/lib/pact_broker/pacts/pact_publication_selector_dataset_module.rb +1 -0
  25. data/lib/pact_broker/pacts/pact_publication_wip_dataset_module.rb +59 -79
  26. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +5 -4
  27. data/lib/pact_broker/pacts/repository.rb +2 -2
  28. data/lib/pact_broker/pacts/selector.rb +8 -2
  29. data/lib/pact_broker/tasks/clean_task.rb +68 -26
  30. data/lib/pact_broker/test/test_data_builder.rb +8 -3
  31. data/lib/pact_broker/version.rb +1 -1
  32. data/lib/pact_broker/versions/branch_service.rb +1 -0
  33. data/lib/pact_broker/versions/repository.rb +2 -20
  34. data/lib/pact_broker/versions/service.rb +2 -6
  35. data/lib/pact_broker/webhooks/execution.rb +8 -8
  36. data/lib/sequel/extensions/pg_advisory_lock.rb +101 -0
  37. data/pact_broker.gemspec +1 -1
  38. metadata +10 -5
@@ -57,6 +57,13 @@ module PactBroker
57
57
  end
58
58
  end
59
59
 
60
+ # Returns the latest pact for each branch, returning a pact for every branch, even if
61
+ # the most recent version of that branch does not have a pact.
62
+ # This is different from for_all_branch_heads, which will find the branch head versions,
63
+ # and return the pacts associated with those versions.
64
+ # This method should not be used for 'pacts for verification', because it will return
65
+ # a pact for branches where that integration should no longer exist.
66
+ # @return [Dataset<PactBroker::Pacts::PactPublication>]
60
67
  def latest_by_consumer_branch
61
68
  branch_versions_join = {
62
69
  Sequel[:pact_publications][:consumer_version_id] => Sequel[:branch_versions][:version_id]
@@ -111,10 +118,29 @@ module PactBroker
111
118
  .limit(1)
112
119
  end
113
120
 
114
- # Return the pacts (if they exist) for the branch heads.
121
+ # Returns the pacts (if they exist) for all the branch heads.
122
+ # If the version for the branch head does not have a pact, then no pact is returned,
123
+ # (unlike latest_by_consumer_branch)
124
+ # This is much more performant than latest_by_consumer_branch and should be used
125
+ # for the 'pacts for verification' response
126
+ # @return [Dataset<PactBroker::Pacts::PactPublication>]
127
+ def for_all_branch_heads
128
+ base_query = self
129
+ base_query = base_query.join(:branch_heads, { Sequel[:bh][:version_id] => Sequel[:pact_publications][:consumer_version_id] }, { table_alias: :bh })
130
+
131
+ if no_columns_selected?
132
+ base_query = base_query.select_all_qualified.select_append(Sequel[:bh][:branch_name].as(:branch_name))
133
+ end
134
+
135
+ base_query.remove_overridden_revisions
136
+ end
137
+
138
+ # Return the pacts (if they exist) for the branch heads of the given branch names
115
139
  # This uses the new logic of finding the branch head and returning any associated pacts,
116
140
  # rather than the old logic of returning the pact for the latest version
117
141
  # on the branch that had a pact.
142
+ # @param [String] branch_name
143
+ # @return [Sequel::Dataset<PactBroker::Pacts::PactPublication>]
118
144
  def for_branch_heads(branch_name)
119
145
  branch_head_join = {
120
146
  Sequel[:pact_publications][:consumer_version_id] => Sequel[:branch_heads][:version_id],
@@ -173,7 +199,10 @@ module PactBroker
173
199
  # The latest pact publication for each tag
174
200
  # This uses the old logic of "the latest pact for a version that has a tag" (which always returns a pact)
175
201
  # rather than "the pact for the latest version with a tag"
176
- # Need to see about updating this.
202
+ #
203
+ # For 'pacts for verification' this has been replaced by for_all_tag_heads
204
+ # This should only be used for the UI
205
+ # @return [Sequel::Dataset<PactBroker::Pacts::PactPublication>]
177
206
  def latest_by_consumer_tag
178
207
  tags_join = {
179
208
  Sequel[:pact_publications][:consumer_version_id] => Sequel[:tags][:version_id],
@@ -202,6 +231,7 @@ module PactBroker
202
231
  # This uses the old logic of "the latest pact for a version that has a tag" (which always returns a pact)
203
232
  # rather than "the pact for the latest version with a tag"
204
233
  # Need to see about updating this.
234
+ # @return [Sequel::Dataset<PactBroker::Pacts::PactPublication>]
205
235
  def latest_for_consumer_tag(tag_name)
206
236
  tags_join = {
207
237
  Sequel[:pact_publications][:consumer_version_id] => Sequel[:tags][:version_id],
@@ -252,6 +282,30 @@ module PactBroker
252
282
  .remove_overridden_revisions_from_complete_query
253
283
  end
254
284
 
285
+ # The pacts for the latest versions for each tag.
286
+ # Will not return a pact if the pact is no longer published for a particular tag
287
+ # NEW LOGIC
288
+ # @return [Sequel::Dataset<PactBroker::Pacts::PactPublication>]
289
+ def for_all_tag_heads
290
+ head_tags = PactBroker::Domain::Tag
291
+ .select_group(:pacticipant_id, :name)
292
+ .select_append{ max(version_order).as(:latest_version_order) }
293
+
294
+ head_tags_join = {
295
+ Sequel[:pact_publications][:consumer_id] => Sequel[:head_tags][:pacticipant_id],
296
+ Sequel[:pact_publications][:consumer_version_order] => Sequel[:head_tags][:latest_version_order]
297
+ }
298
+
299
+ base_query = self
300
+ if no_columns_selected?
301
+ base_query = base_query.select_all_qualified.select_append(Sequel[:head_tags][:name].as(:tag_name))
302
+ end
303
+
304
+ base_query
305
+ .join(head_tags, head_tags_join, { table_alias: :head_tags })
306
+ .remove_overridden_revisions_from_complete_query
307
+ end
308
+
255
309
  def in_environments
256
310
  currently_deployed_join = {
257
311
  Sequel[:pact_publications][:consumer_version_id] => Sequel[:currently_deployed_version_ids][:version_id]
@@ -15,6 +15,7 @@ module PactBroker
15
15
 
16
16
  # Do the "latest" logic last so that the provider/consumer criteria get included in the "latest" query before the join, rather than after
17
17
  query = query.latest_for_main_branches if selector.latest_for_main_branch?
18
+ query = query.for_all_branch_heads if selector.latest_for_each_branch?
18
19
  query = query.latest_for_consumer_branch(selector.branch) if selector.latest_for_branch?
19
20
  query = query.for_latest_consumer_versions_with_tag(selector.tag) if selector.latest_for_tag?
20
21
  query = query.overall_latest if selector.overall_latest?
@@ -1,35 +1,76 @@
1
1
  module PactBroker
2
2
  module Pacts
3
3
  module PactPublicationWipDatasetModule
4
+
5
+ # Use a cut down model of the verifications table just for the WIP calculations.
6
+ # Don't need all the associations and normal domain methods.
7
+ class VerificationForWipCalculations < Sequel::Model(:verifications)
8
+ dataset_module do
9
+ def successful_non_wip_by_provider(provider_id)
10
+ distinct.where(success: true, wip: false, provider_id: provider_id)
11
+ end
12
+
13
+ def verified_before_creation_date_of(record)
14
+ if record
15
+ verified_before_date(record.created_at)
16
+ else
17
+ self
18
+ end
19
+ end
20
+
21
+ def join_branch_versions_excluding_branch(provider_id, branch_name)
22
+ branch_versions_join = {
23
+ Sequel[:verifications][:provider_version_id] => Sequel[:branch_versions][:version_id],
24
+ Sequel[:branch_versions][:pacticipant_id] => provider_id
25
+ }
26
+ join(:branch_versions, branch_versions_join) do
27
+ Sequel.lit("branch_versions.branch_name != ?", branch_name)
28
+ end
29
+ end
30
+
31
+ def join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
32
+ branch_versions_join = {
33
+ Sequel[:verifications][:provider_version_id] => Sequel[:branch_versions][:version_id],
34
+ Sequel[:branch_versions][:pacticipant_id] => provider_id,
35
+ Sequel[:branch_versions][:branch_name] => provider_version_branch
36
+ }
37
+
38
+ join(:branch_versions, branch_versions_join)
39
+ end
40
+
41
+ def verified_before_date(date)
42
+ where { Sequel[:verifications][:execution_date] < date }
43
+ end
44
+ end
45
+ end
46
+
4
47
  def successfully_verified_by_provider_branch_when_not_wip(provider_id, provider_version_branch)
48
+ successful_verifications = VerificationForWipCalculations
49
+ .select(:pact_version_id)
50
+ .distinct
51
+ .successful_non_wip_by_provider(provider_id)
52
+ .join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
53
+
54
+
5
55
  from_self(alias: :pp)
6
56
  .select(Sequel[:pp].*)
7
- .where(Sequel[:pp][:provider_id] => provider_id)
8
- .join_successful_non_wip_verifications_for_provider_id(provider_id)
9
- .join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
10
57
  .distinct
58
+ .join(successful_verifications, { Sequel[:pp][:pact_version_id] => Sequel[:v][:pact_version_id] }, { table_alias: :v })
11
59
  end
12
60
 
13
61
  def successfully_verified_by_provider_another_branch_before_this_branch_first_created(provider_id, provider_version_branch)
14
62
  first_version_for_branch = PactBroker::Domain::Version.first_for_pacticipant_id_and_branch(provider_id, provider_version_branch)
15
63
 
64
+ successful_verifications = VerificationForWipCalculations
65
+ .select(:pact_version_id)
66
+ .distinct
67
+ .successful_non_wip_by_provider(provider_id)
68
+ .join_branch_versions_excluding_branch(provider_id, provider_version_branch)
69
+ .verified_before_creation_date_of(first_version_for_branch)
70
+
16
71
  from_self(alias: :pp)
17
72
  .select(Sequel[:pp].*)
18
- .join_successful_non_wip_verifications_for_provider_id(provider_id)
19
- .join_provider_versions_for_provider_id(provider_id)
20
- .join_branch_versions_excluding_branch(provider_version_branch)
21
- .where(Sequel[:pp][:provider_id] => provider_id)
22
- .verified_before_creation_date_of(first_version_for_branch)
23
- .distinct
24
- end
25
-
26
- def join_branch_versions_excluding_branch(branch_name)
27
- branch_versions_join = {
28
- Sequel[:provider_versions][:id] => Sequel[:branch_versions][:version_id]
29
- }
30
- join(:branch_versions, branch_versions_join) do
31
- Sequel.lit("branch_versions.branch_name != ?", branch_name)
32
- end
73
+ .join(successful_verifications, { Sequel[:pp][:pact_version_id] => Sequel[:v][:pact_version_id] }, { table_alias: :v })
33
74
  end
34
75
 
35
76
  def successfully_verified_by_provider_tag_when_not_wip(provider_tag)
@@ -43,7 +84,6 @@ module PactBroker
43
84
  .select(Sequel[:pp].*)
44
85
  .join(:pact_version_provider_tag_successful_verifications, pact_version_provider_tag_verifications_join, { table_alias: :sv })
45
86
  .distinct
46
-
47
87
  end
48
88
 
49
89
  def successfully_verified_by_provider_another_tag_before_this_tag_first_created(provider_id, provider_tag)
@@ -71,66 +111,6 @@ module PactBroker
71
111
  end
72
112
  .distinct
73
113
  end
74
-
75
- protected
76
-
77
- def verified_before_date(date)
78
- where { Sequel[:verifications][:execution_date] < date }
79
- end
80
-
81
- def join_successful_non_wip_verifications_for_provider_id(provider_id, &block)
82
- verifications_join = {
83
- pact_version_id: :pact_version_id,
84
- Sequel[:verifications][:success] => true,
85
- Sequel[:verifications][:wip] => false,
86
- Sequel[:verifications][:provider_id] => provider_id
87
- }
88
- join(:verifications, verifications_join, {}, &block)
89
- end
90
-
91
- def join_provider_version_tags &block
92
- tags_join = {
93
- Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id],
94
- }
95
- join(:tags, tags_join, { table_alias: :provider_tags }, &block)
96
- end
97
-
98
- def join_provider_version_tags_for_tag(tag)
99
- tags_join = {
100
- Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id],
101
- Sequel[:provider_tags][:name] => tag
102
- }
103
- join(:tags, tags_join, { table_alias: :provider_tags } )
104
- end
105
-
106
- def join_provider_versions_for_provider_id_and_branch(provider_id, provider_version_branch)
107
- versions_join = {
108
- Sequel[:verifications][:provider_version_id] => Sequel[:provider_versions][:id],
109
- Sequel[:provider_versions][:pacticipant_id] => provider_id
110
- }
111
- branch_versions_join = {
112
- Sequel[:provider_versions][:id] => Sequel[:branch_versions][:version_id],
113
- Sequel[:branch_versions][:branch_name] => provider_version_branch
114
- }
115
- join(:versions, versions_join, { table_alias: :provider_versions } )
116
- .join(:branch_versions, branch_versions_join)
117
- end
118
-
119
- def join_provider_versions_for_provider_id(provider_id, &block)
120
- versions_join = {
121
- Sequel[:verifications][:provider_version_id] => Sequel[:provider_versions][:id],
122
- Sequel[:provider_versions][:pacticipant_id] => provider_id
123
- }
124
- join(:versions, versions_join, { table_alias: :provider_versions }, &block)
125
- end
126
-
127
- def verified_before_creation_date_of(record)
128
- if record
129
- verified_before_date(record.created_at)
130
- else
131
- self
132
- end
133
- end
134
114
  end
135
115
  end
136
116
  end
@@ -7,6 +7,7 @@ require "pact_broker/pacts/selector"
7
7
  require "pact_broker/pacts/selectors"
8
8
  require "pact_broker/feature_toggle"
9
9
  require "pact_broker/repositories/scopes"
10
+ require "pact_broker/matrix/unresolved_selector"
10
11
 
11
12
  module PactBroker
12
13
  module Pacts
@@ -63,7 +64,7 @@ module PactBroker
63
64
  provider_tags_names,
64
65
  wip_start_date,
65
66
  explicitly_specified_verifiable_pacts,
66
- :latest_by_consumer_tag
67
+ :for_all_tag_heads
67
68
  )
68
69
 
69
70
  wip_by_consumer_branches = find_wip_pact_versions_for_provider_by_provider_tags(
@@ -71,7 +72,7 @@ module PactBroker
71
72
  provider_tags_names,
72
73
  wip_start_date,
73
74
  explicitly_specified_verifiable_pacts,
74
- :latest_by_consumer_branch
75
+ :for_all_branch_heads
75
76
  )
76
77
 
77
78
  deduplicate_verifiable_pacts(wip_by_consumer_tags + wip_by_consumer_branches).sort
@@ -228,8 +229,8 @@ module PactBroker
228
229
  provider = pacticipant_repository.find_by_name(provider_name)
229
230
  wip_start_date = options.fetch(:include_wip_pacts_since)
230
231
 
231
- potential_wip_by_consumer_branch = PactPublication.for_provider(provider).created_after(wip_start_date).latest_by_consumer_branch
232
- potential_wip_by_consumer_tag = PactPublication.for_provider(provider).created_after(wip_start_date).latest_by_consumer_tag
232
+ potential_wip_by_consumer_branch = PactPublication.for_provider(provider).created_after(wip_start_date).for_all_branch_heads
233
+ potential_wip_by_consumer_tag = PactPublication.for_provider(provider).created_after(wip_start_date).for_all_tag_heads
233
234
 
234
235
  log_debug_for_wip do
235
236
  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)
@@ -33,8 +33,8 @@ module PactBroker
33
33
  scope
34
34
  end
35
35
 
36
- def create params
37
- integration_repository.create_for_pact(params.fetch(:consumer_id), params.fetch(:provider_id))
36
+ # @return [PactBroker::Domain::Pact]
37
+ def create(params)
38
38
  pact_version = find_or_create_pact_version(
39
39
  params.fetch(:consumer_id),
40
40
  params.fetch(:provider_id),
@@ -31,6 +31,8 @@ module PactBroker
31
31
  def type
32
32
  if latest_for_main_branch?
33
33
  :latest_for_main_branch
34
+ elsif latest_for_each_branch?
35
+ :latest_for_each_branch
34
36
  elsif latest_for_branch?
35
37
  :latest_for_branch
36
38
  elsif matching_branch?
@@ -265,12 +267,16 @@ module PactBroker
265
267
  # Not sure if the fallback_tag logic is needed
266
268
  def latest_for_branch? potential_branch = nil
267
269
  if potential_branch
268
- !!(latest && branch == potential_branch)
270
+ latest == true && branch == potential_branch
269
271
  else
270
- !!(latest && !!branch)
272
+ latest == true && branch.is_a?(String)
271
273
  end
272
274
  end
273
275
 
276
+ def latest_for_each_branch?
277
+ latest == true && branch == true
278
+ end
279
+
274
280
  def all_for_tag_and_consumer?
275
281
  !!(tag && !latest? && consumer)
276
282
  end
@@ -1,3 +1,8 @@
1
+ # This task is used to clean up old data in a Pact Broker database
2
+ # to stop performance issues from slowing down responses when there is
3
+ # too much data.
4
+ # See https://docs.pact.io/pact_broker/administration/maintenance
5
+
1
6
  module PactBroker
2
7
  module DB
3
8
  class CleanTask < ::Rake::TaskLib
@@ -7,11 +12,13 @@ module PactBroker
7
12
  attr_accessor :version_deletion_limit
8
13
  attr_accessor :logger
9
14
  attr_accessor :dry_run
15
+ attr_accessor :use_lock # allow disabling of postgres lock if it is causing problems
10
16
 
11
17
  def initialize &block
12
18
  require "pact_broker/db/clean_incremental"
13
19
  @version_deletion_limit = 1000
14
20
  @dry_run = false
21
+ @use_lock = true
15
22
  @keep_version_selectors = PactBroker::DB::CleanIncremental::DEFAULT_KEEP_SELECTORS
16
23
  rake_task(&block)
17
24
  end
@@ -28,42 +35,77 @@ module PactBroker
28
35
  namespace :db do
29
36
  desc "Clean unnecessary pacts and verifications from database"
30
37
  task :clean do | _t, _args |
31
-
32
38
  instance_eval(&block)
33
39
 
34
- require "pact_broker/db/clean_incremental"
35
- require "pact_broker/error"
36
- require "yaml"
37
- require "benchmark"
40
+ with_lock do
41
+ perform_clean
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def perform_clean
49
+ require "pact_broker/db/clean_incremental"
50
+ require "pact_broker/error"
51
+ require "yaml"
52
+ require "benchmark"
38
53
 
39
- raise PactBroker::Error.new("You must specify the version_deletion_limit") unless version_deletion_limit
54
+ raise PactBroker::Error.new("You must specify the version_deletion_limit") unless version_deletion_limit
40
55
 
41
- prefix = dry_run ? "[DRY RUN] " : ""
56
+ if keep_version_selectors.nil? || keep_version_selectors.empty?
57
+ raise PactBroker::Error.new("You must specify which versions to keep")
58
+ else
59
+ add_defaults_to_keep_selectors
60
+ output "Deleting oldest #{version_deletion_limit} versions, keeping versions that match the configured selectors", keep_version_selectors.collect(&:to_hash)
61
+ end
42
62
 
43
- if keep_version_selectors.nil? || keep_version_selectors.empty?
44
- raise PactBroker::Error.new("You must specify which versions to keep")
45
- else
46
- add_defaults_to_keep_selectors
47
- output "#{prefix}Deleting oldest #{version_deletion_limit} versions, keeping versions that match the configured selectors", keep_version_selectors.collect(&:to_hash)
48
- end
63
+ start_time = Time.now
64
+ results = PactBroker::DB::CleanIncremental.call(database_connection,
65
+ keep: keep_version_selectors,
66
+ limit: version_deletion_limit,
67
+ logger: logger,
68
+ dry_run: dry_run
69
+ )
70
+ end_time = Time.now
71
+ elapsed_seconds = (end_time - start_time).to_i
72
+ output "Results (#{elapsed_seconds} seconds)", results
73
+ end
49
74
 
50
- start_time = Time.now
51
- results = PactBroker::DB::CleanIncremental.call(database_connection,
52
- keep: keep_version_selectors,
53
- limit: version_deletion_limit,
54
- logger: logger,
55
- dry_run: dry_run
56
- )
57
- end_time = Time.now
58
- elapsed_seconds = (end_time - start_time).to_i
59
- output "Results (#{elapsed_seconds} seconds)", results
60
- end
75
+ # Use a Postgres advisory lock to ensure that only one clean can run at a time.
76
+ # This allows a cron schedule to be used on the Pact Broker Docker image when deployed
77
+ # on a multi-instance architecture, without all the instances stepping on each other's toes.
78
+ #
79
+ # Any tasks that attempt to run while a clean job is running will skip the clean
80
+ # and exit with a message and a success code.
81
+ #
82
+ # To test that the lock works, run:
83
+ # script/docker/db-start.sh
84
+ # script/docker/db-migrate.sh
85
+ # for i in {0..3}; do PACT_BROKER_TEST_DATABASE_URL=postgres://postgres:postgres@localhost/postgres bundle exec rake pact_broker:db:clean &; done;
86
+ #
87
+ # There will be 3 messages saying "Clean was not performed" and output from one thread showing the clean is being done.
88
+ def with_lock
89
+ if use_lock
90
+ require "pact_broker/db/advisory_lock"
91
+
92
+ lock = PactBroker::DB::AdvisoryLock.new(database_connection, :clean, :pg_try_advisory_lock)
93
+ results = lock.with_lock do
94
+ yield
95
+ end
96
+
97
+ if !lock.lock_obtained?
98
+ output("Clean was not performed as a clean is already in progress. Exiting.")
61
99
  end
100
+ results
101
+ else
102
+ yield
62
103
  end
63
104
  end
64
105
 
65
- def output string, payload = {}
66
- logger ? logger.info(string, payload) : puts("#{string} #{payload.to_json}")
106
+ def output(string, payload = {})
107
+ prefix = dry_run ? "[DRY RUN] " : ""
108
+ logger ? logger.info("#{prefix}#{string}") : puts("#{prefix}#{string} #{payload.to_json}")
67
109
  end
68
110
 
69
111
  def add_defaults_to_keep_selectors
@@ -43,7 +43,6 @@ module PactBroker
43
43
  include PactBroker::Services
44
44
  using PactBroker::StringRefinements
45
45
 
46
-
47
46
  attr_reader :pacticipant
48
47
  attr_reader :consumer
49
48
  attr_reader :provider
@@ -192,8 +191,11 @@ module PactBroker
192
191
  self
193
192
  end
194
193
 
194
+ # Create an Integration object for the current consumer and provider
195
+ # @return [PactBroker::Test::TestDataBuilder]
195
196
  def create_integration
196
- PactBroker::Integrations::Repository.new.create_for_pact(consumer.id, provider.id)
197
+ @integration = PactBroker::Integrations::Repository.new.create_for_pact(consumer.id, provider.id)
198
+ set_created_at_if_set(@now, :integrations, { consumer_id: consumer.id, provider_id: provider.id })
197
199
  self
198
200
  end
199
201
 
@@ -280,7 +282,9 @@ module PactBroker
280
282
  self
281
283
  end
282
284
 
283
- def create_pact params = {}
285
+ # Creates a pact (and integration if one does not already exist) from the given params
286
+ # @return [PactBroker::Test::TestDataBuilder]
287
+ def create_pact(params = {})
284
288
  params.delete(:comment)
285
289
  json_content = params[:json_content] || default_json_content
286
290
  pact_version_sha = params[:pact_version_sha] || generate_pact_version_sha(json_content)
@@ -293,6 +297,7 @@ module PactBroker
293
297
  json_content: prepare_json_content(json_content),
294
298
  version: @consumer_version
295
299
  )
300
+ integration_service.handle_bulk_contract_data_published([@pact])
296
301
  pact_versions_count_after = PactBroker::Pacts::PactVersion.count
297
302
  set_created_at_if_set(params[:created_at], :pact_publications, id: @pact.id)
298
303
  set_created_at_if_set(params[:created_at], :pact_versions, sha: @pact.pact_version_sha) if pact_versions_count_after > pact_versions_count_before
@@ -1,3 +1,3 @@
1
1
  module PactBroker
2
- VERSION = "2.109.0"
2
+ VERSION = "2.110.0"
3
3
  end
@@ -2,6 +2,7 @@ require "forwardable"
2
2
  require "pact_broker/logging"
3
3
  require "pact_broker/repositories"
4
4
  require "pact_broker/messages"
5
+ require "pact_broker/contracts/notice"
5
6
 
6
7
  module PactBroker
7
8
  module Versions
@@ -57,29 +57,11 @@ module PactBroker
57
57
  .single_record
58
58
  end
59
59
 
60
- # The eager loaded relations are hardcoded here to support the PactBroker::Api::Decorators::VersionDecorator
61
- # Newer "find all" implementations for other models pass the relations to eager load in
62
- # from the decorator via the resource.
63
- def find_all_pacticipant_versions_in_reverse_order name, pagination_options = {}
64
- pacticipant = pacticipant_repository.find_by_name!(name)
65
- query = PactBroker::Domain::Version
66
- .where(pacticipant: pacticipant)
67
- .eager(:pacticipant)
68
- .eager(branch_versions: [:version, :branch_head, { branch: :pacticipant }])
69
- .eager(tags: :head_tag)
70
- .eager(:pact_publications)
71
- .reverse_order(:order)
72
- query.all_with_pagination_options(pagination_options)
73
- end
74
-
75
- def find_pacticipant_versions_in_reverse_order(pacticipant_name, options = {}, pagination_options = {})
60
+ def find_pacticipant_versions_in_reverse_order(pacticipant_name, options = {}, pagination_options = {}, eager_load_associations = [])
76
61
  pacticipant = pacticipant_repository.find_by_name!(pacticipant_name)
77
62
  query = PactBroker::Domain::Version
78
63
  .where(pacticipant: pacticipant)
79
- .eager(:pacticipant)
80
- .eager(branch_versions: [:version, :branch_head, { branch: :pacticipant }])
81
- .eager(tags: :head_tag)
82
- .eager(:pact_publications)
64
+ .eager(*eager_load_associations)
83
65
  .reverse_order(:order)
84
66
 
85
67
  if options[:branch_name]
@@ -26,12 +26,8 @@ module PactBroker
26
26
  version_repository.find_latest_by_pacticipant_name_and_branch_name(pacticipant_name, branch_name)
27
27
  end
28
28
 
29
- def self.find_all_pacticipant_versions_in_reverse_order(name, pagination_options = {})
30
- version_repository.find_all_pacticipant_versions_in_reverse_order(name, pagination_options)
31
- end
32
-
33
- def self.find_pacticipant_versions_in_reverse_order(pacticipant_name, options, pagination_options = {})
34
- version_repository.find_pacticipant_versions_in_reverse_order(pacticipant_name, options, pagination_options)
29
+ def self.find_pacticipant_versions_in_reverse_order(pacticipant_name, options, pagination_options = {}, eager_load_associations = [])
30
+ version_repository.find_pacticipant_versions_in_reverse_order(pacticipant_name, options, pagination_options, eager_load_associations)
35
31
  end
36
32
 
37
33
  def self.create_or_overwrite(pacticipant_name, version_number, version)
@@ -2,14 +2,14 @@ require "pact_broker/dataset"
2
2
 
3
3
  module PactBroker
4
4
  module Webhooks
5
- class Execution < Sequel::Model(
6
- Sequel::Model.db[:webhook_executions].select(
7
- Sequel[:webhook_executions][:id],
8
- :triggered_webhook_id,
9
- :success,
10
- :logs,
11
- Sequel[:webhook_executions][:created_at])
12
- )
5
+ class Execution < Sequel::Model(:webhook_executions)
6
+ # Ignore the columns that were used before the TriggeredWebhook class existed.
7
+ # It used to go Webhook -> Execution, and now it goes Webhook -> TriggeredWebhook -> Execution
8
+ # If we ever release a major version where we drop unused columns, those columns could be deleted.
9
+ EXECUTION_COLUMNS = Sequel::Model.db.schema(:webhook_executions).collect(&:first) - [:webhook_id, :pact_publication_id, :consumer_id, :provider_id]
10
+
11
+ set_dataset(Sequel::Model.db[:webhook_executions].select(*EXECUTION_COLUMNS))
12
+
13
13
  set_primary_key :id
14
14
  plugin :timestamps
15
15