pact_broker 2.105.0 → 2.107.0.beta.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +57 -1
- data/Gemfile +3 -0
- data/README.md +1 -1
- data/db/migrations/20221130_add_provider_version_id_index_to_verifications.rb +28 -0
- data/db/migrations/20221208_add_index_to_pact_version_provider_tag_successful_verifications.rb +21 -0
- data/db/migrations/20221215_add_prov_ver_id_ndx_to_latest_verifi_id_for_pact_ver_and_prov_ver.rb +21 -0
- data/db/migrations/20230131_add_cons_ver_id_ndx_to_latest_pp_id_for_cons_ver.rb +21 -0
- data/db/migrations/20230216_add_branch_heads_branch_version_id_index.rb +21 -0
- data/db/migrations/20230428_add_index_for_webhook_executions_pact_publication_id.rb +17 -0
- data/docs/CONFIGURATION.md +1 -1
- data/docs/api/PAGINATION.md +43 -0
- data/lib/pact_broker/api/contracts/base_contract.rb +22 -7
- data/lib/pact_broker/api/contracts/can_i_deploy_query_schema.rb +34 -0
- data/lib/pact_broker/api/contracts/configuration.rb +2 -0
- data/lib/pact_broker/api/contracts/consumer_version_selector_contract.rb +140 -0
- data/lib/pact_broker/api/contracts/dry_validation_errors_formatter.rb +50 -0
- data/lib/pact_broker/api/contracts/dry_validation_macros.rb +79 -0
- data/lib/pact_broker/api/contracts/dry_validation_methods.rb +71 -0
- data/lib/pact_broker/api/contracts/environment_schema.rb +19 -33
- data/lib/pact_broker/api/contracts/pacticipant_create_schema.rb +4 -17
- data/lib/pact_broker/api/contracts/pacticipant_schema.rb +15 -24
- data/lib/pact_broker/api/contracts/pacts_for_verification_json_query_schema.rb +37 -146
- data/lib/pact_broker/api/contracts/pacts_for_verification_query_string_schema.rb +7 -20
- data/lib/pact_broker/api/contracts/publish_contracts_contract_contract.rb +62 -0
- data/lib/pact_broker/api/contracts/publish_contracts_schema.rb +25 -112
- data/lib/pact_broker/api/contracts/put_pact_params_contract.rb +21 -26
- data/lib/pact_broker/api/contracts/utf_8_validation.rb +19 -0
- data/lib/pact_broker/api/contracts/validation_helpers.rb +71 -0
- data/lib/pact_broker/api/contracts/verification_contract.rb +10 -29
- data/lib/pact_broker/api/contracts/webhook_contract.rb +20 -170
- data/lib/pact_broker/api/contracts/webhook_pacticipant_contract.rb +33 -0
- data/lib/pact_broker/api/contracts/webhook_request_contract.rb +125 -0
- data/lib/pact_broker/api/contracts.rb +3 -0
- data/lib/pact_broker/api/decorators/custom_error_problem_json_decorator.rb +36 -0
- data/lib/pact_broker/api/decorators/dashboard_text_decorator.rb +2 -2
- data/lib/pact_broker/api/decorators/extended_pact_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/matrix_decorator.rb +4 -4
- data/lib/pact_broker/api/decorators/matrix_text_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/pact_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/pacticipant_collection_decorator.rb +5 -2
- data/lib/pact_broker/api/decorators/pacticipant_decorator.rb +2 -1
- data/lib/pact_broker/api/decorators/pacts_for_verification_query_decorator.rb +4 -1
- data/lib/pact_broker/api/decorators/pagination_links.rb +11 -0
- data/lib/pact_broker/api/decorators/runtime_error_problem_json_decorator.rb +34 -0
- data/lib/pact_broker/api/decorators/validation_errors_problem_json_decorator.rb +66 -0
- data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +4 -4
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +2 -3
- data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +5 -12
- data/lib/pact_broker/api/resources/all_webhooks.rb +5 -11
- data/lib/pact_broker/api/resources/badge_methods.rb +1 -1
- data/lib/pact_broker/api/resources/base_resource.rb +31 -68
- data/lib/pact_broker/api/resources/branch_version.rb +3 -3
- data/lib/pact_broker/api/resources/can_i_deploy.rb +4 -19
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_branch_to_environment.rb +1 -4
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_tag_to_tag.rb +0 -2
- data/lib/pact_broker/api/resources/can_i_deploy_pacticipant_version_by_tag_to_tag_badge.rb +1 -2
- data/lib/pact_broker/api/resources/currently_deployed_versions_for_environment.rb +2 -2
- data/lib/pact_broker/api/resources/currently_supported_versions_for_environment.rb +2 -2
- data/lib/pact_broker/api/resources/dashboard.rb +3 -3
- data/lib/pact_broker/api/resources/deployed_version.rb +1 -1
- data/lib/pact_broker/api/resources/deployed_versions_for_version_and_environment.rb +2 -2
- data/lib/pact_broker/api/resources/environment.rb +1 -1
- data/lib/pact_broker/api/resources/environments.rb +2 -2
- data/lib/pact_broker/api/resources/error_handling_methods.rb +57 -0
- data/lib/pact_broker/api/resources/error_response_generator.rb +70 -0
- data/lib/pact_broker/api/resources/integrations.rb +1 -1
- data/lib/pact_broker/api/resources/label.rb +1 -1
- data/lib/pact_broker/api/resources/latest_pact.rb +2 -2
- data/lib/pact_broker/api/resources/latest_pacts.rb +1 -1
- data/lib/pact_broker/api/resources/latest_verifications_for_consumer_version.rb +2 -2
- data/lib/pact_broker/api/resources/matrix.rb +2 -2
- data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +1 -1
- data/lib/pact_broker/api/resources/pact.rb +7 -4
- data/lib/pact_broker/api/resources/pact_triggered_webhooks.rb +1 -1
- data/lib/pact_broker/api/resources/pact_version.rb +1 -1
- data/lib/pact_broker/api/resources/pact_versions.rb +1 -1
- data/lib/pact_broker/api/resources/pact_webhooks.rb +7 -14
- data/lib/pact_broker/api/resources/pact_webhooks_status.rb +6 -2
- data/lib/pact_broker/api/resources/pacticipant.rb +1 -1
- data/lib/pact_broker/api/resources/pacticipant_webhooks.rb +7 -5
- data/lib/pact_broker/api/resources/pacticipants.rb +6 -3
- data/lib/pact_broker/api/resources/pacticipants_for_label.rb +1 -1
- data/lib/pact_broker/api/resources/pagination_methods.rb +8 -4
- data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +1 -1
- data/lib/pact_broker/api/resources/provider_pacts.rb +1 -1
- data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +4 -13
- data/lib/pact_broker/api/resources/publish_contracts.rb +8 -3
- data/lib/pact_broker/api/resources/released_version.rb +1 -1
- data/lib/pact_broker/api/resources/released_versions_for_version_and_environment.rb +2 -2
- data/lib/pact_broker/api/resources/tag.rb +1 -1
- data/lib/pact_broker/api/resources/tagged_pact_versions.rb +1 -1
- data/lib/pact_broker/api/resources/triggered_webhook_logs.rb +2 -2
- data/lib/pact_broker/api/resources/verification.rb +2 -2
- data/lib/pact_broker/api/resources/verification_triggered_webhooks.rb +1 -1
- data/lib/pact_broker/api/resources/verifications.rb +4 -6
- data/lib/pact_broker/api/resources/version.rb +1 -1
- data/lib/pact_broker/api/resources/versions.rb +6 -13
- data/lib/pact_broker/api/resources/webhook.rb +7 -6
- data/lib/pact_broker/api/resources/webhook_execution.rb +6 -4
- data/lib/pact_broker/api.rb +3 -13
- data/lib/pact_broker/app.rb +0 -2
- data/lib/pact_broker/application_context.rb +4 -4
- data/lib/pact_broker/certificates/certificate.rb +1 -0
- data/lib/pact_broker/config/setting.rb +1 -0
- data/lib/pact_broker/contracts/service.rb +1 -0
- data/lib/pact_broker/date_helper.rb +1 -1
- data/lib/pact_broker/db/clean_incremental.rb +67 -59
- data/lib/pact_broker/db/delete_overwritten_data.rb +6 -2
- data/lib/pact_broker/deployments/currently_deployed_version_id.rb +2 -0
- data/lib/pact_broker/deployments/deployed_version.rb +2 -0
- data/lib/pact_broker/deployments/deployed_version_service.rb +5 -1
- data/lib/pact_broker/deployments/environment.rb +2 -0
- data/lib/pact_broker/deployments/environment_service.rb +4 -3
- data/lib/pact_broker/deployments/released_version.rb +2 -0
- data/lib/pact_broker/deployments/released_version_service.rb +4 -0
- data/lib/pact_broker/diagnostic/resources/base_resource.rb +1 -1
- data/lib/pact_broker/doc/views/index/publish-contracts.markdown +5 -5
- data/lib/pact_broker/domain/label.rb +1 -0
- data/lib/pact_broker/domain/tag.rb +2 -0
- data/lib/pact_broker/domain/verification.rb +1 -1
- data/lib/pact_broker/domain/version.rb +4 -1
- data/lib/pact_broker/domain/webhook.rb +1 -1
- data/lib/pact_broker/index/service.rb +2 -2
- data/lib/pact_broker/integrations/integration.rb +1 -0
- data/lib/pact_broker/locale/en.yml +36 -14
- data/lib/pact_broker/matrix/query_ids.rb +4 -4
- data/lib/pact_broker/matrix/resolved_selector.rb +6 -1
- data/lib/pact_broker/matrix/service.rb +1 -0
- data/lib/pact_broker/messages.rb +5 -1
- data/lib/pact_broker/pacticipants/repository.rb +16 -14
- data/lib/pact_broker/pacticipants/service.rb +11 -8
- data/lib/pact_broker/pacts/pact_params.rb +6 -17
- data/lib/pact_broker/pacts/pact_version.rb +1 -0
- data/lib/pact_broker/pacts/selected_pact.rb +4 -0
- data/lib/pact_broker/policies.rb +4 -4
- data/lib/pact_broker/repositories/helpers.rb +11 -0
- data/lib/pact_broker/repositories/page.rb +24 -0
- data/lib/pact_broker/string_refinements.rb +4 -0
- data/lib/pact_broker/tasks/clean_task.rb +7 -3
- data/lib/pact_broker/test/http_test_data_builder.rb +46 -2
- data/lib/pact_broker/ui/app.rb +2 -2
- data/lib/pact_broker/ui/views/matrix/show.haml +1 -1
- data/lib/pact_broker/verifications/latest_verification_id_for_pact_version_and_provider_version.rb +1 -1
- data/lib/pact_broker/verifications/pact_version_provider_tag_successful_verification.rb +1 -0
- data/lib/pact_broker/verifications/repository.rb +14 -11
- data/lib/pact_broker/verifications/service.rb +0 -6
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/branch.rb +1 -0
- data/lib/pact_broker/versions/branch_head.rb +2 -1
- data/lib/pact_broker/versions/branch_version.rb +11 -0
- data/lib/pact_broker/versions/repository.rb +12 -0
- data/lib/pact_broker/versions/service.rb +4 -0
- data/lib/pact_broker/webhooks/execution.rb +1 -1
- data/lib/pact_broker/webhooks/repository.rb +1 -1
- data/lib/pact_broker/webhooks/service.rb +3 -25
- data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
- data/lib/pact_broker/webhooks/webhook_event.rb +1 -0
- data/lib/pact_broker/webmachine.rb +22 -0
- data/lib/rack/pact_broker/invalid_uri_protection.rb +1 -1
- data/lib/rack/pact_broker/request_target.rb +1 -1
- data/lib/rack/pact_broker/use_when.rb +6 -5
- data/lib/sequel/plugins/age.rb +13 -0
- data/lib/webmachine/application_monkey_patch.rb +15 -0
- data/lib/webmachine/describe_routes.rb +35 -8
- data/lib/webmachine/render_error_monkey_patch.rb +70 -0
- data/pact_broker.gemspec +7 -18
- metadata +72 -76
- data/lib/pact/doc/README.md +0 -5
- data/lib/pact_broker/api/contracts/dry_validation_predicates.rb +0 -36
- data/lib/pact_broker/api/contracts/dry_validation_workarounds.rb +0 -39
- data/lib/pact_broker/api/contracts/pacticipant_name_contract.rb +0 -24
- data/lib/pact_broker/api/contracts/pacticipant_name_validation.rb +0 -30
- data/lib/pact_broker/api/contracts/request_validations.rb +0 -33
- data/lib/pact_broker/api/resources/error_response_body_generator.rb +0 -41
- data/lib/pact_broker/api/resources/webhook_resource_methods.rb +0 -17
- data/lib/pact_broker/matrix/can_i_deploy_query_schema.rb +0 -46
- data/lib/rack/pact_broker/convert_404_to_hal.rb +0 -20
@@ -25,6 +25,36 @@ module PactBroker
|
|
25
25
|
@options = options
|
26
26
|
end
|
27
27
|
|
28
|
+
def call
|
29
|
+
require "pact_broker/db/models"
|
30
|
+
|
31
|
+
if dry_run?
|
32
|
+
dry_run_results
|
33
|
+
else
|
34
|
+
execute_clean
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
attr_reader :db, :options
|
41
|
+
|
42
|
+
def execute_clean
|
43
|
+
db.transaction do
|
44
|
+
before_counts = current_counts
|
45
|
+
PactBroker::Domain::Version.where(id: versions_to_delete.from_self.select_map(:id)).delete
|
46
|
+
delete_orphan_pact_versions
|
47
|
+
after_counts = current_counts
|
48
|
+
|
49
|
+
TABLES.each_with_object({}) do | table_name, comparison_counts |
|
50
|
+
comparison_counts[table_name.to_s] = {
|
51
|
+
"deleted" => before_counts[table_name] - after_counts[table_name],
|
52
|
+
"kept" => after_counts[table_name]
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
28
58
|
def logger
|
29
59
|
options[:logger] || PactBroker.logger
|
30
60
|
end
|
@@ -42,47 +72,20 @@ module PactBroker
|
|
42
72
|
options[:limit] || 1000
|
43
73
|
end
|
44
74
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
75
|
+
def versions_to_delete(columns = [:id])
|
76
|
+
fully_qualified_columns = columns.collect { |col| Sequel[:versions][col] }
|
77
|
+
PactBroker::Domain::Version
|
78
|
+
.select(*fully_qualified_columns)
|
79
|
+
.left_outer_join(version_ids_to_keep, { Sequel[:versions][:id] => Sequel[:keep_versions][:id] }, table_alias: :keep_versions)
|
80
|
+
.where(Sequel[:keep_versions][:id] => nil)
|
81
|
+
.order(Sequel.asc( Sequel[:versions][:id]))
|
82
|
+
.limit(limit)
|
51
83
|
end
|
52
84
|
|
53
85
|
def version_ids_to_keep
|
54
|
-
@version_ids_to_keep ||=
|
86
|
+
@version_ids_to_keep ||= keep.collect { |selector| PactBroker::Domain::Version.for_selector(selector).select(:id) }.reduce(&:union)
|
55
87
|
end
|
56
88
|
|
57
|
-
def selected_versions_to_keep
|
58
|
-
keep.collect do | selector |
|
59
|
-
PactBroker::Domain::Version.select(:id).for_selector(selector)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def call
|
64
|
-
require "pact_broker/db/models"
|
65
|
-
|
66
|
-
if dry_run?
|
67
|
-
dry_run_results
|
68
|
-
else
|
69
|
-
db.transaction do
|
70
|
-
before_counts = current_counts
|
71
|
-
PactBroker::Domain::Version.where(id: resolve_ids(version_ids_to_delete)).delete
|
72
|
-
delete_orphan_pact_versions
|
73
|
-
after_counts = current_counts
|
74
|
-
|
75
|
-
TABLES.each_with_object({}) do | table_name, comparison_counts |
|
76
|
-
comparison_counts[table_name.to_s] = { "deleted" => before_counts[table_name] - after_counts[table_name], "kept" => after_counts[table_name] }
|
77
|
-
end
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
private
|
83
|
-
|
84
|
-
attr_reader :db, :options
|
85
|
-
|
86
89
|
def current_counts
|
87
90
|
TABLES.each_with_object({}) do | table_name, counts |
|
88
91
|
counts[table_name] = db[table_name].count
|
@@ -122,8 +125,8 @@ module PactBroker
|
|
122
125
|
end
|
123
126
|
|
124
127
|
def dry_run_results
|
125
|
-
to_delete =
|
126
|
-
to_keep =
|
128
|
+
to_delete = dry_run_to_delete_by_pacticipant
|
129
|
+
to_keep = dry_run_to_keep_by_pacticipant
|
127
130
|
|
128
131
|
kept_per_selector = keep.collect do | selector |
|
129
132
|
{
|
@@ -141,7 +144,7 @@ module PactBroker
|
|
141
144
|
|
142
145
|
total_versions_count = PactBroker::Domain::Version.count
|
143
146
|
versions_to_keep_count = version_ids_to_keep.count
|
144
|
-
versions_to_delete_count =
|
147
|
+
versions_to_delete_count = versions_to_delete.count
|
145
148
|
|
146
149
|
{
|
147
150
|
"counts" => {
|
@@ -155,9 +158,15 @@ module PactBroker
|
|
155
158
|
}
|
156
159
|
end
|
157
160
|
|
158
|
-
def
|
159
|
-
|
160
|
-
.
|
161
|
+
def expected_remaining_versions
|
162
|
+
PactBroker::Domain::Version
|
163
|
+
.left_outer_join(versions_to_delete, { Sequel[:versions][:id] => Sequel[:delete_versions][:id] }, table_alias: :delete_versions )
|
164
|
+
.where(Sequel[:delete_versions][:id] => nil)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Returns the latest version that will be kept for each pacticipant
|
168
|
+
def dry_run_latest_versions_to_keep_by_pacticipant
|
169
|
+
latest_undeleted_versions_by_order = expected_remaining_versions
|
161
170
|
.select_group(:pacticipant_id)
|
162
171
|
.select_append{ max(order).as(latest_order) }
|
163
172
|
|
@@ -171,9 +180,9 @@ module PactBroker
|
|
171
180
|
.join(latest_undeleted_versions_by_order, lv_versions_join, { table_alias: :lv })
|
172
181
|
end
|
173
182
|
|
174
|
-
|
175
|
-
|
176
|
-
|
183
|
+
# Returns the earliest version that will be kept for each pacticipant
|
184
|
+
def dry_run_earliest_versions_to_keep_by_pacticipant
|
185
|
+
earliest_undeleted_versions_by_order = expected_remaining_versions
|
177
186
|
.select_group(:pacticipant_id)
|
178
187
|
.select_append{ min(order).as(first_order) }
|
179
188
|
|
@@ -187,13 +196,16 @@ module PactBroker
|
|
187
196
|
.join(earliest_undeleted_versions_by_order, ev_versions_join, { table_alias: :lv })
|
188
197
|
end
|
189
198
|
|
190
|
-
|
191
|
-
|
192
|
-
|
199
|
+
# Returns Hash of pacticipant name => Hash, where the Hash value contains the count, fromVersion and toVersion
|
200
|
+
# that will be deleted.
|
201
|
+
# @return Hash
|
202
|
+
def dry_run_to_delete_by_pacticipant
|
203
|
+
versions_to_delete
|
204
|
+
.select(Sequel[:versions].*)
|
193
205
|
.all
|
194
206
|
.group_by{ | v | v.pacticipant_id }
|
195
|
-
.each_with_object({}) do | (_pacticipant_id, versions),
|
196
|
-
|
207
|
+
.each_with_object({}) do | (_pacticipant_id, versions), hash |
|
208
|
+
hash[versions.first.pacticipant.name] = {
|
197
209
|
"count" => versions.count,
|
198
210
|
"fromVersion" => version_info(versions.first),
|
199
211
|
"toVersion" => version_info(versions.last)
|
@@ -202,14 +214,14 @@ module PactBroker
|
|
202
214
|
end
|
203
215
|
|
204
216
|
# rubocop: disable Metrics/CyclomaticComplexity
|
205
|
-
def
|
206
|
-
latest_to_keep =
|
217
|
+
def dry_run_to_keep_by_pacticipant
|
218
|
+
latest_to_keep = dry_run_latest_versions_to_keep_by_pacticipant.eager(:tags).each_with_object({}) do | version, r |
|
207
219
|
r[version.pacticipant_id] = {
|
208
220
|
"firstVersion" => version_info(version)
|
209
221
|
}
|
210
222
|
end
|
211
223
|
|
212
|
-
earliest_to_keep =
|
224
|
+
earliest_to_keep = dry_run_earliest_versions_to_keep_by_pacticipant.eager(:tags).each_with_object({}) do | version, r |
|
213
225
|
r[version.pacticipant_id] = {
|
214
226
|
"latestVersion" => version_info(version)
|
215
227
|
}
|
@@ -226,14 +238,10 @@ module PactBroker
|
|
226
238
|
# rubocop: enable Metrics/CyclomaticComplexity
|
227
239
|
|
228
240
|
def counts_to_keep
|
229
|
-
|
230
|
-
.invert
|
241
|
+
expected_remaining_versions
|
231
242
|
.select_group(:pacticipant_id)
|
232
243
|
.select_append{ count(1).as(count) }
|
233
|
-
.
|
234
|
-
.each_with_object({}) do | row, counts |
|
235
|
-
counts[row[:pacticipant_id]] = row[:count]
|
236
|
-
end
|
244
|
+
.as_hash(:pacticipant_id, :count)
|
237
245
|
end
|
238
246
|
|
239
247
|
def pacticipants
|
@@ -36,9 +36,13 @@ module PactBroker
|
|
36
36
|
to_keep = deleted_counts.keys.each_with_object({}) do | table_name, new_counts |
|
37
37
|
new_counts[table_name] = kept_counts[table_name] - deleted_counts[table_name]
|
38
38
|
end
|
39
|
-
{
|
39
|
+
deleted_counts.each_with_object({}) do | (key, value), new_hash |
|
40
|
+
new_hash[key] = { toDelete: value, toKeep: to_keep[key] }
|
41
|
+
end
|
40
42
|
else
|
41
|
-
{
|
43
|
+
deleted_counts.each_with_object({}) do | (key, value), new_hash |
|
44
|
+
new_hash[key] = { deleted: value, kept: kept_counts[key] }
|
45
|
+
end
|
42
46
|
end
|
43
47
|
end
|
44
48
|
|
@@ -4,6 +4,8 @@ require "pact_broker/repositories/helpers"
|
|
4
4
|
module PactBroker
|
5
5
|
module Deployments
|
6
6
|
class CurrentlyDeployedVersionId < Sequel::Model
|
7
|
+
set_primary_key :id
|
8
|
+
|
7
9
|
plugin :upsert, identifying_columns: [:pacticipant_id, :environment_id, :target_for_index]
|
8
10
|
|
9
11
|
dataset_module do
|
@@ -4,6 +4,8 @@ require "pact_broker/deployments/currently_deployed_version_id"
|
|
4
4
|
module PactBroker
|
5
5
|
module Deployments
|
6
6
|
class DeployedVersion < Sequel::Model
|
7
|
+
set_primary_key :id
|
8
|
+
|
7
9
|
many_to_one :pacticipant, :class => "PactBroker::Domain::Pacticipant", :key => :pacticipant_id, :primary_key => :id
|
8
10
|
many_to_one :version, :class => "PactBroker::Domain::Version", :key => :version_id, :primary_key => :id
|
9
11
|
many_to_one :environment, :class => "PactBroker::Deployments::Environment", :key => :environment_id, :primary_key => :id
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "pact_broker/deployments/deployed_version"
|
2
2
|
require "pact_broker/repositories/scopes"
|
3
|
+
require "pact_broker/events/publisher"
|
3
4
|
|
4
5
|
module PactBroker
|
5
6
|
module Deployments
|
@@ -7,6 +8,7 @@ module PactBroker
|
|
7
8
|
include PactBroker::Logging
|
8
9
|
extend PactBroker::Repositories::Scopes
|
9
10
|
extend PactBroker::Services
|
11
|
+
extend PactBroker::Events::Publisher
|
10
12
|
|
11
13
|
def self.next_uuid
|
12
14
|
SecureRandom.uuid
|
@@ -22,7 +24,7 @@ module PactBroker
|
|
22
24
|
deployed_version
|
23
25
|
else
|
24
26
|
record_previous_version_undeployed(version.pacticipant, environment, target)
|
25
|
-
DeployedVersion.create(
|
27
|
+
deployed_version = DeployedVersion.create(
|
26
28
|
uuid: uuid,
|
27
29
|
version: version,
|
28
30
|
pacticipant_id: version.pacticipant_id,
|
@@ -30,6 +32,8 @@ module PactBroker
|
|
30
32
|
target: target,
|
31
33
|
auto_created: auto_created
|
32
34
|
)
|
35
|
+
broadcast(:deployed_version_created, { deployed_version: deployed_version })
|
36
|
+
deployed_version
|
33
37
|
end
|
34
38
|
end
|
35
39
|
|
@@ -5,6 +5,8 @@ require "sequel/plugins/serialization"
|
|
5
5
|
module PactBroker
|
6
6
|
module Deployments
|
7
7
|
class Environment < Sequel::Model
|
8
|
+
set_primary_key :id
|
9
|
+
|
8
10
|
OPEN_STRUCT_TO_JSON = lambda { | open_struct | Sequel.object_to_json(open_struct.collect(&:to_h)) }
|
9
11
|
JSON_TO_OPEN_STRUCT = lambda { | json | Sequel.parse_json(json).collect{ | hash| OpenStruct.new(hash) } }
|
10
12
|
plugin :upsert, identifying_columns: [:uuid]
|
@@ -9,7 +9,6 @@ module PactBroker
|
|
9
9
|
module EnvironmentService
|
10
10
|
using PactBroker::StringRefinements
|
11
11
|
extend PactBroker::Repositories::Scopes
|
12
|
-
|
13
12
|
extend self
|
14
13
|
|
15
14
|
def self.included(base)
|
@@ -36,8 +35,6 @@ module PactBroker
|
|
36
35
|
environment.upsert
|
37
36
|
end
|
38
37
|
|
39
|
-
alias_method :update, :replace # For PF
|
40
|
-
|
41
38
|
def find_all
|
42
39
|
scope_for(PactBroker::Deployments::Environment).order(Sequel.function(:lower, :display_name)).all
|
43
40
|
end
|
@@ -57,6 +54,10 @@ module PactBroker
|
|
57
54
|
def find_for_pacticipant(_pacticipant)
|
58
55
|
find_all
|
59
56
|
end
|
57
|
+
|
58
|
+
def scope_for(scope)
|
59
|
+
PactBroker.policy_scope!(scope)
|
60
|
+
end
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
@@ -4,6 +4,8 @@ require "pact_broker/repositories/helpers"
|
|
4
4
|
module PactBroker
|
5
5
|
module Deployments
|
6
6
|
class ReleasedVersion < Sequel::Model
|
7
|
+
set_primary_key :id
|
8
|
+
|
7
9
|
many_to_one :pacticipant, :class => "PactBroker::Domain::Pacticipant", :key => :pacticipant_id, :primary_key => :id
|
8
10
|
many_to_one :version, :class => "PactBroker::Domain::Version", :key => :version_id, :primary_key => :id
|
9
11
|
many_to_one :environment, :class => "PactBroker::Deployments::Environment", :key => :environment_id, :primary_key => :id
|
@@ -1,10 +1,12 @@
|
|
1
1
|
require "pact_broker/deployments/released_version"
|
2
2
|
require "pact_broker/repositories/scopes"
|
3
|
+
require "pact_broker/events/publisher"
|
3
4
|
|
4
5
|
module PactBroker
|
5
6
|
module Deployments
|
6
7
|
class ReleasedVersionService
|
7
8
|
extend PactBroker::Repositories::Scopes
|
9
|
+
extend PactBroker::Events::Publisher
|
8
10
|
|
9
11
|
def self.next_uuid
|
10
12
|
SecureRandom.uuid
|
@@ -25,6 +27,8 @@ module PactBroker
|
|
25
27
|
# error when marking an existing row as supported again IRL.
|
26
28
|
ReleasedVersion.where(id: released_version.id).set_currently_supported
|
27
29
|
released_version.refresh
|
30
|
+
broadcast(:released_version_created, { released_version: released_version })
|
31
|
+
released_version
|
28
32
|
end
|
29
33
|
|
30
34
|
def self.find_currently_supported_versions_for_environment(environment, pacticipant_name: nil, pacticipant_version_number: nil)
|
@@ -33,7 +33,7 @@ This endpoint is designed to be used by a command line tool, and hence, the resp
|
|
33
33
|
### Success
|
34
34
|
|
35
35
|
* `notices`
|
36
|
-
* `
|
36
|
+
* `type`: one of `debug`, `info`, `warning`,`prompt`,`success`, `error`, `danger`
|
37
37
|
* `text`: the text of the notice. This is designed to be displayed in the output of a CLI.
|
38
38
|
|
39
39
|
The `_links` section will contain links to all the resources created by the publication. The relations are:
|
@@ -105,19 +105,19 @@ If there is a conflict with an existing published pact and `allow_dangerous_cont
|
|
105
105
|
{
|
106
106
|
"notices": [
|
107
107
|
{
|
108
|
-
"
|
108
|
+
"type": "debug",
|
109
109
|
"text": "Created Foo version dc5eb529230038a4673b8c971395bd2922d8b240 with branch main and tags main"
|
110
110
|
},
|
111
111
|
{
|
112
|
-
"
|
112
|
+
"type": "info",
|
113
113
|
"text": "Pact published for Foo version dc5eb529230038a4673b8c971395bd2922d8b240 and provider Bar."
|
114
114
|
},
|
115
115
|
{
|
116
|
-
"
|
116
|
+
"type": "debug",
|
117
117
|
"text": " Events detected: contract_published, contract_content_changed (first time any pact published for this consumer with consumer version tagged main)"
|
118
118
|
},
|
119
119
|
{
|
120
|
-
"
|
120
|
+
"type": "debug",
|
121
121
|
"text": " Webhook \"foo webhook\" triggered for event contract_content_changed.\n See logs at http://example.org/triggered-webhooks/1234/logs\""
|
122
122
|
}
|
123
123
|
],
|
@@ -3,6 +3,7 @@ require "pact_broker/db"
|
|
3
3
|
module PactBroker
|
4
4
|
module Domain
|
5
5
|
class Label < Sequel::Model
|
6
|
+
set_primary_key([:name, :pacticipant_id])
|
6
7
|
unrestrict_primary_key
|
7
8
|
|
8
9
|
associate(:many_to_one, :pacticipant, :class => "PactBroker::Domain::Pacticipant", :key => :pacticipant_id, :primary_key => :id)
|
@@ -24,10 +24,12 @@ module PactBroker
|
|
24
24
|
VERSION_COLUMNS = [:id, :number, :repository_ref, :pacticipant_id, :order, :created_at, :updated_at, :build_url]
|
25
25
|
|
26
26
|
class Version < Sequel::Model(Sequel::Model.db[:versions].select(*VERSION_COLUMNS.collect{ | column | Sequel.qualify(:versions, column) }))
|
27
|
+
set_primary_key :id
|
28
|
+
|
27
29
|
plugin :timestamps, update_on_create: true
|
30
|
+
plugin :age
|
28
31
|
plugin :upsert, { identifying_columns: [:pacticipant_id, :number], ignore_columns_on_update: [:id, :created_at, :order] }
|
29
32
|
|
30
|
-
set_primary_key :id
|
31
33
|
one_to_many :pact_publications, order: :revision_number, class: "PactBroker::Pacts::PactPublication", key: :consumer_version_id
|
32
34
|
associate(:many_to_one, :pacticipant, :class => "PactBroker::Domain::Pacticipant", :key => :pacticipant_id, :primary_key => :id)
|
33
35
|
one_to_many :tags, :reciprocal => :version, order: :created_at
|
@@ -41,6 +43,7 @@ module PactBroker
|
|
41
43
|
end
|
42
44
|
|
43
45
|
one_to_many :deployed_versions, class: "PactBroker::Deployments::DeployedVersion", key: :version_id, primary_key: :id, order: [:created_at, :id]
|
46
|
+
one_to_many :released_versions, class: "PactBroker::Deployments::ReleasedVersion", key: :version_id, primary_key: :id, order: [:created_at, :id]
|
44
47
|
|
45
48
|
many_to_one :latest_version_for_pacticipant, read_only: true, key: :id,
|
46
49
|
class: Version,
|
@@ -50,7 +50,7 @@ module PactBroker
|
|
50
50
|
def execute pact, verification, event_context, options
|
51
51
|
logger.info "Executing #{self} event_context=#{event_context}"
|
52
52
|
template_params = template_parameters(pact, verification, event_context, options)
|
53
|
-
webhook_request = request.build(template_params, options.slice(:user_agent, :disable_ssl_verification, :cert_store))
|
53
|
+
webhook_request = request.build(template_params, **options.slice(:user_agent, :disable_ssl_verification, :cert_store))
|
54
54
|
http_response, error = execute_request(webhook_request)
|
55
55
|
success = success?(http_response, options)
|
56
56
|
http_request = webhook_request.http_request
|
@@ -18,7 +18,7 @@ module PactBroker
|
|
18
18
|
DEFAULT_PAGE_NUMBER = 1
|
19
19
|
|
20
20
|
# This method provides data for both the OSS server side rendered index (with and without tags)
|
21
|
-
# and the
|
21
|
+
# and the PactFlow UI. It really needs to be broken into to separate methods, as it's getting too messy
|
22
22
|
# supporting both
|
23
23
|
|
24
24
|
def self.pact_publication_scope
|
@@ -109,7 +109,7 @@ module PactBroker
|
|
109
109
|
# rubocop: disable Metrics/CyclomaticComplexity
|
110
110
|
def self.latest_verification_for_pseudo_branch(pact_publication, is_overall_latest, latest_verifications_for_cv_tags, tags_option, options)
|
111
111
|
if options[:view] == "branch" || (options[:view] == "all" && pact_publication.consumer_version.branch_heads.any?)
|
112
|
-
pact_publication.latest_verification || pact_publication.latest_verification_for_consumer_branches
|
112
|
+
pact_publication.latest_verification || pact_publication.latest_verification_for_consumer_branches(forbid_lazy_load: false)
|
113
113
|
elsif tags_option == true
|
114
114
|
latest_verifications_for_cv_tags
|
115
115
|
.select{ | v | v.consumer_id == pact_publication.consumer_id && v.provider_id == pact_publication.provider_id && pact_publication.head_pact_tags.collect(&:name).include?(v.consumer_version_tag_name) }
|
@@ -8,6 +8,7 @@ require "pact_broker/verifications/latest_verification_for_consumer_and_provider
|
|
8
8
|
module PactBroker
|
9
9
|
module Integrations
|
10
10
|
class Integration < Sequel::Model(Sequel::Model.db[:integrations].select(:id, :consumer_id, :provider_id))
|
11
|
+
set_primary_key :id
|
11
12
|
plugin :insert_ignore, identifying_columns: [:consumer_id, :provider_id]
|
12
13
|
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
|
13
14
|
associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
|
@@ -2,17 +2,10 @@ en:
|
|
2
2
|
errors:
|
3
3
|
not_blank?: "can't be blank"
|
4
4
|
filled?: "can't be blank"
|
5
|
-
valid_method?: "is not a recognised HTTP method"
|
6
5
|
valid_url?: "is not a valid URL eg. http://example.org"
|
7
6
|
base64?: "is not valid Base64"
|
8
|
-
valid_version_number?: "Version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
9
|
-
name_in_path_matches_name_in_pact?: "does not match %{left} name in path ('%{right}')."
|
10
|
-
valid_consumer_version_number?: "Consumer version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
11
|
-
non_templated_host?: "cannot have a template parameter in the host"
|
12
|
-
pacticipant_exists?: "does not match an existing pacticipant"
|
13
7
|
single_line?: "cannot contain multiple lines"
|
14
8
|
no_spaces?: "cannot contain spaces"
|
15
|
-
environment_with_name_exists?: "with name '%{value}' does not exist"
|
16
9
|
none?: "cannot be provided"
|
17
10
|
|
18
11
|
pact_broker:
|
@@ -68,33 +61,61 @@ en:
|
|
68
61
|
version_branch: Configure the version branch to be the value of your repository branch.
|
69
62
|
errors:
|
70
63
|
validation:
|
71
|
-
|
64
|
+
no_spaces: "cannot contain spaces"
|
65
|
+
single_line: "cannot contain multiple lines"
|
66
|
+
environment_not_found: "with name '%{value}' does not exist"
|
67
|
+
blank: "cannot be blank"
|
68
|
+
cannot_be_provided_at_same_time: "%{name_1} and %{name_2} cannot be provided at the same time"
|
69
|
+
blank_with_name: "%{name} cannot be blank"
|
72
70
|
attribute_missing: "Missing required attribute '%{attribute}'"
|
73
71
|
invalid_http_method: "Invalid HTTP method '%{method}'"
|
74
72
|
invalid_url: "Invalid URL '%{url}'. Expected format: http://example.org"
|
75
73
|
pact_missing_pacticipant_name: "was not found at expected path $.%{pacticipant}.name in the submitted pact file."
|
76
|
-
pact_content_modification_not_allowed: "Cannot change the content of the pact for %{consumer_name} version %{consumer_version_number} and provider %{provider_name}, as race conditions will cause unreliable results for can-i-deploy. Each pact must be published with a unique consumer version number. For more information see https://docs.pact.io/go/versioning"
|
74
|
+
pact_content_modification_not_allowed: "Cannot change the content of the pact for %{consumer_name} version %{consumer_version_number} and provider %{provider_name}, as race conditions will cause unreliable results for can-i-deploy. Each pact must be published with a unique consumer version number. Some Pact libraries generate random data when a concrete value for a type matcher is not specified, and this can cause the contract to mutate - ensure you have given example values for all type matchers. For more information see https://docs.pact.io/go/versioning"
|
77
75
|
consumer_version_number_missing: "Please specify the consumer version number by setting the X-Pact-Consumer-Version header."
|
78
76
|
consumer_version_number_header_invalid: "X-Pact-Consumer-Version '%{consumer_version_number}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
79
|
-
consumer_version_number_invalid: "Consumer version number '%{consumer_version_number}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
80
77
|
pacticipant_name_mismatch: "in pact ('%{name_in_pact}') does not match %{pacticipant} name in path ('%{name}')."
|
81
|
-
consumer_name_in_content_mismatch_pacticipant_name: "consumer name in contract content ('%{consumer_name_in_content}') must match pacticipantName ('%{pacticipant_name}')"
|
82
78
|
consumer_name_in_contract_mismatch_pacticipant_name: "consumerName ('%{consumer_name_in_contract}') must match pacticipantName ('%{pacticipant_name}')"
|
83
|
-
|
79
|
+
consumer_name_in_content_mismatch: "consumer name in contract content ('%{consumer_name_in_content}') must match consumerName in contract params ('%{consumer_name}')"
|
80
|
+
provider_name_in_content_mismatch: "provider name in contract content ('%{provider_name_in_content}') must match providerName in contract params ('%{provider_name}')"
|
84
81
|
connection_encoding_not_utf8: "The Sequel connection encoding (%{encoding}) is strongly recommended to be \"utf8\". If you need to set it to %{encoding} for some particular reason, then disable this check by setting config.validate_database_connection_config = false"
|
85
82
|
invalid_webhook_uuid: The UUID can only contain the characters A-Z, a-z, 0-9, _ and -, and must be 16 or more characters.
|
86
83
|
pacticipant_not_found: No pacticipant with name '%{name}' found
|
87
|
-
environment_name_must_be_unique:
|
84
|
+
environment_name_must_be_unique: "name '%{name}' is already used by an existing environment."
|
88
85
|
must_specify_environment_or_tag: Must specify either an environment or a 'to' tag.
|
89
86
|
cannot_specify_tag_and_environment: Cannot specify both a 'to' tag and an environment.
|
90
87
|
cannot_specify_latest_and_environment: Cannot specify both latest=true and an environment.
|
91
88
|
cannot_specify_more_than_one_destination_identifier: Cannot specify more than one of tag, environment and mainBranch.
|
92
89
|
environment_with_name_not_found: "Environment with name '%{name}' does not exist"
|
93
90
|
cannot_modify_version_branch: "The branch for a pacticipant version cannot be changed once set (currently '%{old_branch}', proposed value '%{new_branch}'). Your pact publication/verification publication configurations may be in conflict with each other if you are seeing this error. If the current branch value is incorrect, you must delete the pacticipant version resource at %{version_url} and publish the pacts/verification results again with a consistent branch name."
|
94
|
-
invalid_content_for_content_type: "
|
91
|
+
invalid_content_for_content_type: "content could not be parsed as %{content_type}"
|
95
92
|
cannot_set_currently_deployed_true: The currentlyDeployed property cannot be set back to true. Please record a new deployment.
|
96
93
|
cannot_set_currently_supported_true: The currentlySupported property cannot be set back to true. Please record a new deployment.
|
97
94
|
invalid_limit: The limit must be 1 or greater.
|
95
|
+
pacts_for_verification_selector_fallback_tag: "fallbackTag can only be set if latest is true"
|
96
|
+
pacts_for_verification_selector_matching_branch_requires_provider_version_branch: the providerVersionBranch must be specified when the selector matchingBranch=true is used
|
97
|
+
pacts_for_verification_selector_tag_and_branch_disallowed: "cannot specify both a tag and a branch"
|
98
|
+
pacts_for_verification_selector_fallback_tag_requires_tag: "a tag must be specified when a fallbackTag is specified"
|
99
|
+
pacts_for_verification_selector_fallback_branch_requires_branch: "a branch must be specified when a fallbackBranch is specified"
|
100
|
+
pacts_for_verification_selector_branch_and_latest_false_disallowed: cannot specify a branch with latest=false
|
101
|
+
pacts_for_verification_selector_main_branch_and_latest_false_disallowed: cannot specify mainBranch=true with latest=false
|
102
|
+
pacts_for_verification_selector_fallback_branch_and_latest_false_disallowed: fallbackBranch can only be set if latest is true
|
103
|
+
pacts_for_verification_selector_required_params_missing: must specify a value for environment or tag or branch, or specify mainBranch=true, matchingBranch=true, latest=true, deployed=true, released=true or deployedOrReleased=true
|
104
|
+
pacts_for_verification_selector_main_branch_with_other_param_disallowed: cannot specify mainBranch=true with any other criteria apart from consumer
|
105
|
+
pacts_for_verification_selector_matching_branch_with_other_param_disallowed: cannot specify matchingBranch=true with any other criteria apart from consumer
|
106
|
+
pacts_for_verification_selector_deployed_and_released_disallowed: cannot specify both deployed=true and released=true
|
107
|
+
pacts_for_verification_selector_deployed_and_deployed_or_released_disallowed: cannot specify both deployed=true and deployedOrReleased=true
|
108
|
+
pacts_for_verification_selector_released_and_deployed_or_released_disallowed: cannot specify both released=true and deployedOrReleased=true
|
109
|
+
pacts_for_verification_selector_provider_version_branch_empty: when pending or WIP pacts are enabled and there are no tags provided, the provider version branch must not be an empty string, as it is used in the calculations for WIP/pending. A value must be provided (recommended), or it must not be set at all.
|
110
|
+
pact_name_in_path_mismatch_name_in_pact: "name in pact '%{name_in_pact}' does not match name in URL path '%{name_in_path}'."
|
111
|
+
base64: "is not valid Base64"
|
112
|
+
non_utf_8_char_in_contract: "contract content has a non UTF-8 character at char %{char_number} and cannot be parsed as JSON. Fragment preceding invalid character is: '%{fragment}'"
|
113
|
+
invalid_consumer_version_number: "Consumer version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
114
|
+
invalid_version_number: "Version number '%{value}' cannot be parsed to a version number. The expected format (unless this configuration has been overridden) is a semantic version. eg. 1.3.0 or 2.0.4.rc1"
|
115
|
+
invalid_url: "is not a valid URL eg. http://example.org"
|
116
|
+
pacticipant_with_name_not_found: "does not match an existing pacticipant"
|
117
|
+
invalid_http_method: "is not a recognised HTTP method"
|
118
|
+
webhook_templated_host_not_allowed: "cannot have a template parameter in the host"
|
98
119
|
duplicate_pacticipant: |
|
99
120
|
This is the first time a pact has been published for "%{new_name}".
|
100
121
|
The name "%{new_name}" is very similar to the following existing pacticipants:
|
@@ -109,6 +130,7 @@ en:
|
|
109
130
|
new_line_in_url_path: URL path cannot contain a new line character.
|
110
131
|
tab_in_url_path: URL path cannot contain a tab character.
|
111
132
|
non_utf_8_char_in_request_body: "Request body has a non UTF-8 character at char %{char_number} and cannot be parsed as JSON. Fragment preceding invalid character is: '%{fragment}'"
|
133
|
+
non_utf_8_char_in_contract: "Contract has a non UTF-8 character at char %{char_number} and cannot be parsed as JSON. Fragment preceding invalid character is: '%{fragment}'"
|
112
134
|
|
113
135
|
"400":
|
114
136
|
title: 400 Malformed Request
|
@@ -17,10 +17,10 @@ module PactBroker
|
|
17
17
|
|
18
18
|
def self.from_selectors(selectors)
|
19
19
|
most_specific_criteria = selectors.collect(&:most_specific_criterion)
|
20
|
-
all_pacticipant_ids = selectors.collect(&:pacticipant_id)
|
21
|
-
specified_pacticipant_ids = selectors.select(&:specified?).collect(&:pacticipant_id)
|
22
|
-
pacticipant_version_ids = collect_ids(most_specific_criteria, :pacticipant_version_id)
|
23
|
-
pacticipant_ids = collect_ids(most_specific_criteria, :pacticipant_id)
|
20
|
+
all_pacticipant_ids = selectors.collect(&:pacticipant_id).uniq
|
21
|
+
specified_pacticipant_ids = selectors.select(&:specified?).collect(&:pacticipant_id).uniq
|
22
|
+
pacticipant_version_ids = collect_ids(most_specific_criteria, :pacticipant_version_id).uniq
|
23
|
+
pacticipant_ids = collect_ids(most_specific_criteria, :pacticipant_id).uniq
|
24
24
|
QueryIds.new(all_pacticipant_ids, specified_pacticipant_ids, pacticipant_ids, pacticipant_version_ids)
|
25
25
|
end
|
26
26
|
|