pact_broker 2.72.0 → 2.76.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/.optic/.gitignore +2 -0
- data/.optic/api/specification.json +1 -0
- data/.optic/ignore +14 -0
- data/CHANGELOG.md +66 -0
- data/DEVELOPER_SETUP.md +9 -0
- data/Dockerfile +1 -0
- data/ISSUES.md +3 -3
- data/README.md +1 -1
- data/config/database.yml +1 -1
- data/db/migrations/20210115_add_webhook_foreign_key_indexes.rb +49 -0
- data/db/migrations/20210116_add_context_to_triggered_webhook.rb +11 -0
- data/db/migrations/migration_helper.rb +8 -0
- data/docker-compose-issue-repro-with-pact-broker-docker-image.yml +33 -0
- data/docker-compose-test.yml +4 -4
- data/lib/db.rb +1 -0
- data/lib/pact_broker/api.rb +13 -2
- data/lib/pact_broker/api/decorators.rb +3 -7
- data/lib/pact_broker/api/decorators/configuration.rb +33 -0
- data/lib/pact_broker/api/decorators/decorator_context_creator.rb +13 -0
- data/lib/pact_broker/api/decorators/extended_pact_decorator.rb +9 -1
- data/lib/pact_broker/api/decorators/extended_verification_decorator.rb +8 -0
- data/lib/pact_broker/api/decorators/matrix_decorator.rb +9 -4
- data/lib/pact_broker/api/decorators/pact_collection_decorator.rb +1 -0
- data/lib/pact_broker/api/decorators/pacticipant_collection_decorator.rb +2 -3
- data/lib/pact_broker/api/decorators/reason_decorator.rb +2 -0
- data/lib/pact_broker/api/decorators/tag_decorator.rb +0 -3
- data/lib/pact_broker/api/decorators/verifiable_pact_decorator.rb +3 -1
- data/lib/pact_broker/api/pact_broker_urls.rb +4 -4
- data/lib/pact_broker/api/paths.rb +5 -0
- data/lib/pact_broker/api/renderers/html_pact_renderer.rb +2 -2
- data/lib/pact_broker/api/resources/all_webhooks.rb +3 -3
- data/lib/pact_broker/api/resources/can_i_deploy_badge.rb +1 -1
- data/lib/pact_broker/api/resources/dashboard.rb +2 -2
- data/lib/pact_broker/api/resources/default_base_resource.rb +37 -12
- data/lib/pact_broker/api/resources/error_handler.rb +1 -1
- data/lib/pact_broker/api/resources/error_response_body_generator.rb +41 -0
- data/lib/pact_broker/api/resources/group.rb +1 -1
- data/lib/pact_broker/api/resources/integrations.rb +1 -1
- data/lib/pact_broker/api/resources/label.rb +1 -1
- data/lib/pact_broker/api/resources/latest_pact.rb +2 -2
- data/lib/pact_broker/api/resources/latest_pacts.rb +1 -1
- data/lib/pact_broker/api/resources/latest_verifications_for_consumer_version.rb +2 -2
- data/lib/pact_broker/api/resources/matrix.rb +2 -2
- data/lib/pact_broker/api/resources/matrix_for_consumer_and_provider.rb +1 -1
- data/lib/pact_broker/api/resources/metadata_resource_methods.rb +2 -1
- data/lib/pact_broker/api/resources/pact.rb +2 -2
- data/lib/pact_broker/api/resources/pact_triggered_webhooks.rb +1 -1
- data/lib/pact_broker/api/resources/pact_versions.rb +1 -1
- data/lib/pact_broker/api/resources/pact_webhooks.rb +3 -3
- data/lib/pact_broker/api/resources/pact_webhooks_status.rb +2 -2
- data/lib/pact_broker/api/resources/pacticipant.rb +1 -1
- data/lib/pact_broker/api/resources/pacticipants.rb +3 -3
- data/lib/pact_broker/api/resources/pacticipants_for_label.rb +1 -1
- data/lib/pact_broker/api/resources/previous_distinct_pact_version.rb +1 -1
- data/lib/pact_broker/api/resources/provider_pacts.rb +1 -7
- data/lib/pact_broker/api/resources/provider_pacts_for_verification.rb +2 -2
- data/lib/pact_broker/api/resources/relationships.rb +1 -1
- data/lib/pact_broker/api/resources/tag.rb +1 -1
- data/lib/pact_broker/api/resources/tagged_pact_versions.rb +1 -1
- data/lib/pact_broker/api/resources/verification.rb +2 -2
- data/lib/pact_broker/api/resources/verification_triggered_webhooks.rb +1 -1
- data/lib/pact_broker/api/resources/verifications.rb +1 -1
- data/lib/pact_broker/api/resources/version.rb +1 -1
- data/lib/pact_broker/api/resources/versions.rb +1 -1
- data/lib/pact_broker/api/resources/webhook.rb +2 -2
- data/lib/pact_broker/api/resources/webhook_execution.rb +4 -4
- data/lib/pact_broker/api/resources/webhook_execution_methods.rb +1 -3
- data/lib/pact_broker/api/resources/webhooks.rb +3 -3
- data/lib/pact_broker/app.rb +14 -3
- data/lib/pact_broker/application_context.rb +41 -0
- data/lib/pact_broker/configuration.rb +12 -4
- data/lib/pact_broker/doc/controllers/app.rb +3 -2
- data/lib/pact_broker/domain/version.rb +13 -6
- data/lib/pact_broker/domain/webhook_request.rb +1 -1
- data/lib/pact_broker/error.rb +0 -2
- data/lib/pact_broker/errors.rb +28 -0
- data/lib/pact_broker/errors/error_logger.rb +25 -0
- data/lib/pact_broker/metrics/service.rb +12 -1
- data/lib/pact_broker/pacts/metadata.rb +53 -8
- data/lib/pact_broker/pacts/repository.rb +10 -17
- data/lib/pact_broker/pacts/selector.rb +22 -0
- data/lib/pact_broker/pacts/selectors.rb +4 -0
- data/lib/pact_broker/services.rb +106 -31
- data/lib/pact_broker/tags/tag_with_latest_flag.rb +2 -0
- data/lib/pact_broker/test/http_test_data_builder.rb +83 -21
- data/lib/pact_broker/test/test_data_builder.rb +3 -2
- data/lib/pact_broker/ui/views/index/_getting-started.haml +1 -1
- data/lib/pact_broker/ui/views/index/show-with-tags.haml +16 -16
- data/lib/pact_broker/ui/views/index/show.haml +6 -6
- data/lib/pact_broker/ui/views/layouts/main.haml +2 -2
- data/lib/pact_broker/ui/views/matrix/show.haml +32 -33
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/webhooks/execution_configuration.rb +4 -0
- data/lib/pact_broker/webhooks/execution_configuration_creator.rb +14 -0
- data/lib/pact_broker/webhooks/repository.rb +3 -2
- data/lib/pact_broker/webhooks/service.rb +2 -1
- data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
- data/lib/rack/pact_broker/hal_browser_redirect.rb +42 -0
- data/lib/rack/pact_broker/set_base_url.rb +22 -0
- data/lib/sequel/extensions/statement_timeout.rb +22 -0
- data/optic.yml +5 -0
- data/pact_broker.gemspec +1 -1
- data/public/css/bootstrap-grid.css +3719 -0
- data/public/css/bootstrap-grid.css.map +1 -0
- data/public/css/bootstrap-grid.min.css +7 -0
- data/public/css/bootstrap-grid.min.css.map +1 -0
- data/public/css/bootstrap-reboot.css +331 -0
- data/public/css/bootstrap-reboot.css.map +1 -0
- data/public/css/bootstrap-reboot.min.css +8 -0
- data/public/css/bootstrap-reboot.min.css.map +1 -0
- data/public/css/bootstrap.css +8885 -5604
- data/public/css/bootstrap.css.map +1 -1
- data/public/css/bootstrap.min.css +4 -3
- data/public/css/bootstrap.min.css.map +1 -1
- data/public/images/alert.svg +1 -0
- data/public/images/arrow-switch.svg +1 -0
- data/public/images/check.svg +1 -0
- data/public/images/clock.svg +1 -0
- data/public/images/copy.svg +1 -0
- data/public/images/kebab-horizontal.svg +1 -0
- data/public/javascripts/clipboard.js +3 -3
- data/public/javascripts/{jquery-3.3.1.js → jquery-3.5.1.js} +1150 -642
- data/public/javascripts/jquery-3.5.1.min.js +2 -0
- data/public/javascripts/jquery-3.5.1.min.map +1 -0
- data/public/javascripts/matrix.js +2 -2
- data/public/js/bootstrap.bundle.js +7013 -0
- data/public/js/bootstrap.bundle.js.map +1 -0
- data/public/js/bootstrap.bundle.min.js +7 -0
- data/public/js/bootstrap.bundle.min.js.map +1 -0
- data/public/js/bootstrap.js +3862 -1804
- data/public/js/bootstrap.js.map +1 -0
- data/public/js/bootstrap.min.js +6 -6
- data/public/js/bootstrap.min.js.map +1 -0
- data/public/stylesheets/index.css +56 -3
- data/public/stylesheets/matrix.css +55 -5
- data/public/stylesheets/pact.css +14 -0
- data/regression/.gitignore +1 -0
- data/regression/can_i_deploy_spec.rb +42 -0
- data/regression/regression_helper.rb +37 -0
- data/regression/script/approval-all.sh +6 -0
- data/script/exercise-api-for-optic.sh +3 -0
- data/script/reproduce-issue-starting-up.rb +43 -0
- data/script/reproduce-issue.rb +9 -21
- data/spec/lib/pact_broker/api/decorators/extended_pact_decorator_spec.rb +1 -0
- data/spec/lib/pact_broker/api/decorators/matrix_decorator_spec.rb +20 -8
- data/spec/lib/pact_broker/api/decorators/verifiable_pact_decorator_spec.rb +5 -7
- data/spec/lib/pact_broker/api/pact_broker_urls_spec.rb +10 -6
- data/spec/lib/pact_broker/api/resources/can_i_deploy_badge_spec.rb +1 -1
- data/spec/lib/pact_broker/api/resources/default_base_resource_spec.rb +59 -10
- data/spec/lib/pact_broker/api/resources/error_response_body_generator_spec.rb +69 -0
- data/spec/lib/pact_broker/db/log_quietener_spec.rb +1 -1
- data/spec/lib/pact_broker/doc/controllers/app_spec.rb +3 -5
- data/spec/lib/pact_broker/errors/error_logger_spec.rb +62 -0
- data/spec/lib/pact_broker/errors_spec.rb +55 -0
- data/spec/lib/pact_broker/pacts/metadata_spec.rb +73 -0
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_fallback_spec.rb +2 -2
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +33 -13
- data/spec/lib/pact_broker/pacts/selected_pact_spec.rb +23 -0
- data/spec/lib/pact_broker/webhooks/repository_spec.rb +5 -2
- data/spec/lib/pact_broker/webhooks/service_spec.rb +2 -1
- data/spec/lib/rack/pact_broker/hal_browser_redirect_spec.rb +27 -0
- data/tasks/rspec.rake +6 -0
- metadata +65 -17
- data/public/css/bootstrap-theme.css +0 -587
- data/public/css/bootstrap-theme.css.map +0 -1
- data/public/css/bootstrap-theme.min.css +0 -6
- data/public/css/bootstrap-theme.min.css.map +0 -1
- data/public/fonts/glyphicons-halflings-regular.svg +0 -288
- data/public/javascripts/jquery-3.3.1.min.js +0 -2
- data/public/javascripts/jquery-3.3.1.min.map +0 -1
- data/spec/lib/pact_broker/api/resources/error_handler_spec.rb +0 -195
@@ -8,6 +8,7 @@ module PactBroker
|
|
8
8
|
allow_any_instance_of(PactBroker::Api::PactBrokerUrls).to receive(:pact_version_url_with_metadata).and_return('http://pact')
|
9
9
|
allow(PactBroker::Pacts::BuildVerifiablePactNotices).to receive(:call).and_return(notices)
|
10
10
|
allow_any_instance_of(PactBroker::Pacts::VerifiablePactMessages).to receive(:pact_version_short_description).and_return('short desc')
|
11
|
+
allow_any_instance_of(VerifiablePactDecorator).to receive(:build_metadata_for_pact_for_verification).and_return(metadata)
|
11
12
|
end
|
12
13
|
|
13
14
|
let(:pending_reason) { "the pending reason" }
|
@@ -45,13 +46,15 @@ module PactBroker
|
|
45
46
|
name: "name",
|
46
47
|
provider_name: "Bar",
|
47
48
|
pending_provider_tags: pending_provider_tags,
|
48
|
-
consumer_tags: consumer_tags
|
49
|
+
consumer_tags: consumer_tags,
|
50
|
+
selectors: PactBroker::Pacts::Selectors.new([PactBroker::Pacts::ResolvedSelector.new({ latest: true }, double('version', number: "2", id: 1))]))
|
49
51
|
end
|
50
52
|
let(:pending_provider_tags) { %w[dev] }
|
51
53
|
let(:consumer_tags) { %w[dev] }
|
52
54
|
let(:options) { { user_options: { base_url: 'http://example.org', include_pending_status: include_pending_status } } }
|
53
55
|
let(:include_pending_status) { true }
|
54
56
|
let(:wip){ false }
|
57
|
+
let(:metadata) { double('metadata') }
|
55
58
|
let(:json) { decorator.to_json(options) }
|
56
59
|
|
57
60
|
subject { JSON.parse(json) }
|
@@ -61,7 +64,7 @@ module PactBroker
|
|
61
64
|
end
|
62
65
|
|
63
66
|
it "creates the pact version url" do
|
64
|
-
expect(decorator).to receive(:pact_version_url_with_metadata).with(pact,
|
67
|
+
expect(decorator).to receive(:pact_version_url_with_metadata).with(pact, metadata, 'http://example.org')
|
65
68
|
subject
|
66
69
|
end
|
67
70
|
|
@@ -84,11 +87,6 @@ module PactBroker
|
|
84
87
|
it "includes the wip flag" do
|
85
88
|
expect(subject['verificationProperties']['wip']).to be true
|
86
89
|
end
|
87
|
-
|
88
|
-
it "includes it in the metadata" do
|
89
|
-
expect(decorator).to receive(:pact_version_url_with_metadata).with(pact, { wip: true }, 'http://example.org')
|
90
|
-
subject
|
91
|
-
end
|
92
90
|
end
|
93
91
|
end
|
94
92
|
end
|
@@ -36,6 +36,7 @@ module PactBroker
|
|
36
36
|
pacticipant: consumer,
|
37
37
|
number: "2/4")
|
38
38
|
end
|
39
|
+
let(:tag) { double('tag', name: "feat/foo", version: version) }
|
39
40
|
|
40
41
|
matcher :match_route_in_api do |api|
|
41
42
|
match do |url|
|
@@ -106,13 +107,9 @@ module PactBroker
|
|
106
107
|
end
|
107
108
|
|
108
109
|
describe "webhook metadata" do
|
109
|
-
let(:expected_metadata) do
|
110
|
-
{ consumer_version_number: "123/456", consumer_version_tags: %w[dev], wip: "true" }
|
111
|
-
end
|
112
|
-
|
113
110
|
it "builds the webhook metadata" do
|
114
|
-
encoded_metadata = PactBrokerUrls.encode_metadata(
|
115
|
-
expect(PactBrokerUrls.decode_pact_metadata(encoded_metadata)).to eq
|
111
|
+
encoded_metadata = PactBrokerUrls.encode_metadata("some" => "metadata")
|
112
|
+
expect(PactBrokerUrls.decode_pact_metadata(encoded_metadata)).to eq "some" => "metadata"
|
116
113
|
end
|
117
114
|
end
|
118
115
|
|
@@ -168,6 +165,13 @@ module PactBroker
|
|
168
165
|
|
169
166
|
it { is_expected.to eq "http://example.org/matrix/provider/Bar%2FBar/latest/meep/consumer/Foo%2FFoo/latest/bar/badge.svg" }
|
170
167
|
end
|
168
|
+
|
169
|
+
describe "tag_url" do
|
170
|
+
subject { PactBrokerUrls.tag_url(base_url, tag) }
|
171
|
+
|
172
|
+
it { is_expected.to match_route_in_api(PactBroker::API) }
|
173
|
+
it { is_expected.to eq "http://example.org/pacticipants/Foo%2FFoo/versions/2%2F4/tags/feat%2Ffoo" }
|
174
|
+
end
|
171
175
|
end
|
172
176
|
end
|
173
177
|
end
|
@@ -15,7 +15,7 @@ module PactBroker
|
|
15
15
|
allow(pacticipant_service).to receive(:find_pacticipant_by_name).and_return(pacticipant)
|
16
16
|
allow(version_service).to receive(:find_by_pacticipant_name_and_latest_tag).and_return(version)
|
17
17
|
allow(PactBroker.configuration).to receive(:show_backtrace_in_error_response?).and_return(false)
|
18
|
-
allow(
|
18
|
+
allow(PactBroker::Errors).to receive(:generate_error_reference).and_return("abcd")
|
19
19
|
end
|
20
20
|
|
21
21
|
let(:pacticipant_service) { class_double("PactBroker::Pacticipant::Service").as_stubbed_const }
|
@@ -1,20 +1,30 @@
|
|
1
1
|
require 'pact_broker/api/resources/default_base_resource'
|
2
|
+
require 'pact_broker/application_context'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Api
|
5
6
|
module Resources
|
6
7
|
describe DefaultBaseResource do
|
7
|
-
|
8
|
+
before do
|
9
|
+
allow(env).to receive(:[]).with("pactbroker.base_url").and_return(nil)
|
10
|
+
end
|
11
|
+
let(:request) { double('request', body: body, uri: uri, base_uri: URI("http://example.org/"), env: env, path_info: path_info).as_null_object }
|
12
|
+
let(:path_info) { { application_context: application_context, key1: "foo%20bar", key2: :value2, key3: 1.2 }}
|
13
|
+
let(:application_context) { PactBroker::ApplicationContext.default_application_context }
|
8
14
|
let(:response) { double('response').as_null_object }
|
9
15
|
let(:uri) { URI('http://example.org/path?query') }
|
10
16
|
let(:body) { double('body', to_s: body_string) }
|
11
17
|
let(:body_string) { '' }
|
12
18
|
let(:env) { double('env').as_null_object }
|
13
19
|
|
14
|
-
subject { BaseResource.new(request, response) }
|
20
|
+
subject(:resource) { BaseResource.new(request, response) }
|
15
21
|
|
16
22
|
its(:resource_url) { is_expected.to eq 'http://example.org/path' }
|
17
23
|
|
24
|
+
describe "identifier_from_path" do
|
25
|
+
its(:identifier_from_path) { is_expected.to eq key1: "foo bar", key2: :value2, key3: 1.2 }
|
26
|
+
end
|
27
|
+
|
18
28
|
describe "params" do
|
19
29
|
let(:body_string) { { foo: 'bar' }.to_json }
|
20
30
|
|
@@ -78,19 +88,19 @@ module PactBroker
|
|
78
88
|
end
|
79
89
|
|
80
90
|
describe "base_url" do
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
end
|
91
|
+
before do
|
92
|
+
allow(env).to receive(:[]).with("pactbroker.base_url").and_return("http://rack")
|
93
|
+
end
|
85
94
|
|
86
|
-
|
87
|
-
|
95
|
+
context "when pactbroker.base_url is set on the env" do
|
96
|
+
it "uses that" do
|
97
|
+
expect(subject.base_url).to eq "http://rack"
|
88
98
|
end
|
89
99
|
end
|
90
100
|
|
91
|
-
context "when
|
101
|
+
context "when the rack env value is not set" do
|
92
102
|
before do
|
93
|
-
allow(
|
103
|
+
allow(env).to receive(:[]).with("pactbroker.base_url").and_return(nil)
|
94
104
|
end
|
95
105
|
|
96
106
|
it "returns the base URL from the request" do
|
@@ -133,6 +143,39 @@ module PactBroker
|
|
133
143
|
end
|
134
144
|
end
|
135
145
|
end
|
146
|
+
|
147
|
+
describe "forbidden?" do
|
148
|
+
context "with the resource_authorizer configured" do
|
149
|
+
let(:application_context) { PactBroker::ApplicationContext.default_application_context(resource_authorizer: resource_authorizer) }
|
150
|
+
let(:resource_authorizer) { double('resource_authorizer', call: allowed) }
|
151
|
+
let(:allowed) { true }
|
152
|
+
|
153
|
+
it "calls the resource authorizer" do
|
154
|
+
expect(resource_authorizer).to receive(:call).with(resource)
|
155
|
+
resource.forbidden?
|
156
|
+
end
|
157
|
+
|
158
|
+
context "when the authorizer returns true" do
|
159
|
+
it "returns false" do
|
160
|
+
expect(resource.forbidden?).to eq false
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
context "when the authorizer returns false" do
|
165
|
+
let(:allowed) { false }
|
166
|
+
|
167
|
+
it "returns true" do
|
168
|
+
expect(resource.forbidden?).to eq true
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
context "with no resource_authorizer configured" do
|
175
|
+
it "returns false" do
|
176
|
+
expect(resource.forbidden?).to eq false
|
177
|
+
end
|
178
|
+
end
|
136
179
|
end
|
137
180
|
|
138
181
|
ALL_RESOURCES = ObjectSpace.each_object(::Class)
|
@@ -144,22 +187,28 @@ module PactBroker
|
|
144
187
|
before do
|
145
188
|
# stub out all path info params for pf
|
146
189
|
allow(path_info).to receive(:[]).and_return('1')
|
190
|
+
allow(path_info).to receive(:[]).with(:application_context).and_return(application_context)
|
147
191
|
end
|
192
|
+
let(:application_context) { PactBroker::ApplicationContext.default_application_context(before_resource: before_resource, after_resource: after_resource) }
|
148
193
|
let(:request) { double('request', uri: URI("http://example.org"), path_info: path_info).as_null_object }
|
149
194
|
let(:path_info) { {} }
|
150
195
|
let(:response) { double('response').as_null_object }
|
151
196
|
let(:resource) { resource_class.new(request, response) }
|
197
|
+
let(:before_resource) { double('before_resource', call: nil) }
|
198
|
+
let(:after_resource) { double('after_resource', call: nil) }
|
152
199
|
|
153
200
|
it "includes OPTIONS in the list of allowed_methods" do
|
154
201
|
expect(resource.allowed_methods).to include "OPTIONS"
|
155
202
|
end
|
156
203
|
|
157
204
|
it "calls super in its constructor" do
|
205
|
+
expect(application_context.before_resource).to receive(:call)
|
158
206
|
expect(PactBroker.configuration.before_resource).to receive(:call)
|
159
207
|
resource
|
160
208
|
end
|
161
209
|
|
162
210
|
it "calls super in finish_request" do
|
211
|
+
expect(application_context.after_resource).to receive(:call)
|
163
212
|
expect(PactBroker.configuration.after_resource).to receive(:call)
|
164
213
|
resource.finish_request
|
165
214
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'pact_broker/api/resources/error_response_body_generator'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Resources
|
6
|
+
describe ErrorResponseBodyGenerator do
|
7
|
+
describe ".call" do
|
8
|
+
before do
|
9
|
+
allow(error).to receive(:backtrace).and_return(["backtrace"])
|
10
|
+
end
|
11
|
+
let(:error) { StandardError.new('test error') }
|
12
|
+
let(:error_reference) { "bYWfnyWPlf" }
|
13
|
+
|
14
|
+
subject { JSON.parse(ErrorResponseBodyGenerator.call(error, error_reference)) }
|
15
|
+
|
16
|
+
it "includes an error reference" do
|
17
|
+
expect(subject['error']).to include 'reference' => "bYWfnyWPlf"
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when show_backtrace_in_error_response? is true" do
|
21
|
+
before do
|
22
|
+
allow(PactBroker.configuration).to receive(:show_backtrace_in_error_response?).and_return(true)
|
23
|
+
end
|
24
|
+
|
25
|
+
context "when the error is a PactBroker::Error or subclass" do
|
26
|
+
let(:error) { Class.new(PactBroker::Error).new('test error') }
|
27
|
+
|
28
|
+
it "uses the error message as the message" do
|
29
|
+
expect(subject['error']).to include 'message' => "test error"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "includes the backtrace in the error response" do
|
33
|
+
expect(subject['error']).to include ('backtrace')
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when show_backtrace_in_error_response? is false" do
|
39
|
+
before do
|
40
|
+
allow(PactBroker.configuration).to receive(:show_backtrace_in_error_response?).and_return(false)
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when the error is a PactBroker::Error or subclass" do
|
44
|
+
let(:error) { Class.new(PactBroker::Error).new('test error') }
|
45
|
+
|
46
|
+
it "uses the error message as the message" do
|
47
|
+
expect(subject['error']).to include 'message' => "test error"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not include the backtrace in the error response" do
|
51
|
+
expect(subject['error']).to_not include ('backtrace')
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when the error is not a PactBroker::Error or subclass" do
|
56
|
+
it "uses a hardcoded error message" do
|
57
|
+
expect(subject['error']['message']).to match /An error/
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does not include the backtrace in the error response" do
|
61
|
+
expect(subject['error']).to_not include ('backtrace')
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -42,7 +42,7 @@ module PactBroker
|
|
42
42
|
expect(logs.string).to include "ERROR -- :"
|
43
43
|
end
|
44
44
|
|
45
|
-
it "does not
|
45
|
+
it "does not append a friendly message so people will correctly panic" do
|
46
46
|
expect(logs.string).to_not include "Don't panic."
|
47
47
|
end
|
48
48
|
end
|
@@ -4,13 +4,13 @@ module PactBroker
|
|
4
4
|
module Doc
|
5
5
|
module Controllers
|
6
6
|
describe App do
|
7
|
-
|
8
7
|
describe "GET relation" do
|
9
8
|
|
10
9
|
let(:app) { PactBroker::Doc::Controllers::App }
|
10
|
+
let(:rack_env) { {} }
|
11
11
|
|
12
12
|
context "when the resource exists" do
|
13
|
-
subject { get "/webhooks" }
|
13
|
+
subject { get "/webhooks", nil, rack_env }
|
14
14
|
|
15
15
|
it "returns a 200 status" do
|
16
16
|
subject
|
@@ -34,9 +34,7 @@ module PactBroker
|
|
34
34
|
end
|
35
35
|
|
36
36
|
context "with the base_url set" do
|
37
|
-
|
38
|
-
allow(PactBroker.configuration).to receive(:base_url).and_return('http://example.org/pact-broker')
|
39
|
-
end
|
37
|
+
let(:rack_env) { { "pactbroker.base_url" => "http://example.org/pact-broker"} }
|
40
38
|
|
41
39
|
it "returns absolute links" do
|
42
40
|
expect(subject.body).to include "href='http://example.org/pact-broker/css"
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'pact_broker/errors/error_logger'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Errors
|
5
|
+
describe ErrorLogger do
|
6
|
+
before do
|
7
|
+
allow(ErrorLogger).to receive(:logger).and_return(logger)
|
8
|
+
allow(error).to receive(:backtrace).and_return(["backtrace"])
|
9
|
+
allow(PactBroker::Errors).to receive(:reportable_error?).and_return(reportable)
|
10
|
+
end
|
11
|
+
|
12
|
+
let(:logger) { double('logger').as_null_object }
|
13
|
+
let(:error) { StandardError.new('test error') }
|
14
|
+
let(:env) { double('env') }
|
15
|
+
let(:error_reference) { "bYWfnyWPlf" }
|
16
|
+
let(:reportable) { true }
|
17
|
+
|
18
|
+
subject { ErrorLogger.call(error, error_reference, env) }
|
19
|
+
|
20
|
+
context "when the error class is in the warning_error_classes list" do
|
21
|
+
let(:error) { Sequel::ForeignKeyConstraintViolation.new }
|
22
|
+
|
23
|
+
it "logs at warn so as not to wake everyone up in the middle of the night" do
|
24
|
+
expect(logger).to receive(:warn).with(/bYWfnyWPlf/, error)
|
25
|
+
subject
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when the error cause class is in the warning_error_classes list" do
|
30
|
+
class TestCauseError < StandardError; end
|
31
|
+
|
32
|
+
before do
|
33
|
+
allow(PactBroker.configuration).to receive(:warning_error_classes).and_return([TestCauseError])
|
34
|
+
allow(error).to receive(:cause).and_return(TestCauseError.new)
|
35
|
+
end
|
36
|
+
|
37
|
+
let(:error) { StandardError.new("message") }
|
38
|
+
|
39
|
+
it "logs at warn so as not to wake everyone up in the middle of the night" do
|
40
|
+
expect(logger).to receive(:warn).with(/bYWfnyWPlf/, error)
|
41
|
+
subject
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when the error is reportable" do
|
46
|
+
it "logs at error" do
|
47
|
+
expect(ErrorLogger).to receive(:log_error).with(error, /bYWfnyWPlf/)
|
48
|
+
subject
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when the error is not reportable and not a warning level" do
|
53
|
+
let(:reportable) { false }
|
54
|
+
|
55
|
+
it "logs at info" do
|
56
|
+
expect(logger).to receive(:info).with(/bYWfnyWPlf/, error)
|
57
|
+
subject
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'pact_broker/errors'
|
2
|
+
require 'pact_broker/configuration'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Errors
|
6
|
+
describe ".report" do
|
7
|
+
before do
|
8
|
+
PactBroker.configuration.add_api_error_reporter do | error, options |
|
9
|
+
thing.call(error, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
PactBroker.configuration.add_api_error_reporter do | error, options |
|
13
|
+
thing.another_call(error, options)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:error) { StandardError.new('test error') }
|
18
|
+
let(:thing) { double('thing', call: nil, another_call: nil) }
|
19
|
+
let(:request) { double('request', env: env ) }
|
20
|
+
let(:error_reference) { "bYWfnyWPlf" }
|
21
|
+
let(:expected_options) { { env: env, error_reference: "bYWfnyWPlf" } }
|
22
|
+
let(:env) { double('env') }
|
23
|
+
|
24
|
+
subject { PactBroker::Errors.report(error, error_reference, request) }
|
25
|
+
|
26
|
+
|
27
|
+
it "invokes the api error reporters" do
|
28
|
+
expect(thing).to receive(:call).with(error, expected_options)
|
29
|
+
expect(thing).to receive(:another_call).with(error, expected_options)
|
30
|
+
subject
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when the error reporter raises an error itself" do
|
34
|
+
class TestError < StandardError; end
|
35
|
+
|
36
|
+
let(:logger) { double('logger').as_null_object }
|
37
|
+
|
38
|
+
before do
|
39
|
+
expect(thing).to receive(:call).and_raise(TestError.new)
|
40
|
+
allow(PactBroker::Errors).to receive(:logger).and_return(logger)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "logs the error" do
|
44
|
+
expect(logger).to receive(:error).at_least(1).times
|
45
|
+
subject
|
46
|
+
end
|
47
|
+
|
48
|
+
it "does not propagate the error" do
|
49
|
+
expect(thing).to receive(:another_call)
|
50
|
+
subject
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require 'pact_broker/pacts/metadata'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Pacts
|
5
|
+
module Metadata
|
6
|
+
describe "#build_metadata_for_pact_for_verification" do
|
7
|
+
let(:selectors) do
|
8
|
+
Selectors.new([ResolvedSelector.new({ latest: true, consumer: "consumer", tag: "tag" }, consumer_version)])
|
9
|
+
end
|
10
|
+
let(:consumer_version) { double('version', number: "2") }
|
11
|
+
let(:verifiable_pact) { double('PactBroker::Pacts::VerifiablePact', wip: wip, selectors: selectors) }
|
12
|
+
let(:wip) { false }
|
13
|
+
|
14
|
+
subject { Metadata.build_metadata_for_pact_for_verification(verifiable_pact) }
|
15
|
+
|
16
|
+
it "builds the metadata with the resolved selectors" do
|
17
|
+
expect(subject).to eq({
|
18
|
+
"s" => [
|
19
|
+
{
|
20
|
+
"l" => true,
|
21
|
+
"t" => "tag",
|
22
|
+
"cvn" => "2"
|
23
|
+
}
|
24
|
+
]
|
25
|
+
})
|
26
|
+
end
|
27
|
+
|
28
|
+
context "when wip is true" do
|
29
|
+
let(:wip) { true }
|
30
|
+
|
31
|
+
it { is_expected.to eq "w" => true }
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "parse_metadata" do
|
37
|
+
let(:incoming_metadata) do
|
38
|
+
{
|
39
|
+
"cvn" => "2",
|
40
|
+
"cvt" => ["tag"],
|
41
|
+
"w" => true,
|
42
|
+
"s" => [
|
43
|
+
{
|
44
|
+
"l" => true,
|
45
|
+
"t" => "tag",
|
46
|
+
"cvn" => "2"
|
47
|
+
}
|
48
|
+
]
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
let(:parsed_metadata) do
|
53
|
+
{
|
54
|
+
:consumer_version_number => "2",
|
55
|
+
:consumer_version_tags => ["tag"],
|
56
|
+
:wip => true,
|
57
|
+
:consumer_version_selectors => [
|
58
|
+
{
|
59
|
+
:latest => true,
|
60
|
+
:tag => "tag",
|
61
|
+
:consumer_version_number => "2"
|
62
|
+
}
|
63
|
+
]
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
it "expands the key names" do
|
68
|
+
expect(Metadata.parse_metadata(incoming_metadata)).to eq parsed_metadata
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|