pact_broker 2.80.0 → 2.81.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +2 -2
  3. data/CHANGELOG.md +21 -0
  4. data/db/ddl_statements/latest_verifications_for_pact_versions.rb +28 -0
  5. data/db/migrations/20210711_add_consumer_version_order_to_pact_publication.rb +12 -0
  6. data/db/migrations/20210712_add_interaction_count_to_pact_versions.rb +8 -0
  7. data/lib/db.rb +4 -0
  8. data/lib/pact_broker/api.rb +8 -10
  9. data/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema.rb +25 -5
  10. data/lib/pact_broker/api/contracts/verifiable_pacts_query_schema.rb +0 -1
  11. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +24 -0
  12. data/lib/pact_broker/api/resources/dashboard.rb +4 -1
  13. data/lib/pact_broker/api/resources/deployed_versions_for_version_and_environment.rb +3 -7
  14. data/lib/pact_broker/api/resources/index.rb +10 -12
  15. data/lib/pact_broker/api/resources/latest_provider_pacts.rb +1 -1
  16. data/lib/pact_broker/api/resources/pagination_methods.rb +14 -0
  17. data/lib/pact_broker/api/resources/tag.rb +14 -0
  18. data/lib/pact_broker/configuration.rb +4 -1
  19. data/lib/pact_broker/db/data_migrations/set_consumer_version_order_for_pact_publications.rb +28 -0
  20. data/lib/pact_broker/db/data_migrations/set_interactions_counts.rb +41 -0
  21. data/lib/pact_broker/db/migrate_data.rb +2 -0
  22. data/lib/pact_broker/db/seed_example_data.rb +5 -0
  23. data/lib/pact_broker/deployments/deployed_version_service.rb +13 -9
  24. data/lib/pact_broker/domain/verification.rb +40 -0
  25. data/lib/pact_broker/domain/version.rb +4 -0
  26. data/lib/pact_broker/index/service.rb +4 -5
  27. data/lib/pact_broker/integrations/integration.rb +27 -6
  28. data/lib/pact_broker/logging.rb +10 -0
  29. data/lib/pact_broker/matrix/unresolved_selector.rb +1 -1
  30. data/lib/pact_broker/metrics/service.rb +17 -0
  31. data/lib/pact_broker/pacts/all_pact_publications.rb +4 -2
  32. data/lib/pact_broker/pacts/content.rb +2 -2
  33. data/lib/pact_broker/pacts/metadata.rb +11 -5
  34. data/lib/pact_broker/pacts/pact_publication.rb +41 -6
  35. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +55 -11
  36. data/lib/pact_broker/pacts/pact_publication_selector_dataset_module.rb +20 -0
  37. data/lib/pact_broker/pacts/pact_version.rb +14 -15
  38. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +86 -31
  39. data/lib/pact_broker/pacts/parse.rb +1 -0
  40. data/lib/pact_broker/pacts/repository.rb +51 -41
  41. data/lib/pact_broker/pacts/selector.rb +18 -2
  42. data/lib/pact_broker/pacts/service.rb +13 -22
  43. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +11 -0
  44. data/lib/pact_broker/repositories/helpers.rb +4 -0
  45. data/lib/pact_broker/repositories/scopes.rb +15 -0
  46. data/lib/pact_broker/test/test_data_builder.rb +2 -1
  47. data/lib/pact_broker/ui/helpers/matrix_helper.rb +1 -0
  48. data/lib/pact_broker/ui/views/index/show-with-tags.haml +1 -1
  49. data/lib/pact_broker/ui/views/matrix/show.haml +2 -0
  50. data/lib/pact_broker/verifications/latest_verification_for_pact_version.rb +2 -2
  51. data/lib/pact_broker/verifications/repository.rb +9 -10
  52. data/lib/pact_broker/version.rb +1 -1
  53. data/public/javascripts/matrix.js +3 -0
  54. data/spec/features/create_tag_spec.rb +10 -0
  55. data/spec/features/execute_webhook_spec.rb +1 -3
  56. data/spec/features/get_integrations_spec.rb +2 -2
  57. data/spec/features/get_provider_pacts_for_verification_spec.rb +5 -3
  58. data/spec/features/metadata_spec.rb +66 -0
  59. data/spec/features/publish_verification_results_and_version_spec.rb +70 -0
  60. data/spec/fixtures/approvals/get_provider_pacts_for_verification.approved.json +2 -2
  61. data/spec/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema_combinations_spec.rb +9 -0
  62. data/spec/lib/pact_broker/api/contracts/verifiable_pacts_json_query_schema_spec.rb +15 -0
  63. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +12 -0
  64. data/spec/lib/pact_broker/api/resources/dashboard_spec.rb +23 -2
  65. data/spec/lib/pact_broker/api/resources/latest_provider_pacts_spec.rb +3 -3
  66. data/spec/lib/pact_broker/api/resources/provider_pacts_spec.rb +1 -1
  67. data/spec/lib/pact_broker/api/resources/tag_spec.rb +39 -13
  68. data/spec/lib/pact_broker/db/data_migrations/set_interactions_counts_spec.rb +38 -0
  69. data/spec/lib/pact_broker/deployments/deployed_version_service_spec.rb +42 -0
  70. data/spec/lib/pact_broker/domain/verification_spec.rb +17 -0
  71. data/spec/lib/pact_broker/index/service_spec.rb +28 -16
  72. data/spec/lib/pact_broker/integrations/integration_spec.rb +21 -10
  73. data/spec/lib/pact_broker/metrics/service_spec.rb +25 -0
  74. data/spec/lib/pact_broker/pacts/content_spec.rb +1 -1
  75. data/spec/lib/pact_broker/pacts/metadata_spec.rb +95 -29
  76. data/spec/lib/pact_broker/pacts/pact_publication_selector_dataset_module_spec.rb +39 -0
  77. data/spec/lib/pact_broker/pacts/pact_version_spec.rb +68 -12
  78. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +1 -1
  79. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +1 -1
  80. data/spec/lib/pact_broker/pacts/repository_spec.rb +59 -52
  81. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +9 -0
  82. data/spec/lib/pact_broker/verifications/latest_verification_for_pact_version_spec.rb +18 -0
  83. data/spec/support/shared_context.rb +0 -1
  84. metadata +20 -3
@@ -0,0 +1,41 @@
1
+ require "pact_broker/pacts/content"
2
+
3
+ module PactBroker
4
+ module DB
5
+ module DataMigrations
6
+ class SetInteractionsCounts
7
+ def self.call(connection)
8
+ self_join = {
9
+ Sequel[:pact_publications][:consumer_id] => Sequel[:pp2][:consumer_id],
10
+ Sequel[:pact_publications][:provider_id] => Sequel[:pp2][:provider_id]
11
+ }
12
+
13
+ pact_versions_join = {
14
+ Sequel[:pact_versions][:id] => Sequel[:pact_publications][:pact_version_id],
15
+ Sequel[:pact_versions][:interactions_count] => nil,
16
+ Sequel[:pact_versions][:messages_count] => nil
17
+ }
18
+
19
+ base_query = connection[:pact_publications]
20
+ base_query = base_query.select(Sequel[:pact_versions][:id], Sequel[:pact_versions][:content])
21
+
22
+ latest_pact_publications_query = base_query.left_join(base_query.select(:consumer_id, :provider_id, :consumer_version_order), self_join, { table_alias: :pp2 } ) do
23
+ Sequel[:pp2][:consumer_version_order] > Sequel[:pact_publications][:consumer_version_order]
24
+ end
25
+ .join(:pact_versions, pact_versions_join)
26
+ .where(Sequel[:pp2][:consumer_version_order] => nil)
27
+
28
+ latest_pact_publications_query.each do | row |
29
+ content = PactBroker::Pacts::Content.from_json(row[:content])
30
+ connection.from(:pact_versions)
31
+ .where(id: row[:id])
32
+ .update(
33
+ messages_count: content.messages&.count || 0,
34
+ interactions_count: content.interactions&.count || 0
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -25,6 +25,8 @@ module PactBroker
25
25
  DataMigrations::SetPacticipantDisplayName.call(database_connection)
26
26
  DataMigrations::SetPacticipantMainBranch.call(database_connection)
27
27
  DataMigrations::SetWebhookUuid.call(database_connection)
28
+ DataMigrations::SetConsumerVersionOrderForPactPublications.call(database_connection)
29
+ DataMigrations::SetExtraColumnsForTags.call(database_connection)
28
30
  end
29
31
  end
30
32
  end
@@ -11,6 +11,7 @@ module PactBroker
11
11
  new.call
12
12
  end
13
13
 
14
+ # rubocop: disable Metrics/MethodLength
14
15
  def call(consumer_name: CONSUMER_NAME, provider_name: PROVIDER_NAME)
15
16
  return unless database_empty?
16
17
  PactBroker::Test::TestDataBuilder.new
@@ -31,6 +32,9 @@ module PactBroker
31
32
  .create_consumer_version("725c6ccb7cf7efc51b4394f9828585eea9c379d9", branch: "feat/new-thing", created_at: days_ago(7))
32
33
  .create_consumer_version_tag("feat-new-thing", created_at: days_ago(7))
33
34
  .create_pact(json_content: pact_2, created_at: days_ago(7))
35
+ .create_consumer_version("6c992f831da299364cf31be6008ee4752189f6d4", branch: "feat/new-thing", created_at: days_ago(6))
36
+ .create_consumer_version_tag("feat-new-thing", created_at: days_ago(6))
37
+ .create_pact(json_content: pact_2, created_at: days_ago(7))
34
38
  .create_consumer_version("7bd4d9173522826dc3e8704fd62dde0424f4c827", branch: "main", created_at: days_ago(1))
35
39
  .create_consumer_version_tag("main", created_at: days_ago(1))
36
40
  .create_pact(json_content: pact_3, created_at: days_ago(1))
@@ -42,6 +46,7 @@ module PactBroker
42
46
  .create_deployed_version_for_consumer_version(environment_name: "test", created_at: days_ago(0.5))
43
47
  .republish_same_pact(created_at: days_ago(0.5))
44
48
  end
49
+ # rubocop: enable Metrics/MethodLength
45
50
 
46
51
  def database_empty?
47
52
  PactBroker::Pacticipants::Service.find_all_pacticipants.empty?
@@ -13,15 +13,19 @@ module PactBroker
13
13
  DeployedVersion.where(uuid: uuid).single_record
14
14
  end
15
15
 
16
- def self.create(uuid, version, environment, target)
17
- record_previous_version_undeployed(version.pacticipant, environment, target)
18
- DeployedVersion.create(
19
- uuid: uuid,
20
- version: version,
21
- pacticipant_id: version.pacticipant_id,
22
- environment: environment,
23
- target: target
24
- )
16
+ def self.find_or_create(uuid, version, environment, target)
17
+ if (deployed_version = find_currently_deployed_version_for_version_and_environment_and_target(version, environment, target))
18
+ deployed_version
19
+ else
20
+ record_previous_version_undeployed(version.pacticipant, environment, target)
21
+ DeployedVersion.create(
22
+ uuid: uuid,
23
+ version: version,
24
+ pacticipant_id: version.pacticipant_id,
25
+ environment: environment,
26
+ target: target
27
+ )
28
+ end
25
29
  end
26
30
 
27
31
  def self.find_deployed_versions_for_version_and_environment(version, environment)
@@ -27,6 +27,30 @@ module PactBroker
27
27
  dataset_module do
28
28
  include PactBroker::Repositories::Helpers
29
29
 
30
+ def for_provider_name(provider_name)
31
+ where(provider: PactBroker::Domain::Pacticipant.find_by_name(provider_name))
32
+ end
33
+
34
+ def for_consumer_name(consumer_name)
35
+ where(consumer: PactBroker::Domain::Pacticipant.find_by_name(consumer_name))
36
+ end
37
+
38
+ def latest_by_pact_version
39
+ base_query = self
40
+ base_join = {
41
+ Sequel[:verifications][:pact_version_id] => Sequel[:v2][:pact_version_id]
42
+ }
43
+
44
+ if no_columns_selected?
45
+ base_query = base_query.select_all_qualified
46
+ end
47
+
48
+ base_query.left_join(base_query.select(Sequel[:verifications][:id], Sequel[:verifications][:pact_version_id]), base_join, { table_alias: :v2 }) do
49
+ Sequel[:v2][:id] > Sequel[:verifications][:id]
50
+ end
51
+ .where(Sequel[:v2][:id] => nil)
52
+ end
53
+
30
54
  def latest_verification_ids_for_all_consumer_version_tags
31
55
  verif_pact_join = { Sequel[:verifications][:pact_version_id] => Sequel[:lpp][:pact_version_id] }
32
56
  tag_join = { Sequel[:lpp][:consumer_version_id] => Sequel[:cvt][:version_id] }
@@ -103,6 +127,10 @@ module PactBroker
103
127
  .join(latest_ids_for_cv_tags, join_cols, { table_alias: :t2 })
104
128
  end
105
129
 
130
+ def remove_verifications_for_overridden_consumer_versions
131
+ join(:latest_pact_publication_ids_for_consumer_versions, { pact_version_id: :pact_version_id } )
132
+ end
133
+
106
134
  # Expects to be joined with AllPactPublications or subclass
107
135
  # Beware that when columns with the same name exist in both datasets
108
136
  # you may get the wrong column back in your model.
@@ -143,6 +171,18 @@ module PactBroker
143
171
  .left_outer_join(:tags, {version_id: :consumer_version_id})
144
172
  .where(Sequel.qualify(:tags, :name) => nil)
145
173
  end
174
+
175
+ def join_pact_publications
176
+ join(:pact_publications, { Sequel[:pact_publications][:pact_version_id] => Sequel[:verifications][:pact_version_id] })
177
+ end
178
+
179
+ def for_consumer_name_and_consumer_version_number(consumer_name, consumer_version_number)
180
+ consumer_versions = PactBroker::Domain::Version.select(:id).where_pacticipant_name_and_version_number(consumer_name, consumer_version_number)
181
+ join(:pact_publications, {
182
+ Sequel[:pact_publications][:pact_version_id] => Sequel[:verifications][:pact_version_id],
183
+ Sequel[:pact_publications][:consumer_version_id] => consumer_versions
184
+ })
185
+ end
146
186
  end
147
187
 
148
188
  def pact_version_sha
@@ -62,6 +62,10 @@ module PactBroker
62
62
  where_pacticipant_name(pacticipant_name).where_number(version_number).single_record
63
63
  end
64
64
 
65
+ def where_pacticipant_name_and_version_number(pacticipant_name, version_number)
66
+ where_pacticipant_name(pacticipant_name).where_number(version_number)
67
+ end
68
+
65
69
  def first_for_pacticipant_id_and_branch(pacticipant_id, branch)
66
70
  where(pacticipant_id: pacticipant_id, branch: branch).order(:created_at).first
67
71
  end
@@ -102,9 +102,9 @@ module PactBroker
102
102
  end
103
103
  end
104
104
 
105
- def self.find_index_items_for_api(consumer_name: nil, provider_name: nil, **_ignored)
105
+ def self.find_index_items_for_api(consumer_name: nil, provider_name: nil, page_number: nil, page_size: nil, **_ignored)
106
106
  latest_pp_ids = latest_pact_publication_ids
107
- pact_publications = head_pact_publications(consumer_name: consumer_name, provider_name: provider_name, tags: true)
107
+ pact_publications = head_pact_publications(consumer_name: consumer_name, provider_name: provider_name, tags: true, page_number: page_number, page_size: page_size)
108
108
  .eager(:consumer)
109
109
  .eager(:provider)
110
110
  .eager(:pact_version)
@@ -173,7 +173,7 @@ module PactBroker
173
173
  ]
174
174
 
175
175
  query.order(*order_columns)
176
- .paginate(options[:page_number] || DEFAULT_PAGE_NUMBER, options[:page_size] || DEFAULT_PAGE_SIZE)
176
+ .paginate(options[:page_number] || DEFAULT_PAGE_NUMBER, options[:page_size] || DEFAULT_PAGE_SIZE)
177
177
  end
178
178
 
179
179
  # eager loading the tag stuff doesn't seem to make it quicker
@@ -196,8 +196,7 @@ module PactBroker
196
196
  def self.query_pact_publication_ids_by_tags(base, tags)
197
197
  latest = base.overall_latest
198
198
  return latest.union(base.latest_for_consumer_tag(tags)) if tags.is_a?(Array)
199
- return latest.union(base.latest_by_consumer_tag) if tags
200
-
199
+ return latest.union(base.latest_by_consumer_tag).union(base.for_environment(nil)) if tags
201
200
  latest
202
201
  end
203
202
 
@@ -7,26 +7,47 @@ require "pact_broker/webhooks/webhook"
7
7
  module PactBroker
8
8
  module Integrations
9
9
  class Integration < Sequel::Model
10
+ set_primary_key [:consumer_id, :provider_id]
10
11
  associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
11
12
  associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
12
- associate(:one_to_one, :latest_pact, :class => "PactBroker::Pacts::LatestPactPublications", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id])
13
13
  associate(:one_to_one, :latest_verification, :class => "PactBroker::Verifications::LatestVerificationForConsumerAndProvider", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id])
14
14
  associate(:one_to_many, :latest_triggered_webhooks, :class => "PactBroker::Webhooks::LatestTriggeredWebhook", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id])
15
15
 
16
+ # When viewing the index, every latest_pact in the database will match at least one of the rows, so
17
+ # it makes sense to load the entire table and match each pact to the appropriate row.
18
+ # Update: now we have pagination, we should probably filter the pacts by consumer/provider id.
19
+ LATEST_PACT_EAGER_LOADER = proc do |eo_opts|
20
+ eo_opts[:rows].each do |integration|
21
+ integration.associations[:latest_pact] = []
22
+ end
23
+
24
+ PactBroker::Pacts::PactPublication.overall_latest.each do | pact |
25
+ eo_opts[:rows].each do | integration |
26
+ if integration.consumer_id == pact.consumer_id && integration.provider_id == pact.provider_id
27
+ integration.associations[:latest_pact] = pact
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ one_to_one(:latest_pact, class: "PactBroker::Pacts::PactPublication", :key => [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id], :eager_loader=> LATEST_PACT_EAGER_LOADER) do | _ds |
34
+ PactBroker::Pacts::PactPublication.overall_latest_for_consumer_id_and_provider_id(consumer_id, provider_id)
35
+ end
36
+
16
37
  # When viewing the index, every webhook in the database will match at least one of the rows, so
17
38
  # it makes sense to load the entire table and match each webhook to the appropriate row.
18
39
  # This will only work when using eager loading. The keys are just blanked out to avoid errors.
19
40
  # I don't understand how they work at all.
20
41
  # It would be nice to do this declaratively.
21
42
  many_to_many :webhooks, class: "PactBroker::Webhooks::Webhook", :left_key => [], left_primary_key: [], :eager_loader=>(proc do |eo_opts|
22
- eo_opts[:rows].each do |row|
23
- row.associations[:webhooks] = []
43
+ eo_opts[:rows].each do |integration|
44
+ integration.associations[:webhooks] = []
24
45
  end
25
46
 
26
47
  PactBroker::Webhooks::Webhook.each do | webhook |
27
- eo_opts[:rows].each do | row |
28
- if webhook.is_for?(row)
29
- row.associations[:webhooks] << webhook
48
+ eo_opts[:rows].each do | integration |
49
+ if webhook.is_for?(integration)
50
+ integration.associations[:webhooks] << webhook
30
51
  end
31
52
  end
32
53
  end
@@ -31,6 +31,16 @@ module PactBroker
31
31
  end
32
32
  end
33
33
 
34
+ def log_with_tag(tag)
35
+ if logger.respond_to?(:tagged)
36
+ logger.tagged(tag) do
37
+ yield
38
+ end
39
+ else
40
+ yield
41
+ end
42
+ end
43
+
34
44
  def log_error e, description = nil
35
45
  if logger.instance_of?(SemanticLogger::Logger)
36
46
  if description
@@ -78,7 +78,7 @@ module PactBroker
78
78
  end
79
79
 
80
80
  def all_for_pacticipant?
81
- !!pacticipant_name && !pacticipant_version_number && !tag && !latest && !environment_name && !max_age
81
+ !!pacticipant_name && !pacticipant_version_number && !tag && !branch && !latest && !environment_name && !max_age
82
82
  end
83
83
 
84
84
  def latest_for_pacticipant_and_tag?
@@ -22,6 +22,7 @@ module PactBroker
22
22
  # rubocop: disable Metrics/MethodLength
23
23
  def metrics
24
24
  {
25
+ interactions: interactions_counts,
25
26
  pacticipants: {
26
27
  count: PactBroker::Domain::Pacticipant.count
27
28
  },
@@ -74,6 +75,22 @@ module PactBroker
74
75
  end
75
76
  # rubocop: enable Metrics/MethodLength
76
77
 
78
+ def interactions_counts
79
+ latest_pact_versions = PactBroker::Pacts::PactVersion.where(
80
+ id: PactBroker::Pacts::PactPublication.overall_latest.from_self.select(:pact_version_id)
81
+ )
82
+ counts = latest_pact_versions
83
+ .select(
84
+ Sequel.function(:sum, :interactions_count).as(:interactions_count),
85
+ Sequel.function(:sum, :messages_count).as(:messages_count)
86
+ ).first
87
+ {
88
+ latestInteractionsCount: counts[:interactions_count] || 0,
89
+ latestMessagesCount: counts[:messages_count] || 0,
90
+ latestInteractionsAndMessagesCount: (counts[:interactions_count] || 0) + (counts[:messages_count] || 0)
91
+ }
92
+ end
93
+
77
94
  def pact_revision_counts
78
95
  query = "select revision_count as number_of_revisions, count(consumer_version_id) as consumer_version_count
79
96
  from (select consumer_version_id, count(*) as revision_count from pact_publications group by consumer_version_id) foo
@@ -17,6 +17,7 @@ module PactBroker
17
17
  associate(:one_to_many, :tags, :class => "PactBroker::Domain::Tag", :reciprocal => :version, :key => :version_id, :primary_key => :consumer_version_id)
18
18
  associate(:many_to_one, :pact_version, :key => :pact_version_id, :primary_key => :id)
19
19
  associate(:many_to_one, :latest_verification, :class => "PactBroker::Verifications::LatestVerificationForPactVersion", key: :pact_version_id, primary_key: :pact_version_id)
20
+ associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id)
20
21
 
21
22
  dataset_module do
22
23
  include PactBroker::Repositories::Helpers
@@ -98,7 +99,8 @@ module PactBroker
98
99
  consumer.id = consumer_id
99
100
  provider = Domain::Pacticipant.new(name: provider_name)
100
101
  provider.id = provider_id
101
- consumer_version = OpenStruct.new(
102
+ consumer_version_struct = OpenStruct.new(
103
+ id: consumer_version_id,
102
104
  number: consumer_version_number,
103
105
  order: consumer_version_order,
104
106
  pacticipant: consumer,
@@ -107,7 +109,7 @@ module PactBroker
107
109
  Domain::Pact.new(
108
110
  id: id,
109
111
  consumer: consumer,
110
- consumer_version: consumer_version,
112
+ consumer_version: consumer_version_struct,
111
113
  provider: provider,
112
114
  consumer_version_number: consumer_version_number,
113
115
  revision_number: revision_number,
@@ -95,11 +95,11 @@ module PactBroker
95
95
  end
96
96
 
97
97
  def messages
98
- pact_hash.is_a?(Hash) ? pact_hash["messages"] : nil
98
+ pact_hash.is_a?(Hash) && pact_hash["messages"].is_a?(Array) ? pact_hash["messages"] : nil
99
99
  end
100
100
 
101
101
  def interactions
102
- pact_hash.is_a?(Hash) ? pact_hash["interactions"] : nil
102
+ pact_hash.is_a?(Hash) && pact_hash["interactions"].is_a?(Array) ? pact_hash["interactions"] : nil
103
103
  end
104
104
 
105
105
  def messages_or_interactions
@@ -5,7 +5,8 @@ module PactBroker
5
5
 
6
6
  MAPPINGS = [
7
7
  [:consumer_version_tags, "cvt"],
8
- [:consumer_version_number, "cvn"],
8
+ [:consumer_version_number, "cvn"], # for old urls
9
+ [:consumer_version_id, "cv"],
9
10
  [:wip, "w"],
10
11
  [:consumer_version_selectors, "s"],
11
12
  [:tag, "t"],
@@ -21,11 +22,11 @@ module PactBroker
21
22
  if selection_parameters[:tag]
22
23
  {
23
24
  "cvt" => [selection_parameters[:tag]],
24
- "cvn" => pact.consumer_version_number
25
+ "cv" => pact.consumer_version.id
25
26
  }
26
27
  else
27
28
  {
28
- "cvn" => pact.consumer_version_number
29
+ "cv" => pact.consumer_version.id
29
30
  }
30
31
  end
31
32
  end
@@ -56,7 +57,7 @@ module PactBroker
56
57
  {
57
58
  "t" => selector.tag,
58
59
  "l" => selector.latest,
59
- "cvn" => selector.consumer_version.number
60
+ "cv" => selector.consumer_version.id
60
61
  }.compact
61
62
  end
62
63
  }
@@ -76,9 +77,14 @@ module PactBroker
76
77
  end
77
78
 
78
79
  def parse_hash(hash)
80
+ require "pact_broker/domain/version" # can't load this before the db models
79
81
  hash.each_with_object({}) do | (key, value), new_hash |
80
82
  long_key = MAPPINGS.find{ |mapping| mapping.last == key }&.first
81
- new_hash[long_key || key] = parse_object(value)
83
+ if long_key == :consumer_version_id
84
+ new_hash[:consumer_version_number] = PactBroker::Domain::Version.find(id: value.to_i)&.number
85
+ else
86
+ new_hash[long_key || key] = parse_object(value)
87
+ end
82
88
  end
83
89
  end
84
90
  end
@@ -23,7 +23,13 @@ module PactBroker
23
23
  associate(:many_to_one, :consumer_version, :class => "PactBroker::Domain::Version", :key => :consumer_version_id, :primary_key => :id)
24
24
  associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id)
25
25
  associate(:many_to_one, :integration, class: "PactBroker::Integrations::Integration", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id])
26
- one_to_one(:latest_verification, class: "PactBroker::Verifications::LatestVerificationForPactVersion", key: :pact_version_id, primary_key: :pact_version_id)
26
+
27
+ one_to_one(:latest_verification, class: "PactBroker::Domain::Verification", key: :pact_version_id, primary_key: :pact_version_id) do | ds |
28
+ ds.unlimited.latest_by_pact_version
29
+ end
30
+
31
+ # TODO rename to consumer_version_tags
32
+ associate(:one_to_many, :tags, :class => "PactBroker::Domain::Tag", :key => :version_id, :primary_key => :consumer_version_id)
27
33
 
28
34
  one_to_many(:head_pact_publications_for_tags,
29
35
  class: PactPublication,
@@ -41,8 +47,8 @@ module PactBroker
41
47
  include PactPublicationWipDatasetModule
42
48
  end
43
49
 
44
- def self.subtract(a, b)
45
- b_ids = b.collect(&:id)
50
+ def self.subtract(a, *b)
51
+ b_ids = b.flat_map{ |pact_publications| pact_publications.collect(&:id) }
46
52
  a.reject{ |pact_publication| b_ids.include?(pact_publication.id) }
47
53
  end
48
54
 
@@ -64,7 +70,7 @@ module PactBroker
64
70
  end
65
71
 
66
72
  def consumer_version_tags
67
- consumer_version.tags
73
+ tags
68
74
  end
69
75
 
70
76
  def latest_verification
@@ -95,7 +101,7 @@ module PactBroker
95
101
  created_at: created_at,
96
102
  head_tag_names: [],
97
103
  db_model: self
98
- )
104
+ )
99
105
  end
100
106
 
101
107
  def to_domain_lightweight
@@ -112,12 +118,23 @@ module PactBroker
112
118
  )
113
119
  end
114
120
 
121
+ # Think we really could just use the version here.
115
122
  def to_version_domain
116
- OpenStruct.new(number: consumer_version.number, pacticipant: consumer, tags: consumer_version.tags, order: consumer_version.order, branch: consumer_version.branch)
123
+ OpenStruct.new(
124
+ id: consumer_version.id,
125
+ number: consumer_version.number,
126
+ pacticipant: consumer,
127
+ tags: consumer_version.tags,
128
+ order: consumer_version.order,
129
+ branch: consumer_version.branch,
130
+ current_deployed_versions: consumer_version.current_deployed_versions,
131
+ current_supported_released_versions: consumer_version.current_supported_released_versions
132
+ )
117
133
  end
118
134
 
119
135
  def to_version_domain_lightweight
120
136
  OpenStruct.new(
137
+ id: consumer_version.id,
121
138
  number: consumer_version.number,
122
139
  pacticipant: consumer,
123
140
  order: consumer_version.order,
@@ -127,6 +144,24 @@ module PactBroker
127
144
  )
128
145
  end
129
146
 
147
+ def to_domain_with_content
148
+ to_domain
149
+ end
150
+
151
+ def to_head_pact
152
+ HeadPact.new(to_domain, consumer_version.number, values[:tag_name])
153
+ end
154
+
155
+ def pact_version_sha
156
+ pact_version.sha
157
+ end
158
+
159
+ def <=> other
160
+ self_fields = [consumer.name.downcase, provider.name.downcase, consumer_version_order || 0]
161
+ other_fields = [other.consumer.name.downcase, other.provider.name.downcase, other.consumer_version_order || 0]
162
+ self_fields <=> other_fields
163
+ end
164
+
130
165
  private
131
166
 
132
167
  def cached_domain_for_delegation