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
@@ -14,13 +14,14 @@ module PactBroker
|
|
14
14
|
|
15
15
|
include PactBroker::Logging
|
16
16
|
|
17
|
-
def self.call pact
|
18
|
-
new(pact).call
|
17
|
+
def self.call pact, options = {}
|
18
|
+
new(pact, options).call
|
19
19
|
end
|
20
20
|
|
21
|
-
def initialize pact
|
21
|
+
def initialize pact, options = {}
|
22
22
|
@json_content = pact.json_content
|
23
23
|
@pact = pact
|
24
|
+
@options = options
|
24
25
|
end
|
25
26
|
|
26
27
|
def call
|
@@ -40,12 +41,17 @@ module PactBroker
|
|
40
41
|
<link rel='stylesheet' type='text/css' href='/stylesheets/pact.css'>
|
41
42
|
<link rel='stylesheet' type='text/css' href='/stylesheets/github-json.css'>
|
42
43
|
<script src='/javascripts/highlight.pack.js'></script>
|
44
|
+
<script src='/javascripts/jquery-2.1.1.min.js'></script>
|
45
|
+
<script src='/js/bootstrap.min.js'></script>
|
46
|
+
<script src='/javascripts/pact.js'></script>
|
43
47
|
<script>hljs.initHighlightingOnLoad();</script>"
|
44
48
|
end
|
45
49
|
|
46
50
|
def pact_metadata
|
47
51
|
"<div class='pact-metadata'>
|
48
52
|
<ul>
|
53
|
+
#{badge_list_item}
|
54
|
+
#{badge_markdown_item}
|
49
55
|
<li>
|
50
56
|
<span class='name'>#{@pact.consumer.name} version:</span>
|
51
57
|
<span class='value'>#{@pact.consumer_version_number}#{tags}</span>
|
@@ -64,6 +70,36 @@ module PactBroker
|
|
64
70
|
</div>"
|
65
71
|
end
|
66
72
|
|
73
|
+
def badge_list_item
|
74
|
+
"<li class='badge'>
|
75
|
+
<img src='#{badge_url}'/>
|
76
|
+
</li>
|
77
|
+
"
|
78
|
+
end
|
79
|
+
|
80
|
+
def badge_markdown_item
|
81
|
+
"<li class='badge-markdown' style='display:none'>
|
82
|
+
<textarea rows='3' cols='100'>#{badge_markdown}</textarea>
|
83
|
+
</li>"
|
84
|
+
end
|
85
|
+
|
86
|
+
def badge_markdown
|
87
|
+
warning = if badges_protected?
|
88
|
+
"If the broker is protected by authentication, set `enable_public_badge_access` to true in the configuration to enable badges to be embedded in a markdown file.\n"
|
89
|
+
else
|
90
|
+
""
|
91
|
+
end
|
92
|
+
"#{warning}[![#{@pact.consumer.name}/#{@pact.provider.name} Pact Status](#{badge_url})](#{badge_target_url})"
|
93
|
+
end
|
94
|
+
|
95
|
+
def badges_protected?
|
96
|
+
!PactBroker.configuration.enable_public_badge_access
|
97
|
+
end
|
98
|
+
|
99
|
+
def base_url
|
100
|
+
@options[:base_url] || ''
|
101
|
+
end
|
102
|
+
|
67
103
|
def title
|
68
104
|
"Pact between #{@pact.consumer.name} and #{@pact.provider.name}"
|
69
105
|
end
|
@@ -80,6 +116,14 @@ module PactBroker
|
|
80
116
|
PactBroker::Api::PactBrokerUrls.pact_url '', @pact
|
81
117
|
end
|
82
118
|
|
119
|
+
def badge_target_url
|
120
|
+
base_url
|
121
|
+
end
|
122
|
+
|
123
|
+
def badge_url
|
124
|
+
@options[:badge_url]
|
125
|
+
end
|
126
|
+
|
83
127
|
def tags
|
84
128
|
if @pact.consumer_version_tag_names.any?
|
85
129
|
" (#{@pact.consumer_version_tag_names.join(", ")})"
|
@@ -17,11 +17,11 @@ module PactBroker
|
|
17
17
|
end
|
18
18
|
|
19
19
|
def resource_exists?
|
20
|
-
|
20
|
+
true
|
21
21
|
end
|
22
22
|
|
23
23
|
def is_authorized?(authorization_header)
|
24
|
-
|
24
|
+
super || PactBroker.configuration.enable_public_badge_access
|
25
25
|
end
|
26
26
|
|
27
27
|
def forbidden?
|
@@ -31,7 +31,7 @@ module PactBroker
|
|
31
31
|
private
|
32
32
|
|
33
33
|
def to_svg
|
34
|
-
|
34
|
+
badge_service.pact_verification_badge pact, label, initials, verification_status
|
35
35
|
end
|
36
36
|
|
37
37
|
def pact
|
@@ -27,7 +27,11 @@ module PactBroker
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def to_html
|
30
|
-
PactBroker.configuration.html_pact_renderer.call(
|
30
|
+
PactBroker.configuration.html_pact_renderer.call(
|
31
|
+
pact, {
|
32
|
+
base_url: base_url,
|
33
|
+
badge_url: "#{resource_url}/badge.svg"
|
34
|
+
})
|
31
35
|
end
|
32
36
|
|
33
37
|
def pact
|
@@ -79,7 +79,11 @@ module PactBroker
|
|
79
79
|
end
|
80
80
|
|
81
81
|
def to_html
|
82
|
-
PactBroker.configuration.html_pact_renderer.call(
|
82
|
+
PactBroker.configuration.html_pact_renderer.call(
|
83
|
+
pact, {
|
84
|
+
base_url: base_url,
|
85
|
+
badge_url: badge_url_for_latest_pact(pact, base_url)
|
86
|
+
})
|
83
87
|
end
|
84
88
|
|
85
89
|
def delete_resource
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'pact_broker/api/resources/base_resource'
|
2
|
+
require 'pact_broker/api/decorators/pact_webhooks_status_decorator'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
|
6
|
+
module Api
|
7
|
+
module Resources
|
8
|
+
|
9
|
+
class PactWebhooksStatus < BaseResource
|
10
|
+
|
11
|
+
def allowed_methods
|
12
|
+
["GET"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def content_types_provided
|
16
|
+
[["application/hal+json", :to_json]]
|
17
|
+
end
|
18
|
+
|
19
|
+
def resource_exists?
|
20
|
+
consumer && provider
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_json
|
24
|
+
decorator_for(latest_triggered_webhooks).to_json(user_options: decorator_context(identifier_from_path))
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def latest_triggered_webhooks
|
30
|
+
@latest_triggered_webhooks ||= webhook_service.find_latest_triggered_webhooks(consumer, provider)
|
31
|
+
end
|
32
|
+
|
33
|
+
def pact
|
34
|
+
@pact ||= pact_service.find_latest_pact(pact_params)
|
35
|
+
end
|
36
|
+
|
37
|
+
def webhooks
|
38
|
+
webhook_service.find_by_consumer_and_provider consumer, provider
|
39
|
+
end
|
40
|
+
|
41
|
+
def consumer
|
42
|
+
@consumer ||= find_pacticipant(identifier_from_path[:consumer_name], "consumer")
|
43
|
+
end
|
44
|
+
|
45
|
+
def provider
|
46
|
+
@provider ||= find_pacticipant(identifier_from_path[:provider_name], "provider")
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_pacticipant name, role
|
50
|
+
pacticipant_service.find_pacticipant_by_name(name).tap do | pacticipant |
|
51
|
+
set_json_error_message("No #{role} with name '#{name}' found") if pacticipant.nil?
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def decorator_for latest_triggered_webhooks
|
56
|
+
PactBroker::Api::Decorators::PactWebhooksStatusDecorator.new(latest_triggered_webhooks)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'pact_broker/api/resources/base_resource'
|
2
|
+
require 'pact_broker/webhooks/triggered_webhook'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Api
|
6
|
+
module Resources
|
7
|
+
|
8
|
+
class TriggeredWebhookLogs < BaseResource
|
9
|
+
|
10
|
+
def content_types_provided
|
11
|
+
[["text/plain", :to_text]]
|
12
|
+
end
|
13
|
+
|
14
|
+
def allowed_methods
|
15
|
+
["GET"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def resource_exists?
|
19
|
+
triggered_webhook
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_text
|
23
|
+
# Too simple to bother putting into a service
|
24
|
+
triggered_webhook.webhook_executions.collect(&:logs).join("\n")
|
25
|
+
end
|
26
|
+
|
27
|
+
def triggered_webhook
|
28
|
+
@triggered_webhook ||= begin
|
29
|
+
criteria = {webhook_uuid: identifier_from_path[:uuid], trigger_uuid: identifier_from_path[:trigger_uuid]}
|
30
|
+
PactBroker::Webhooks::TriggeredWebhook.where(criteria).single_record
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -7,18 +7,38 @@ module PactBroker
|
|
7
7
|
|
8
8
|
class Webhook < BaseResource
|
9
9
|
|
10
|
+
def content_types_accepted
|
11
|
+
[["application/json", :from_json]]
|
12
|
+
end
|
13
|
+
|
10
14
|
def content_types_provided
|
11
15
|
[["application/hal+json", :to_json]]
|
12
16
|
end
|
13
17
|
|
14
18
|
def allowed_methods
|
15
|
-
["GET", "DELETE"]
|
19
|
+
["GET", "PUT", "DELETE"]
|
16
20
|
end
|
17
21
|
|
18
22
|
def resource_exists?
|
19
23
|
webhook
|
20
24
|
end
|
21
25
|
|
26
|
+
def malformed_request?
|
27
|
+
if request.put?
|
28
|
+
return invalid_json? || validation_errors?(webhook)
|
29
|
+
end
|
30
|
+
false
|
31
|
+
end
|
32
|
+
|
33
|
+
def from_json
|
34
|
+
if webhook
|
35
|
+
@webhook = webhook_service.update_by_uuid uuid, new_webhook
|
36
|
+
response.body = to_json
|
37
|
+
else
|
38
|
+
404
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
22
42
|
def to_json
|
23
43
|
Decorators::WebhookDecorator.new(webhook).to_json(user_options: { base_url: base_url })
|
24
44
|
end
|
@@ -30,16 +50,24 @@ module PactBroker
|
|
30
50
|
|
31
51
|
private
|
32
52
|
|
53
|
+
def validation_errors? webhook
|
54
|
+
errors = webhook_service.errors(new_webhook)
|
55
|
+
set_json_validation_error_messages(errors.messages) if !errors.empty?
|
56
|
+
!errors.empty?
|
57
|
+
end
|
58
|
+
|
33
59
|
def webhook
|
34
60
|
@webhook ||= webhook_service.find_by_uuid uuid
|
35
61
|
end
|
36
62
|
|
63
|
+
def new_webhook
|
64
|
+
@new_webhook ||= Decorators::WebhookDecorator.new(PactBroker::Domain::Webhook.new).from_json(request_body)
|
65
|
+
end
|
66
|
+
|
37
67
|
def uuid
|
38
68
|
identifier_from_path[:uuid]
|
39
69
|
end
|
40
|
-
|
41
70
|
end
|
42
71
|
end
|
43
|
-
|
44
72
|
end
|
45
73
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'pact_broker/api/resources/base_resource'
|
2
2
|
require 'pact_broker/services'
|
3
3
|
require 'pact_broker/api/decorators/webhook_execution_result_decorator'
|
4
|
+
require 'pact_broker/constants'
|
4
5
|
|
5
6
|
module PactBroker
|
6
7
|
module Api
|
@@ -13,10 +14,15 @@ module PactBroker
|
|
13
14
|
end
|
14
15
|
|
15
16
|
def process_post
|
16
|
-
webhook_execution_result = webhook_service.execute_webhook_now webhook
|
17
|
+
webhook_execution_result = webhook_service.execute_webhook_now webhook, pact
|
17
18
|
response.headers['Content-Type'] = 'application/hal+json;charset=utf-8'
|
18
19
|
response.body = post_response_body webhook_execution_result
|
19
|
-
webhook_execution_result.success?
|
20
|
+
if webhook_execution_result.success?
|
21
|
+
true
|
22
|
+
else
|
23
|
+
response.headers[PactBroker::DO_NOT_ROLLBACK] = 'true'
|
24
|
+
500
|
25
|
+
end
|
20
26
|
end
|
21
27
|
|
22
28
|
def resource_exists?
|
@@ -33,6 +39,10 @@ module PactBroker
|
|
33
39
|
@webhook ||= webhook_service.find_by_uuid uuid
|
34
40
|
end
|
35
41
|
|
42
|
+
def pact
|
43
|
+
@pact ||= pact_service.find_latest_pact consumer_name: webhook.consumer_name, provider_name: webhook.provider_name
|
44
|
+
end
|
45
|
+
|
36
46
|
def uuid
|
37
47
|
identifier_from_path[:uuid]
|
38
48
|
end
|
data/lib/pact_broker/api.rb
CHANGED
@@ -49,7 +49,10 @@ module PactBroker
|
|
49
49
|
|
50
50
|
# Webhooks
|
51
51
|
add ['webhooks', 'provider', :provider_name, 'consumer', :consumer_name ], Api::Resources::PactWebhooks, {resource_name: "pact_webhooks"}
|
52
|
+
add ['webhooks', 'provider', :provider_name, 'consumer', :consumer_name, 'status' ], Api::Resources::PactWebhooksStatus, {resource_name: "pact_webhooks_status"}
|
53
|
+
|
52
54
|
add ['webhooks', :uuid ], Api::Resources::Webhook, {resource_name: "webhook"}
|
55
|
+
add ['webhooks', :uuid, 'trigger', :trigger_uuid, 'logs' ], Api::Resources::TriggeredWebhookLogs, {resource_name: "triggered_webhook_logs"}
|
53
56
|
add ['webhooks', :uuid, 'execute' ], Api::Resources::WebhookExecution, {resource_name: "execute_webhook"}
|
54
57
|
add ['webhooks'], Api::Resources::Webhooks, {resource_name: "webhooks"}
|
55
58
|
|
data/lib/pact_broker/app.rb
CHANGED
@@ -23,7 +23,7 @@ module PactBroker
|
|
23
23
|
@configuration = PactBroker.configuration
|
24
24
|
yield configuration
|
25
25
|
post_configure
|
26
|
-
|
26
|
+
prepare_database
|
27
27
|
prepare_app
|
28
28
|
end
|
29
29
|
|
@@ -45,15 +45,18 @@ module PactBroker
|
|
45
45
|
PactBroker.logger = configuration.logger
|
46
46
|
SuckerPunch.logger = configuration.logger
|
47
47
|
configure_database_connection
|
48
|
+
configure_sucker_punch
|
48
49
|
end
|
49
50
|
|
50
|
-
def
|
51
|
+
def prepare_database
|
51
52
|
if configuration.auto_migrate_db
|
52
53
|
logger.info "Migrating database"
|
53
54
|
PactBroker::DB.run_migrations configuration.database_connection
|
54
55
|
else
|
55
56
|
logger.info "Skipping database migrations"
|
56
57
|
end
|
58
|
+
require 'pact_broker/webhooks/service'
|
59
|
+
PactBroker::Webhooks::Service.fail_retrying_triggered_webhooks
|
57
60
|
end
|
58
61
|
|
59
62
|
def configure_database_connection
|
@@ -119,6 +122,12 @@ module PactBroker
|
|
119
122
|
builder
|
120
123
|
end
|
121
124
|
|
125
|
+
def configure_sucker_punch
|
126
|
+
SuckerPunch.exception_handler = -> (ex, klass, args) do
|
127
|
+
PactBroker.log_error(ex, "Unhandled Suckerpunch error for #{klass}.perform(#{args.inspect})")
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
122
131
|
def running_app
|
123
132
|
@running_app ||= begin
|
124
133
|
apps = @cascade_apps
|
@@ -128,6 +137,5 @@ module PactBroker
|
|
128
137
|
@app_builder
|
129
138
|
end
|
130
139
|
end
|
131
|
-
|
132
140
|
end
|
133
141
|
end
|
@@ -12,6 +12,7 @@ module PactBroker
|
|
12
12
|
include PactBroker::Logging
|
13
13
|
|
14
14
|
SPACE_DASH_UNDERSCORE = /[\s_\-]/
|
15
|
+
CACHE = {}
|
15
16
|
|
16
17
|
def pact_verification_badge pact, label, initials, verification_status
|
17
18
|
return static_svg(pact, verification_status) unless pact
|
@@ -23,6 +24,10 @@ module PactBroker
|
|
23
24
|
dynamic_svg(title, status, color) || static_svg(pact, verification_status)
|
24
25
|
end
|
25
26
|
|
27
|
+
def clear_cache
|
28
|
+
CACHE.clear
|
29
|
+
end
|
30
|
+
|
26
31
|
private
|
27
32
|
|
28
33
|
def badge_title pact, label, initials
|
@@ -79,7 +84,7 @@ module PactBroker
|
|
79
84
|
response = do_request(uri)
|
80
85
|
response.code == '200' ? response.body : nil
|
81
86
|
rescue StandardError => e
|
82
|
-
|
87
|
+
logger.error "Error retrieving badge from #{uri} due to #{e.class} - #{e.message}"
|
83
88
|
nil
|
84
89
|
end
|
85
90
|
end
|
@@ -95,11 +100,27 @@ module PactBroker
|
|
95
100
|
end
|
96
101
|
|
97
102
|
def do_request(uri)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
103
|
+
with_cache uri do
|
104
|
+
request = Net::HTTP::Get.new(uri)
|
105
|
+
Net::HTTP.start(uri.hostname, uri.port,
|
106
|
+
use_ssl: uri.scheme == 'https',
|
107
|
+
read_timeout: 3,
|
108
|
+
open_timeout: 1,
|
109
|
+
ssl_timeout: 1,
|
110
|
+
continue_timeout: 1) do |http|
|
111
|
+
http.request request
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def with_cache uri
|
117
|
+
if !(response = CACHE[uri])
|
118
|
+
response = yield
|
119
|
+
if response.code == '200'
|
120
|
+
CACHE[uri] = response
|
121
|
+
end
|
102
122
|
end
|
123
|
+
response
|
103
124
|
end
|
104
125
|
|
105
126
|
def static_svg pact, verification_status
|
@@ -11,13 +11,14 @@ module PactBroker
|
|
11
11
|
|
12
12
|
class Configuration
|
13
13
|
|
14
|
-
SAVABLE_SETTING_NAMES = [:order_versions_by_date, :use_case_sensitive_resource_names, :
|
14
|
+
SAVABLE_SETTING_NAMES = [:order_versions_by_date, :use_case_sensitive_resource_names, :enable_public_badge_access, :shields_io_base_url]
|
15
15
|
|
16
16
|
attr_accessor :log_dir, :database_connection, :auto_migrate_db, :use_hal_browser, :html_pact_renderer
|
17
17
|
attr_accessor :validate_database_connection_config, :enable_diagnostic_endpoints, :version_parser
|
18
18
|
attr_accessor :use_case_sensitive_resource_names, :order_versions_by_date
|
19
19
|
attr_accessor :semver_formats
|
20
|
-
attr_accessor :
|
20
|
+
attr_accessor :enable_public_badge_access, :shields_io_base_url
|
21
|
+
attr_accessor :webhook_retry_schedule
|
21
22
|
attr_writer :logger
|
22
23
|
|
23
24
|
def initialize
|
@@ -39,7 +40,7 @@ module PactBroker
|
|
39
40
|
config.use_hal_browser = true
|
40
41
|
config.validate_database_connection_config = true
|
41
42
|
config.enable_diagnostic_endpoints = true
|
42
|
-
config.
|
43
|
+
config.enable_public_badge_access = false # For security
|
43
44
|
config.shields_io_base_url = "https://img.shields.io".freeze
|
44
45
|
config.use_case_sensitive_resource_names = true
|
45
46
|
config.html_pact_renderer = default_html_pact_render
|
@@ -48,13 +49,14 @@ module PactBroker
|
|
48
49
|
# consistently extract an orderable object from the consumer application version number.
|
49
50
|
config.order_versions_by_date = false
|
50
51
|
config.semver_formats = ["%M.%m.%p%s%d","%M.%m", "%M"]
|
52
|
+
config.webhook_retry_schedule = [10, 60, 120, 300, 600, 1200] #10 sec, 1 min, 2 min, 5 min, 10 min, 20 min => 38 minutes
|
51
53
|
config
|
52
54
|
end
|
53
55
|
|
54
56
|
def self.default_html_pact_render
|
55
|
-
lambda { |pact|
|
57
|
+
lambda { |pact, options|
|
56
58
|
require 'pact_broker/api/renderers/html_pact_renderer'
|
57
|
-
PactBroker::Api::Renderers::HtmlPactRenderer.call pact
|
59
|
+
PactBroker::Api::Renderers::HtmlPactRenderer.call pact, options
|
58
60
|
}
|
59
61
|
end
|
60
62
|
|
@@ -106,6 +108,11 @@ module PactBroker
|
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
111
|
+
def enable_badge_resources= enable_badge_resources
|
112
|
+
puts "Pact Broker configuration property `enable_badge_resources` is deprecated. Please use `enable_public_badge_access`"
|
113
|
+
self.enable_public_badge_access = enable_badge_resources
|
114
|
+
end
|
115
|
+
|
109
116
|
def save_to_database
|
110
117
|
# Can't require a Sequel::Model class before the connection has been set
|
111
118
|
require 'pact_broker/config/save'
|
@@ -1,22 +1,23 @@
|
|
1
1
|
require 'pact_broker/verifications/verification_status'
|
2
|
+
require 'pact_broker/webhooks/status'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Domain
|
5
|
-
|
6
6
|
class Relationship
|
7
7
|
|
8
8
|
attr_reader :consumer, :provider, :latest_pact, :latest_verification, :webhooks
|
9
9
|
|
10
|
-
def initialize consumer, provider, latest_pact = nil, latest_verification = nil, webhooks = []
|
10
|
+
def initialize consumer, provider, latest_pact = nil, latest_verification = nil, webhooks = [], triggered_webhooks = []
|
11
11
|
@consumer = consumer
|
12
12
|
@provider = provider
|
13
13
|
@latest_pact = latest_pact
|
14
14
|
@latest_verification = latest_verification
|
15
15
|
@webhooks = webhooks
|
16
|
+
@triggered_webhooks = triggered_webhooks
|
16
17
|
end
|
17
18
|
|
18
|
-
def self.create consumer, provider, latest_pact, latest_verification, webhooks = []
|
19
|
-
new consumer, provider, latest_pact, latest_verification, webhooks
|
19
|
+
def self.create consumer, provider, latest_pact, latest_verification, webhooks = [], triggered_webhooks = []
|
20
|
+
new consumer, provider, latest_pact, latest_verification, webhooks, triggered_webhooks
|
20
21
|
end
|
21
22
|
|
22
23
|
def eq? other
|
@@ -45,6 +46,14 @@ module PactBroker
|
|
45
46
|
@webhooks.any?
|
46
47
|
end
|
47
48
|
|
49
|
+
def webhook_status
|
50
|
+
@webhook_status ||= PactBroker::Webhooks::Status.new(@latest_pact, @webhooks, @triggered_webhooks).to_sym
|
51
|
+
end
|
52
|
+
|
53
|
+
def last_webhook_execution_date
|
54
|
+
@last_webhook_execution_date ||= @triggered_webhooks.any? ? @triggered_webhooks.sort{|a, b| a.created_at <=> b.created_at }.last.created_at : nil
|
55
|
+
end
|
56
|
+
|
48
57
|
def verification_status
|
49
58
|
@verification_status ||= PactBroker::Verifications::Status.new(@latest_pact, @latest_verification).to_sym
|
50
59
|
end
|
@@ -4,9 +4,7 @@ require 'pact_broker/logging'
|
|
4
4
|
require 'pact_broker/api/contracts/webhook_contract'
|
5
5
|
|
6
6
|
module PactBroker
|
7
|
-
|
8
7
|
module Domain
|
9
|
-
|
10
8
|
class Webhook
|
11
9
|
|
12
10
|
include Messages
|
@@ -33,9 +31,9 @@ module PactBroker
|
|
33
31
|
request && request.description
|
34
32
|
end
|
35
33
|
|
36
|
-
def execute
|
34
|
+
def execute options
|
37
35
|
logger.info "Executing #{self}"
|
38
|
-
request.execute
|
36
|
+
request.execute options
|
39
37
|
end
|
40
38
|
|
41
39
|
def to_s
|
@@ -50,7 +48,5 @@ module PactBroker
|
|
50
48
|
provider && provider.name
|
51
49
|
end
|
52
50
|
end
|
53
|
-
|
54
51
|
end
|
55
|
-
|
56
52
|
end
|
@@ -11,7 +11,7 @@ module PactBroker
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def success?
|
14
|
-
!@response.nil? && @response.code.to_i <
|
14
|
+
!@response.nil? && @response.code.to_i < 300
|
15
15
|
end
|
16
16
|
|
17
17
|
def response
|
@@ -25,7 +25,6 @@ module PactBroker
|
|
25
25
|
def logs
|
26
26
|
@logs
|
27
27
|
end
|
28
|
-
|
29
28
|
end
|
30
29
|
end
|
31
30
|
end
|