pact_broker 2.31.0 → 2.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/db/migrations/20190509_create_version_sequence.rb +8 -0
- data/db/migrations/20190510_set_version_sequence.rb +9 -0
- data/db/migrations/20190511_create_integrations_view.rb +19 -0
- data/db/migrations/20190523_add_enabled_column_to_webhooks.rb +5 -0
- data/db/migrations/20190524_set_webhooks_enabled.rb +10 -0
- data/db/migrations/20190525_add_description_column_to_webhooks.rb +5 -0
- data/lib/pact_broker/api.rb +3 -0
- data/lib/pact_broker/api/decorators/base_decorator.rb +0 -3
- data/lib/pact_broker/api/decorators/integration_decorator.rb +40 -0
- data/lib/pact_broker/api/decorators/integrations_decorator.rb +19 -0
- data/lib/pact_broker/api/decorators/pact_decorator.rb +1 -1
- data/lib/pact_broker/api/decorators/pact_details_decorator.rb +1 -6
- data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +12 -0
- data/lib/pact_broker/api/decorators/verifiable_pacts_decorator.rb +20 -0
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +5 -1
- data/lib/pact_broker/api/decorators/webhook_execution_result_decorator.rb +0 -1
- data/lib/pact_broker/api/decorators/webhooks_decorator.rb +2 -2
- data/lib/pact_broker/api/pact_broker_urls.rb +37 -3
- data/lib/pact_broker/api/resources/base_resource.rb +4 -0
- data/lib/pact_broker/api/resources/dashboard.rb +1 -1
- data/lib/pact_broker/api/resources/integrations.rb +10 -2
- data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +8 -14
- data/lib/pact_broker/api/resources/pact.rb +15 -3
- data/lib/pact_broker/api/resources/verification.rb +0 -2
- data/lib/pact_broker/api/resources/verifications.rb +18 -1
- data/lib/pact_broker/api/resources/webhook.rb +1 -1
- data/lib/pact_broker/api/resources/webhook_execution.rb +18 -9
- data/lib/pact_broker/app.rb +10 -11
- data/lib/pact_broker/db.rb +2 -2
- data/lib/pact_broker/db/data_migrations/helpers.rb +11 -0
- data/lib/pact_broker/db/data_migrations/set_latest_version_sequence_value.rb +29 -0
- data/lib/pact_broker/db/data_migrations/set_webhooks_enabled.rb +17 -0
- data/lib/pact_broker/db/migrate_data.rb +2 -0
- data/lib/pact_broker/db/seed_example_data.rb +6 -3
- data/lib/pact_broker/domain/order_versions.rb +14 -1
- data/lib/pact_broker/domain/verification.rb +4 -0
- data/lib/pact_broker/domain/webhook.rb +13 -3
- data/lib/pact_broker/domain/webhook_request.rb +3 -2
- data/lib/pact_broker/index/service.rb +3 -0
- data/lib/pact_broker/integrations/integration.rb +10 -0
- data/lib/pact_broker/integrations/service.rb +5 -0
- data/lib/pact_broker/matrix/parse_query.rb +2 -0
- data/lib/pact_broker/matrix/row.rb +8 -0
- data/lib/pact_broker/matrix/service.rb +1 -2
- data/lib/pact_broker/pacts/service.rb +16 -9
- data/lib/pact_broker/test/test_data_builder.rb +6 -2
- data/lib/pact_broker/verifications/sequence.rb +0 -2
- data/lib/pact_broker/verifications/service.rb +10 -2
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/sequence.rb +38 -0
- data/lib/pact_broker/webhooks/job.rb +19 -7
- data/lib/pact_broker/webhooks/render.rb +30 -13
- data/lib/pact_broker/webhooks/repository.rb +3 -4
- data/lib/pact_broker/webhooks/service.rb +60 -34
- data/lib/pact_broker/webhooks/trigger_service.rb +6 -6
- data/lib/pact_broker/webhooks/webhook.rb +9 -1
- data/lib/pact_broker/webhooks/webhook_request_template.rb +11 -7
- data/lib/rack/pact_broker/database_transaction.rb +6 -2
- data/script/publish-new.sh +23 -1
- data/script/publish.sh +13 -4
- data/script/seed.rb +53 -52
- data/spec/features/create_webhook_spec.rb +2 -0
- data/spec/features/execute_webhook_spec.rb +4 -3
- data/spec/features/get_integrations_spec.rb +17 -0
- data/spec/features/get_pacts_to_verify_spec.rb +7 -3
- data/spec/features/publish_verification_spec.rb +8 -1
- data/spec/features/update_webhook_spec.rb +47 -0
- data/spec/integration/webhooks/certificate_spec.rb +1 -1
- data/spec/lib/pact_broker/api/contracts/webhook_contract_spec.rb +12 -0
- data/spec/lib/pact_broker/api/decorators/integration_decorator_spec.rb +82 -0
- data/spec/lib/pact_broker/api/decorators/integrations_decorator_spec.rb +29 -0
- data/spec/lib/pact_broker/api/decorators/pact_decorator_spec.rb +12 -4
- data/spec/lib/pact_broker/api/decorators/verifiable_pact_decorator_spec.rb +30 -0
- data/spec/lib/pact_broker/api/decorators/verifiable_pacts_decorator_spec.rb +29 -0
- data/spec/lib/pact_broker/api/decorators/webhook_decorator_spec.rb +20 -1
- data/spec/lib/pact_broker/api/decorators/webhook_execution_result_decorator_spec.rb +0 -4
- data/spec/lib/pact_broker/api/decorators/webhooks_decorator_spec.rb +5 -4
- data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +64 -1
- data/spec/lib/pact_broker/api/resources/pact_spec.rb +0 -3
- data/spec/lib/pact_broker/api/resources/verifications_spec.rb +40 -10
- data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +13 -3
- data/spec/lib/pact_broker/app_spec.rb +28 -4
- data/spec/lib/pact_broker/db/data_migrations/set_latest_version_sequence_value_spec.rb +68 -0
- data/spec/lib/pact_broker/domain/order_versions_spec.rb +1 -4
- data/spec/lib/pact_broker/domain/webhook_spec.rb +10 -6
- data/spec/lib/pact_broker/matrix/parse_query_spec.rb +15 -7
- data/spec/lib/pact_broker/pacts/service_spec.rb +13 -5
- data/spec/lib/pact_broker/verifications/service_spec.rb +15 -3
- data/spec/lib/pact_broker/versions/repository_spec.rb +1 -1
- data/spec/lib/pact_broker/webhooks/job_spec.rb +52 -15
- data/spec/lib/pact_broker/webhooks/render_spec.rb +28 -7
- data/spec/lib/pact_broker/webhooks/repository_spec.rb +23 -32
- data/spec/lib/pact_broker/webhooks/service_spec.rb +186 -62
- data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +6 -5
- data/spec/lib/pact_broker/webhooks/webhook_request_template_spec.rb +12 -5
- data/spec/lib/rack/pact_broker/database_transaction_spec.rb +10 -0
- data/spec/lib/rack/pact_broker/ui_request_filter_spec.rb +9 -0
- data/spec/migrations/23_pact_versions_spec.rb +7 -1
- data/spec/support/database_cleaner.rb +11 -1
- data/spec/support/metadata_test_server.rb +40 -0
- data/spec/support/verification_job.rb +34 -0
- data/spec/support/webhook_endpoint_middleware.rb +22 -0
- metadata +37 -2
@@ -19,6 +19,9 @@ module PactBroker
|
|
19
19
|
.eager(:latest_triggered_webhooks)
|
20
20
|
.eager(:webhooks)
|
21
21
|
|
22
|
+
rows = rows.consumer(options[:consumer_name]) if options[:consumer_name]
|
23
|
+
rows = rows.provider(options[:provider_name]) if options[:provider_name]
|
24
|
+
|
22
25
|
if !options[:tags]
|
23
26
|
rows = rows.where(consumer_version_tag_name: nil)
|
24
27
|
else
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'pact_broker/db'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Integrations
|
5
|
+
class Integration < Sequel::Model
|
6
|
+
associate(:many_to_one, :consumer, :class => "PactBroker::Domain::Pacticipant", :key => :consumer_id, :primary_key => :id)
|
7
|
+
associate(:many_to_one, :provider, :class => "PactBroker::Domain::Pacticipant", :key => :provider_id, :primary_key => :id)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'pact_broker/services'
|
2
2
|
require 'pact_broker/repositories'
|
3
3
|
require 'pact_broker/logging'
|
4
|
+
require 'pact_broker/integrations/integration'
|
4
5
|
|
5
6
|
module PactBroker
|
6
7
|
module Integrations
|
@@ -9,6 +10,10 @@ module PactBroker
|
|
9
10
|
extend PactBroker::Services
|
10
11
|
include PactBroker::Logging
|
11
12
|
|
13
|
+
def self.find_all
|
14
|
+
PactBroker::Integrations::Integration.eager(:consumer).eager(:provider).all
|
15
|
+
end
|
16
|
+
|
12
17
|
def self.delete(consumer_name, provider_name)
|
13
18
|
consumer = pacticipant_service.find_pacticipant_by_name(consumer_name)
|
14
19
|
provider = pacticipant_service.find_pacticipant_by_name(provider_name)
|
@@ -25,6 +25,14 @@ module PactBroker
|
|
25
25
|
include PactBroker::Repositories::Helpers
|
26
26
|
include PactBroker::Logging
|
27
27
|
|
28
|
+
def consumer consumer_name
|
29
|
+
where(name_like(:consumer_name, consumer_name))
|
30
|
+
end
|
31
|
+
|
32
|
+
def provider provider_name
|
33
|
+
where(name_like(:provider_name, provider_name))
|
34
|
+
end
|
35
|
+
|
28
36
|
def matching_selectors selectors
|
29
37
|
if selectors.size == 1
|
30
38
|
where_consumer_or_provider_is(selectors.first)
|
@@ -16,9 +16,8 @@ module PactBroker
|
|
16
16
|
QueryResultsWithDeploymentStatusSummary.new(query_results.rows, query_results.selectors, query_results.options, query_results.resolved_selectors, query_results.integrations, deployment_status_summary)
|
17
17
|
end
|
18
18
|
|
19
|
-
def find_for_consumer_and_provider params
|
19
|
+
def find_for_consumer_and_provider params, options = {}
|
20
20
|
selectors = [{ pacticipant_name: params[:consumer_name] }, { pacticipant_name: params[:provider_name] }]
|
21
|
-
options = { latestby: 'cvpv' }
|
22
21
|
find(selectors, options)
|
23
22
|
end
|
24
23
|
|
@@ -40,20 +40,20 @@ module PactBroker
|
|
40
40
|
pact_repository.delete(params)
|
41
41
|
end
|
42
42
|
|
43
|
-
def create_or_update_pact params
|
43
|
+
def create_or_update_pact params, webhook_options
|
44
44
|
provider = pacticipant_repository.find_by_name_or_create params[:provider_name]
|
45
45
|
consumer = pacticipant_repository.find_by_name_or_create params[:consumer_name]
|
46
46
|
consumer_version = version_repository.find_by_pacticipant_id_and_number_or_create consumer.id, params[:consumer_version_number]
|
47
47
|
existing_pact = pact_repository.find_by_version_and_provider(consumer_version.id, provider.id)
|
48
48
|
|
49
49
|
if existing_pact
|
50
|
-
update_pact params, existing_pact
|
50
|
+
update_pact params, existing_pact, webhook_options
|
51
51
|
else
|
52
|
-
create_pact params, consumer_version, provider
|
52
|
+
create_pact params, consumer_version, provider, webhook_options
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
def merge_pact params
|
56
|
+
def merge_pact params, webhook_options
|
57
57
|
provider = pacticipant_repository.find_by_name_or_create params[:provider_name]
|
58
58
|
consumer = pacticipant_repository.find_by_name_or_create params[:consumer_name]
|
59
59
|
consumer_version = version_repository.find_by_pacticipant_id_and_number_or_create consumer.id, params[:consumer_version_number]
|
@@ -61,7 +61,7 @@ module PactBroker
|
|
61
61
|
|
62
62
|
params.merge!(json_content: Merger.merge_pacts(existing_pact.json_content, params[:json_content]))
|
63
63
|
|
64
|
-
update_pact params, existing_pact
|
64
|
+
update_pact params, existing_pact, webhook_options
|
65
65
|
end
|
66
66
|
|
67
67
|
def find_all_pact_versions_between consumer, options
|
@@ -113,7 +113,7 @@ module PactBroker
|
|
113
113
|
private
|
114
114
|
|
115
115
|
# Overwriting an existing pact with the same consumer/provider/consumer version number
|
116
|
-
def update_pact params, existing_pact
|
116
|
+
def update_pact params, existing_pact, webhook_options
|
117
117
|
logger.info "Updating existing pact publication with params #{params.reject{ |k, v| k == :json_content}}"
|
118
118
|
logger.debug "Content #{params[:json_content]}"
|
119
119
|
pact_version_sha = generate_sha(params[:json_content])
|
@@ -121,13 +121,13 @@ module PactBroker
|
|
121
121
|
update_params = { pact_version_sha: pact_version_sha, json_content: json_content }
|
122
122
|
updated_pact = pact_repository.update(existing_pact.id, update_params)
|
123
123
|
|
124
|
-
webhook_trigger_service.trigger_webhooks_for_updated_pact(existing_pact, updated_pact)
|
124
|
+
webhook_trigger_service.trigger_webhooks_for_updated_pact(existing_pact, updated_pact, merge_consumer_version_info(webhook_options, updated_pact))
|
125
125
|
|
126
126
|
updated_pact
|
127
127
|
end
|
128
128
|
|
129
129
|
# When no publication for the given consumer/provider/consumer version number exists
|
130
|
-
def create_pact params, version, provider
|
130
|
+
def create_pact params, version, provider, webhook_options
|
131
131
|
logger.info "Creating new pact publication with params #{params.reject{ |k, v| k == :json_content}}"
|
132
132
|
logger.debug "Content #{params[:json_content]}"
|
133
133
|
pact_version_sha = generate_sha(params[:json_content])
|
@@ -139,7 +139,7 @@ module PactBroker
|
|
139
139
|
pact_version_sha: pact_version_sha,
|
140
140
|
json_content: json_content
|
141
141
|
)
|
142
|
-
webhook_trigger_service.trigger_webhooks_for_new_pact pact
|
142
|
+
webhook_trigger_service.trigger_webhooks_for_new_pact(pact, merge_consumer_version_info(webhook_options, pact))
|
143
143
|
pact
|
144
144
|
end
|
145
145
|
|
@@ -150,6 +150,13 @@ module PactBroker
|
|
150
150
|
def add_interaction_ids(json_content)
|
151
151
|
Content.from_json(json_content).with_ids.to_json
|
152
152
|
end
|
153
|
+
|
154
|
+
def merge_consumer_version_info(webhook_options, pact)
|
155
|
+
webhook_context = webhook_options.fetch(:webhook_context, {}).merge(
|
156
|
+
consumer_version_tags: pact.consumer_version_tag_names
|
157
|
+
)
|
158
|
+
webhook_options.merge(webhook_context: webhook_context)
|
159
|
+
end
|
153
160
|
end
|
154
161
|
end
|
155
162
|
end
|
@@ -228,8 +228,8 @@ module PactBroker
|
|
228
228
|
params[:events] || [{ name: PactBroker::Webhooks::WebhookEvent::DEFAULT_EVENT_NAME }]
|
229
229
|
end
|
230
230
|
events = event_params.collect{ |e| PactBroker::Webhooks::WebhookEvent.new(e) }
|
231
|
-
|
232
|
-
request = PactBroker::Webhooks::WebhookRequestTemplate.new(
|
231
|
+
template_params = { method: 'POST', url: 'http://example.org', headers: {'Content-Type' => 'application/json'}, username: params[:username], password: params[:password]}
|
232
|
+
request = PactBroker::Webhooks::WebhookRequestTemplate.new(template_params.merge(params))
|
233
233
|
@webhook = PactBroker::Webhooks::Repository.new.create uuid, PactBroker::Domain::Webhook.new(request: request, events: events), consumer, provider
|
234
234
|
self
|
235
235
|
end
|
@@ -242,6 +242,10 @@ module PactBroker
|
|
242
242
|
create_webhook(parameters.merge(consumer: nil, provider: nil))
|
243
243
|
end
|
244
244
|
|
245
|
+
def create_global_verification_webhook parameters = {}
|
246
|
+
create_webhook(parameters.merge(consumer: nil, provider: nil, event_names: [PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED]))
|
247
|
+
end
|
248
|
+
|
245
249
|
def create_provider_webhook parameters = {}
|
246
250
|
create_webhook(parameters.merge(consumer: nil))
|
247
251
|
end
|
@@ -18,14 +18,22 @@ module PactBroker
|
|
18
18
|
verification_repository.next_number
|
19
19
|
end
|
20
20
|
|
21
|
-
def create next_verification_number, params, pact
|
21
|
+
def create next_verification_number, params, pact, webhook_options
|
22
22
|
logger.info "Creating verification #{next_verification_number} for pact_id=#{pact.id} from params #{params}"
|
23
23
|
verification = PactBroker::Domain::Verification.new
|
24
24
|
provider_version_number = params.fetch('providerApplicationVersion')
|
25
25
|
PactBroker::Api::Decorators::VerificationDecorator.new(verification).from_hash(params)
|
26
26
|
verification.number = next_verification_number
|
27
27
|
verification = verification_repository.create(verification, provider_version_number, pact)
|
28
|
-
|
28
|
+
webhook_context = webhook_options[:webhook_context].merge(
|
29
|
+
provider_version_tags: verification.provider_version_tag_names
|
30
|
+
)
|
31
|
+
|
32
|
+
webhook_service.trigger_webhooks(pact,
|
33
|
+
verification,
|
34
|
+
PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED,
|
35
|
+
webhook_options.merge(webhook_context: webhook_context)
|
36
|
+
)
|
29
37
|
verification
|
30
38
|
end
|
31
39
|
|
data/lib/pact_broker/version.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'sequel'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Versions
|
5
|
+
class Sequence < Sequel::Model(:version_sequence_number)
|
6
|
+
|
7
|
+
dataset_module do
|
8
|
+
# The easiest way to implement a cross database compatible sequence.
|
9
|
+
# Sad, I know.
|
10
|
+
def next_val
|
11
|
+
db.transaction do
|
12
|
+
for_update.first
|
13
|
+
select_all.update(value: Sequel[:value]+1)
|
14
|
+
row = first
|
15
|
+
if row
|
16
|
+
row.value
|
17
|
+
else
|
18
|
+
# The first row should have been created in the migration, so this code
|
19
|
+
# should only ever be executed in a test context, after we've truncated all the
|
20
|
+
# tables after a test.
|
21
|
+
# There would be a risk of a race condition creating two rows if this
|
22
|
+
# code executed in prod, as I don't think you can lock an empty table
|
23
|
+
# to prevent another record being inserted.
|
24
|
+
max_version_order = PactBroker::Domain::Version.max(:order)
|
25
|
+
value = max_version_order ? max_version_order + 100 : 1
|
26
|
+
insert(value: value)
|
27
|
+
value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Table: version_sequence_number
|
37
|
+
# Columns:
|
38
|
+
# value | integer | NOT NULL
|
@@ -18,14 +18,23 @@ module PactBroker
|
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
-
attr_reader :triggered_webhook, :error_count
|
21
|
+
attr_reader :triggered_webhook, :error_count, :data
|
22
22
|
|
23
23
|
def perform_with_connection(data)
|
24
24
|
@data = data
|
25
|
-
|
25
|
+
triggered_webhook_id = data[:triggered_webhook].id
|
26
|
+
@triggered_webhook = PactBroker::Webhooks::TriggeredWebhook.find(id: triggered_webhook_id)
|
27
|
+
if triggered_webhook
|
28
|
+
perform_with_triggered_webhook
|
29
|
+
else
|
30
|
+
logger.info "Could not find webhook with id: #{triggered_webhook_id}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def perform_with_triggered_webhook
|
26
35
|
@error_count = data[:error_count] || 0
|
27
36
|
begin
|
28
|
-
webhook_execution_result = PactBroker::Webhooks::Service.execute_triggered_webhook_now
|
37
|
+
webhook_execution_result = PactBroker::Webhooks::Service.execute_triggered_webhook_now(triggered_webhook, webhook_options(data))
|
29
38
|
if webhook_execution_result.success?
|
30
39
|
handle_success
|
31
40
|
else
|
@@ -36,11 +45,14 @@ module PactBroker
|
|
36
45
|
end
|
37
46
|
end
|
38
47
|
|
39
|
-
def
|
40
|
-
|
48
|
+
def webhook_options(data)
|
49
|
+
execution_options = data[:execution_options].merge(
|
41
50
|
success_log_message: "Successfully executed webhook",
|
42
|
-
failure_log_message: failure_log_message
|
43
|
-
|
51
|
+
failure_log_message: failure_log_message
|
52
|
+
)
|
53
|
+
{
|
54
|
+
execution_options: execution_options,
|
55
|
+
webhook_context: data[:webhook_context]
|
44
56
|
}
|
45
57
|
end
|
46
58
|
|
@@ -4,15 +4,16 @@ module PactBroker
|
|
4
4
|
|
5
5
|
TEMPLATE_PARAMETER_REGEXP = /\$\{pactbroker\.[^\}]+\}/
|
6
6
|
|
7
|
-
def self.call(template, pact, trigger_verification,
|
7
|
+
def self.call(template, pact, trigger_verification, webhook_context, &escaper)
|
8
|
+
base_url = webhook_context[:base_url]
|
8
9
|
verification = trigger_verification || (pact && pact.latest_verification)
|
9
10
|
params = {
|
10
|
-
'${pactbroker.pactUrl}' => pact ? PactBroker::Api::PactBrokerUrls.
|
11
|
+
'${pactbroker.pactUrl}' => pact ? PactBroker::Api::PactBrokerUrls.pact_version_url_with_metadata(pact, base_url) : "",
|
11
12
|
'${pactbroker.verificationResultUrl}' => verification_url(verification, base_url),
|
12
|
-
'${pactbroker.consumerVersionNumber}' => pact
|
13
|
+
'${pactbroker.consumerVersionNumber}' => consumer_version_number(pact, webhook_context),
|
13
14
|
'${pactbroker.providerVersionNumber}' => verification ? verification.provider_version_number : "",
|
14
|
-
'${pactbroker.providerVersionTags}' => provider_version_tags(verification),
|
15
|
-
'${pactbroker.consumerVersionTags}' => consumer_version_tags(pact),
|
15
|
+
'${pactbroker.providerVersionTags}' => provider_version_tags(verification, webhook_context),
|
16
|
+
'${pactbroker.consumerVersionTags}' => consumer_version_tags(pact, webhook_context),
|
16
17
|
'${pactbroker.consumerName}' => pact ? pact.consumer_name : "",
|
17
18
|
'${pactbroker.providerName}' => pact ? pact.provider_name : "",
|
18
19
|
'${pactbroker.githubVerificationStatus}' => github_verification_status(verification),
|
@@ -47,19 +48,35 @@ module PactBroker
|
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
|
-
def self.
|
51
|
-
if
|
52
|
-
|
51
|
+
def self.consumer_version_number(pact, webhook_context)
|
52
|
+
if webhook_context[:consumer_version_number]
|
53
|
+
webhook_context[:consumer_version_number]
|
53
54
|
else
|
54
|
-
""
|
55
|
+
pact ? pact.consumer_version_number : ""
|
55
56
|
end
|
56
57
|
end
|
57
58
|
|
58
|
-
def self.
|
59
|
-
if
|
60
|
-
|
59
|
+
def self.consumer_version_tags pact, webhook_context
|
60
|
+
if webhook_context[:consumer_version_tags]
|
61
|
+
webhook_context[:consumer_version_tags].join(", ")
|
61
62
|
else
|
62
|
-
|
63
|
+
if pact
|
64
|
+
pact.consumer_version.tags.collect(&:name).join(", ")
|
65
|
+
else
|
66
|
+
""
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.provider_version_tags verification, webhook_context
|
72
|
+
if webhook_context[:provider_version_tags]
|
73
|
+
webhook_context[:provider_version_tags].join(", ")
|
74
|
+
else
|
75
|
+
if verification
|
76
|
+
verification.provider_version.tags.collect(&:name).join(", ")
|
77
|
+
else
|
78
|
+
""
|
79
|
+
end
|
63
80
|
end
|
64
81
|
end
|
65
82
|
|
@@ -34,6 +34,8 @@ module PactBroker
|
|
34
34
|
|
35
35
|
def update_by_uuid uuid, webhook
|
36
36
|
existing_webhook = Webhook.find(uuid: uuid)
|
37
|
+
existing_webhook.consumer_id = pacticipant_repository.find_by_name(webhook.consumer.name).id if webhook.consumer
|
38
|
+
existing_webhook.provider_id = pacticipant_repository.find_by_name(webhook.provider.name).id if webhook.provider
|
37
39
|
existing_webhook.update_from_domain(webhook).save
|
38
40
|
existing_webhook.headers.collect(&:delete)
|
39
41
|
existing_webhook.events.collect(&:delete)
|
@@ -82,10 +84,6 @@ module PactBroker
|
|
82
84
|
Webhook.where(consumer: consumer, provider: provider).destroy
|
83
85
|
end
|
84
86
|
|
85
|
-
def find_for_pact_and_event_name pact, event_name
|
86
|
-
find_by_consumer_and_or_provider_and_event_name(pact.consumer, pact.provider, event_name)
|
87
|
-
end
|
88
|
-
|
89
87
|
def find_by_consumer_and_or_provider_and_event_name consumer, provider, event_name
|
90
88
|
find_by_consumer_and_provider_and_event_name(consumer, provider, event_name) +
|
91
89
|
find_by_consumer_and_provider_and_event_name(nil, provider, event_name) +
|
@@ -100,6 +98,7 @@ module PactBroker
|
|
100
98
|
}
|
101
99
|
Webhook
|
102
100
|
.select_all_qualified
|
101
|
+
.enabled
|
103
102
|
.where(criteria)
|
104
103
|
.join(:webhook_events, { webhook_id: :id })
|
105
104
|
.where(Sequel[:webhook_events][:name] => event_name)
|
@@ -9,6 +9,7 @@ require 'pact_broker/webhooks/status'
|
|
9
9
|
require 'pact_broker/webhooks/webhook_event'
|
10
10
|
require 'pact_broker/verifications/placeholder_verification'
|
11
11
|
require 'pact_broker/pacts/placeholder_pact'
|
12
|
+
require 'pact_broker/api/decorators/webhook_decorator'
|
12
13
|
|
13
14
|
module PactBroker
|
14
15
|
|
@@ -40,7 +41,10 @@ module PactBroker
|
|
40
41
|
webhook_repository.find_by_uuid uuid
|
41
42
|
end
|
42
43
|
|
43
|
-
def self.update_by_uuid uuid,
|
44
|
+
def self.update_by_uuid uuid, params
|
45
|
+
webhook = webhook_repository.find_by_uuid(uuid)
|
46
|
+
maintain_redacted_params(webhook, params)
|
47
|
+
PactBroker::Api::Decorators::WebhookDecorator.new(webhook).from_hash(params)
|
44
48
|
webhook_repository.update_by_uuid uuid, webhook
|
45
49
|
end
|
46
50
|
|
@@ -63,31 +67,35 @@ module PactBroker
|
|
63
67
|
webhook_repository.find_all
|
64
68
|
end
|
65
69
|
|
66
|
-
def self.test_execution webhook
|
67
|
-
|
70
|
+
def self.test_execution webhook, options
|
71
|
+
execution_options = options[:execution_options].merge(
|
72
|
+
failure_log_message: "Webhook execution failed",
|
73
|
+
)
|
74
|
+
merged_options = options.merge(execution_options: execution_options)
|
68
75
|
verification = nil
|
69
76
|
if webhook.trigger_on_provider_verification_published?
|
70
77
|
verification = verification_service.search_for_latest(webhook.consumer_name, webhook.provider_name) || PactBroker::Verifications::PlaceholderVerification.new
|
71
78
|
end
|
72
79
|
|
73
80
|
pact = pact_service.search_for_latest_pact(consumer_name: webhook.consumer_name, provider_name: webhook.provider_name) || PactBroker::Pacts::PlaceholderPact.new
|
74
|
-
webhook.execute(pact, verification,
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
81
|
+
webhook.execute(pact, verification, merged_options)
|
82
|
+
end
|
83
|
+
|
84
|
+
# # TODO delete?
|
85
|
+
# def self.execute_webhook_now webhook, pact, verification = nil
|
86
|
+
# triggered_webhook = webhook_repository.create_triggered_webhook(next_uuid, webhook, pact, verification, USER)
|
87
|
+
# execution_options = { failure_log_message: "Webhook execution failed"}
|
88
|
+
# webhook_execution_result = execute_triggered_webhook_now triggered_webhook, execution_options
|
89
|
+
# if webhook_execution_result.success?
|
90
|
+
# webhook_repository.update_triggered_webhook_status triggered_webhook, TriggeredWebhook::STATUS_SUCCESS
|
91
|
+
# else
|
92
|
+
# webhook_repository.update_triggered_webhook_status triggered_webhook, TriggeredWebhook::STATUS_FAILURE
|
93
|
+
# end
|
94
|
+
# webhook_execution_result
|
95
|
+
# end
|
96
|
+
|
97
|
+
def self.execute_triggered_webhook_now triggered_webhook, webhook_options
|
98
|
+
webhook_execution_result = triggered_webhook.execute webhook_options
|
91
99
|
webhook_repository.create_execution triggered_webhook, webhook_execution_result
|
92
100
|
webhook_execution_result
|
93
101
|
end
|
@@ -108,17 +116,17 @@ module PactBroker
|
|
108
116
|
webhook_repository.find_by_consumer_and_provider consumer, provider
|
109
117
|
end
|
110
118
|
|
111
|
-
def self.trigger_webhooks pact, verification, event_name
|
119
|
+
def self.trigger_webhooks pact, verification, event_name, options
|
112
120
|
webhooks = webhook_repository.find_by_consumer_and_or_provider_and_event_name pact.consumer, pact.provider, event_name
|
113
121
|
|
114
122
|
if webhooks.any?
|
115
|
-
run_later(webhooks, pact, verification, event_name)
|
123
|
+
run_later(webhooks, pact, verification, event_name, options)
|
116
124
|
else
|
117
|
-
logger.debug "No
|
125
|
+
logger.debug "No enabled webhooks found for consumer \"#{pact.consumer.name}\" and provider \"#{pact.provider.name}\" and event #{event_name}"
|
118
126
|
end
|
119
127
|
end
|
120
128
|
|
121
|
-
def self.run_later webhooks, pact, verification, event_name
|
129
|
+
def self.run_later webhooks, pact, verification, event_name, options
|
122
130
|
trigger_uuid = next_uuid
|
123
131
|
webhooks.each do | webhook |
|
124
132
|
begin
|
@@ -126,8 +134,9 @@ module PactBroker
|
|
126
134
|
logger.info "Scheduling job for #{webhook.description} with uuid #{webhook.uuid}"
|
127
135
|
job_data = {
|
128
136
|
triggered_webhook: triggered_webhook,
|
129
|
-
|
130
|
-
|
137
|
+
webhook_context: options.fetch(:webhook_context),
|
138
|
+
execution_options: options.fetch(:execution_options),
|
139
|
+
database_connector: options.fetch(:database_connector)
|
131
140
|
}
|
132
141
|
# Delay slightly to make sure the request transaction has finished before we execute the webhook
|
133
142
|
Job.perform_in(5, job_data)
|
@@ -137,14 +146,6 @@ module PactBroker
|
|
137
146
|
end
|
138
147
|
end
|
139
148
|
|
140
|
-
def self.job_database_connector
|
141
|
-
Thread.current[:pact_broker_thread_data].database_connector
|
142
|
-
end
|
143
|
-
|
144
|
-
def self.base_url
|
145
|
-
Thread.current[:pact_broker_thread_data].base_url
|
146
|
-
end
|
147
|
-
|
148
149
|
def self.find_latest_triggered_webhooks_for_pact pact
|
149
150
|
webhook_repository.find_latest_triggered_webhooks_for_pact pact
|
150
151
|
end
|
@@ -164,6 +165,31 @@ module PactBroker
|
|
164
165
|
def self.find_triggered_webhooks_for_verification verification
|
165
166
|
webhook_repository.find_triggered_webhooks_for_verification(verification)
|
166
167
|
end
|
168
|
+
|
169
|
+
private
|
170
|
+
|
171
|
+
# Dirty hack to maintain existing password or Authorization header if it is submitted with value ****
|
172
|
+
# This is required because the password and Authorization header is **** out in the API response
|
173
|
+
# for security purposes, so it would need to be re-entered with every response.
|
174
|
+
# TODO implement proper 'secrets' management.
|
175
|
+
def self.maintain_redacted_params(webhook, params)
|
176
|
+
if webhook.request.password && password_key_does_not_exist_or_is_starred?(params)
|
177
|
+
params['request']['password'] = webhook.request.password
|
178
|
+
end
|
179
|
+
|
180
|
+
new_headers = params['request']['headers'] ||= {}
|
181
|
+
existing_headers = webhook.request.headers
|
182
|
+
starred_new_headers = new_headers.select { |key, value| value =~ /^\**$/ }
|
183
|
+
starred_new_headers.each do | (key, value) |
|
184
|
+
new_headers[key] = existing_headers[key]
|
185
|
+
end
|
186
|
+
params['request']['headers'] = new_headers
|
187
|
+
params
|
188
|
+
end
|
189
|
+
|
190
|
+
def self.password_key_does_not_exist_or_is_starred?(params)
|
191
|
+
!params['request'].key?('password') || params.dig('request','password') =~ /^\**$/
|
192
|
+
end
|
167
193
|
end
|
168
194
|
end
|
169
195
|
end
|