pact_broker 2.76.1 → 2.76.2
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 +7 -0
- data/ISSUES.md +10 -2
- data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +16 -5
- data/lib/pact_broker/api/resources/verifications.rb +5 -2
- data/lib/pact_broker/api/resources/webhook_execution.rb +1 -1
- data/lib/pact_broker/domain/webhook.rb +8 -8
- data/lib/pact_broker/hash_refinements.rb +4 -0
- data/lib/pact_broker/pacts/service.rb +4 -2
- data/lib/pact_broker/test/http_test_data_builder.rb +63 -18
- data/lib/pact_broker/verifications/service.rb +2 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/pact_and_verification_parameters.rb +10 -3
- data/lib/pact_broker/webhooks/service.rb +8 -7
- data/lib/pact_broker/webhooks/trigger_service.rb +56 -23
- data/lib/pact_broker/webhooks/triggered_webhook.rb +3 -1
- data/script/reproduce-issue-starting-up.rb +13 -23
- data/script/reproduce-issue.rb +2 -1
- data/script/trigger-release.sh +1 -1
- data/script/webhook-server.ru +5 -5
- data/spec/lib/pact_broker/api/resources/verifications_spec.rb +2 -5
- data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +3 -2
- data/spec/lib/pact_broker/domain/webhook_spec.rb +6 -6
- data/spec/lib/pact_broker/pacts/service_spec.rb +7 -5
- data/spec/lib/pact_broker/verifications/service_spec.rb +4 -1
- data/spec/lib/pact_broker/webhooks/render_spec.rb +6 -5
- data/spec/lib/pact_broker/webhooks/service_spec.rb +13 -9
- data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +60 -18
- metadata +2 -3
- data/docker-compose-issue-repro.yml +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdc8ed42038e4b622005f53471a000d870efd99a6dbd6b773aa9e8a3f9a993cb
|
4
|
+
data.tar.gz: d2f42cd3e13007471cdd33fabbe515afa9c9ff4896566868accd9961f66f557f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a250f5f452356d3a9eb87659933cc47d0e947b7ce10a8c984d7cd296a28bc9be7dcfe82bd37fba29919f570a949b9b4a46b1622d6d242b92698268e54018aadf
|
7
|
+
data.tar.gz: c136cbe836ed813de2819480cf3347de86248f00258e0f8e89ec33375cf0c929186a65c51ef620995c11d2c596d496bec858c430894f80bacd6f647877f4af3e
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
<a name="v2.76.2"></a>
|
2
|
+
### v2.76.2 (2021-01-29)
|
3
|
+
|
4
|
+
#### Bug Fixes
|
5
|
+
|
6
|
+
* trigger one webhook for each pact publication that the verified content belongs to when using the 'pacts for verification' API (#378) ([114ccad0](/../../commit/114ccad0))
|
7
|
+
|
1
8
|
<a name="v2.76.1"></a>
|
2
9
|
### v2.76.1 (2021-01-28)
|
3
10
|
|
data/ISSUES.md
CHANGED
@@ -11,13 +11,21 @@ To use it:
|
|
11
11
|
* Run the Pact Broker using a specific Pact Broker Docker image by setting the required tag for the pact-broker service in the docker-compose-issue-repro-with-pact-broker-docker-image.yml file.
|
12
12
|
|
13
13
|
```
|
14
|
-
|
14
|
+
# might need to try twice if it doesn't connect to postgres
|
15
|
+
docker-compose -f docker-compose-issue-repro-with-pact-broker-docker-image.yml up pact-broker
|
16
|
+
|
17
|
+
# if needing webhooks - new window
|
18
|
+
docker-compose -f docker-compose-issue-repro-with-pact-broker-docker-image.yml up webhook-server
|
19
|
+
|
20
|
+
# new window
|
21
|
+
docker-compose -f docker-compose-issue-repro-with-pact-broker-docker-image.yml run repro-issue
|
22
|
+
|
15
23
|
```
|
16
24
|
|
17
25
|
* Run the reproduction script.
|
18
26
|
|
19
27
|
```
|
20
|
-
docker-compose -f docker-compose-issue-repro-with-pact-broker-docker-image.yml
|
28
|
+
docker-compose -f docker-compose-issue-repro-with-pact-broker-docker-image.yml run repro-issue
|
21
29
|
```
|
22
30
|
|
23
31
|
You can modify `script/reproduce-issue.rb` and then re-run it with the change applied.
|
@@ -11,23 +11,34 @@ services:
|
|
11
11
|
POSTGRES_DB: postgres
|
12
12
|
|
13
13
|
pact-broker:
|
14
|
-
image: pactfoundation/pact-broker:2.
|
14
|
+
image: pactfoundation/pact-broker:2.76.0.0
|
15
15
|
ports:
|
16
16
|
- "9292:9292"
|
17
|
-
depends_on:
|
18
|
-
|
17
|
+
# depends_on:
|
18
|
+
# - postgres
|
19
19
|
environment:
|
20
20
|
PACT_BROKER_PORT: '9292'
|
21
|
-
PACT_BROKER_DATABASE_URL: "postgres://postgres:password@postgres/postgres"
|
21
|
+
#PACT_BROKER_DATABASE_URL: "postgres://postgres:password@postgres/postgres"
|
22
|
+
PACT_BROKER_DATABASE_URL: "sqlite:////tmp/pact_broker.sqlite3"
|
22
23
|
PACT_BROKER_LOG_LEVEL: INFO
|
23
24
|
PACT_BROKER_SQL_LOG_LEVEL: DEBUG
|
25
|
+
PACT_BROKER_WEBHOOK_SCHEME_WHITELIST: "http https"
|
26
|
+
PACT_BROKER_WEBHOOK_HOST_WHITELIST: "/.*/"
|
24
27
|
|
25
28
|
repro-issue:
|
26
29
|
build: .
|
27
30
|
depends_on:
|
28
31
|
- pact-broker
|
29
|
-
command:
|
32
|
+
command: -wait http://pact-broker:9292 -timeout 30s /home/script/reproduce-issue.rb
|
33
|
+
entrypoint: dockerize
|
30
34
|
environment:
|
31
35
|
- PACT_BROKER_BASE_URL=http://pact-broker:9292
|
32
36
|
volumes:
|
33
37
|
- $PWD:/home
|
38
|
+
working_dir: /home
|
39
|
+
|
40
|
+
webhook-server:
|
41
|
+
build: .
|
42
|
+
entrypoint: ["/bin/sh", "-c", "bundle exec rackup -p 9393 -o 0.0.0.0 /home/script/webhook-server.ru"]
|
43
|
+
volumes:
|
44
|
+
- ./script/webhook-server.ru:/home/script/webhook-server.ru
|
@@ -50,7 +50,7 @@ module PactBroker
|
|
50
50
|
end
|
51
51
|
|
52
52
|
def from_json
|
53
|
-
verification = verification_service.create(next_verification_number, verification_params, pact, webhook_options)
|
53
|
+
verification = verification_service.create(next_verification_number, verification_params, pact, event_context, webhook_options)
|
54
54
|
response.body = decorator_for(verification).to_json(decorator_options)
|
55
55
|
true
|
56
56
|
end
|
@@ -81,11 +81,14 @@ module PactBroker
|
|
81
81
|
metadata[:wip] == 'true'
|
82
82
|
end
|
83
83
|
|
84
|
+
def event_context
|
85
|
+
metadata
|
86
|
+
end
|
87
|
+
|
84
88
|
def webhook_options
|
85
89
|
{
|
86
90
|
database_connector: database_connector,
|
87
91
|
webhook_execution_configuration: webhook_execution_configuration
|
88
|
-
.with_webhook_context(metadata)
|
89
92
|
}
|
90
93
|
end
|
91
94
|
|
@@ -26,7 +26,7 @@ module PactBroker
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def process_post
|
29
|
-
webhook_execution_result = webhook_service.test_execution(webhook, webhook_execution_configuration)
|
29
|
+
webhook_execution_result = webhook_service.test_execution(webhook, webhook_execution_configuration.webhook_context, webhook_execution_configuration)
|
30
30
|
response.headers['Content-Type'] = 'application/hal+json;charset=utf-8'
|
31
31
|
response.body = post_response_body(webhook_execution_result)
|
32
32
|
true
|
@@ -52,15 +52,15 @@ module PactBroker
|
|
52
52
|
request && request.description
|
53
53
|
end
|
54
54
|
|
55
|
-
def execute pact, verification, options
|
56
|
-
logger.info "Executing #{self}
|
57
|
-
webhook_request = request.build(template_parameters(pact, verification, options))
|
55
|
+
def execute pact, verification, event_context, options
|
56
|
+
logger.info "Executing #{self} event_context=#{event_context}"
|
57
|
+
webhook_request = request.build(template_parameters(pact, verification, event_context, options))
|
58
58
|
http_response, error = execute_request(webhook_request)
|
59
59
|
|
60
60
|
PactBroker::Webhooks::WebhookExecutionResult.new(
|
61
61
|
webhook_request.http_request,
|
62
62
|
http_response,
|
63
|
-
generate_logs(webhook_request, http_response, error,
|
63
|
+
generate_logs(webhook_request, http_response, error, event_context, options.fetch(:logging_options)),
|
64
64
|
error
|
65
65
|
)
|
66
66
|
end
|
@@ -106,18 +106,18 @@ module PactBroker
|
|
106
106
|
return http_response, error
|
107
107
|
end
|
108
108
|
|
109
|
-
def template_parameters(pact, verification, options)
|
110
|
-
PactBroker::Webhooks::PactAndVerificationParameters.new(pact, verification,
|
109
|
+
def template_parameters(pact, verification, event_context, options)
|
110
|
+
PactBroker::Webhooks::PactAndVerificationParameters.new(pact, verification, event_context).to_hash
|
111
111
|
end
|
112
112
|
|
113
|
-
def generate_logs(webhook_request, http_response, error,
|
113
|
+
def generate_logs(webhook_request, http_response, error, event_context, logging_options)
|
114
114
|
webhook_request_logger = PactBroker::Webhooks::WebhookRequestLogger.new(logging_options)
|
115
115
|
webhook_request_logger.log(
|
116
116
|
uuid,
|
117
117
|
webhook_request,
|
118
118
|
http_response,
|
119
119
|
error,
|
120
|
-
|
120
|
+
event_context
|
121
121
|
)
|
122
122
|
end
|
123
123
|
end
|
@@ -152,7 +152,8 @@ module PactBroker
|
|
152
152
|
update_params = { pact_version_sha: pact_version_sha, json_content: json_content }
|
153
153
|
updated_pact = pact_repository.update(existing_pact.id, update_params)
|
154
154
|
|
155
|
-
|
155
|
+
event_context = { consumer_version_tags: updated_pact.consumer_version_tag_names }
|
156
|
+
webhook_trigger_service.trigger_webhooks_for_updated_pact(existing_pact, updated_pact, event_context, merge_consumer_version_info(webhook_options, updated_pact))
|
156
157
|
|
157
158
|
updated_pact
|
158
159
|
end
|
@@ -170,7 +171,8 @@ module PactBroker
|
|
170
171
|
pact_version_sha: pact_version_sha,
|
171
172
|
json_content: json_content
|
172
173
|
)
|
173
|
-
|
174
|
+
event_context = { consumer_version_tags: pact.consumer_version_tag_names }
|
175
|
+
webhook_trigger_service.trigger_webhooks_for_new_pact(pact, event_context, merge_consumer_version_info(webhook_options, pact))
|
174
176
|
pact
|
175
177
|
end
|
176
178
|
|
@@ -24,8 +24,8 @@ module PactBroker
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
def sleep
|
28
|
-
Kernel.sleep
|
27
|
+
def sleep(seconds = 0.5)
|
28
|
+
Kernel.sleep(seconds)
|
29
29
|
self
|
30
30
|
end
|
31
31
|
|
@@ -111,28 +111,22 @@ module PactBroker
|
|
111
111
|
self
|
112
112
|
end
|
113
113
|
|
114
|
+
def verify_latest_pact_for_tag(success: true, provider: last_provider_name, consumer: last_consumer_name, consumer_version_tag: , provider_version:, provider_version_tag: nil)
|
115
|
+
@last_provider_name = provider
|
116
|
+
@last_consumer_name = consumer
|
117
|
+
url_of_pact_to_verify = "pacts/provider/#{encode(provider)}/consumer/#{encode(consumer)}/latest/#{encode(consumer_version_tag)}"
|
118
|
+
publish_verification_results(url_of_pact_to_verify, provider, provider_version, provider_version_tag, success)
|
119
|
+
separate
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
114
123
|
def verify_pact(index: 0, success:, provider: last_provider_name, provider_version_tag: , provider_version: )
|
115
124
|
@last_provider_name = provider
|
116
125
|
pact_to_verify = @pacts_for_verification_response.body["_embedded"]["pacts"][index]
|
117
126
|
raise "No pact found to verify at index #{index}" unless pact_to_verify
|
118
127
|
url_of_pact_to_verify = pact_to_verify["_links"]["self"]["href"]
|
119
128
|
|
120
|
-
|
121
|
-
create_tag(pacticipant: provider, version: provider_version, tag: tag)
|
122
|
-
end
|
123
|
-
puts "" if [*provider_version_tag].any?
|
124
|
-
|
125
|
-
pact_response = client.get(url_of_pact_to_verify).tap { |response| check_for_error(response) }
|
126
|
-
verification_results_url = pact_response.body["_links"]["pb:publish-verification-results"]["href"]
|
127
|
-
|
128
|
-
results = {
|
129
|
-
success: success,
|
130
|
-
testResults: [],
|
131
|
-
providerApplicationVersion: provider_version
|
132
|
-
}
|
133
|
-
puts "Publishing verification"
|
134
|
-
puts results.to_yaml
|
135
|
-
response = client.post(verification_results_url, results.to_json).tap { |response| check_for_error(response) }
|
129
|
+
publish_verification_results(url_of_pact_to_verify, provider, provider_version, provider_version_tag, success)
|
136
130
|
separate
|
137
131
|
self
|
138
132
|
end
|
@@ -156,6 +150,36 @@ module PactBroker
|
|
156
150
|
self
|
157
151
|
end
|
158
152
|
|
153
|
+
def create_global_webhook_for_verification_published(uuid: nil, url: "https://postman-echo.com/post")
|
154
|
+
puts "Creating global webhook for contract changed event with uuid #{uuid}"
|
155
|
+
uuid ||= SecureRandom.uuid
|
156
|
+
request_body = {
|
157
|
+
"description" => "A webhook for all consumers and providers",
|
158
|
+
"events" => [{
|
159
|
+
"name" => "contract_published"
|
160
|
+
},{
|
161
|
+
"name" => "provider_verification_published"
|
162
|
+
}],
|
163
|
+
"request" => {
|
164
|
+
"method" => "POST",
|
165
|
+
"url" => url,
|
166
|
+
"headers" => { "Content-Type" => "application/json"},
|
167
|
+
"body" => {
|
168
|
+
"eventName" => "${pactbroker.eventName}",
|
169
|
+
"consumerVersionNumber" => "${pactbroker.consumerVersionNumber}",
|
170
|
+
"consumerVersionTags" => "${pactbroker.consumerVersionTags}",
|
171
|
+
"githubVerificationStatus" => "${pactbroker.githubVerificationStatus}",
|
172
|
+
"providerVersionNumber" => "${pactbroker.providerVersionNumber}",
|
173
|
+
"providerVersionTags" => "${pactbroker.providerVersionTags}"
|
174
|
+
}
|
175
|
+
}
|
176
|
+
}
|
177
|
+
path = "webhooks/#{uuid}"
|
178
|
+
response = client.put(path, request_body.to_json).tap { |response| check_for_error(response) }
|
179
|
+
separate
|
180
|
+
self
|
181
|
+
end
|
182
|
+
|
159
183
|
def delete_webhook(uuid:)
|
160
184
|
puts "Deleting webhook with uuid #{uuid}"
|
161
185
|
path = "webhooks/#{uuid}"
|
@@ -220,6 +244,27 @@ module PactBroker
|
|
220
244
|
}
|
221
245
|
end
|
222
246
|
|
247
|
+
private
|
248
|
+
|
249
|
+
def publish_verification_results(url_of_pact_to_verify, provider, provider_version, provider_version_tag, success)
|
250
|
+
[*provider_version_tag].each do | tag |
|
251
|
+
create_tag(pacticipant: provider, version: provider_version, tag: tag)
|
252
|
+
end
|
253
|
+
puts "" if [*provider_version_tag].any?
|
254
|
+
|
255
|
+
pact_response = client.get(url_of_pact_to_verify).tap { |response| check_for_error(response) }
|
256
|
+
verification_results_url = pact_response.body["_links"]["pb:publish-verification-results"]["href"]
|
257
|
+
|
258
|
+
results = {
|
259
|
+
success: success,
|
260
|
+
testResults: [],
|
261
|
+
providerApplicationVersion: provider_version
|
262
|
+
}
|
263
|
+
puts "Publishing verification"
|
264
|
+
puts results.to_yaml
|
265
|
+
response = client.post(verification_results_url, results.to_json).tap { |response| check_for_error(response) }
|
266
|
+
end
|
267
|
+
|
223
268
|
def encode string
|
224
269
|
ERB::Util.url_encode(string)
|
225
270
|
end
|
@@ -20,7 +20,7 @@ module PactBroker
|
|
20
20
|
verification_repository.next_number
|
21
21
|
end
|
22
22
|
|
23
|
-
def create next_verification_number, params, pact, webhook_options
|
23
|
+
def create next_verification_number, params, pact, event_context, webhook_options
|
24
24
|
logger.info "Creating verification #{next_verification_number} for pact_id=#{pact.id}", payload: params.reject{ |k,_| k == "testResults"}
|
25
25
|
verification = PactBroker::Domain::Verification.new
|
26
26
|
provider_version_number = params.fetch('providerApplicationVersion')
|
@@ -35,6 +35,7 @@ module PactBroker
|
|
35
35
|
webhook_trigger_service.trigger_webhooks_for_verification_results_publication(
|
36
36
|
pact,
|
37
37
|
verification,
|
38
|
+
event_context.merge(provider_version_tags: verification.provider_version_tag_names),
|
38
39
|
webhook_options.deep_merge(webhook_execution_configuration: execution_configuration)
|
39
40
|
)
|
40
41
|
verification
|
data/lib/pact_broker/version.rb
CHANGED
@@ -13,6 +13,7 @@ module PactBroker
|
|
13
13
|
BITBUCKET_VERIFICATION_STATUS = 'pactbroker.bitbucketVerificationStatus'
|
14
14
|
CONSUMER_LABELS = 'pactbroker.consumerLabels'
|
15
15
|
PROVIDER_LABELS = 'pactbroker.providerLabels'
|
16
|
+
EVENT_NAME = 'pactbroker.eventName'
|
16
17
|
|
17
18
|
ALL = [
|
18
19
|
CONSUMER_NAME,
|
@@ -26,7 +27,8 @@ module PactBroker
|
|
26
27
|
GITHUB_VERIFICATION_STATUS,
|
27
28
|
BITBUCKET_VERIFICATION_STATUS,
|
28
29
|
CONSUMER_LABELS,
|
29
|
-
PROVIDER_LABELS
|
30
|
+
PROVIDER_LABELS,
|
31
|
+
EVENT_NAME
|
30
32
|
]
|
31
33
|
|
32
34
|
def initialize(pact, trigger_verification, webhook_context)
|
@@ -49,7 +51,8 @@ module PactBroker
|
|
49
51
|
GITHUB_VERIFICATION_STATUS => github_verification_status,
|
50
52
|
BITBUCKET_VERIFICATION_STATUS => bitbucket_verification_status,
|
51
53
|
CONSUMER_LABELS => pacticipant_labels(pact && pact.consumer),
|
52
|
-
PROVIDER_LABELS => pacticipant_labels(pact && pact.provider)
|
54
|
+
PROVIDER_LABELS => pacticipant_labels(pact && pact.provider),
|
55
|
+
EVENT_NAME => event_name
|
53
56
|
}
|
54
57
|
end
|
55
58
|
|
@@ -116,6 +119,10 @@ module PactBroker
|
|
116
119
|
def pacticipant_labels pacticipant
|
117
120
|
pacticipant && pacticipant.labels ? pacticipant.labels.collect(&:name).join(", ") : ""
|
118
121
|
end
|
122
|
+
|
123
|
+
def event_name
|
124
|
+
webhook_context.fetch(:event_name)
|
125
|
+
end
|
119
126
|
end
|
120
127
|
end
|
121
|
-
end
|
128
|
+
end
|
@@ -87,7 +87,7 @@ module PactBroker
|
|
87
87
|
webhook_repository.find_all
|
88
88
|
end
|
89
89
|
|
90
|
-
def self.test_execution webhook, execution_configuration
|
90
|
+
def self.test_execution webhook, event_context, execution_configuration
|
91
91
|
merged_options = execution_configuration.with_failure_log_message("Webhook execution failed").to_hash
|
92
92
|
|
93
93
|
verification = nil
|
@@ -96,7 +96,7 @@ module PactBroker
|
|
96
96
|
end
|
97
97
|
|
98
98
|
pact = pact_service.search_for_latest_pact(consumer_name: webhook.consumer_name, provider_name: webhook.provider_name) || PactBroker::Pacts::PlaceholderPact.new
|
99
|
-
webhook.execute(pact, verification, merged_options)
|
99
|
+
webhook.execute(pact, verification, event_context.merge(event_name: "test"), merged_options)
|
100
100
|
end
|
101
101
|
|
102
102
|
def self.execute_triggered_webhook_now triggered_webhook, webhook_execution_configuration_hash
|
@@ -121,23 +121,24 @@ module PactBroker
|
|
121
121
|
webhook_repository.find_by_consumer_and_provider consumer, provider
|
122
122
|
end
|
123
123
|
|
124
|
-
def self.trigger_webhooks pact, verification, event_name, options
|
124
|
+
def self.trigger_webhooks pact, verification, event_name, event_context, options
|
125
125
|
webhooks = webhook_repository.find_by_consumer_and_or_provider_and_event_name pact.consumer, pact.provider, event_name
|
126
126
|
|
127
127
|
if webhooks.any?
|
128
128
|
webhook_execution_configuration = options.fetch(:webhook_execution_configuration).with_webhook_context(event_name: event_name)
|
129
|
-
|
129
|
+
# bit messy to merge in base_url here, but easier than a big refactor
|
130
|
+
base_url = options.fetch(:webhook_execution_configuration).webhook_context.fetch(:base_url)
|
131
|
+
run_later(webhooks, pact, verification, event_name, event_context.merge(event_name: event_name, base_url: base_url), options.merge(webhook_execution_configuration: webhook_execution_configuration))
|
130
132
|
else
|
131
133
|
logger.info "No enabled webhooks found for consumer \"#{pact.consumer.name}\" and provider \"#{pact.provider.name}\" and event #{event_name}"
|
132
134
|
end
|
133
135
|
end
|
134
136
|
|
135
|
-
def self.run_later webhooks, pact, verification, event_name, options
|
137
|
+
def self.run_later webhooks, pact, verification, event_name, event_context, options
|
136
138
|
trigger_uuid = next_uuid
|
137
139
|
webhooks.each do | webhook |
|
138
140
|
begin
|
139
|
-
|
140
|
-
triggered_webhook = webhook_repository.create_triggered_webhook(trigger_uuid, webhook, pact, verification, RESOURCE_CREATION, event_name, webhook_context)
|
141
|
+
triggered_webhook = webhook_repository.create_triggered_webhook(trigger_uuid, webhook, pact, verification, RESOURCE_CREATION, event_name, event_context)
|
141
142
|
logger.info "Scheduling job for webhook with uuid #{webhook.uuid}"
|
142
143
|
logger.debug "Schedule webhook with options #{options}"
|
143
144
|
job_data = { triggered_webhook: triggered_webhook }.deep_merge(options)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'pact_broker/services'
|
2
|
+
require 'pact_broker/hash_refinements'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Webhooks
|
@@ -8,50 +9,56 @@ module PactBroker
|
|
8
9
|
extend PactBroker::Repositories
|
9
10
|
extend PactBroker::Services
|
10
11
|
include PactBroker::Logging
|
12
|
+
using PactBroker::HashRefinements
|
11
13
|
|
12
|
-
def trigger_webhooks_for_new_pact(pact, webhook_options)
|
13
|
-
webhook_service.trigger_webhooks pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, webhook_options
|
14
|
+
def trigger_webhooks_for_new_pact(pact, event_context, webhook_options)
|
15
|
+
webhook_service.trigger_webhooks pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, event_context, webhook_options
|
14
16
|
if pact_is_new_or_newly_tagged_or_pact_has_changed_since_previous_version?(pact)
|
15
|
-
webhook_service.trigger_webhooks pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, webhook_options
|
17
|
+
webhook_service.trigger_webhooks pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, webhook_options
|
16
18
|
else
|
17
19
|
logger.info "Pact content has not changed since previous version, not triggering webhooks for changed content"
|
18
20
|
end
|
19
21
|
end
|
20
22
|
|
21
|
-
def trigger_webhooks_for_updated_pact(existing_pact, updated_pact, webhook_options)
|
22
|
-
webhook_service.trigger_webhooks updated_pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, webhook_options
|
23
|
+
def trigger_webhooks_for_updated_pact(existing_pact, updated_pact, event_context, webhook_options)
|
24
|
+
webhook_service.trigger_webhooks updated_pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, event_context, webhook_options
|
23
25
|
# TODO this should use the sha!
|
24
26
|
if existing_pact.pact_version_sha != updated_pact.pact_version_sha
|
25
27
|
logger.info "Existing pact for version #{existing_pact.consumer_version_number} has been updated with new content, triggering webhooks for changed content"
|
26
|
-
webhook_service.trigger_webhooks updated_pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, webhook_options
|
28
|
+
webhook_service.trigger_webhooks updated_pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, webhook_options
|
27
29
|
else
|
28
30
|
logger.info "Pact content has not changed since previous revision, not triggering webhooks for changed content"
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
def trigger_webhooks_for_verification_results_publication(pact, verification, webhook_options)
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
def trigger_webhooks_for_verification_results_publication(pact, verification, event_context, webhook_options)
|
35
|
+
expand_events(event_context).each do | reconstituted_event_context |
|
36
|
+
if verification.success
|
37
|
+
webhook_service.trigger_webhooks(
|
38
|
+
pact,
|
39
|
+
verification,
|
40
|
+
PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED,
|
41
|
+
reconstituted_event_context,
|
42
|
+
webhook_options
|
43
|
+
)
|
44
|
+
else
|
45
|
+
webhook_service.trigger_webhooks(
|
46
|
+
pact,
|
47
|
+
verification,
|
48
|
+
PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED,
|
49
|
+
reconstituted_event_context,
|
50
|
+
webhook_options
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
41
54
|
webhook_service.trigger_webhooks(
|
42
55
|
pact,
|
43
56
|
verification,
|
44
|
-
PactBroker::Webhooks::WebhookEvent::
|
57
|
+
PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED,
|
58
|
+
reconstituted_event_context,
|
45
59
|
webhook_options
|
46
60
|
)
|
47
61
|
end
|
48
|
-
|
49
|
-
webhook_service.trigger_webhooks(
|
50
|
-
pact,
|
51
|
-
verification,
|
52
|
-
PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED,
|
53
|
-
webhook_options
|
54
|
-
)
|
55
62
|
end
|
56
63
|
|
57
64
|
private
|
@@ -68,6 +75,32 @@ module PactBroker
|
|
68
75
|
previous_pact.nil? || new_pact.pact_version_sha != previous_pact.pact_version_sha
|
69
76
|
end
|
70
77
|
|
78
|
+
def merge_consumer_version_selectors(consumer_version_number, selectors, event_context)
|
79
|
+
event_context.merge(
|
80
|
+
consumer_version_number: consumer_version_number,
|
81
|
+
consumer_version_tags: selectors.collect{ | selector | selector[:tag] }.compact.uniq
|
82
|
+
)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Now that we de-duplicate the pact contents when verifying though the 'pacts for verification' API,
|
86
|
+
# we no longer get a webhook triggered for the verification results publication of each indiviual
|
87
|
+
# consumer version tag, meaning that only the most recent commit will get the updated verification status.
|
88
|
+
# To fix this, each URL of the pacts returned by the 'pacts for verification' API now contains the
|
89
|
+
# relevant selectors in the metadata, so that when the verification results are published,
|
90
|
+
# we can parse that metadata, and trigger one webhook for each consumer version like we used to.
|
91
|
+
# Actually, we used to trigger one webhook per tag, but given that the most likely use of the
|
92
|
+
# verification published webhook is for reporting git statuses,
|
93
|
+
# it makes more sense to trigger per consumer version number (ie. commit).
|
94
|
+
def expand_events(event_context)
|
95
|
+
triggers = if event_context[:consumer_version_selectors].is_a?(Array)
|
96
|
+
event_context[:consumer_version_selectors]
|
97
|
+
.group_by{ | selector | selector[:consumer_version_number] }
|
98
|
+
.collect { | consumer_version_number, selectors | merge_consumer_version_selectors(consumer_version_number, selectors, event_context.without(:consumer_version_selectors)) }
|
99
|
+
else
|
100
|
+
[event_context]
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
71
104
|
def print_debug_messages(changed_pacts)
|
72
105
|
if changed_pacts.any?
|
73
106
|
messages = changed_pacts.collect do |tag, previous_pact|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'sequel'
|
2
2
|
require 'pact_broker/repositories/helpers'
|
3
3
|
require 'pact_broker/webhooks/execution'
|
4
|
+
require 'pact_broker/hash_refinements'
|
4
5
|
|
5
6
|
# Represents the relationship between a webhook and the event and object
|
6
7
|
# that caused it to be triggered. eg a pact publication
|
@@ -8,6 +9,7 @@ require 'pact_broker/webhooks/execution'
|
|
8
9
|
module PactBroker
|
9
10
|
module Webhooks
|
10
11
|
class TriggeredWebhook < Sequel::Model(:triggered_webhooks)
|
12
|
+
using PactBroker::HashRefinements
|
11
13
|
plugin :timestamps, update_on_create: true
|
12
14
|
plugin :serialization, :json, :event_context
|
13
15
|
|
@@ -60,7 +62,7 @@ module PactBroker
|
|
60
62
|
# getting a random 'no method to_domain for null' error
|
61
63
|
# not sure on which object, so splitting this out into two lines
|
62
64
|
pact = pact_publication.to_domain
|
63
|
-
webhook.to_domain.execute(pact, verification, options)
|
65
|
+
webhook.to_domain.execute(pact, verification, event_context.symbolize_keys, options)
|
64
66
|
end
|
65
67
|
|
66
68
|
def consumer_name
|
@@ -1,43 +1,33 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
$LOAD_PATH << "#{Dir.pwd}/lib"
|
4
|
-
|
5
3
|
begin
|
6
4
|
|
5
|
+
$LOAD_PATH << "#{Dir.pwd}/lib"
|
7
6
|
require 'pact_broker/test/http_test_data_builder'
|
8
7
|
base_url = ENV['PACT_BROKER_BASE_URL'] || 'http://localhost:9292'
|
9
8
|
|
10
|
-
td = PactBroker::Test::HttpTestDataBuilder.new(base_url
|
11
|
-
td.delete_integration(consumer: "
|
12
|
-
.
|
13
|
-
.
|
14
|
-
.
|
15
|
-
.
|
9
|
+
td = PactBroker::Test::HttpTestDataBuilder.new(base_url)
|
10
|
+
td.delete_integration(consumer: "Foo", provider: "Bar")
|
11
|
+
.delete_integration(consumer: "foo-consumer", provider: "bar-provider")
|
12
|
+
.create_pacticipant("foo-consumer")
|
13
|
+
.create_pacticipant("foo-provider")
|
14
|
+
.create_global_webhook_for_verification_published(uuid: "ba8feb17-558a-4b3f-a078-f52c6fafd014", url: "http://webhook-server:9393")
|
15
|
+
.publish_pact(consumer: "foo-consumer", consumer_version: "1", provider: "bar-provider", content_id: "111", tag: "main")
|
16
|
+
.publish_pact(consumer: "foo-consumer", consumer_version: "2", provider: "bar-provider", content_id: "111", tag: ["feat/x", "feat/y"])
|
17
|
+
.sleep(10)
|
16
18
|
.get_pacts_for_verification(
|
17
|
-
enable_pending: true,
|
18
19
|
provider_version_tag: "main",
|
19
|
-
|
20
|
-
consumer_version_selectors: [{ tag: "main", latest: true }])
|
20
|
+
consumer_version_selectors: [{ tag: "main", latest: true }, { tag: "feat/x", latest: true }, { tag: "feat/y", latest: true }])
|
21
21
|
.verify_pact(
|
22
22
|
index: 0,
|
23
23
|
provider_version_tag: "main",
|
24
24
|
provider_version: "1",
|
25
|
-
success:
|
25
|
+
success: true
|
26
26
|
)
|
27
|
-
|
28
|
-
enable_pending: true,
|
29
|
-
provider_version_tag: "main",
|
30
|
-
include_wip_pacts_since: "2020-01-01",
|
31
|
-
consumer_version_selectors: [{ tag: "main", latest: true }])
|
32
|
-
.can_i_deploy(pacticipant: "MyProvider", version: "1", to: "prod")
|
33
|
-
.can_i_deploy(pacticipant: "MyConsumer", version: "1", to: "prod")
|
34
|
-
.deploy_to_prod(pacticipant: "MyProvider", version: "1")
|
35
|
-
.can_i_deploy(pacticipant: "MyConsumer", version: "1", to: "prod")
|
36
|
-
.deploy_to_prod(pacticipant: "MyConsumer", version: "1")
|
27
|
+
|
37
28
|
|
38
29
|
rescue StandardError => e
|
39
30
|
puts "#{e.class} #{e.message}"
|
40
31
|
puts e.backtrace
|
41
32
|
exit 1
|
42
33
|
end
|
43
|
-
|
data/script/reproduce-issue.rb
CHANGED
@@ -6,7 +6,8 @@ begin
|
|
6
6
|
base_url = ENV['PACT_BROKER_BASE_URL'] || 'http://localhost:9292'
|
7
7
|
|
8
8
|
td = PactBroker::Test::HttpTestDataBuilder.new(base_url)
|
9
|
-
td.delete_integration(consumer: "
|
9
|
+
td.delete_integration(consumer: "Foo", provider: "Bar")
|
10
|
+
.delete_integration(consumer: "foo-consumer", provider: "bar-provider")
|
10
11
|
.publish_pact(consumer: "foo-consumer", consumer_version: "1", provider: "bar-provider", content_id: "111", tag: "main")
|
11
12
|
.get_pacts_for_verification(
|
12
13
|
enable_pending: true,
|
data/script/trigger-release.sh
CHANGED
@@ -19,7 +19,7 @@ output=$(curl -v https://api.github.com/repos/${repository_slug}/dispatches \
|
|
19
19
|
-H "Authorization: Bearer $GITHUB_ACCESS_TOKEN_FOR_PF_RELEASES" \
|
20
20
|
-d "{\"event_type\": \"release-triggered\", \"client_payload\": {\"increment\": ${increment}}}" 2>&1)
|
21
21
|
|
22
|
-
if ! echo "${output}" | grep "HTTP
|
22
|
+
if ! echo "${output}" | grep "HTTP\/.* 204" > /dev/null; then
|
23
23
|
echo "$output" | sed "s/${GITHUB_ACCESS_TOKEN_FOR_PF_RELEASES}/********/g"
|
24
24
|
echo "Failed to trigger release"
|
25
25
|
exit 1
|
data/script/webhook-server.ru
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'rack/utils'
|
2
|
+
STDOUT.sync = true
|
3
|
+
puts "Starting webhook server"
|
2
4
|
|
3
|
-
count = 0
|
4
5
|
run -> (env) {
|
5
|
-
|
6
|
-
|
7
|
-
puts Rack::Utils.parse_nested_query(env['QUERY_STRING'])
|
6
|
+
status = 200
|
7
|
+
puts Rack::Utils.parse_nested_query(env['QUERY_STRING']) if env['QUERY_STRING'] && env['QUERY_STRING'] != ''
|
8
8
|
puts env['rack.input'].read
|
9
|
-
[status, {}, ["
|
9
|
+
[status, {"Content-Type" => "text/plain"}, ["Webhook response.\n"]]
|
10
10
|
}
|
@@ -81,16 +81,12 @@ module PactBroker
|
|
81
81
|
expect(subject.headers['Location']).to eq("http://example.org/pacts/provider/Provider/consumer/Consumer/pact-version/1234/verification-results/2")
|
82
82
|
end
|
83
83
|
|
84
|
-
it "merges the upstream verification metdata into the webhook context" do
|
85
|
-
expect(webhook_execution_configuration).to receive(:with_webhook_context).with(parsed_metadata)
|
86
|
-
subject
|
87
|
-
end
|
88
|
-
|
89
84
|
it "stores the verification in the database" do
|
90
85
|
expect(PactBroker::Verifications::Service).to receive(:create).with(
|
91
86
|
next_verification_number,
|
92
87
|
hash_including('some' => 'params', 'wip' => false),
|
93
88
|
pact,
|
89
|
+
parsed_metadata,
|
94
90
|
{
|
95
91
|
webhook_execution_configuration: webhook_execution_configuration,
|
96
92
|
database_connector: database_connector
|
@@ -117,6 +113,7 @@ module PactBroker
|
|
117
113
|
anything,
|
118
114
|
hash_including('wip' => true),
|
119
115
|
anything,
|
116
|
+
anything,
|
120
117
|
anything
|
121
118
|
)
|
122
119
|
subject
|
@@ -30,7 +30,8 @@ module PactBroker
|
|
30
30
|
let(:pact) { instance_double("PactBroker::Domain::Pact") }
|
31
31
|
let(:consumer_name) { "foo" }
|
32
32
|
let(:provider_name) { "bar" }
|
33
|
-
let(:webhook_execution_configuration) { instance_double(PactBroker::Webhooks::ExecutionConfiguration) }
|
33
|
+
let(:webhook_execution_configuration) { instance_double(PactBroker::Webhooks::ExecutionConfiguration, webhook_context: event_context) }
|
34
|
+
let(:event_context) { { some: "data" } }
|
34
35
|
|
35
36
|
before do
|
36
37
|
allow(PactBroker::Webhooks::Service).to receive(:test_execution).and_return(execution_result)
|
@@ -39,7 +40,7 @@ module PactBroker
|
|
39
40
|
end
|
40
41
|
|
41
42
|
it "executes the webhook" do
|
42
|
-
expect(PactBroker::Webhooks::Service).to receive(:test_execution).with(webhook, webhook_execution_configuration)
|
43
|
+
expect(PactBroker::Webhooks::Service).to receive(:test_execution).with(webhook, event_context, webhook_execution_configuration)
|
43
44
|
subject
|
44
45
|
end
|
45
46
|
|
@@ -12,9 +12,9 @@ module PactBroker
|
|
12
12
|
let(:webhook_template_parameters_hash) { { 'foo' => 'bar' } }
|
13
13
|
let(:http_request) { double('http request') }
|
14
14
|
let(:http_response) { double('http response') }
|
15
|
-
let(:
|
15
|
+
let(:event_context) { { some: 'things' } }
|
16
16
|
let(:logging_options) { { other: 'options' } }
|
17
|
-
let(:options) { {
|
17
|
+
let(:options) { { logging_options: logging_options } }
|
18
18
|
let(:pact) { double('pact') }
|
19
19
|
let(:verification) { double('verification') }
|
20
20
|
let(:logger) { double('logger').as_null_object }
|
@@ -61,11 +61,11 @@ module PactBroker
|
|
61
61
|
|
62
62
|
let(:webhook_request_logger) { instance_double(PactBroker::Webhooks::WebhookRequestLogger, log: "logs") }
|
63
63
|
|
64
|
-
let(:execute) { subject.execute
|
64
|
+
let(:execute) { subject.execute(pact, verification, event_context, options) }
|
65
65
|
|
66
66
|
it "creates the template parameters" do
|
67
67
|
expect(PactBroker::Webhooks::PactAndVerificationParameters).to receive(:new).with(
|
68
|
-
pact, verification,
|
68
|
+
pact, verification, event_context
|
69
69
|
)
|
70
70
|
execute
|
71
71
|
end
|
@@ -81,7 +81,7 @@ module PactBroker
|
|
81
81
|
end
|
82
82
|
|
83
83
|
it "generates the execution logs" do
|
84
|
-
expect(webhook_request_logger).to receive(:log).with(uuid, webhook_request, http_response, nil,
|
84
|
+
expect(webhook_request_logger).to receive(:log).with(uuid, webhook_request, http_response, nil, event_context)
|
85
85
|
execute
|
86
86
|
end
|
87
87
|
|
@@ -106,7 +106,7 @@ module PactBroker
|
|
106
106
|
end
|
107
107
|
|
108
108
|
it "generates the execution logs" do
|
109
|
-
expect(webhook_request_logger).to receive(:log).with(uuid, webhook_request, nil, instance_of(error_class),
|
109
|
+
expect(webhook_request_logger).to receive(:log).with(uuid, webhook_request, nil, instance_of(error_class), event_context)
|
110
110
|
execute
|
111
111
|
end
|
112
112
|
|
@@ -33,7 +33,7 @@ module PactBroker
|
|
33
33
|
let(:provider) { double('provider', id: 2) }
|
34
34
|
let(:version) { double('version', id: 3, pacticipant_id: 1) }
|
35
35
|
let(:existing_pact) { nil }
|
36
|
-
let(:new_pact) { double('new_pact', consumer_version_tag_names: %[dev], json_content: json_content) }
|
36
|
+
let(:new_pact) { double('new_pact', consumer_version_tag_names: %w[dev], json_content: json_content) }
|
37
37
|
let(:json_content) { { the: "contract" }.to_json }
|
38
38
|
let(:json_content_with_ids) { { the: "contract with ids" }.to_json }
|
39
39
|
let(:previous_pacts) { [] }
|
@@ -49,7 +49,7 @@ module PactBroker
|
|
49
49
|
let(:content_with_interaction_ids) { double('content_with_interaction_ids', to_json: json_content_with_ids) }
|
50
50
|
let(:webhook_options) { { webhook_execution_configuration: webhook_execution_configuration } }
|
51
51
|
let(:webhook_execution_configuration) { instance_double(PactBroker::Webhooks::ExecutionConfiguration) }
|
52
|
-
|
52
|
+
let(:expected_event_context) { { consumer_version_tags: ["dev"] } }
|
53
53
|
|
54
54
|
before do
|
55
55
|
allow(Content).to receive(:from_json).and_return(content)
|
@@ -73,12 +73,12 @@ module PactBroker
|
|
73
73
|
end
|
74
74
|
|
75
75
|
it "sets the consumer version tags" do
|
76
|
-
expect(webhook_execution_configuration).to receive(:with_webhook_context).with(consumer_version_tags: %[dev]).and_return(webhook_execution_configuration)
|
76
|
+
expect(webhook_execution_configuration).to receive(:with_webhook_context).with(consumer_version_tags: %w[dev]).and_return(webhook_execution_configuration)
|
77
77
|
subject
|
78
78
|
end
|
79
79
|
|
80
80
|
it "triggers webhooks" do
|
81
|
-
expect(webhook_trigger_service).to receive(:trigger_webhooks_for_new_pact).with(new_pact, webhook_options)
|
81
|
+
expect(webhook_trigger_service).to receive(:trigger_webhooks_for_new_pact).with(new_pact, expected_event_context, webhook_options)
|
82
82
|
subject
|
83
83
|
end
|
84
84
|
end
|
@@ -92,6 +92,8 @@ module PactBroker
|
|
92
92
|
)
|
93
93
|
end
|
94
94
|
|
95
|
+
let(:expected_event_context) { { consumer_version_tags: ["dev"] } }
|
96
|
+
|
95
97
|
it "creates the sha before adding the interaction ids" do
|
96
98
|
expect(PactBroker::Pacts::GenerateSha).to receive(:call).ordered
|
97
99
|
expect(content).to receive(:with_ids).ordered
|
@@ -104,7 +106,7 @@ module PactBroker
|
|
104
106
|
end
|
105
107
|
|
106
108
|
it "triggers webhooks" do
|
107
|
-
expect(webhook_trigger_service).to receive(:trigger_webhooks_for_updated_pact).with(existing_pact, new_pact, webhook_options)
|
109
|
+
expect(webhook_trigger_service).to receive(:trigger_webhooks_for_updated_pact).with(existing_pact, new_pact, expected_event_context, webhook_options)
|
108
110
|
subject
|
109
111
|
end
|
110
112
|
end
|
@@ -22,6 +22,8 @@ module PactBroker
|
|
22
22
|
end
|
23
23
|
|
24
24
|
let(:options) { { webhook_execution_configuration: webhook_execution_configuration } }
|
25
|
+
let(:event_context) { { some: "data" } }
|
26
|
+
let(:expected_event_context) { { some: "data", provider_version_tags: ["dev"] } }
|
25
27
|
let(:webhook_execution_configuration) { instance_double(PactBroker::Webhooks::ExecutionConfiguration) }
|
26
28
|
let(:params) { { 'success' => true, 'providerApplicationVersion' => '4.5.6', 'wip' => true, 'testResults' => { 'some' => 'results' }} }
|
27
29
|
let(:pact) do
|
@@ -30,7 +32,7 @@ module PactBroker
|
|
30
32
|
.create_provider_version_tag('dev')
|
31
33
|
.and_return(:pact)
|
32
34
|
end
|
33
|
-
let(:create_verification) { subject.create 3, params, pact, options }
|
35
|
+
let(:create_verification) { subject.create 3, params, pact, event_context, options }
|
34
36
|
|
35
37
|
it "logs the creation" do
|
36
38
|
expect(logger).to receive(:info).with(/.*verification.*3/, payload: {"providerApplicationVersion"=>"4.5.6", "success"=>true, "wip"=>true})
|
@@ -67,6 +69,7 @@ module PactBroker
|
|
67
69
|
expect(PactBroker::Webhooks::TriggerService).to have_received(:trigger_webhooks_for_verification_results_publication).with(
|
68
70
|
pact,
|
69
71
|
verification,
|
72
|
+
expected_event_context,
|
70
73
|
options
|
71
74
|
)
|
72
75
|
end
|
@@ -94,7 +94,7 @@ module PactBroker
|
|
94
94
|
[ double("label", name: "foo"), double("label", name: "bar") ]
|
95
95
|
end
|
96
96
|
|
97
|
-
let(:webhook_context) { { base_url: base_url } }
|
97
|
+
let(:webhook_context) { { base_url: base_url, event_name: "something" } }
|
98
98
|
|
99
99
|
let(:nil_pact) { nil }
|
100
100
|
let(:nil_verification) { nil }
|
@@ -158,7 +158,8 @@ module PactBroker
|
|
158
158
|
{
|
159
159
|
consumer_version_number: "webhook-version-number",
|
160
160
|
consumer_version_tags: %w[webhook tags],
|
161
|
-
base_url: base_url
|
161
|
+
base_url: base_url,
|
162
|
+
event_name: "something"
|
162
163
|
|
163
164
|
}
|
164
165
|
end
|
@@ -186,16 +187,16 @@ module PactBroker
|
|
186
187
|
let(:base_url) { "http://broker" }
|
187
188
|
|
188
189
|
let(:template_parameters) do
|
189
|
-
PactAndVerificationParameters.new(placeholder_pact, nil, { base_url: base_url }).to_hash
|
190
|
+
PactAndVerificationParameters.new(placeholder_pact, nil, { base_url: base_url, event_name: "something" }).to_hash
|
190
191
|
end
|
191
192
|
|
192
193
|
it "does not blow up with a placeholder pact" do
|
193
|
-
template_parameters = PactAndVerificationParameters.new(placeholder_pact, nil, { base_url: base_url }).to_hash
|
194
|
+
template_parameters = PactAndVerificationParameters.new(placeholder_pact, nil, { base_url: base_url, event_name: "something" }).to_hash
|
194
195
|
Render.call("", template_parameters)
|
195
196
|
end
|
196
197
|
|
197
198
|
it "does not blow up with a placeholder verification" do
|
198
|
-
template_parameters = PactAndVerificationParameters.new(placeholder_pact, placeholder_verification, { base_url: base_url }).to_hash
|
199
|
+
template_parameters = PactAndVerificationParameters.new(placeholder_pact, placeholder_verification, { base_url: base_url, event_name: "something" }).to_hash
|
199
200
|
Render.call("", template_parameters)
|
200
201
|
end
|
201
202
|
end
|
@@ -181,7 +181,9 @@ module PactBroker
|
|
181
181
|
let(:webhooks) { [instance_double(PactBroker::Domain::Webhook, description: 'description', uuid: '1244')]}
|
182
182
|
let(:triggered_webhook) { instance_double(PactBroker::Webhooks::TriggeredWebhook) }
|
183
183
|
let(:webhook_execution_configuration) { double('webhook_execution_configuration', webhook_context: webhook_context) }
|
184
|
-
let(:webhook_context) {
|
184
|
+
let(:webhook_context) { { base_url: "http://example.org" } }
|
185
|
+
let(:event_context) { { some: "data" } }
|
186
|
+
let(:expected_event_context) { { some: "data", event_name: PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, base_url: "http://example.org" } }
|
185
187
|
let(:options) do
|
186
188
|
{ database_connector: double('database_connector'),
|
187
189
|
webhook_execution_configuration: webhook_execution_configuration,
|
@@ -196,7 +198,7 @@ module PactBroker
|
|
196
198
|
allow(Job).to receive(:perform_in)
|
197
199
|
end
|
198
200
|
|
199
|
-
subject { Service.trigger_webhooks
|
201
|
+
subject { Service.trigger_webhooks(pact, verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, options) }
|
200
202
|
|
201
203
|
it "finds the webhooks" do
|
202
204
|
expect_any_instance_of(PactBroker::Webhooks::Repository).to receive(:find_by_consumer_and_or_provider_and_event_name).with(consumer, provider, PactBroker::Webhooks::WebhookEvent::DEFAULT_EVENT_NAME)
|
@@ -205,7 +207,7 @@ module PactBroker
|
|
205
207
|
|
206
208
|
context "when webhooks are found" do
|
207
209
|
it "executes the webhook" do
|
208
|
-
expect(Service).to receive(:run_later).with(webhooks, pact, verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, options)
|
210
|
+
expect(Service).to receive(:run_later).with(webhooks, pact, verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, expected_event_context, options)
|
209
211
|
subject
|
210
212
|
end
|
211
213
|
|
@@ -258,6 +260,7 @@ module PactBroker
|
|
258
260
|
instance_double(PactBroker::Webhooks::ExecutionConfiguration, to_hash: execution_configuration_hash)
|
259
261
|
end
|
260
262
|
let(:execution_configuration_hash) { { the: 'options' } }
|
263
|
+
let(:event_context) { { some: "data" } }
|
261
264
|
|
262
265
|
before do
|
263
266
|
allow(PactBroker::Pacts::Service).to receive(:search_for_latest_pact).and_return(pact)
|
@@ -266,7 +269,7 @@ module PactBroker
|
|
266
269
|
allow(execution_configuration).to receive(:with_failure_log_message).and_return(execution_configuration)
|
267
270
|
end
|
268
271
|
|
269
|
-
subject { Service.test_execution(webhook, execution_configuration) }
|
272
|
+
subject { Service.test_execution(webhook, event_context, execution_configuration) }
|
270
273
|
|
271
274
|
it "searches for the latest matching pact" do
|
272
275
|
expect(PactBroker::Pacts::Service).to receive(:search_for_latest_pact).with(consumer_name: 'consumer', provider_name: 'provider')
|
@@ -279,7 +282,7 @@ module PactBroker
|
|
279
282
|
|
280
283
|
context "when the trigger is not for a verification" do
|
281
284
|
it "executes the webhook with the pact" do
|
282
|
-
expect(webhook).to receive(:execute).with(pact, nil, execution_configuration_hash)
|
285
|
+
expect(webhook).to receive(:execute).with(pact, nil, event_context.merge(event_name: "test"), execution_configuration_hash)
|
283
286
|
subject
|
284
287
|
end
|
285
288
|
end
|
@@ -288,7 +291,7 @@ module PactBroker
|
|
288
291
|
let(:pact) { nil }
|
289
292
|
|
290
293
|
it "executes the webhook with a placeholder pact" do
|
291
|
-
expect(webhook).to receive(:execute).with(an_instance_of(PactBroker::Pacts::PlaceholderPact), anything, anything)
|
294
|
+
expect(webhook).to receive(:execute).with(an_instance_of(PactBroker::Pacts::PlaceholderPact), anything, anything, anything)
|
292
295
|
subject
|
293
296
|
end
|
294
297
|
end
|
@@ -302,7 +305,7 @@ module PactBroker
|
|
302
305
|
end
|
303
306
|
|
304
307
|
it "executes the webhook with the pact and the verification" do
|
305
|
-
expect(webhook).to receive(:execute).with(pact, verification, execution_configuration_hash)
|
308
|
+
expect(webhook).to receive(:execute).with(pact, verification, event_context.merge(event_name: "test"), execution_configuration_hash)
|
306
309
|
subject
|
307
310
|
end
|
308
311
|
|
@@ -310,7 +313,7 @@ module PactBroker
|
|
310
313
|
let(:verification) { nil }
|
311
314
|
|
312
315
|
it "executes the webhook with a placeholder verification" do
|
313
|
-
expect(webhook).to receive(:execute).with(anything, an_instance_of(PactBroker::Verifications::PlaceholderVerification), anything)
|
316
|
+
expect(webhook).to receive(:execute).with(anything, an_instance_of(PactBroker::Verifications::PlaceholderVerification), anything, anything)
|
314
317
|
subject
|
315
318
|
end
|
316
319
|
end
|
@@ -329,6 +332,7 @@ module PactBroker
|
|
329
332
|
.with_webhook_context(base_url: 'http://example.org')
|
330
333
|
.with_show_response(true)
|
331
334
|
end
|
335
|
+
let(:event_context) { { some: "data", base_url: "http://example.org" }}
|
332
336
|
let(:options) do
|
333
337
|
{
|
334
338
|
database_connector: database_connector,
|
@@ -347,7 +351,7 @@ module PactBroker
|
|
347
351
|
.and_return(:pact)
|
348
352
|
end
|
349
353
|
|
350
|
-
subject { PactBroker::Webhooks::Service.trigger_webhooks
|
354
|
+
subject { PactBroker::Webhooks::Service.trigger_webhooks(pact, td.verification, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, options) }
|
351
355
|
|
352
356
|
it "executes the HTTP request of the webhook" do
|
353
357
|
subject
|
@@ -11,6 +11,7 @@ module PactBroker
|
|
11
11
|
let(:previous_pact_version_sha) { "111" }
|
12
12
|
let(:previous_pacts) { { untagged: previous_pact } }
|
13
13
|
let(:logger) { double('logger').as_null_object }
|
14
|
+
let(:event_context) { { some: "data" } }
|
14
15
|
let(:webhook_options) { { the: 'options'} }
|
15
16
|
|
16
17
|
before do
|
@@ -21,27 +22,27 @@ module PactBroker
|
|
21
22
|
|
22
23
|
shared_examples_for "triggering a contract_published event" do
|
23
24
|
it "triggers a contract_published webhook" do
|
24
|
-
expect(webhook_service).to receive(:trigger_webhooks).with(pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, webhook_options)
|
25
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_PUBLISHED, event_context, webhook_options)
|
25
26
|
subject
|
26
27
|
end
|
27
28
|
end
|
28
29
|
|
29
30
|
shared_examples_for "triggering a contract_content_changed event" do
|
30
31
|
it "triggers a contract_content_changed webhook" do
|
31
|
-
expect(webhook_service).to receive(:trigger_webhooks).with(pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, webhook_options)
|
32
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, nil, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, webhook_options)
|
32
33
|
subject
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
37
|
shared_examples_for "not triggering a contract_content_changed event" do
|
37
38
|
it "does not trigger a contract_content_changed webhook" do
|
38
|
-
expect(webhook_service).to_not receive(:trigger_webhooks).with(anything, anything, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, anything)
|
39
|
+
expect(webhook_service).to_not receive(:trigger_webhooks).with(anything, anything, PactBroker::Webhooks::WebhookEvent::CONTRACT_CONTENT_CHANGED, event_context, anything)
|
39
40
|
subject
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
43
44
|
describe "#trigger_webhooks_for_new_pact" do
|
44
|
-
subject { TriggerService.trigger_webhooks_for_new_pact(pact, webhook_options) }
|
45
|
+
subject { TriggerService.trigger_webhooks_for_new_pact(pact, event_context, webhook_options) }
|
45
46
|
|
46
47
|
context "when no previous untagged pact exists" do
|
47
48
|
let(:previous_pact) { nil }
|
@@ -117,7 +118,7 @@ module PactBroker
|
|
117
118
|
end
|
118
119
|
let(:existing_pact_version_sha) { pact_version_sha }
|
119
120
|
|
120
|
-
subject { TriggerService.trigger_webhooks_for_updated_pact(existing_pact, pact, webhook_options) }
|
121
|
+
subject { TriggerService.trigger_webhooks_for_updated_pact(existing_pact, pact, event_context, webhook_options) }
|
121
122
|
|
122
123
|
context "when the pact version sha of the previous revision is different" do
|
123
124
|
let(:existing_pact_version_sha) { "456" }
|
@@ -140,32 +141,73 @@ module PactBroker
|
|
140
141
|
describe "#trigger_webhooks_for_verification_results_publication" do
|
141
142
|
let(:verification) { double("verification", success: success) }
|
142
143
|
let(:success) { true }
|
144
|
+
# See lib/pact_broker/pacts/metadata.rb build_metadata_for_pact_for_verification
|
145
|
+
let(:selector_1) { { latest: true, consumer_version_number: "1", tag: "prod" } }
|
146
|
+
let(:selector_2) { { latest: true, consumer_version_number: "1", tag: "main" } }
|
147
|
+
let(:selector_3) { { latest: true, consumer_version_number: "2", tag: "feat/2" } }
|
148
|
+
let(:event_context) do
|
149
|
+
{
|
150
|
+
consumer_version_selectors: [selector_1, selector_2, selector_3],
|
151
|
+
other: "foo"
|
152
|
+
}
|
153
|
+
end
|
154
|
+
let(:expected_event_context_1) { { consumer_version_number: "1", consumer_version_tags: ["prod", "main"], other: "foo" } }
|
155
|
+
let(:expected_event_context_2) { { consumer_version_number: "2", consumer_version_tags: ["feat/2"], other: "foo" } }
|
143
156
|
|
144
|
-
subject { TriggerService.trigger_webhooks_for_verification_results_publication(pact, verification, webhook_options) }
|
157
|
+
subject { TriggerService.trigger_webhooks_for_verification_results_publication(pact, verification, event_context, webhook_options) }
|
145
158
|
|
146
159
|
context "when the verification is successful" do
|
147
|
-
|
148
|
-
|
149
|
-
|
160
|
+
|
161
|
+
context "when there are consumer_version_selectors in the event_context" do
|
162
|
+
it "triggers a provider_verification_succeeded webhook for each consumer version (ie. commit)" do
|
163
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED, expected_event_context_1, webhook_options)
|
164
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED, expected_event_context_2, webhook_options)
|
165
|
+
subject
|
166
|
+
end
|
167
|
+
|
168
|
+
it "triggers a provider_verification_published webhook for each consumer version (ie. commit)" do
|
169
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, expected_event_context_1, webhook_options)
|
170
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, expected_event_context_2, webhook_options)
|
171
|
+
subject
|
172
|
+
end
|
150
173
|
end
|
151
174
|
|
152
|
-
|
153
|
-
|
154
|
-
|
175
|
+
context "when there are no consumer_version_selectors" do
|
176
|
+
let(:event_context) { { some: "data" } }
|
177
|
+
|
178
|
+
it "passes through the event context" do
|
179
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_SUCCEEDED, event_context, webhook_options)
|
180
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, event_context, webhook_options)
|
181
|
+
subject
|
182
|
+
end
|
155
183
|
end
|
156
184
|
end
|
157
185
|
|
158
186
|
context "when the verification is not successful" do
|
159
187
|
let(:success) { false }
|
160
188
|
|
161
|
-
|
162
|
-
|
163
|
-
|
189
|
+
context "when there are consumer_version_selectors in the event_context" do
|
190
|
+
it "triggers a provider_verification_failed webhook for each consumer version (ie. commit)" do
|
191
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED, expected_event_context_1, webhook_options)
|
192
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED, expected_event_context_2, webhook_options)
|
193
|
+
subject
|
194
|
+
end
|
195
|
+
|
196
|
+
it "triggeres a provider_verification_published webhook for each consumer version (ie. commit)" do
|
197
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, expected_event_context_1, webhook_options)
|
198
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, expected_event_context_2, webhook_options)
|
199
|
+
subject
|
200
|
+
end
|
164
201
|
end
|
165
202
|
|
166
|
-
|
167
|
-
|
168
|
-
|
203
|
+
context "when there are no consumer_version_selectors" do
|
204
|
+
let(:event_context) { { some: "data" } }
|
205
|
+
|
206
|
+
it "passes through the event context" do
|
207
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_FAILED, event_context, webhook_options)
|
208
|
+
expect(webhook_service).to receive(:trigger_webhooks).with(pact, verification, PactBroker::Webhooks::WebhookEvent::VERIFICATION_PUBLISHED, event_context, webhook_options)
|
209
|
+
subject
|
210
|
+
end
|
169
211
|
end
|
170
212
|
end
|
171
213
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact_broker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.76.
|
4
|
+
version: 2.76.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bethany Skurrie
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-01-
|
13
|
+
date: 2021-01-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: httparty
|
@@ -566,7 +566,6 @@ files:
|
|
566
566
|
- docker-compose-ci-mysql.yml
|
567
567
|
- docker-compose-dev-postgres.yml
|
568
568
|
- docker-compose-issue-repro-with-pact-broker-docker-image.yml
|
569
|
-
- docker-compose-issue-repro.yml
|
570
569
|
- docker-compose-test.yml
|
571
570
|
- docs/images/Pactflow logo - black small.png
|
572
571
|
- example/Gemfile
|
@@ -1,22 +0,0 @@
|
|
1
|
-
version: "3"
|
2
|
-
|
3
|
-
services:
|
4
|
-
pact-broker:
|
5
|
-
build: .
|
6
|
-
ports:
|
7
|
-
- "9292:9292"
|
8
|
-
entrypoint: /usr/local/bin/start
|
9
|
-
environment:
|
10
|
-
- RACK_ENV=production
|
11
|
-
volumes:
|
12
|
-
- $PWD:/home
|
13
|
-
|
14
|
-
repro-issue:
|
15
|
-
build: .
|
16
|
-
depends_on:
|
17
|
-
- pact-broker
|
18
|
-
command: dockerize -wait http://pact-broker:9292 -timeout 30s /home/script/reproduce-issue.rb
|
19
|
-
environment:
|
20
|
-
- PACT_BROKER_BASE_URL=http://pact-broker:9292
|
21
|
-
volumes:
|
22
|
-
- $PWD:/home
|