pact_broker 2.76.2 → 2.79.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +12 -0
  3. data/.github/workflows/release_gem.yml +1 -0
  4. data/.github/workflows/test-ruby-3.yml +19 -0
  5. data/.github/workflows/test.yml +16 -7
  6. data/.gitignore +3 -1
  7. data/CHANGELOG.md +53 -0
  8. data/DEVELOPER_DOCUMENTATION.md +13 -0
  9. data/DEVELOPER_SETUP.md +62 -3
  10. data/Dockerfile +1 -0
  11. data/ISSUES.md +7 -7
  12. data/config.ru +2 -1
  13. data/db/ddl_statements/head_pact_tags.rb +24 -1
  14. data/db/ddl_statements/latest_tagged_pact_consumer_version_orders.rb +11 -0
  15. data/db/ddl_statements/latest_tagged_pact_publications.rb +6 -0
  16. data/db/ddl_statements/latest_verification_ids_for_consumer_version_tags.rb +13 -0
  17. data/db/migrations/20210117_add_branch_to_version.rb +9 -0
  18. data/db/migrations/20210202_add_created_at_to_head_pact_tags.rb +14 -0
  19. data/db/migrations/20210205_add_pacticipant_id_to_tag.rb +17 -0
  20. data/db/migrations/20210206_add_index_to_tags_and_versions.rb +27 -0
  21. data/db/migrations/20210207_optimise_latest_verification_ids_for_consumer_version_tags.rb +13 -0
  22. data/db/migrations/20210208_optimise_latest_tagged_pact_cv_orders.rb +13 -0
  23. data/db/migrations/20210210_create_environments_table.rb +16 -0
  24. data/docker-compose-dev-postgres.yml +9 -1
  25. data/lib/pact_broker/api.rb +7 -2
  26. data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +8 -0
  27. data/lib/pact_broker/api/contracts/environment_schema.rb +49 -0
  28. data/lib/pact_broker/api/decorators/base_decorator.rb +11 -0
  29. data/lib/pact_broker/api/decorators/dashboard_decorator.rb +5 -1
  30. data/lib/pact_broker/api/decorators/environment_decorator.rb +30 -0
  31. data/lib/pact_broker/api/decorators/environments_decorator.rb +21 -0
  32. data/lib/pact_broker/api/decorators/matrix_decorator.rb +3 -1
  33. data/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator.rb +2 -0
  34. data/lib/pact_broker/api/decorators/version_decorator.rb +15 -2
  35. data/lib/pact_broker/api/pact_broker_urls.rb +8 -0
  36. data/lib/pact_broker/api/resources/default_base_resource.rb +18 -0
  37. data/lib/pact_broker/api/resources/environment.rb +76 -0
  38. data/lib/pact_broker/api/resources/environments.rb +75 -0
  39. data/lib/pact_broker/api/resources/index.rb +20 -0
  40. data/lib/pact_broker/api/resources/latest_version.rb +27 -0
  41. data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +1 -0
  42. data/lib/pact_broker/api/resources/version.rb +15 -9
  43. data/lib/pact_broker/app.rb +1 -1
  44. data/lib/pact_broker/certificates/certificate.rb +1 -1
  45. data/lib/pact_broker/config/setting.rb +1 -1
  46. data/lib/pact_broker/config/space_delimited_integer_list.rb +25 -0
  47. data/lib/pact_broker/configuration.rb +22 -1
  48. data/lib/pact_broker/db/data_migrations/helpers.rb +4 -0
  49. data/lib/pact_broker/db/data_migrations/set_extra_columns_for_tags.rb +29 -0
  50. data/lib/pact_broker/db/migrate_data.rb +1 -0
  51. data/lib/pact_broker/db/seed_example_data.rb +13 -13
  52. data/lib/pact_broker/deployments/environment.rb +15 -0
  53. data/lib/pact_broker/deployments/environment_service.rb +39 -0
  54. data/lib/pact_broker/doc/views/index/environment.markdown +37 -0
  55. data/lib/pact_broker/doc/views/index/environments.markdown +53 -0
  56. data/lib/pact_broker/doc/views/index/latest-pact-versions.markdown +1 -1
  57. data/lib/pact_broker/doc/views/index/pacticipant-version-tag.markdown +1 -0
  58. data/lib/pact_broker/doc/views/index/pacticipant-version.markdown +13 -0
  59. data/lib/pact_broker/domain/index_item.rb +18 -4
  60. data/lib/pact_broker/domain/pacticipant.rb +9 -5
  61. data/lib/pact_broker/domain/tag.rb +131 -71
  62. data/lib/pact_broker/domain/verification.rb +3 -2
  63. data/lib/pact_broker/domain/version.rb +58 -23
  64. data/lib/pact_broker/domain/webhook.rb +6 -3
  65. data/lib/pact_broker/index/service.rb +55 -49
  66. data/lib/pact_broker/locale/en.yml +3 -1
  67. data/lib/pact_broker/matrix/quick_row.rb +8 -0
  68. data/lib/pact_broker/metrics/service.rb +1 -1
  69. data/lib/pact_broker/pacts/eager_loaders.rb +52 -0
  70. data/lib/pact_broker/pacts/latest_pact_publication_id_for_consumer_version.rb +18 -13
  71. data/lib/pact_broker/pacts/lazy_loaders.rb +14 -0
  72. data/lib/pact_broker/pacts/pact_publication.rb +38 -84
  73. data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +297 -0
  74. data/lib/pact_broker/pacts/pact_version.rb +1 -2
  75. data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +286 -0
  76. data/lib/pact_broker/pacts/repository.rb +5 -240
  77. data/lib/pact_broker/pacts/selected_pact.rb +4 -0
  78. data/lib/pact_broker/pacts/selector.rb +56 -1
  79. data/lib/pact_broker/pacts/selectors.rb +16 -0
  80. data/lib/pact_broker/pacts/service.rb +2 -6
  81. data/lib/pact_broker/pacts/squash_pacts_for_verification.rb +1 -4
  82. data/lib/pact_broker/pacts/verifiable_pact.rb +23 -2
  83. data/lib/pact_broker/pacts/verifiable_pact_messages.rb +56 -16
  84. data/lib/pact_broker/repositories/helpers.rb +4 -0
  85. data/lib/pact_broker/services.rb +9 -0
  86. data/lib/pact_broker/tags/eager_loaders.rb +47 -0
  87. data/lib/pact_broker/tags/repository.rb +3 -1
  88. data/lib/pact_broker/tags/service.rb +0 -3
  89. data/lib/pact_broker/tags/tag_with_latest_flag.rb +1 -0
  90. data/lib/pact_broker/test/http_test_data_builder.rb +23 -7
  91. data/lib/pact_broker/test/test_data_builder.rb +50 -3
  92. data/lib/pact_broker/ui/view_models/index_item.rb +19 -2
  93. data/lib/pact_broker/ui/view_models/matrix_line.rb +38 -2
  94. data/lib/pact_broker/ui/views/index/show-with-tags.haml +14 -6
  95. data/lib/pact_broker/ui/views/matrix/show.haml +12 -2
  96. data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +7 -5
  97. data/lib/pact_broker/version.rb +1 -1
  98. data/lib/pact_broker/versions/eager_loaders.rb +71 -0
  99. data/lib/pact_broker/versions/lazy_loaders.rb +13 -0
  100. data/lib/pact_broker/versions/repository.rb +22 -2
  101. data/lib/pact_broker/versions/service.rb +5 -1
  102. data/lib/pact_broker/webhooks/execution.rb +3 -2
  103. data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +2 -0
  104. data/lib/pact_broker/webhooks/triggered_webhook.rb +11 -4
  105. data/lib/pact_broker/webhooks/webhook.rb +1 -1
  106. data/lib/pact_broker/webhooks/webhook_event.rb +1 -1
  107. data/lib/pact_broker/webhooks/webhook_execution_result.rb +6 -1
  108. data/lib/pact_broker/webhooks/webhook_request_logger.rb +7 -1
  109. data/lib/rack/pact_broker/set_base_url.rb +35 -5
  110. data/lib/sequel/plugins/upsert.rb +18 -4
  111. data/pact_broker.gemspec +1 -1
  112. data/public/javascripts/clipboard.js +8 -2
  113. data/public/stylesheets/index.css +26 -2
  114. data/public/stylesheets/matrix.css +0 -21
  115. data/regression/can_i_deploy_spec.rb +5 -4
  116. data/regression/index_spec.rb +26 -0
  117. data/regression/regression_helper.rb +29 -3
  118. data/regression/script/clear.sh +3 -0
  119. data/regression/script/run.sh +3 -0
  120. data/script/demonstrate-version-branches.rb +33 -0
  121. data/script/pry.rb +2 -2
  122. data/spec/features/create_environment_spec.rb +47 -0
  123. data/spec/features/create_tag_spec.rb +32 -0
  124. data/spec/features/create_version_spec.rb +70 -0
  125. data/spec/features/delete_environment_spec.rb +16 -0
  126. data/spec/features/end_deployment_spec.rb +29 -0
  127. data/spec/features/get_environment_spec.rb +19 -0
  128. data/spec/features/get_environments_spec.rb +20 -0
  129. data/spec/features/record_deployment_spec.rb +28 -0
  130. data/spec/features/update_environment_spec.rb +44 -0
  131. data/spec/fixtures/approvals/modifiable_resources.approved.json +6 -0
  132. data/spec/fixtures/dashboard.json +4 -2
  133. data/spec/lib/pact_broker/api/contracts/environment_schema_spec.rb +83 -0
  134. data/spec/lib/pact_broker/api/decorators/dashboard_decorator_spec.rb +4 -2
  135. data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +11 -6
  136. data/spec/lib/pact_broker/api/decorators/verifiable_pacts_query_decorator_spec.rb +6 -0
  137. data/spec/lib/pact_broker/api/decorators/version_decorator_spec.rb +18 -0
  138. data/spec/lib/pact_broker/api/resources/default_base_resource_approval_spec.rb +1 -1
  139. data/spec/lib/pact_broker/api/resources/provider_pacts_for_verification_spec.rb +4 -0
  140. data/spec/lib/pact_broker/api/resources/webhook_execution_result_spec.rb +56 -0
  141. data/spec/lib/pact_broker/config/space_delimited_integer_list_spec.rb +47 -0
  142. data/spec/lib/pact_broker/configuration_spec.rb +12 -0
  143. data/spec/lib/pact_broker/domain/tag_spec.rb +101 -27
  144. data/spec/lib/pact_broker/domain/version_spec.rb +103 -15
  145. data/spec/lib/pact_broker/domain/webhook_spec.rb +1 -1
  146. data/spec/lib/pact_broker/index/service_spec.rb +89 -15
  147. data/spec/lib/pact_broker/pacts/pact_publication_dataset_module_spec.rb +400 -0
  148. data/spec/lib/pact_broker/pacts/pact_publication_spec.rb +434 -14
  149. data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +1 -1
  150. data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +1 -1
  151. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_branch_spec.rb +224 -0
  152. data/spec/lib/pact_broker/pacts/repository_find_wip_pact_versions_for_provider_spec.rb +20 -7
  153. data/spec/lib/pact_broker/pacts/selector_spec.rb +3 -2
  154. data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +2 -3
  155. data/spec/lib/pact_broker/pacts/service_spec.rb +2 -2
  156. data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +57 -10
  157. data/spec/lib/pact_broker/tags/repository_spec.rb +2 -0
  158. data/spec/lib/pact_broker/versions/repository_spec.rb +54 -0
  159. data/spec/lib/pact_broker/webhooks/webhook_request_logger_spec.rb +8 -0
  160. data/spec/lib/rack/pact_broker/set_base_url_spec.rb +86 -0
  161. data/spec/lib/sequel/plugins/upsert_spec.rb +31 -3
  162. data/spec/migrations/change_migration_strategy_spec.rb +3 -3
  163. data/spec/service_consumers/hal_relation_proxy_app.rb +3 -1
  164. data/spec/service_consumers/provider_states_for_pact_broker_client.rb +16 -0
  165. data/spec/spec_helper.rb +17 -5
  166. data/spec/support/approvals.rb +24 -0
  167. data/spec/support/shared_examples_for_responses.rb +11 -0
  168. data/tasks/database.rb +1 -1
  169. data/tasks/db.rake +1 -0
  170. data/tasks/rspec.rake +1 -1
  171. data/vendor/hal-browser/styles.css +6 -0
  172. metadata +70 -11
@@ -15,17 +15,22 @@ module PactBroker
15
15
  end
16
16
  end
17
17
 
18
- # Table: latest_pact_publications_by_consumer_versions
18
+ # Table: latest_pact_publication_ids_for_consumer_versions
19
+ # Primary Key: (provider_id, consumer_version_id)
19
20
  # Columns:
20
- # id | integer |
21
- # consumer_id | integer |
22
- # consumer_name | text |
23
- # consumer_version_id | integer |
24
- # consumer_version_number | text |
25
- # consumer_version_order | integer |
26
- # provider_id | integer |
27
- # provider_name | text |
28
- # revision_number | integer |
29
- # pact_version_id | integer |
30
- # pact_version_sha | text |
31
- # created_at | timestamp without time zone |
21
+ # consumer_id | integer | NOT NULL
22
+ # consumer_version_id | integer | NOT NULL
23
+ # provider_id | integer | NOT NULL
24
+ # pact_publication_id | integer | NOT NULL
25
+ # pact_version_id | integer | NOT NULL
26
+ # created_at | timestamp without time zone |
27
+ # Indexes:
28
+ # latest_pact_publication_ids_for_consume_pact_publication_id_key | UNIQUE btree (pact_publication_id)
29
+ # unq_latest_ppid_prov_conver | UNIQUE btree (provider_id, consumer_version_id)
30
+ # lpp_provider_id_consumer_id_index | btree (provider_id, consumer_id)
31
+ # Foreign key constraints:
32
+ # latest_pact_publication_ids_for_consum_consumer_version_id_fkey | (consumer_version_id) REFERENCES versions(id) ON DELETE CASCADE
33
+ # latest_pact_publication_ids_for_consum_pact_publication_id_fkey | (pact_publication_id) REFERENCES pact_publications(id) ON DELETE CASCADE
34
+ # latest_pact_publication_ids_for_consumer_v_pact_version_id_fkey | (pact_version_id) REFERENCES pact_versions(id) ON DELETE CASCADE
35
+ # latest_pact_publication_ids_for_consumer_versi_consumer_id_fkey | (consumer_id) REFERENCES pacticipants(id) ON DELETE CASCADE
36
+ # latest_pact_publication_ids_for_consumer_versi_provider_id_fkey | (provider_id) REFERENCES pacticipants(id) ON DELETE CASCADE
@@ -0,0 +1,14 @@
1
+ module PactBroker
2
+ module Pacts
3
+ module LazyLoaders
4
+ HEAD_PACT_PUBLICATIONS_FOR_TAGS = lambda {
5
+ consumer_version_tag_names = PactBroker::Domain::Tag.select(:name).where(version_id: consumer_version_id)
6
+ PactPublication
7
+ .for_consumer(consumer)
8
+ .for_provider(provider)
9
+ .latest_for_consumer_tag(consumer_version_tag_names)
10
+ .from_self.order_by(:tag_name)
11
+ }
12
+ end
13
+ end
14
+ end
@@ -4,6 +4,9 @@ require 'pact_broker/pacts/pact_version'
4
4
  require 'pact_broker/repositories/helpers'
5
5
  require 'pact_broker/integrations/integration'
6
6
  require 'pact_broker/tags/head_pact_tags'
7
+ require 'pact_broker/pacts/pact_publication_dataset_module'
8
+ require 'pact_broker/pacts/eager_loaders'
9
+ require 'pact_broker/pacts/lazy_loaders'
7
10
 
8
11
  module PactBroker
9
12
  module Pacts
@@ -20,93 +23,25 @@ module PactBroker
20
23
  associate(:many_to_one, :pact_version, class: "PactBroker::Pacts::PactVersion", :key => :pact_version_id, :primary_key => :id)
21
24
  associate(:many_to_one, :integration, class: "PactBroker::Integrations::Integration", key: [:consumer_id, :provider_id], primary_key: [:consumer_id, :provider_id])
22
25
  one_to_one(:latest_verification, class: "PactBroker::Verifications::LatestVerificationForPactVersion", key: :pact_version_id, primary_key: :pact_version_id)
23
- one_to_many(:head_pact_tags, class: "PactBroker::Tags::HeadPactTag", primary_key: :id, key: :pact_publication_id)
26
+
27
+ one_to_many(:head_pact_publications_for_tags,
28
+ class: PactPublication,
29
+ read_only: true,
30
+ dataset: PactBroker::Pacts::LazyLoaders::HEAD_PACT_PUBLICATIONS_FOR_TAGS,
31
+ eager_loader: PactBroker::Pacts::EagerLoaders::HeadPactPublicationsForTags
32
+ )
24
33
 
25
34
  plugin :upsert, identifying_columns: [:consumer_version_id, :provider_id, :revision_number]
26
35
  plugin :timestamps, update_on_create: true
27
36
 
28
37
  dataset_module do
29
38
  include PactBroker::Repositories::Helpers
39
+ include PactPublicationDatasetModule
40
+ end
30
41
 
31
- def remove_overridden_revisions
32
- join(:latest_pact_publication_ids_for_consumer_versions, { Sequel[:lp][:pact_publication_id] => Sequel[:pact_publications][:id] }, { table_alias: :lp})
33
- end
34
-
35
- def join_consumer_versions(table_alias = :cv)
36
- join(:versions, { Sequel[:pact_publications][:consumer_version_id] => Sequel[table_alias][:id] }, { table_alias: table_alias })
37
- end
38
-
39
- def join_consumer_version_tags(table_alias = :ct)
40
- join(:tags, { Sequel[table_alias][:version_id] => Sequel[:pact_publications][:consumer_version_id]}, { table_alias: table_alias })
41
- end
42
-
43
- def join_consumer_version_tags_with_names(consumer_version_tag_names)
44
- join(:tags, {
45
- Sequel[:ct][:version_id] => Sequel[:pact_publications][:consumer_version_id],
46
- Sequel[:ct][:name] => consumer_version_tag_names
47
- }, {
48
- table_alias: :ct
49
- })
50
- end
51
-
52
- def join_providers(table_alias = :providers)
53
- join(:pacticipants, { Sequel[:pact_publications][:provider_id] => Sequel[table_alias][:id] }, { table_alias: table_alias })
54
- end
55
-
56
- def join_consumers(table_alias = :consumers)
57
- join(:pacticipants, { Sequel[:pact_publications][:consumer_id] => Sequel[table_alias][:id] }, { table_alias: table_alias })
58
- end
59
-
60
- def join_pact_versions
61
- join(:pact_versions, { Sequel[:pact_publications][:pact_version_id] => Sequel[:pact_versions][:id] })
62
- end
63
-
64
- def eager_load_pact_versions
65
- eager(:pact_versions)
66
- end
67
-
68
- def tag tag_name
69
- filter = name_like(Sequel.qualify(:tags, :name), tag_name)
70
- join(:tags, {version_id: :consumer_version_id}).where(filter)
71
- end
72
-
73
- def provider_name_like(name)
74
- where(name_like(Sequel[:providers][:name], name))
75
- end
76
-
77
- def consumer_name_like(name)
78
- where(name_like(Sequel[:consumers][:name], name))
79
- end
80
-
81
- def consumer_version_number_like(number)
82
- where(name_like(Sequel[:cv][:number], number))
83
- end
84
-
85
- def consumer_version_tag(tag)
86
- where(Sequel[:ct][:name] => tag)
87
- end
88
-
89
- def order_by_consumer_name
90
- order_append_ignore_case(Sequel[:consumers][:name])
91
- end
92
-
93
- def order_by_consumer_version_order
94
- order_append(Sequel[:cv][:order])
95
- end
96
-
97
- def where_consumer_if_set(consumer)
98
- if consumer
99
- where(consumer: consumer)
100
- else
101
- self
102
- end
103
- end
104
-
105
- def delete
106
- require 'pact_broker/webhooks/triggered_webhook'
107
- PactBroker::Webhooks::TriggeredWebhook.where(pact_publication: self).delete
108
- super
109
- end
42
+ def self.subtract(a, b)
43
+ b_ids = b.collect(&:id)
44
+ a.reject{ |pact_publication| b_ids.include?(pact_publication.id) }
110
45
  end
111
46
 
112
47
  def before_create
@@ -114,10 +49,16 @@ module PactBroker
114
49
  self.revision_number ||= 1
115
50
  end
116
51
 
52
+ def head_pact_tags
53
+ consumer_version.tags.select{ |tag| head_tag_names.include?(tag.name) }
54
+ end
55
+
117
56
  # The names of the tags for which this pact is the latest pact with that tag
118
57
  # (ie. it is not necessarily the pact for the latest consumer version with the given tag)
119
58
  def head_tag_names
120
- @head_tag_names ||= PactBroker::Domain::Tag.head_tags_for_pact_publication(self).collect(&:name)
59
+ @head_tag_names ||= head_pact_publications_for_tags
60
+ .select { |head_pact_publication| head_pact_publication.id == id }
61
+ .collect { | head_pact_publication| head_pact_publication.values.fetch(:tag_name) }
121
62
  end
122
63
 
123
64
  def consumer_version_tags
@@ -128,6 +69,19 @@ module PactBroker
128
69
  pact_version.latest_verification
129
70
  end
130
71
 
72
+ def latest_for_branch?
73
+ return nil unless consumer_version.branch
74
+ self_order = self.consumer_version.order
75
+ versions_join = {
76
+ Sequel[:pact_publications][:consumer_version_id] => Sequel[:cv][:id]
77
+ }
78
+ PactPublication.where(consumer_id: consumer_id, provider_id: provider_id)
79
+ .join_consumer_versions(:cv, { Sequel[:cv][:branch] => consumer_version.branch} ) do
80
+ Sequel[:cv][:order] > self_order
81
+ end
82
+ .empty?
83
+ end
84
+
131
85
  def to_domain
132
86
  PactBroker::Domain::Pact.new(
133
87
  id: id,
@@ -160,11 +114,11 @@ module PactBroker
160
114
  end
161
115
 
162
116
  def to_version_domain
163
- OpenStruct.new(number: consumer_version.number, pacticipant: consumer, tags: consumer_version.tags, order: consumer_version.order)
117
+ OpenStruct.new(number: consumer_version.number, pacticipant: consumer, tags: consumer_version.tags, order: consumer_version.order, branch: consumer_version.branch)
164
118
  end
165
119
 
166
120
  def to_version_domain_lightweight
167
- OpenStruct.new(number: consumer_version.number, pacticipant: consumer, order: consumer_version.order)
121
+ OpenStruct.new(number: consumer_version.number, pacticipant: consumer, order: consumer_version.order, branch: consumer_version.branch)
168
122
  end
169
123
 
170
124
  private
@@ -178,7 +132,7 @@ end
178
132
 
179
133
  # Table: pact_publications
180
134
  # Columns:
181
- # id | integer | PRIMARY KEY DEFAULT nextval('pact_publications_id_seq'::regclass)
135
+ # id | integer | PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY
182
136
  # consumer_version_id | integer | NOT NULL
183
137
  # provider_id | integer | NOT NULL
184
138
  # revision_number | integer | NOT NULL
@@ -0,0 +1,297 @@
1
+ module PactBroker
2
+ module Pacts
3
+ module PactPublicationDatasetModule
4
+ def for_provider provider
5
+ where(provider: provider)
6
+ end
7
+
8
+ def for_consumer consumer
9
+ where(consumer: consumer)
10
+ end
11
+
12
+ def for_provider_and_consumer_version_selector provider, selector
13
+ # Does not yet support "all pacts for specified tag" - that code is still in the Pact::Repository
14
+ query = for_provider(provider)
15
+ query = query.for_consumer(PactBroker::Domain::Pacticipant.find_by_name(selector.consumer)) if selector.consumer
16
+ # Do this last so that the provider/consumer criteria get included in the "latest" query before the join, rather than after
17
+ query = query.latest_for_consumer_branch(selector.branch) if selector.latest_for_branch?
18
+ query = query.latest_for_consumer_tag(selector.tag) if selector.latest_for_tag?
19
+ query = query.overall_latest if selector.overall_latest?
20
+ query
21
+ end
22
+
23
+ def latest_by_consumer_branch
24
+ versions_join = {
25
+ Sequel[:pact_publications][:consumer_version_id] => Sequel[:cv][:id]
26
+ }
27
+
28
+ base_query = join(:versions, versions_join, { table_alias: :cv }) do
29
+ Sequel.lit("cv.branch is not null")
30
+ end
31
+
32
+ self_join = {
33
+ Sequel[:pact_publications][:consumer_id] => Sequel[:pp2][:consumer_id],
34
+ Sequel[:cv][:branch] => Sequel[:pp2][:branch]
35
+ }
36
+
37
+ if no_columns_selected?
38
+ base_query = base_query.select_all_qualified.select_append(Sequel[:cv][:branch])
39
+ end
40
+
41
+ base_query.left_join(base_query.select(:consumer_id, :branch, :order), self_join, { table_alias: :pp2 } ) do
42
+ Sequel[:pp2][:order] > Sequel[:cv][:order]
43
+ end
44
+ .where(Sequel[:pp2][:order] => nil)
45
+ .remove_overridden_revisions_from_complete_query
46
+ end
47
+
48
+ def overall_latest
49
+ base_query = join_consumer_versions # won't need to do this when we add the order to latest_pact_publication_ids_for_consumer_versions
50
+
51
+ self_join = {
52
+ Sequel[:pact_publications][:consumer_id] => Sequel[:pp2][:consumer_id],
53
+ Sequel[:pact_publications][:provider_id] => Sequel[:pp2][:provider_id]
54
+ }
55
+
56
+ base_query = base_query.select_all_qualified if no_columns_selected?
57
+
58
+ base_query.left_join(base_query.select(:consumer_id, :provider_id, :order), self_join, { table_alias: :pp2 } ) do
59
+ Sequel[:pp2][:order] > Sequel[:cv][:order]
60
+ end
61
+ .where(Sequel[:pp2][:order] => nil)
62
+ .remove_overridden_revisions_from_complete_query
63
+ end
64
+
65
+ def latest_for_consumer_branch(branch)
66
+ versions_join = {
67
+ Sequel[:pact_publications][:consumer_version_id] => Sequel[:cv][:id],
68
+ Sequel[:cv][:branch] => branch
69
+ }
70
+
71
+ base_query = join(:versions, versions_join, { table_alias: :cv }) do
72
+ Sequel.lit("cv.branch is not null")
73
+ end
74
+
75
+ self_join = {
76
+ Sequel[:pact_publications][:consumer_id] => Sequel[:pp2][:consumer_id],
77
+ Sequel[:cv][:branch] => Sequel[:pp2][:branch]
78
+ }
79
+
80
+ if no_columns_selected?
81
+ base_query = base_query.select_all_qualified.select_append(Sequel[:cv][:branch])
82
+ end
83
+
84
+ base_query.left_join(base_query.select(:consumer_id, :branch, :order), self_join, { table_alias: :pp2 } ) do
85
+ Sequel[:pp2][:order] > Sequel[:cv][:order]
86
+ end
87
+ .where(Sequel[:pp2][:order] => nil)
88
+ .remove_overridden_revisions_from_complete_query
89
+ end
90
+
91
+ def latest_by_consumer_tag
92
+ tags_join = {
93
+ Sequel[:pact_publications][:consumer_version_id] => Sequel[:tags][:version_id]
94
+ }
95
+
96
+ base_query = join(:tags, tags_join)
97
+
98
+ if no_columns_selected?
99
+ base_query = base_query.select_all_qualified.select_append(Sequel[:tags][:name].as(:tag_name))
100
+ end
101
+
102
+ joined_query = base_query.select(
103
+ Sequel[:pact_publications][:consumer_id],
104
+ Sequel[:tags][:version_order],
105
+ Sequel[:tags][:name].as(:tag_name)
106
+ )
107
+
108
+ self_join = {
109
+ Sequel[:pact_publications][:consumer_id] => Sequel[:pp2][:consumer_id],
110
+ Sequel[:tags][:name] => Sequel[:pp2][:tag_name]
111
+ }
112
+ base_query.left_join(joined_query, self_join, { table_alias: :pp2 } ) do
113
+ Sequel[:pp2][:version_order] > Sequel[:tags][:version_order]
114
+ end
115
+ .where(Sequel[:pp2][:version_order] => nil)
116
+ .remove_overridden_revisions_from_complete_query
117
+ end
118
+
119
+ def latest_for_consumer_tag(tag_name)
120
+ tags_join = {
121
+ Sequel[:pact_publications][:consumer_version_id] => Sequel[:tags][:version_id],
122
+ Sequel[:tags][:name] => tag_name
123
+ }
124
+
125
+ base_query = self
126
+ if no_columns_selected?
127
+ base_query = base_query.select_all_qualified.select_append(Sequel[:tags][:name].as(:tag_name))
128
+ end
129
+
130
+ base_query = base_query
131
+ .join(:tags, tags_join)
132
+ .where(Sequel[:tags][:name] => tag_name)
133
+
134
+ joined_query = base_query.select(
135
+ Sequel[:pact_publications][:consumer_id],
136
+ Sequel[:tags][:name].as(:tag_name),
137
+ Sequel[:tags][:version_order]
138
+ )
139
+
140
+ self_join = {
141
+ Sequel[:pact_publications][:consumer_id] => Sequel[:pp2][:consumer_id],
142
+ Sequel[:tags][:name] => Sequel[:pp2][:tag_name]
143
+ }
144
+
145
+ base_query.left_join(joined_query, self_join, { table_alias: :pp2 } ) do
146
+ Sequel[:pp2][:version_order] > Sequel[:tags][:version_order]
147
+ end
148
+ .where(Sequel[:pp2][:version_order] => nil)
149
+ .remove_overridden_revisions_from_complete_query
150
+ end
151
+
152
+ def successfully_verified_by_provider_branch(provider_id, provider_version_branch)
153
+ verifications_join = {
154
+ pact_version_id: :pact_version_id,
155
+ Sequel[:verifications][:success] => true,
156
+ Sequel[:verifications][:wip] => false,
157
+ Sequel[:verifications][:provider_id] => provider_id
158
+ }
159
+ versions_join = {
160
+ Sequel[:verifications][:provider_version_id] => Sequel[:provider_versions][:id],
161
+ Sequel[:provider_versions][:branch] => provider_version_branch,
162
+ Sequel[:provider_versions][:pacticipant_id] => provider_id
163
+ }
164
+
165
+ from_self(alias: :pp).select(Sequel[:pp].*)
166
+ .join(:verifications, verifications_join)
167
+ .join(:versions, versions_join, { table_alias: :provider_versions } )
168
+ .where(Sequel[:pp][:provider_id] => provider_id)
169
+ .distinct
170
+ end
171
+
172
+ def successfully_verified_by_provider_tag(provider_id, provider_tag)
173
+ verifications_join = {
174
+ pact_version_id: :pact_version_id,
175
+ Sequel[:verifications][:success] => true,
176
+ Sequel[:verifications][:wip] => false,
177
+ Sequel[:verifications][:provider_id] => provider_id
178
+ }
179
+ tags_join = {
180
+ Sequel[:verifications][:provider_version_id] => Sequel[:provider_tags][:version_id],
181
+ Sequel[:provider_tags][:name] => provider_tag
182
+ }
183
+
184
+ from_self(alias: :pp).select(Sequel[:pp].*)
185
+ .join(:verifications, verifications_join)
186
+ .join(:tags, tags_join, { table_alias: :provider_tags } )
187
+ .where(Sequel[:pp][:provider_id] => provider_id)
188
+ .distinct
189
+ end
190
+
191
+ def created_after date
192
+ where(Sequel.lit("#{first_source_alias}.created_at > ?", date))
193
+ end
194
+
195
+ def remove_overridden_revisions(pact_publications_alias = :pact_publications)
196
+ join(:latest_pact_publication_ids_for_consumer_versions, { Sequel[:lp][:pact_publication_id] => Sequel[pact_publications_alias][:id] }, { table_alias: :lp})
197
+ end
198
+
199
+ def remove_overridden_revisions_from_complete_query
200
+ from_self(alias: :p)
201
+ .select(Sequel[:p].*)
202
+ .remove_overridden_revisions(:p)
203
+ end
204
+
205
+ def join_consumer_versions(table_alias = :cv, extra_join_criteria = {}, &block)
206
+ versions_join = {
207
+ Sequel[:pact_publications][:consumer_version_id] => Sequel[table_alias][:id]
208
+ }.merge(extra_join_criteria)
209
+ join(:versions, versions_join, { table_alias: table_alias }, &block)
210
+ end
211
+
212
+ def join_consumer_version_tags(table_alias = :ct)
213
+ join(:tags, { Sequel[table_alias][:version_id] => Sequel[:pact_publications][:consumer_version_id]}, { table_alias: table_alias })
214
+ end
215
+
216
+ def join_consumer_version_tags_with_names(consumer_version_tag_names)
217
+ join(:tags, {
218
+ Sequel[:ct][:version_id] => Sequel[:pact_publications][:consumer_version_id],
219
+ Sequel[:ct][:name] => consumer_version_tag_names
220
+ }, {
221
+ table_alias: :ct
222
+ })
223
+ end
224
+
225
+ def join_providers(table_alias = :providers, base_table = :pact_publications, extra_join_criteria = {})
226
+ provider_join = {
227
+ Sequel[base_table][:provider_id] => Sequel[table_alias][:id]
228
+ }.merge(extra_join_criteria)
229
+ join(:pacticipants, provider_join, { table_alias: table_alias })
230
+ end
231
+
232
+ def join_consumers(table_alias = :consumers, base_table = :pact_publications, extra_join_criteria = {})
233
+ consumer_join = {
234
+ Sequel[base_table][:consumer_id] => Sequel[table_alias][:id]
235
+ }.merge(extra_join_criteria)
236
+ join(:pacticipants, consumer_join, { table_alias: table_alias })
237
+ end
238
+
239
+ def join_pact_versions
240
+ join(:pact_versions, { Sequel[:pact_publications][:pact_version_id] => Sequel[:pact_versions][:id] })
241
+ end
242
+
243
+ def eager_load_pact_versions
244
+ eager(:pact_versions)
245
+ end
246
+
247
+ def tag tag_name
248
+ filter = name_like(Sequel.qualify(:tags, :name), tag_name)
249
+ join(:tags, {version_id: :consumer_version_id}).where(filter)
250
+ end
251
+
252
+ def provider_name_like(name)
253
+ where(name_like(Sequel[:providers][:name], name))
254
+ end
255
+
256
+ def consumer_name_like(name)
257
+ where(name_like(Sequel[:consumers][:name], name))
258
+ end
259
+
260
+ def consumer_version_number_like(number)
261
+ where(name_like(Sequel[:cv][:number], number))
262
+ end
263
+
264
+ def consumer_version_tag(tag)
265
+ where(Sequel[:ct][:name] => tag)
266
+ end
267
+
268
+ def order_by_consumer_name
269
+ order_append_ignore_case(Sequel[:consumers][:name])
270
+ end
271
+
272
+ def order_by_consumer_version_order
273
+ order_append(Sequel[:cv][:order])
274
+ end
275
+
276
+ def where_consumer_if_set(consumer)
277
+ if consumer
278
+ where(consumer: consumer)
279
+ else
280
+ self
281
+ end
282
+ end
283
+
284
+ def delete
285
+ require 'pact_broker/webhooks/triggered_webhook'
286
+ PactBroker::Webhooks::TriggeredWebhook.where(pact_publication: self).delete
287
+ super
288
+ end
289
+
290
+ private
291
+
292
+ def no_columns_selected?
293
+ opts[:select].nil?
294
+ end
295
+ end
296
+ end
297
+ end