pact_broker 2.4.2 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +4 -2
- data/CHANGELOG.md +54 -0
- data/DEVELOPER_DOCUMENTATION.md +11 -7
- data/README.md +5 -1
- data/UPGRADING.md +18 -0
- data/db/migrations/19_make_pact_version_content_sha_not_nullable.rb +9 -1
- data/db/migrations/25_make_pv_pacticipants_mandatory.rb +8 -0
- data/db/migrations/38_create_triggered_webhooks_table.rb +19 -0
- data/db/migrations/39_add_triggered_webhooks_fk_to_execution.rb +24 -0
- data/db/migrations/40_create_latest_triggered_webhooks_view.rb +24 -0
- data/db/migrations/41_migrate_execution_data.rb +47 -0
- data/db/test/backwards_compatibility/.rspec +3 -0
- data/db/test/backwards_compatibility/Appraisals +49 -0
- data/db/test/backwards_compatibility/Gemfile +11 -0
- data/db/test/backwards_compatibility/Rakefile +55 -0
- data/db/test/backwards_compatibility/config.ru +18 -0
- data/db/test/backwards_compatibility/gemfiles/1.18.0.gemfile +14 -0
- data/db/test/backwards_compatibility/gemfiles/1.18.0.gemfile.lock +210 -0
- data/db/test/backwards_compatibility/gemfiles/2.0.0.gemfile +14 -0
- data/db/test/backwards_compatibility/gemfiles/2.0.0.gemfile.lock +208 -0
- data/db/test/backwards_compatibility/gemfiles/2.1.0.gemfile +14 -0
- data/db/test/backwards_compatibility/gemfiles/2.1.0.gemfile.lock +209 -0
- data/db/test/backwards_compatibility/gemfiles/2.2.0.gemfile +14 -0
- data/db/test/backwards_compatibility/gemfiles/2.2.0.gemfile.lock +197 -0
- data/db/test/backwards_compatibility/gemfiles/2.3.0.gemfile +13 -0
- data/db/test/backwards_compatibility/gemfiles/2.3.0.gemfile.lock +196 -0
- data/db/test/backwards_compatibility/gemfiles/2.4.2.gemfile +13 -0
- data/db/test/backwards_compatibility/gemfiles/2.4.2.gemfile.lock +196 -0
- data/db/test/backwards_compatibility/gemfiles/head.gemfile +13 -0
- data/db/test/backwards_compatibility/gemfiles/head.gemfile.lock +200 -0
- data/db/test/backwards_compatibility/spec/fixtures/foo-bar.json +22 -0
- data/db/test/backwards_compatibility/spec/publish_pact_spec.rb +72 -0
- data/db/test/backwards_compatibility/spec/spec_helper.rb +20 -0
- data/db/test/backwards_compatibility/spec/support/fixture_helpers.rb +12 -0
- data/db/test/backwards_compatibility/spec/support/request_helpers.rb +20 -0
- data/example/Gemfile +2 -2
- data/example/pact_broker_database.sqlite3 +0 -0
- data/lib/pact_broker/api/decorators/pact_collection_decorator.rb +1 -2
- data/lib/pact_broker/api/decorators/pact_decorator.rb +12 -10
- data/lib/pact_broker/api/decorators/pact_versions_decorator.rb +1 -2
- data/lib/pact_broker/api/decorators/pact_webhooks_status_decorator.rb +123 -0
- data/lib/pact_broker/api/decorators/versions_decorator.rb +17 -6
- data/lib/pact_broker/api/decorators/webhook_decorator.rb +8 -10
- data/lib/pact_broker/api/decorators/webhooks_decorator.rb +0 -1
- data/lib/pact_broker/api/pact_broker_urls.rb +13 -1
- data/lib/pact_broker/api/renderers/html_pact_renderer.rb +47 -3
- data/lib/pact_broker/api/resources/badge.rb +3 -3
- data/lib/pact_broker/api/resources/base_resource.rb +1 -1
- data/lib/pact_broker/api/resources/latest_pact.rb +5 -1
- data/lib/pact_broker/api/resources/pact.rb +5 -1
- data/lib/pact_broker/api/resources/pact_webhooks_status.rb +61 -0
- data/lib/pact_broker/api/resources/triggered_webhook_logs.rb +36 -0
- data/lib/pact_broker/api/resources/webhook.rb +31 -3
- data/lib/pact_broker/api/resources/webhook_execution.rb +12 -2
- data/lib/pact_broker/api.rb +3 -0
- data/lib/pact_broker/app.rb +11 -3
- data/lib/pact_broker/badges/service.rb +26 -5
- data/lib/pact_broker/configuration.rb +12 -5
- data/lib/pact_broker/constants.rb +1 -1
- data/lib/pact_broker/diagnostic/resources/heartbeat.rb +1 -2
- data/lib/pact_broker/doc/views/pact-webhooks.markdown +1 -1
- data/lib/pact_broker/doc/views/webhooks-webhooks.markdown +1 -1
- data/lib/pact_broker/doc/views/webhooks.markdown +1 -1
- data/lib/pact_broker/domain/relationship.rb +13 -4
- data/lib/pact_broker/domain/verification.rb +0 -4
- data/lib/pact_broker/domain/webhook.rb +2 -6
- data/lib/pact_broker/domain/webhook_execution_result.rb +1 -2
- data/lib/pact_broker/domain/webhook_request.rb +59 -40
- data/lib/pact_broker/pacticipants/service.rb +4 -3
- data/lib/pact_broker/pacts/repository.rb +8 -0
- data/lib/pact_broker/pacts/service.rb +2 -0
- data/lib/pact_broker/services.rb +1 -1
- data/lib/pact_broker/ui/view_models/relationship.rb +29 -2
- data/lib/pact_broker/ui/views/relationships/show.haml +7 -10
- data/lib/pact_broker/verifications/repository.rb +8 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/execution.rb +25 -4
- data/lib/pact_broker/webhooks/job.rb +55 -13
- data/lib/pact_broker/webhooks/latest_triggered_webhook.rb +9 -0
- data/lib/pact_broker/webhooks/redact_logs.rb +10 -0
- data/lib/pact_broker/webhooks/repository.rb +76 -8
- data/lib/pact_broker/webhooks/service.rb +48 -8
- data/lib/pact_broker/webhooks/status.rb +29 -0
- data/lib/pact_broker/webhooks/triggered_webhook.rb +96 -0
- data/lib/pact_broker/webhooks/webhook.rb +19 -8
- data/lib/rack/pact_broker/database_transaction.rb +9 -3
- data/pact_broker.gemspec +3 -3
- data/public/javascripts/pact.js +5 -0
- data/public/stylesheets/pact.css +14 -1
- data/public/stylesheets/relationships.css +0 -1
- data/script/db-spec.sh +7 -0
- data/script/seed.rb +13 -8
- data/spec/features/create_webhook_spec.rb +1 -1
- data/spec/features/delete_pact_spec.rb +5 -1
- data/spec/features/delete_webhook_spec.rb +2 -1
- data/spec/features/edit_webhook_spec.rb +61 -0
- data/spec/features/execute_webhook_spec.rb +73 -0
- data/spec/features/get_latest_pact_badge_spec.rb +1 -1
- data/spec/features/get_latest_tagged_pact_badge_spec.rb +1 -1
- data/spec/features/get_latest_untagged_pact_badge_spec.rb +1 -1
- data/spec/features/get_pact_spec.rb +1 -1
- data/spec/features/merge_pact_spec.rb +1 -1
- data/spec/features/publish_pact_spec.rb +1 -1
- data/spec/integration/app_spec.rb +1 -1
- data/spec/integration/endpoints/group.rb +1 -1
- data/spec/lib/pact_broker/api/decorators/latest_pact_decorator_spec.rb +2 -1
- data/spec/lib/pact_broker/api/decorators/pact_decorator_spec.rb +8 -6
- data/spec/lib/pact_broker/api/decorators/pact_webhooks_status_decorator_spec.rb +134 -0
- data/spec/lib/pact_broker/api/decorators/relationships_csv_decorator_spec.rb +1 -1
- data/spec/lib/pact_broker/api/decorators/representable_pact_spec.rb +1 -1
- data/spec/lib/pact_broker/api/renderers/html_pact_renderer_spec.rb +27 -1
- data/spec/lib/pact_broker/api/resources/badge_spec.rb +32 -15
- data/spec/lib/pact_broker/api/resources/base_resource_spec.rb +17 -0
- data/spec/lib/pact_broker/api/resources/latest_pact_spec.rb +5 -3
- data/spec/lib/pact_broker/api/resources/pact_spec.rb +9 -2
- data/spec/lib/pact_broker/api/resources/triggered_webhook_logs_spec.rb +28 -0
- data/spec/lib/pact_broker/api/resources/webhook_execution_spec.rb +15 -5
- data/spec/lib/pact_broker/api/resources/webhook_spec.rb +43 -31
- data/spec/lib/pact_broker/app_spec.rb +12 -8
- data/spec/lib/pact_broker/badges/service_spec.rb +15 -1
- data/spec/lib/pact_broker/configuration_spec.rb +3 -2
- data/spec/lib/pact_broker/domain/relationship_spec.rb +24 -0
- data/spec/lib/pact_broker/domain/webhook_request_spec.rb +47 -31
- data/spec/lib/pact_broker/domain/webhook_spec.rb +4 -6
- data/spec/lib/pact_broker/pacticipants/service_spec.rb +16 -1
- data/spec/lib/pact_broker/pacts/repository_spec.rb +22 -1
- data/spec/lib/pact_broker/pacts/service_spec.rb +32 -1
- data/spec/lib/pact_broker/ui/view_models/relationship_spec.rb +44 -0
- data/spec/lib/pact_broker/verifications/repository_spec.rb +19 -0
- data/spec/lib/pact_broker/verifications/service_spec.rb +1 -1
- data/spec/lib/pact_broker/webhooks/job_spec.rb +80 -19
- data/spec/lib/pact_broker/webhooks/redact_logs_spec.rb +49 -0
- data/spec/lib/pact_broker/webhooks/repository_spec.rb +271 -21
- data/spec/lib/pact_broker/webhooks/service_spec.rb +70 -3
- data/spec/lib/pact_broker/webhooks/status_spec.rb +48 -0
- data/spec/lib/pact_broker/webhooks/triggered_webhook_spec.rb +40 -0
- data/spec/lib/rack/pact_broker/database_transaction_spec.rb +14 -4
- data/spec/migrations/23_pact_versions_spec.rb +8 -30
- data/spec/migrations/24_populate_pact_contents_spec.rb +3 -21
- data/spec/migrations/34_latest_tagged_pacts_spec.rb +1 -17
- data/spec/migrations/34_pact_revisions_spec.rb +7 -23
- data/spec/migrations/41_migrate_execution_data_spec.rb +109 -0
- data/spec/service_consumers/pact_helper.rb +5 -1
- data/spec/spec_helper.rb +15 -7
- data/spec/support/database_cleaner.rb +15 -2
- data/spec/support/migration_helpers.rb +16 -0
- data/spec/support/test_data_builder.rb +41 -9
- data/tasks/database.rb +7 -2
- data/tasks/db.rake +10 -0
- data/tasks/rspec.rake +1 -1
- data/vendor/hal-browser/browser.html +3 -2
- data/vendor/hal-browser/js/hal/resource.js +16 -2
- metadata +72 -13
- data/script/record_verification.sh +0 -4
@@ -5,50 +5,107 @@ module PactBroker
|
|
5
5
|
describe Job do
|
6
6
|
|
7
7
|
before do
|
8
|
-
|
8
|
+
PactBroker.configuration.webhook_retry_schedule = [10, 60, 120, 300, 600, 1200]
|
9
|
+
allow(PactBroker::Webhooks::Service).to receive(:execute_triggered_webhook_now).and_return(result)
|
10
|
+
allow(PactBroker::Webhooks::Service).to receive(:update_triggered_webhook_status)
|
9
11
|
end
|
10
12
|
|
11
|
-
let(:
|
13
|
+
let(:triggered_webhook) { instance_double("PactBroker::Webhooks::TriggeredWebhook", webhook_uuid: '1234') }
|
14
|
+
let(:result) { instance_double("PactBroker::Domain::WebhookExecutionResult", success?: success)}
|
15
|
+
let(:success) { true }
|
16
|
+
|
17
|
+
context "when the job succeeds" do
|
18
|
+
subject { Job.new.perform(triggered_webhook: triggered_webhook) }
|
19
|
+
|
20
|
+
it "does not reschedule the job" do
|
21
|
+
expect(Job).to_not receive(:perform_in)
|
22
|
+
subject
|
23
|
+
end
|
24
|
+
|
25
|
+
it "updates the triggered_webhook status to 'success'" do
|
26
|
+
expect(PactBroker::Webhooks::Service).to receive(:update_triggered_webhook_status)
|
27
|
+
.with(triggered_webhook, TriggeredWebhook::STATUS_SUCCESS)
|
28
|
+
subject
|
29
|
+
end
|
30
|
+
end
|
12
31
|
|
13
32
|
context "when an error occurs for the first time" do
|
14
33
|
before do
|
15
|
-
allow(PactBroker::Webhooks::Service).to receive(:
|
34
|
+
allow(PactBroker::Webhooks::Service).to receive(:execute_triggered_webhook_now).and_raise("an error")
|
16
35
|
end
|
17
36
|
|
37
|
+
subject { Job.new.perform(triggered_webhook: triggered_webhook) }
|
38
|
+
|
18
39
|
it "reschedules the job in 10 seconds" do
|
19
|
-
expect(Job).to receive(:perform_in).with(10, {
|
20
|
-
|
40
|
+
expect(Job).to receive(:perform_in).with(10, {triggered_webhook: triggered_webhook, error_count: 1})
|
41
|
+
subject
|
42
|
+
end
|
43
|
+
|
44
|
+
it "updates the triggered_webhook status to 'retrying'" do
|
45
|
+
expect(PactBroker::Webhooks::Service).to receive(:update_triggered_webhook_status)
|
46
|
+
.with(triggered_webhook, TriggeredWebhook::STATUS_RETRYING)
|
47
|
+
subject
|
21
48
|
end
|
22
49
|
end
|
23
50
|
|
24
51
|
context "when the webhook execution result is not successful for the first time" do
|
25
|
-
|
26
|
-
|
27
|
-
|
52
|
+
let(:success) { false }
|
53
|
+
|
54
|
+
subject { Job.new.perform(triggered_webhook: triggered_webhook) }
|
28
55
|
|
29
56
|
it "reschedules the job in 10 seconds" do
|
30
|
-
expect(Job).to receive(:perform_in).with(10, {
|
31
|
-
|
57
|
+
expect(Job).to receive(:perform_in).with(10, {triggered_webhook: triggered_webhook, error_count: 1})
|
58
|
+
subject
|
59
|
+
end
|
60
|
+
|
61
|
+
it "executes the job with an log message indicating that the webhook will be retried" do
|
62
|
+
expect(PactBroker::Webhooks::Service).to receive(:execute_triggered_webhook_now)
|
63
|
+
.with(triggered_webhook, {
|
64
|
+
failure_log_message: "Retrying webhook in 10 seconds",
|
65
|
+
success_log_message: "Successfully executed webhook"
|
66
|
+
})
|
67
|
+
subject
|
68
|
+
end
|
69
|
+
|
70
|
+
it "updates the triggered_webhook status to 'retrying'" do
|
71
|
+
expect(PactBroker::Webhooks::Service).to receive(:update_triggered_webhook_status)
|
72
|
+
.with(triggered_webhook, TriggeredWebhook::STATUS_RETRYING)
|
73
|
+
subject
|
32
74
|
end
|
33
75
|
end
|
34
76
|
|
35
77
|
context "when an error occurs for the second time" do
|
36
78
|
before do
|
37
|
-
allow(PactBroker::Webhooks::Service).to receive(:
|
79
|
+
allow(PactBroker::Webhooks::Service).to receive(:execute_triggered_webhook_now).and_raise("an error")
|
38
80
|
end
|
39
81
|
|
82
|
+
subject { Job.new.perform(triggered_webhook: triggered_webhook, error_count: 1) }
|
83
|
+
|
40
84
|
it "reschedules the job in 60 seconds" do
|
41
|
-
expect(Job).to receive(:perform_in).with(60, {
|
42
|
-
|
85
|
+
expect(Job).to receive(:perform_in).with(60, {triggered_webhook: triggered_webhook, error_count: 2})
|
86
|
+
subject
|
43
87
|
end
|
44
|
-
end
|
45
88
|
|
46
|
-
|
47
|
-
|
48
|
-
|
89
|
+
it "updates the triggered_webhook status to 'retrying'" do
|
90
|
+
expect(PactBroker::Webhooks::Service).to receive(:update_triggered_webhook_status)
|
91
|
+
.with(triggered_webhook, TriggeredWebhook::STATUS_RETRYING)
|
92
|
+
subject
|
49
93
|
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "when the job is not successful for the last time" do
|
97
|
+
let(:success) { false }
|
98
|
+
|
99
|
+
subject { Job.new.perform(triggered_webhook: triggered_webhook, error_count: 6) }
|
50
100
|
|
51
|
-
|
101
|
+
it "executes the job with an log message indicating that the webhook has failed" do
|
102
|
+
expect(PactBroker::Webhooks::Service).to receive(:execute_triggered_webhook_now)
|
103
|
+
.with(triggered_webhook, {
|
104
|
+
failure_log_message: "Webhook execution failed after 7 attempts",
|
105
|
+
success_log_message: "Successfully executed webhook"
|
106
|
+
})
|
107
|
+
subject
|
108
|
+
end
|
52
109
|
|
53
110
|
it "does not reschedule the job" do
|
54
111
|
expect(Job).to_not receive(:perform_in)
|
@@ -60,8 +117,12 @@ module PactBroker
|
|
60
117
|
expect(Job.logger).to receive(:error).with(/Failed to execute/)
|
61
118
|
subject
|
62
119
|
end
|
63
|
-
end
|
64
120
|
|
121
|
+
it "updates the triggered_webhook status to 'failed'" do
|
122
|
+
expect(PactBroker::Webhooks::Service).to receive(:update_triggered_webhook_status).with(triggered_webhook, TriggeredWebhook::STATUS_FAILURE)
|
123
|
+
subject
|
124
|
+
end
|
125
|
+
end
|
65
126
|
end
|
66
127
|
end
|
67
128
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'pact_broker/webhooks/redact_logs'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Webhooks
|
5
|
+
describe RedactLogs do
|
6
|
+
describe ".call" do
|
7
|
+
let(:string) do
|
8
|
+
"Authorization: foo\nX-Thing: bar"
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:x_auth_string) do
|
12
|
+
"X-Authorization: bar foo\nX-Thing: bar"
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:x_auth_token) do
|
16
|
+
"X-Auth-Token: bar foo\nX-Thing: bar"
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:x_authorization_token) do
|
20
|
+
"X-Authorization-Token: bar foo\nX-Thing: bar"
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:string_lower) do
|
24
|
+
"authorization: foo\nX-Thing: bar"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "hides the value of the Authorization header" do
|
28
|
+
expect(RedactLogs.call(string)).to eq "Authorization: [REDACTED]\nX-Thing: bar"
|
29
|
+
end
|
30
|
+
|
31
|
+
it "hides the value of the X-Authorization header" do
|
32
|
+
expect(RedactLogs.call(x_auth_string)).to eq "X-Authorization: [REDACTED]\nX-Thing: bar"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "hides the value of the X-Auth-Token header" do
|
36
|
+
expect(RedactLogs.call(x_auth_token)).to eq "X-Auth-Token: [REDACTED]\nX-Thing: bar"
|
37
|
+
end
|
38
|
+
|
39
|
+
it "hides the value of the X-Authorization-Token header" do
|
40
|
+
expect(RedactLogs.call(x_authorization_token)).to eq "X-Authorization-Token: [REDACTED]\nX-Thing: bar"
|
41
|
+
end
|
42
|
+
|
43
|
+
it "hides the value of the authorization header" do
|
44
|
+
expect(RedactLogs.call(string_lower)).to eq "authorization: [REDACTED]\nX-Thing: bar"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -5,6 +5,7 @@ module PactBroker
|
|
5
5
|
module Webhooks
|
6
6
|
describe Repository do
|
7
7
|
|
8
|
+
let(:td) { TestDataBuilder.new }
|
8
9
|
let(:url) { 'http://example.org' }
|
9
10
|
let(:body) { {'some' => 'json' } }
|
10
11
|
let(:headers) { {'Content-Type' => 'application/json', 'Accept' => 'application/json'} }
|
@@ -187,6 +188,51 @@ module PactBroker
|
|
187
188
|
|
188
189
|
end
|
189
190
|
|
191
|
+
describe "update_by_uuid" do
|
192
|
+
let(:uuid) { '1234' }
|
193
|
+
let(:td) { TestDataBuilder.new }
|
194
|
+
let(:old_webhook_params) do
|
195
|
+
{
|
196
|
+
uuid: uuid,
|
197
|
+
method: 'POST',
|
198
|
+
url: 'http://example.org',
|
199
|
+
body: '{"foo":1}',
|
200
|
+
headers: {'Content-Type' => 'application/json'},
|
201
|
+
username: 'username',
|
202
|
+
password: 'password'
|
203
|
+
}
|
204
|
+
end
|
205
|
+
let(:new_webhook_params) do
|
206
|
+
{
|
207
|
+
method: 'GET',
|
208
|
+
url: 'http://example.com',
|
209
|
+
body: 'foo',
|
210
|
+
headers: {'Content-Type' => 'text/plain'}
|
211
|
+
}
|
212
|
+
end
|
213
|
+
before do
|
214
|
+
td.create_consumer
|
215
|
+
.create_provider
|
216
|
+
.create_webhook(old_webhook_params)
|
217
|
+
end
|
218
|
+
let(:new_webhook) do
|
219
|
+
PactBroker::Domain::Webhook.new(request: PactBroker::Domain::WebhookRequest.new(new_webhook_params))
|
220
|
+
end
|
221
|
+
|
222
|
+
subject { Repository.new.update_by_uuid uuid, new_webhook }
|
223
|
+
|
224
|
+
it "updates the webhook" do
|
225
|
+
updated_webhook = subject
|
226
|
+
expect(updated_webhook.uuid).to eq uuid
|
227
|
+
expect(updated_webhook.request.method).to eq 'GET'
|
228
|
+
expect(updated_webhook.request.url).to eq 'http://example.com'
|
229
|
+
expect(updated_webhook.request.body).to eq 'foo'
|
230
|
+
expect(updated_webhook.request.headers).to eq 'Content-Type' => 'text/plain'
|
231
|
+
expect(updated_webhook.request.username).to eq nil
|
232
|
+
expect(updated_webhook.request.password).to eq nil
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
190
236
|
describe "find_all" do
|
191
237
|
before do
|
192
238
|
Repository.new.create uuid, webhook, consumer, provider
|
@@ -240,20 +286,65 @@ module PactBroker
|
|
240
286
|
end
|
241
287
|
end
|
242
288
|
|
289
|
+
describe "create_triggered_webhook" do
|
290
|
+
before do
|
291
|
+
td.create_consumer
|
292
|
+
.create_provider
|
293
|
+
.create_webhook
|
294
|
+
.create_consumer_version
|
295
|
+
.create_pact
|
296
|
+
end
|
297
|
+
|
298
|
+
subject { Repository.new.create_triggered_webhook '1234', td.webhook, td.pact, 'pact_publication' }
|
299
|
+
|
300
|
+
it "creates a TriggeredWebhook" do
|
301
|
+
expect(subject.webhook_uuid ).to eq td.webhook.uuid
|
302
|
+
expect(subject.consumer).to eq td.consumer
|
303
|
+
expect(subject.provider).to eq td.provider
|
304
|
+
expect(subject.trigger_uuid).to eq '1234'
|
305
|
+
expect(subject.trigger_type).to eq 'pact_publication'
|
306
|
+
end
|
307
|
+
|
308
|
+
it "sets the webhook" do
|
309
|
+
expect(subject.webhook.uuid).to eq td.webhook.uuid
|
310
|
+
end
|
311
|
+
|
312
|
+
it "sets the webhook_uuid" do
|
313
|
+
expect(subject.webhook_uuid).to eq td.webhook.uuid
|
314
|
+
end
|
315
|
+
|
316
|
+
it "sets the consumer" do
|
317
|
+
expect(subject.consumer).to eq td.consumer
|
318
|
+
end
|
319
|
+
|
320
|
+
it "sets the provider" do
|
321
|
+
expect(subject.provider).to eq td.provider
|
322
|
+
end
|
323
|
+
|
324
|
+
it "sets the PactPublication" do
|
325
|
+
expect(subject.pact_publication.id).to eq td.pact.id
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
243
329
|
describe "create_execution" do
|
244
|
-
|
330
|
+
before do
|
331
|
+
td.create_consumer
|
332
|
+
.create_provider
|
333
|
+
.create_consumer_version
|
334
|
+
.create_pact
|
335
|
+
.create_webhook
|
336
|
+
.create_triggered_webhook
|
337
|
+
end
|
338
|
+
|
339
|
+
let(:webhook_domain) { Repository.new.find_by_uuid td.webhook.uuid }
|
245
340
|
let(:webhook_execution_result) { instance_double("PactBroker::Domain::WebhookExecutionResult", success?: true, logs: "logs") }
|
246
341
|
|
247
|
-
subject { Repository.new.create_execution
|
342
|
+
subject { Repository.new.create_execution td.triggered_webhook, webhook_execution_result }
|
248
343
|
|
249
344
|
it "saves a new webhook execution " do
|
250
345
|
expect { subject }.to change { Execution.count }.by(1)
|
251
346
|
end
|
252
347
|
|
253
|
-
it "sets the webhook" do
|
254
|
-
expect(subject.webhook.uuid).to eq webhook_domain.uuid
|
255
|
-
end
|
256
|
-
|
257
348
|
it "sets the success" do
|
258
349
|
expect(subject.success).to be true
|
259
350
|
end
|
@@ -261,32 +352,191 @@ module PactBroker
|
|
261
352
|
it "sets the logs" do
|
262
353
|
expect(subject.logs).to eq "logs"
|
263
354
|
end
|
355
|
+
end
|
264
356
|
|
265
|
-
|
266
|
-
|
357
|
+
describe "unlink_triggered_webhooks_by_webhook_uuid" do
|
358
|
+
let(:td) { TestDataBuilder.new }
|
359
|
+
|
360
|
+
before do
|
361
|
+
td.create_consumer
|
362
|
+
.create_provider
|
363
|
+
.create_consumer_version
|
364
|
+
.create_pact
|
365
|
+
.create_webhook
|
366
|
+
.create_triggered_webhook
|
367
|
+
.create_deprecated_webhook_execution
|
267
368
|
end
|
268
369
|
|
269
|
-
|
270
|
-
|
370
|
+
subject { Repository.new.unlink_triggered_webhooks_by_webhook_uuid td.webhook.uuid }
|
371
|
+
|
372
|
+
it "sets the webhook id to nil" do
|
373
|
+
webhook_id = Webhook.find(uuid: td.webhook.uuid).id
|
374
|
+
expect { subject }.to change {
|
375
|
+
TriggeredWebhook.find(id: td.triggered_webhook.id).webhook_id
|
376
|
+
}.from(webhook_id).to(nil)
|
271
377
|
end
|
272
378
|
|
273
|
-
it "sets the
|
274
|
-
|
379
|
+
it "sets the webhook id to nil for the deprecated webhook execution field" do
|
380
|
+
webhook_id = Webhook.find(uuid: td.webhook.uuid).id
|
381
|
+
expect { subject }.to change {
|
382
|
+
DeprecatedExecution.find(id: td.webhook_execution.id).webhook_id
|
383
|
+
}.from(webhook_id).to(nil)
|
275
384
|
end
|
276
385
|
end
|
277
386
|
|
278
|
-
describe "
|
279
|
-
|
280
|
-
|
281
|
-
|
387
|
+
describe "delete_executions_by_pacticipant" do
|
388
|
+
before do
|
389
|
+
td.create_consumer
|
390
|
+
.create_provider
|
391
|
+
.create_webhook
|
392
|
+
.create_consumer_version
|
393
|
+
.create_pact
|
394
|
+
.create_triggered_webhook
|
395
|
+
.create_webhook_execution
|
396
|
+
# Replicate the old way of doing it
|
397
|
+
end
|
282
398
|
|
283
|
-
|
399
|
+
context "with triggered webhooks" do
|
400
|
+
it "deletes the execution by consumer" do
|
401
|
+
expect { Repository.new.delete_executions_by_pacticipant td.consumer }
|
402
|
+
.to change { Execution.count }.by(-1)
|
403
|
+
end
|
284
404
|
|
285
|
-
|
286
|
-
|
405
|
+
it "deletes the execution by provider" do
|
406
|
+
expect { Repository.new.delete_executions_by_pacticipant td.provider }
|
407
|
+
.to change { Execution.count }.by(-1)
|
408
|
+
end
|
409
|
+
|
410
|
+
it "does not delete executions for non related pacticipants" do
|
411
|
+
another_consumer = td.create_consumer.and_return(:consumer)
|
412
|
+
expect { Repository.new.delete_executions_by_pacticipant another_consumer }
|
413
|
+
.to change { Execution.count }.by(0)
|
414
|
+
end
|
415
|
+
end
|
416
|
+
|
417
|
+
context "with deprecated executions (before the triggered webhook table was introduced)" do
|
418
|
+
before do
|
419
|
+
Sequel::Model.db[:webhook_executions].update(triggered_webhook_id: nil, consumer_id: td.consumer.id, provider_id: td.provider.id)
|
420
|
+
TriggeredWebhook.select_all.delete
|
421
|
+
end
|
422
|
+
|
423
|
+
it "deletes the execution by consumer" do
|
424
|
+
expect { Repository.new.delete_executions_by_pacticipant td.consumer }
|
425
|
+
.to change { Execution.count }.by(-1)
|
426
|
+
end
|
427
|
+
|
428
|
+
it "deletes the execution by provider" do
|
429
|
+
expect { Repository.new.delete_executions_by_pacticipant td.provider }
|
430
|
+
.to change { Execution.count }.by(-1)
|
431
|
+
end
|
432
|
+
|
433
|
+
it "does not delete executions for non related pacticipants" do
|
434
|
+
another_consumer = td.create_consumer.and_return(:consumer)
|
435
|
+
expect { Repository.new.delete_executions_by_pacticipant another_consumer }
|
436
|
+
.to change { Execution.count }.by(0)
|
437
|
+
end
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
describe "find_latest_triggered_webhooks" do
|
442
|
+
before do
|
443
|
+
td
|
444
|
+
.create_pact_with_hierarchy("Foo", "1.0.0", "Bar")
|
445
|
+
.create_webhook
|
446
|
+
.create_triggered_webhook
|
447
|
+
.create_webhook_execution
|
448
|
+
.create_pact_with_hierarchy
|
449
|
+
.create_webhook(uuid: '123')
|
450
|
+
.create_triggered_webhook(trigger_uuid: '256', created_at: DateTime.new(2016))
|
451
|
+
.create_webhook_execution
|
452
|
+
.create_triggered_webhook(trigger_uuid: '332', created_at: DateTime.new(2017))
|
453
|
+
.create_webhook_execution
|
454
|
+
.create_webhook(uuid: '987')
|
455
|
+
.create_triggered_webhook(trigger_uuid: '876', created_at: DateTime.new(2017))
|
456
|
+
.create_webhook_execution
|
457
|
+
.create_triggered_webhook(trigger_uuid: '638', created_at: DateTime.new(2018))
|
458
|
+
.create_webhook_execution
|
459
|
+
end
|
460
|
+
|
461
|
+
subject { Repository.new.find_latest_triggered_webhooks(td.consumer, td.provider) }
|
462
|
+
|
463
|
+
it "finds the latest triggered webhooks" do
|
464
|
+
expect(subject.collect(&:trigger_uuid).sort).to eq ['332', '638']
|
465
|
+
end
|
466
|
+
|
467
|
+
context "when there are two 'latest' triggered webhooks at the same time" do
|
468
|
+
before do
|
469
|
+
td.create_triggered_webhook(trigger_uuid: '888', created_at: DateTime.new(2018))
|
470
|
+
.create_webhook_execution
|
471
|
+
end
|
472
|
+
|
473
|
+
it "returns the one with the bigger ID" do
|
474
|
+
expect(subject.collect(&:trigger_uuid).sort).to eq ['332', '888']
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
context "when there are no triggered webhooks for the given consumer and provider" do
|
479
|
+
before do
|
480
|
+
td.create_consumer
|
481
|
+
.create_provider
|
482
|
+
end
|
483
|
+
|
484
|
+
it "returns an empty list" do
|
485
|
+
expect(subject).to be_empty
|
486
|
+
end
|
487
|
+
end
|
488
|
+
end
|
489
|
+
|
490
|
+
describe "fail_retrying_triggered_webhooks" do
|
491
|
+
before do
|
492
|
+
td.create_pact_with_hierarchy
|
493
|
+
.create_webhook
|
494
|
+
.create_triggered_webhook(status: TriggeredWebhook::STATUS_RETRYING)
|
495
|
+
.create_triggered_webhook(status: TriggeredWebhook::STATUS_SUCCESS)
|
496
|
+
.create_triggered_webhook(status: TriggeredWebhook::STATUS_NOT_RUN)
|
497
|
+
.create_triggered_webhook(status: TriggeredWebhook::STATUS_FAILURE)
|
498
|
+
end
|
499
|
+
|
500
|
+
it "sets the triggered_webhooks with retrying status to failed" do
|
501
|
+
Repository.new.fail_retrying_triggered_webhooks
|
502
|
+
expect(TriggeredWebhook.failed.count).to eq 2
|
503
|
+
expect(TriggeredWebhook.retrying.count).to eq 0
|
504
|
+
expect(TriggeredWebhook.successful.count).to eq 1
|
505
|
+
expect(TriggeredWebhook.not_run.count).to eq 1
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
describe "delete_triggered_webhooks_by_pact_publication_id" do
|
510
|
+
before do
|
511
|
+
td.create_pact_with_hierarchy
|
512
|
+
.create_webhook
|
513
|
+
.create_triggered_webhook
|
514
|
+
.create_webhook_execution
|
515
|
+
.create_pact_with_hierarchy("A Consumer", "1.2.3", "A Provider")
|
516
|
+
.create_webhook
|
517
|
+
.create_triggered_webhook
|
518
|
+
.create_webhook_execution
|
519
|
+
.create_deprecated_webhook_execution
|
520
|
+
end
|
521
|
+
|
522
|
+
subject { Repository.new.delete_triggered_webhooks_by_pact_publication_ids [td.pact.id] }
|
523
|
+
|
524
|
+
it "deletes the triggered webhook" do
|
287
525
|
expect { subject }.to change {
|
288
|
-
|
289
|
-
|
526
|
+
TriggeredWebhook.count
|
527
|
+
}.by(-1)
|
528
|
+
end
|
529
|
+
|
530
|
+
it "deletes the webhook_execution" do
|
531
|
+
expect { subject }.to change {
|
532
|
+
Execution.exclude(triggered_webhook_id: nil).count
|
533
|
+
}.by(-1)
|
534
|
+
end
|
535
|
+
|
536
|
+
it "deletes the deprecated webhook_execution" do
|
537
|
+
expect { subject }.to change {
|
538
|
+
Execution.exclude(consumer_id: nil).count
|
539
|
+
}.by(-1)
|
290
540
|
end
|
291
541
|
end
|
292
542
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'pact_broker/webhooks/service'
|
3
|
+
require 'pact_broker/webhooks/triggered_webhook'
|
3
4
|
require 'webmock/rspec'
|
4
5
|
require 'sucker_punch/testing/inline'
|
5
6
|
|
@@ -7,6 +8,24 @@ module PactBroker
|
|
7
8
|
|
8
9
|
module Webhooks
|
9
10
|
describe Service do
|
11
|
+
let(:td) { TestDataBuilder.new }
|
12
|
+
|
13
|
+
describe ".delete_by_uuid" do
|
14
|
+
before do
|
15
|
+
td.create_pact_with_hierarchy
|
16
|
+
.create_webhook
|
17
|
+
.create_triggered_webhook
|
18
|
+
.create_deprecated_webhook_execution
|
19
|
+
end
|
20
|
+
|
21
|
+
subject { Service.delete_by_uuid td.webhook.uuid }
|
22
|
+
|
23
|
+
it "deletes the webhook" do
|
24
|
+
expect { subject }.to change {
|
25
|
+
Webhook.count
|
26
|
+
}.by(-1)
|
27
|
+
end
|
28
|
+
end
|
10
29
|
|
11
30
|
describe ".execute_webhooks" do
|
12
31
|
|
@@ -15,9 +34,11 @@ module PactBroker
|
|
15
34
|
let(:consumer) { PactBroker::Domain::Pacticipant.new(name: 'Consumer') }
|
16
35
|
let(:provider) { PactBroker::Domain::Pacticipant.new(name: 'Provider') }
|
17
36
|
let(:webhooks) { [instance_double(PactBroker::Domain::Webhook, description: 'description', uuid: '1244')]}
|
37
|
+
let(:triggered_webhook) { instance_double(PactBroker::Webhooks::TriggeredWebhook) }
|
18
38
|
|
19
39
|
before do
|
20
40
|
allow_any_instance_of(PactBroker::Webhooks::Repository).to receive(:find_by_consumer_and_provider).and_return(webhooks)
|
41
|
+
allow_any_instance_of(PactBroker::Webhooks::Repository).to receive(:create_triggered_webhook).and_return(triggered_webhook)
|
21
42
|
allow(Job).to receive(:perform_async)
|
22
43
|
end
|
23
44
|
|
@@ -30,7 +51,7 @@ module PactBroker
|
|
30
51
|
|
31
52
|
context "when webhooks are found" do
|
32
53
|
it "executes the webhook" do
|
33
|
-
expect(Service).to receive(:run_later).with(webhooks)
|
54
|
+
expect(Service).to receive(:run_later).with(webhooks, pact)
|
34
55
|
subject
|
35
56
|
end
|
36
57
|
end
|
@@ -61,6 +82,44 @@ module PactBroker
|
|
61
82
|
end
|
62
83
|
end
|
63
84
|
|
85
|
+
describe ".execute_webhook_now integration test" do
|
86
|
+
let(:td) { TestDataBuilder.new }
|
87
|
+
|
88
|
+
let!(:http_request) do
|
89
|
+
stub_request(:get, "http://example.org").
|
90
|
+
to_return(:status => 200)
|
91
|
+
end
|
92
|
+
|
93
|
+
let!(:pact) do
|
94
|
+
td.create_consumer
|
95
|
+
.create_provider
|
96
|
+
.create_consumer_version
|
97
|
+
.create_pact
|
98
|
+
.create_webhook(method: 'GET', url: 'http://example.org')
|
99
|
+
.and_return(:pact)
|
100
|
+
end
|
101
|
+
|
102
|
+
subject { PactBroker::Webhooks::Service.execute_webhook_now td.webhook, pact }
|
103
|
+
|
104
|
+
it "executes the HTTP request of the webhook" do
|
105
|
+
subject
|
106
|
+
expect(http_request).to have_been_made
|
107
|
+
end
|
108
|
+
|
109
|
+
it "saves the triggered webhook" do
|
110
|
+
expect { subject }.to change { PactBroker::Webhooks::TriggeredWebhook.count }.by(1)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "saves the execution" do
|
114
|
+
expect { subject }.to change { PactBroker::Webhooks::Execution.count }.by(1)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "marks the triggered webhook as a success" do
|
118
|
+
subject
|
119
|
+
expect(TriggeredWebhook.first.status).to eq TriggeredWebhook::STATUS_SUCCESS
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
64
123
|
describe ".execute_webhooks integration test" do
|
65
124
|
let!(:http_request) do
|
66
125
|
stub_request(:get, "http://example.org").
|
@@ -68,8 +127,7 @@ module PactBroker
|
|
68
127
|
end
|
69
128
|
|
70
129
|
let(:pact) do
|
71
|
-
|
72
|
-
.create_consumer
|
130
|
+
td.create_consumer
|
73
131
|
.create_provider
|
74
132
|
.create_consumer_version
|
75
133
|
.create_pact
|
@@ -84,9 +142,18 @@ module PactBroker
|
|
84
142
|
expect(http_request).to have_been_made
|
85
143
|
end
|
86
144
|
|
145
|
+
it "saves the triggered webhook" do
|
146
|
+
expect { subject }.to change { PactBroker::Webhooks::TriggeredWebhook.count }.by(1)
|
147
|
+
end
|
148
|
+
|
87
149
|
it "saves the execution" do
|
88
150
|
expect { subject }.to change { PactBroker::Webhooks::Execution.count }.by(1)
|
89
151
|
end
|
152
|
+
|
153
|
+
it "marks the triggered webhook as a success" do
|
154
|
+
subject
|
155
|
+
expect(TriggeredWebhook.first.status).to eq TriggeredWebhook::STATUS_SUCCESS
|
156
|
+
end
|
90
157
|
end
|
91
158
|
end
|
92
159
|
end
|