pact_broker 2.81.0 → 2.82.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +1 -1
  3. data/CHANGELOG.md +30 -0
  4. data/DEVELOPER_SETUP.md +1 -1
  5. data/README.md +7 -5
  6. data/config.ru +3 -28
  7. data/db/migrations/20210722_add_index_to_triggered_webhooks_webhook_uuid.rb +7 -0
  8. data/db/migrations/20210810_set_allow_contract_modification.rb +17 -0
  9. data/docs/CONFIGURATION.md +398 -0
  10. data/docs/configuration.yml +320 -0
  11. data/example/Gemfile +4 -4
  12. data/example/README.md +15 -22
  13. data/example/config.ru +1 -24
  14. data/example/config/pact_broker.yml +9 -0
  15. data/example/config/puma.rb +3 -0
  16. data/lib/db.rb +1 -1
  17. data/lib/pact_broker/api/authorization/resource_access_policy.rb +68 -0
  18. data/lib/pact_broker/api/authorization/resource_access_rules.rb +40 -0
  19. data/lib/pact_broker/api/decorators/deployed_version_decorator.rb +2 -0
  20. data/lib/pact_broker/api/decorators/released_version_decorator.rb +2 -0
  21. data/lib/pact_broker/api/middleware/basic_auth.rb +63 -0
  22. data/lib/pact_broker/api/resources/pact.rb +15 -6
  23. data/lib/pact_broker/api/resources/tag.rb +1 -14
  24. data/lib/pact_broker/app.rb +52 -30
  25. data/lib/pact_broker/config/basic_auth_configuration.rb +38 -0
  26. data/lib/pact_broker/config/load.rb +21 -10
  27. data/lib/pact_broker/config/runtime_configuration.rb +188 -0
  28. data/lib/pact_broker/config/runtime_configuration_coercion_methods.rb +41 -0
  29. data/lib/pact_broker/config/runtime_configuration_database_methods.rb +119 -0
  30. data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +61 -0
  31. data/lib/pact_broker/configuration.rb +67 -131
  32. data/lib/pact_broker/contracts/notice.rb +4 -0
  33. data/lib/pact_broker/contracts/service.rb +4 -4
  34. data/lib/pact_broker/db/models.rb +3 -0
  35. data/lib/pact_broker/db/validate_encoding.rb +0 -4
  36. data/lib/pact_broker/deployments/deployed_version.rb +8 -2
  37. data/lib/pact_broker/deployments/deployed_version_service.rb +13 -6
  38. data/lib/pact_broker/deployments/environment.rb +1 -1
  39. data/lib/pact_broker/deployments/released_version.rb +8 -0
  40. data/lib/pact_broker/deployments/released_version_service.rb +12 -0
  41. data/lib/pact_broker/doc/views/provider-pacts-for-verification.markdown +4 -0
  42. data/lib/pact_broker/domain/pacticipant.rb +17 -13
  43. data/lib/pact_broker/domain/verification.rb +4 -22
  44. data/lib/pact_broker/domain/version.rb +9 -5
  45. data/lib/pact_broker/domain/webhook.rb +4 -0
  46. data/lib/pact_broker/error.rb +1 -0
  47. data/lib/pact_broker/errors.rb +1 -1
  48. data/lib/pact_broker/feature_toggle.rb +3 -5
  49. data/lib/pact_broker/hash_refinements.rb +0 -1
  50. data/lib/pact_broker/index/service.rb +4 -6
  51. data/lib/pact_broker/initializers/database_connection.rb +80 -0
  52. data/lib/pact_broker/integrations/integration.rb +5 -0
  53. data/lib/pact_broker/integrations/service.rb +4 -2
  54. data/lib/pact_broker/locale/en.yml +1 -0
  55. data/lib/pact_broker/logging.rb +2 -1
  56. data/lib/pact_broker/matrix/integration.rb +1 -1
  57. data/lib/pact_broker/matrix/parse_can_i_deploy_query.rb +2 -2
  58. data/lib/pact_broker/matrix/quick_row.rb +10 -0
  59. data/lib/pact_broker/matrix/repository.rb +64 -3
  60. data/lib/pact_broker/metrics/service.rb +16 -13
  61. data/lib/pact_broker/pacticipants/repository.rb +4 -0
  62. data/lib/pact_broker/pacticipants/service.rb +9 -1
  63. data/lib/pact_broker/pacts/pact_publication.rb +10 -13
  64. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +6 -1
  65. data/lib/pact_broker/pacts/pact_publication_selector_dataset_module.rb +1 -2
  66. data/lib/pact_broker/pacts/pact_version.rb +25 -11
  67. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +54 -77
  68. data/lib/pact_broker/pacts/selected_pact.rb +1 -1
  69. data/lib/pact_broker/pacts/selector.rb +15 -2
  70. data/lib/pact_broker/pacts/selectors.rb +4 -0
  71. data/lib/pact_broker/pacts/service.rb +4 -0
  72. data/lib/pact_broker/repositories/scopes.rb +12 -1
  73. data/lib/pact_broker/string_refinements.rb +6 -0
  74. data/lib/pact_broker/tags/service.rb +8 -1
  75. data/lib/pact_broker/test/http_test_data_builder.rb +11 -5
  76. data/lib/pact_broker/ui/views/index/_css_and_js.haml +11 -9
  77. data/lib/pact_broker/ui/views/index/_pagination.haml +3 -1
  78. data/lib/pact_broker/ui/views/layouts/main.haml +5 -3
  79. data/lib/pact_broker/ui/views/matrix/show.haml +10 -8
  80. data/lib/pact_broker/verifications/required_verification.rb +28 -0
  81. data/lib/pact_broker/verifications/service.rb +49 -1
  82. data/lib/pact_broker/version.rb +1 -1
  83. data/lib/pact_broker/versions/repository.rb +15 -0
  84. data/lib/pact_broker/versions/service.rb +32 -2
  85. data/lib/pact_broker/webhooks/event_listener.rb +3 -0
  86. data/lib/pact_broker/webhooks/trigger_service.rb +30 -14
  87. data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
  88. data/lib/pact_broker/webhooks/webhook.rb +2 -2
  89. data/lib/pact_broker/webhooks/webhook_event.rb +6 -1
  90. data/lib/semantic_logger/formatters/short.rb +29 -0
  91. data/pact_broker.gemspec +1 -0
  92. data/script/data/auto-create-things-for-tags.rb +19 -0
  93. data/script/data/contract-published-requiring-verification.rb +27 -0
  94. data/script/{reproduce-issue-expand-currently-deployed.rb → data/expand-currently-deployed.rb} +0 -0
  95. data/script/docs/generate-configuration-docs.rb +86 -0
  96. data/spec/features/get_latest_pact_badge_spec.rb +1 -0
  97. data/spec/features/get_matrix_badge_spec.rb +1 -0
  98. data/spec/features/publish_pact_spec.rb +21 -7
  99. data/spec/features/wip_pacts_spec.rb +1 -1
  100. data/spec/fixtures/approvals/matrix_integration_environment_spec.approved.json +62 -0
  101. data/spec/fixtures/approvals/matrix_integration_ignore_spec.approved.json +124 -0
  102. data/spec/fixtures/approvals/matrix_integration_spec.approved.json +173 -0
  103. data/spec/fixtures/approvals/publish_contract_no_branch.approved.json +9 -9
  104. data/spec/fixtures/approvals/publish_contract_nothing_exists.approved.json +7 -7
  105. data/spec/fixtures/approvals/publish_contract_nothing_exists_with_webhook.approved.json +5 -5
  106. data/spec/fixtures/approvals/publish_contract_verification_already_exists.approved.json +5 -5
  107. data/spec/lib/pact_broker/api/middleware/basic_auth_spec.rb +312 -0
  108. data/spec/lib/pact_broker/api/resources/tag_spec.rb +14 -39
  109. data/spec/lib/pact_broker/app_basic_auth_spec.rb +122 -0
  110. data/spec/lib/pact_broker/config/load_spec.rb +33 -6
  111. data/spec/lib/pact_broker/config/runtime_configuration_logging_methods_spec.rb +22 -0
  112. data/spec/lib/pact_broker/config/runtime_configuration_spec.rb +71 -0
  113. data/spec/lib/pact_broker/configuration_spec.rb +51 -25
  114. data/spec/lib/pact_broker/errors/error_logger_spec.rb +3 -0
  115. data/spec/lib/pact_broker/feature_toggle_spec.rb +18 -19
  116. data/spec/lib/pact_broker/matrix/integration_environment_spec.rb +12 -0
  117. data/spec/lib/pact_broker/matrix/integration_ignore_spec.rb +15 -3
  118. data/spec/lib/pact_broker/matrix/integration_spec.rb +47 -6
  119. data/spec/lib/pact_broker/matrix/parse_can_i_deploy_query_spec.rb +16 -1
  120. data/spec/lib/pact_broker/matrix/repository_dependency_spec.rb +0 -2
  121. data/spec/lib/pact_broker/matrix/repository_spec.rb +0 -2
  122. data/spec/lib/pact_broker/metrics/service_spec.rb +44 -0
  123. data/spec/lib/pact_broker/pacticipants/service_spec.rb +28 -5
  124. data/spec/lib/pact_broker/pacts/pact_publication_selector_dataset_module_spec.rb +25 -0
  125. data/spec/lib/pact_broker/pacts/pact_version_spec.rb +30 -1
  126. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +107 -20
  127. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +1 -1
  128. data/spec/lib/pact_broker/tags/service_spec.rb +24 -8
  129. data/spec/lib/pact_broker/verifications/service_spec.rb +146 -0
  130. data/spec/lib/pact_broker/versions/repository_spec.rb +38 -2
  131. data/spec/lib/pact_broker/versions/service_spec.rb +93 -2
  132. data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +54 -2
  133. data/spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb +3 -3
  134. data/spec/spec_helper.rb +2 -1
  135. data/spec/support/approvals.rb +29 -0
  136. metadata +52 -13
  137. data/example/basic_auth/Gemfile +0 -5
  138. data/example/basic_auth/Procfile +0 -1
  139. data/example/basic_auth/README.md +0 -43
  140. data/example/basic_auth/config.ru +0 -19
  141. data/example/example_data.sql +0 -19
  142. data/spec/lib/pact_broker/config/save_and_load_spec.rb +0 -25
  143. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +0 -50
@@ -1,3 +1,4 @@
1
+ require "pact_broker/logging"
1
2
  require "pact_broker/repositories/helpers"
2
3
  require "pact_broker/matrix/row"
3
4
  require "pact_broker/matrix/quick_row"
@@ -20,6 +21,7 @@ module PactBroker
20
21
  class Repository
21
22
  include PactBroker::Repositories::Helpers
22
23
  include PactBroker::Repositories
24
+ include PactBroker::Logging
23
25
 
24
26
  # TODO move latest verification logic in to database
25
27
 
@@ -59,7 +61,7 @@ module PactBroker
59
61
  def find specified_selectors, options = {}
60
62
  resolved_ignore_selectors = resolve_ignore_selectors(options)
61
63
  resolved_specified_selectors = resolve_versions_and_add_ids(specified_selectors, :specified, resolved_ignore_selectors)
62
- integrations = find_integrations_for_specified_selectors(resolved_specified_selectors, infer_selectors_for_integrations?(options))
64
+ integrations = find_integrations_for_specified_selectors(resolved_specified_selectors, options)
63
65
  resolved_selectors = add_any_inferred_selectors(resolved_specified_selectors, resolved_ignore_selectors, integrations, options)
64
66
  considered_rows, ignored_rows = find_considered_and_ignored_rows(resolved_selectors, resolved_ignore_selectors, options)
65
67
  QueryResults.new(considered_rows.sort, ignored_rows.sort, specified_selectors, options, resolved_selectors, resolved_ignore_selectors, integrations)
@@ -81,10 +83,18 @@ module PactBroker
81
83
  return considered_rows, ignored_rows
82
84
  end
83
85
 
84
- def find_integrations_for_specified_selectors(resolved_specified_selectors, infer_integrations)
86
+ def find_integrations_for_specified_selectors(resolved_specified_selectors, options)
87
+ if infer_selectors_for_integrations?(options)
88
+ find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors, options)
89
+ else
90
+ find_integrations_for_specified_selectors_only(resolved_specified_selectors)
91
+ end
92
+ end
93
+
94
+ def find_integrations_for_specified_selectors_only(resolved_specified_selectors)
85
95
  specified_pacticipant_names = resolved_specified_selectors.collect(&:pacticipant_name)
86
96
  base_model_for_integrations
87
- .distinct_integrations(resolved_specified_selectors, infer_integrations)
97
+ .distinct_integrations(resolved_specified_selectors, false)
88
98
  .collect(&:to_hash)
89
99
  .collect do | integration_hash |
90
100
  required = is_a_row_for_this_integration_required?(specified_pacticipant_names, integration_hash[:consumer_name])
@@ -92,6 +102,57 @@ module PactBroker
92
102
  end
93
103
  end
94
104
 
105
+ def find_integrations_for_specified_selectors_with_inferred_integrations(resolved_specified_selectors, options)
106
+ integrations = integrations_where_specified_selector_is_consumer(resolved_specified_selectors) +
107
+ integrations_where_specified_selector_is_provider(resolved_specified_selectors, options)
108
+ deduplicate_integrations(integrations)
109
+ end
110
+
111
+ def integrations_where_specified_selector_is_consumer(resolved_specified_selectors)
112
+ resolved_specified_selectors.flat_map do | selector |
113
+ base_model_for_integrations
114
+ .distinct_integrations_for_selector_as_consumer(selector)
115
+ .all
116
+ .collect do | integration |
117
+ Integration.from_hash(
118
+ consumer_id: integration[:consumer_id],
119
+ consumer_name: integration[:consumer_name],
120
+ provider_id: integration[:provider_id],
121
+ provider_name: integration[:provider_name],
122
+ required: true
123
+ )
124
+ end
125
+ end
126
+ end
127
+
128
+ def integrations_where_specified_selector_is_provider(resolved_specified_selectors, options)
129
+ integrations_involving_specified_providers = PactBroker::Integrations::Integration
130
+ .where(provider_id: resolved_specified_selectors.collect(&:pacticipant_id))
131
+ .eager(:consumer)
132
+ .all
133
+
134
+ destination_selector = PactBroker::Matrix::UnresolvedSelector.new(options.slice(:latest, :tag, :branch, :environment_name).compact)
135
+
136
+ integrations_involving_specified_providers.collect do | integration |
137
+ required = PactBroker::Domain::Version.where(pacticipant: integration.consumer).for_selector(destination_selector).any?
138
+
139
+ Integration.from_hash(
140
+ consumer_id: integration.consumer.id,
141
+ consumer_name: integration.consumer.name,
142
+ provider_id: integration.provider.id,
143
+ provider_name: integration.provider.name,
144
+ required: required
145
+ )
146
+ end
147
+ end
148
+
149
+ def deduplicate_integrations(integrations)
150
+ integrations
151
+ .group_by{ | integration| [integration.consumer_id, integration.provider_id] }
152
+ .values
153
+ .collect { | duplicate_integrations | duplicate_integrations.find(&:required?) || duplicate_integrations.first }
154
+ end
155
+
95
156
  def add_any_inferred_selectors(resolved_specified_selectors, resolved_ignore_selectors, integrations, options)
96
157
  if infer_selectors_for_integrations?(options)
97
158
  resolved_specified_selectors + inferred_selectors(resolved_specified_selectors, resolved_ignore_selectors, integrations, options)
@@ -1,16 +1,6 @@
1
1
  require "pact_broker/configuration"
2
- require "pact_broker/pacts/pact_publication"
3
- require "pact_broker/pacts/pact_version"
4
- require "pact_broker/domain/pacticipant"
5
- require "pact_broker/integrations/integration"
6
- require "pact_broker/domain/verification"
7
- require "pact_broker/domain/version"
2
+ require "pact_broker/db/models"
8
3
  require "pact_broker/api/decorators/format_date_time"
9
- require "pact_broker/webhooks/webhook"
10
- require "pact_broker/webhooks/triggered_webhook"
11
- require "pact_broker/webhooks/execution"
12
- require "pact_broker/matrix/row"
13
- require "pact_broker/matrix/head_row"
14
4
 
15
5
  module PactBroker
16
6
  module Metrics
@@ -24,7 +14,8 @@ module PactBroker
24
14
  {
25
15
  interactions: interactions_counts,
26
16
  pacticipants: {
27
- count: PactBroker::Domain::Pacticipant.count
17
+ count: PactBroker::Domain::Pacticipant.count,
18
+ withMainBranchSetCount: PactBroker::Domain::Pacticipant.with_main_branch_set.count
28
19
  },
29
20
  integrations: {
30
21
  count: PactBroker::Integrations::Integration.count
@@ -52,7 +43,8 @@ module PactBroker
52
43
  distribution: verification_distribution
53
44
  },
54
45
  pacticipantVersions: {
55
- count: PactBroker::Domain::Version.count
46
+ count: PactBroker::Domain::Version.count,
47
+ withBranchSetCount: PactBroker::Domain::Version.with_branch_set.count
56
48
  },
57
49
  webhooks: {
58
50
  count: PactBroker::Webhooks::Webhook.count
@@ -70,6 +62,17 @@ module PactBroker
70
62
  },
71
63
  matrix: {
72
64
  count: matrix_count
65
+ },
66
+ environments: {
67
+ count: PactBroker::Deployments::Environment.count
68
+ },
69
+ deployedVersions: {
70
+ count: PactBroker::Deployments::DeployedVersion.count,
71
+ currentlyDeployedCount: PactBroker::Deployments::DeployedVersion.currently_deployed.count
72
+ },
73
+ releasedVersions: {
74
+ count: PactBroker::Deployments::ReleasedVersion.count,
75
+ currentlySupportedCount: PactBroker::Deployments::ReleasedVersion.currently_supported.count
73
76
  }
74
77
  }
75
78
  end
@@ -99,6 +99,10 @@ module PactBroker
99
99
  string_match_query = Sequel.|( *terms.map { |term| Sequel.ilike(Sequel[:pacticipants][:name], "%#{term}%") })
100
100
  PactBroker::Domain::Pacticipant.where(string_match_query)
101
101
  end
102
+
103
+ def set_main_branch(pacticipant, main_branch)
104
+ pacticipant.update(main_branch: main_branch)
105
+ end
102
106
  end
103
107
  end
104
108
  end
@@ -4,7 +4,6 @@ require "pact_broker/messages"
4
4
  require "pact_broker/pacticipants/find_potential_duplicate_pacticipant_names"
5
5
 
6
6
  module PactBroker
7
-
8
7
  module Pacticipants
9
8
  class Service
10
9
 
@@ -90,6 +89,15 @@ module PactBroker
90
89
  def self.pacticipant_names
91
90
  pacticipant_repository.pacticipant_names
92
91
  end
92
+
93
+ def self.maybe_set_main_branch(pacticipant, potential_main_branch)
94
+ if pacticipant.main_branch.nil? && PactBroker.configuration.auto_detect_main_branch && PactBroker.configuration.main_branch_candidates.include?(potential_main_branch)
95
+ logger.info "Setting #{pacticipant.name} main_branch to '#{potential_main_branch}' (because the #{pacticipant.name} main_branch was nil and auto_detect_main_branch=true)"
96
+ pacticipant_repository.set_main_branch(pacticipant, potential_main_branch)
97
+ else
98
+ pacticipant
99
+ end
100
+ end
93
101
  end
94
102
  end
95
103
  end
@@ -24,10 +24,6 @@ module PactBroker
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
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
27
  # TODO rename to consumer_version_tags
32
28
  associate(:one_to_many, :tags, :class => "PactBroker::Domain::Tag", :key => :version_id, :primary_key => :consumer_version_id)
33
29
 
@@ -173,13 +169,14 @@ end
173
169
 
174
170
  # Table: pact_publications
175
171
  # Columns:
176
- # id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
177
- # consumer_version_id | integer | NOT NULL
178
- # provider_id | integer | NOT NULL
179
- # revision_number | integer | NOT NULL
180
- # pact_version_id | integer | NOT NULL
181
- # created_at | timestamp without time zone | NOT NULL
182
- # consumer_id | integer |
172
+ # id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
173
+ # consumer_version_id | integer | NOT NULL
174
+ # provider_id | integer | NOT NULL
175
+ # revision_number | integer | NOT NULL
176
+ # pact_version_id | integer | NOT NULL
177
+ # created_at | timestamp without time zone | NOT NULL
178
+ # consumer_id | integer |
179
+ # consumer_version_order | integer |
183
180
  # Indexes:
184
181
  # pact_publications_pkey | PRIMARY KEY btree (id)
185
182
  # cv_prov_revision_unq | UNIQUE btree (consumer_version_id, provider_id, revision_number)
@@ -191,6 +188,6 @@ end
191
188
  # pact_publications_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id)
192
189
  # pact_publications_provider_id_fkey | (provider_id) REFERENCES pacticipants(id)
193
190
  # Referenced By:
194
- # webhook_executions | webhook_executions_pact_publication_id_fkey | (pact_publication_id) REFERENCES pact_publications(id)
195
- # triggered_webhooks | triggered_webhooks_pact_publication_id_fkey | (pact_publication_id) REFERENCES pact_publications(id)
196
191
  # latest_pact_publication_ids_for_consumer_versions | latest_pact_publication_ids_for_consum_pact_publication_id_fkey | (pact_publication_id) REFERENCES pact_publications(id) ON DELETE CASCADE
192
+ # triggered_webhooks | triggered_webhooks_pact_publication_id_fkey | (pact_publication_id) REFERENCES pact_publications(id)
193
+ # webhook_executions | webhook_executions_pact_publication_id_fkey | (pact_publication_id) REFERENCES pact_publications(id)
@@ -26,7 +26,12 @@ module PactBroker
26
26
  end
27
27
 
28
28
  def for_consumer_version_tag tag_name
29
- join(:tags, { version_id: :consumer_version_id, Sequel[:tags][:name] => tag_name })
29
+ base_query = self
30
+ if no_columns_selected?
31
+ base_query = base_query.select_all_qualified.select_append(Sequel[:tags][:name].as(:tag_name))
32
+ end
33
+
34
+ base_query.join(:tags, { version_id: :consumer_version_id, Sequel[:tags][:name] => tag_name })
30
35
  end
31
36
 
32
37
  def for_consumer_name_and_maybe_version_number(consumer_name, consumer_version_number)
@@ -3,17 +3,16 @@ module PactBroker
3
3
  module PactPublicationSelectorDatasetModule
4
4
  # rubocop: disable Metrics/CyclomaticComplexity
5
5
  def for_provider_and_consumer_version_selector provider, selector
6
- # Does not yet support "all pacts for specified tag" - that code is still in the Pact::Repository
7
6
  query = for_provider(provider)
8
7
  query = query.for_consumer(PactBroker::Domain::Pacticipant.find_by_name(selector.consumer)) if selector.consumer
9
8
  query = query.for_currently_deployed_versions(selector.environment_name) if selector.currently_deployed?
10
9
  query = query.for_currently_supported_versions(selector.environment_name) if selector.currently_supported?
10
+ query = query.for_consumer_version_tag(selector.tag) if selector.all_for_tag?
11
11
 
12
12
  if selector.environment_name && !selector.currently_deployed? && !selector.currently_supported?
13
13
  query = query.for_environment(selector.environment_name)
14
14
  end
15
15
 
16
-
17
16
  # Do the "latest" logic last so that the provider/consumer criteria get included in the "latest" query before the join, rather than after
18
17
  query = query.latest_for_main_branches if selector.latest_for_main_branch?
19
18
  query = query.latest_for_consumer_branch(selector.branch) if selector.latest_for_branch?
@@ -14,9 +14,13 @@ module PactBroker
14
14
  associate(:many_to_one, :consumer, class: "PactBroker::Domain::Pacticipant", key: :consumer_id, primary_key: :id)
15
15
  associate(:many_to_many, :consumer_versions, class: "PactBroker::Domain::Version", join_table: :pact_publications, left_key: :pact_version_id, right_key: :consumer_version_id, order: :order)
16
16
 
17
- one_to_one(:latest_verification, class: "PactBroker::Domain::Verification", key: :pact_version_id, primary_key: :id) do | ds |
18
- ds.unlimited.latest_by_pact_version
19
- end
17
+ one_to_one(:latest_verification,
18
+ class: "PactBroker::Domain::Verification",
19
+ read_only: true,
20
+ dataset: lambda { PactBroker::Domain::Verification.where(id: PactBroker::Domain::Verification.select(Sequel.function(:max, :id)).where(pact_version_id: id)) },
21
+ key: :pact_version_id, primary_key: :id,
22
+ eager_block: lambda { | ds | ds.latest_by_pact_version }
23
+ )
20
24
 
21
25
  # do not eager load this - it won't work because of the limit(1)
22
26
  one_through_one(:latest_consumer_version, class: "PactBroker::Domain::Version", join_table: :pact_publications, left_key: :pact_version_id, right_key: :consumer_version_id) do | ds |
@@ -26,6 +30,14 @@ module PactBroker
26
30
  dataset_module do
27
31
  include PactBroker::Repositories::Helpers
28
32
 
33
+ def for_pact_domain(pact_domain)
34
+ where(
35
+ sha: pact_domain.pact_version_sha,
36
+ consumer_id: pact_domain.consumer.id,
37
+ provider_id: pact_domain.provider.id
38
+ ).single_record
39
+ end
40
+
29
41
  def join_successful_verifications
30
42
  verifications_join = {
31
43
  Sequel[:verifications][:pact_version_id] => Sequel[:pact_versions][:id],
@@ -118,12 +130,14 @@ end
118
130
 
119
131
  # Table: pact_versions
120
132
  # Columns:
121
- # id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
122
- # consumer_id | integer | NOT NULL
123
- # provider_id | integer | NOT NULL
124
- # sha | text | NOT NULL
125
- # content | text |
126
- # created_at | timestamp without time zone | NOT NULL
133
+ # id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
134
+ # consumer_id | integer | NOT NULL
135
+ # provider_id | integer | NOT NULL
136
+ # sha | text | NOT NULL
137
+ # content | text |
138
+ # created_at | timestamp without time zone | NOT NULL
139
+ # messages_count | integer |
140
+ # interactions_count | integer |
127
141
  # Indexes:
128
142
  # pact_versions_pkey | PRIMARY KEY btree (id)
129
143
  # unq_pvc_con_prov_sha | UNIQUE btree (consumer_id, provider_id, sha)
@@ -131,7 +145,7 @@ end
131
145
  # pact_versions_consumer_id_fkey | (consumer_id) REFERENCES pacticipants(id)
132
146
  # pact_versions_provider_id_fkey | (provider_id) REFERENCES pacticipants(id)
133
147
  # Referenced By:
134
- # pact_publications | pact_publications_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id)
135
- # verifications | verifications_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id)
136
148
  # latest_pact_publication_ids_for_consumer_versions | latest_pact_publication_ids_for_consumer_v_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id) ON DELETE CASCADE
137
149
  # latest_verification_id_for_pact_version_and_provider_version | latest_v_id_for_pv_and_pv_pact_version_id_fk | (pact_version_id) REFERENCES pact_versions(id) ON DELETE CASCADE
150
+ # pact_publications | pact_publications_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id)
151
+ # verifications | verifications_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id)
@@ -20,8 +20,7 @@ module PactBroker
20
20
  include PactBroker::Repositories::Scopes
21
21
 
22
22
  def find(provider_name, consumer_version_selectors)
23
- selected_pacts = find_pacts_by_selector(provider_name, consumer_version_selectors) +
24
- find_pacts_for_which_all_versions_for_the_tag_are_required(provider_name, consumer_version_selectors)
23
+ selected_pacts = find_pacts_by_selector(provider_name, consumer_version_selectors)
25
24
  selected_pacts = selected_pacts + find_pacts_for_fallback_tags(selected_pacts, provider_name, consumer_version_selectors)
26
25
  merge_selected_pacts(selected_pacts)
27
26
  end
@@ -100,38 +99,58 @@ module PactBroker
100
99
  end
101
100
  end
102
101
 
103
- # rubocop: disable Metrics/CyclomaticComplexity
104
102
  def find_pacts_by_selector(provider_name, consumer_version_selectors)
105
103
  provider = pacticipant_repository.find_by_name(provider_name)
106
104
 
107
- selectors = if consumer_version_selectors.empty?
108
- Selectors.create_for_overall_latest
109
- else
110
- consumer_version_selectors.select(&:latest_for_tag?) +
111
- consumer_version_selectors.select(&:latest_for_branch?) +
112
- consumer_version_selectors.select(&:latest_for_main_branch?) +
113
- consumer_version_selectors.select(&:overall_latest?) +
114
- consumer_version_selectors.select(&:currently_deployed?) +
115
- consumer_version_selectors.select(&:currently_supported?)
116
- end
117
-
118
- selectors.flat_map do | selector |
105
+ specified_selectors_or_defaults(consumer_version_selectors, provider).flat_map do | selector |
119
106
  query = scope_for(PactPublication).for_provider_and_consumer_version_selector(provider, selector)
120
107
  query.all.collect do | pact_publication |
121
- resolved_selector = if selector.currently_deployed? || selector.currently_supported?
122
- environment = environment_service.find_by_name(pact_publication.values.fetch(:environment_name))
123
- selector.resolve_for_environment(pact_publication.consumer_version, environment, pact_publication.values[:target])
124
- else
125
- selector.resolve(pact_publication.consumer_version)
126
- end
127
- SelectedPact.new(
128
- pact_publication.to_domain,
129
- Selectors.new(resolved_selector)
130
- )
108
+ create_selected_pact(pact_publication, selector)
109
+ end
110
+ end
111
+ end
112
+
113
+ def create_selected_pact(pact_publication, selector)
114
+ resolved_selector = if selector.currently_deployed? || selector.currently_supported?
115
+ environment = environment_service.find_by_name(pact_publication.values.fetch(:environment_name))
116
+ selector.resolve_for_environment(pact_publication.consumer_version, environment, pact_publication.values[:target])
117
+ else
118
+ selector.resolve(pact_publication.consumer_version)
119
+ end
120
+ SelectedPact.new(pact_publication.to_domain, Selectors.new(resolved_selector))
121
+ end
122
+
123
+ def specified_selectors_or_defaults(consumer_version_selectors, provider)
124
+ if consumer_version_selectors.empty?
125
+ default_selectors(provider)
126
+ else
127
+ consumer_version_selectors
128
+ end
129
+ end
130
+
131
+ def default_selectors(provider)
132
+ selectors = selector_for_latest_main_version_or_overall_latest(provider)
133
+ selectors << Selector.for_currently_deployed
134
+ selectors << Selector.for_currently_supported
135
+ selectors
136
+ end
137
+
138
+ def selector_for_latest_main_version_or_overall_latest(provider)
139
+ selectors = Selectors.new
140
+ consumers = integration_service.find_for_provider(provider).collect(&:consumer)
141
+
142
+ consumers.collect do | consumer |
143
+ if consumer.main_branch && PactBroker::Domain::Version.for_selector(PactBroker::Matrix::UnresolvedSelector.new(branch: consumer.main_branch, latest: true)).any?
144
+ selectors << Selector.for_main_branch.for_consumer(consumer.name)
145
+ elsif consumer.main_branch && PactBroker::Domain::Version.for_selector(PactBroker::Matrix::UnresolvedSelector.new(tag: consumer.main_branch, latest: true)).any?
146
+ selectors << Selector.latest_for_tag(consumer.main_branch).for_consumer(consumer.name)
147
+ else
148
+ selectors << Selector.overall_latest.for_consumer(consumer.name)
131
149
  end
132
150
  end
151
+
152
+ selectors
133
153
  end
134
- # rubocop: enable Metrics/CyclomaticComplexity
135
154
 
136
155
  def find_pacts_for_which_the_latest_version_for_the_fallback_tag_is_required(provider_name, selectors)
137
156
  selectors.collect do | selector |
@@ -148,17 +167,6 @@ module PactBroker
148
167
  end.flatten
149
168
  end
150
169
 
151
-
152
- def find_pacts_for_which_all_versions_for_the_tag_are_required(provider_name, consumer_version_selectors)
153
- # The tags for which all versions are specified
154
- # Need to move support for this into PactPublication.for_provider_and_consumer_version_selector
155
- selectors = consumer_version_selectors.select(&:all_for_tag?)
156
-
157
- selectors.flat_map do | selector |
158
- find_all_pact_versions_for_provider_with_consumer_version_tags(provider_name, selector)
159
- end
160
- end
161
-
162
170
  def find_provider_tags_for_which_pact_publication_id_is_pending(pact_publication, successfully_verified_head_pact_publication_ids_for_each_provider_tag)
163
171
  successfully_verified_head_pact_publication_ids_for_each_provider_tag
164
172
  .select do | _, pact_publication_ids |
@@ -184,17 +192,6 @@ module PactBroker
184
192
  .sort
185
193
  end
186
194
 
187
- # Tag object with created_at date for the first time that tag was created
188
- def provider_tag_objects_for(provider, provider_tags_names)
189
- PactBroker::Domain::Tag
190
- .select_group(Sequel[:tags][:name], Sequel[:pacticipant_id])
191
- .select_append(Sequel.function(:min, Sequel[:tags][:created_at]).as(:created_at))
192
- .distinct
193
- .where(pacticipant_id: provider.id)
194
- .where(name: provider_tags_names)
195
- .all
196
- end
197
-
198
195
  # TODO ? find the WIP pacts by consumer branch
199
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)
200
197
  potential_wip_pacts_by_consumer_tag_query = PactPublication.for_provider(provider).created_after(wip_start_date).send(pact_publication_scope)
@@ -262,33 +259,6 @@ module PactBroker
262
259
  deduplicate_verifiable_pacts(verifiable_pacts).sort
263
260
  end
264
261
 
265
- def find_all_pact_versions_for_provider_with_consumer_version_tags provider_name, selector
266
- provider = pacticipant_repository.find_by_name(provider_name)
267
- consumer = selector.consumer ? pacticipant_repository.find_by_name(selector.consumer) : nil
268
-
269
- scope_for(PactPublication)
270
- .select_all_qualified
271
- .select_append(Sequel[:cv][:order].as(:consumer_version_order))
272
- .select_append(Sequel[:ct][:name].as(:consumer_version_tag_name))
273
- .remove_overridden_revisions
274
- .join_consumer_versions(:cv)
275
- .join_consumer_version_tags_with_names(selector.tag)
276
- .where(provider: provider)
277
- .where_consumer_if_set(consumer)
278
- .eager(:consumer)
279
- .eager(:consumer_version)
280
- .eager(:provider)
281
- .eager(:pact_version)
282
- .all
283
- .group_by(&:pact_version_id)
284
- .values
285
- .collect do | pact_publications |
286
- latest_pact_publication = pact_publications.sort_by{ |p| p.values.fetch(:consumer_version_order) }.last
287
- SelectedPact.new(latest_pact_publication.to_domain, Selectors.new(selector).resolve(latest_pact_publication.consumer_version))
288
- end
289
- end
290
-
291
-
292
262
  def remove_non_wip_for_branch(pact_publications_query, provider, provider_version_branch, specified_pact_version_shas)
293
263
  specified_explicitly = pact_publications_query.for_pact_version_sha(specified_pact_version_shas)
294
264
  verified_by_this_branch = pact_publications_query.successfully_verified_by_provider_branch_when_not_wip(provider.id, provider_version_branch)
@@ -319,8 +289,15 @@ module PactBroker
319
289
 
320
290
  def collect_consumer_name_and_version_number(pact_publications_query)
321
291
  pact_publications_query.eager(:provider).eager(:consumer).eager(:consumer_version).order(:consumer_version_order).all.sort.collect do |p|
322
- tag_suffix = p.values[:tag_name] ? " (tag #{p.values[:tag_name]})" : ""
323
- "#{p.consumer_name} #{p.consumer_version_number}" + tag_suffix
292
+ suffix = if p.values[:tag_name]
293
+ " (tag #{p.values[:tag_name]})"
294
+ elsif p.values[:branch]
295
+ " (branch #{p.values[:branch]})"
296
+ else
297
+ ""
298
+ end
299
+
300
+ "#{p.consumer_name} #{p.consumer_version_number}" + suffix
324
301
  end
325
302
  end
326
303