pact_broker 2.57.0 → 2.58.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -0
- data/example/config.ru +1 -1
- data/lib/pact_broker/api/contracts/verification_contract.rb +2 -0
- data/lib/pact_broker/api/resources/error_handler.rb +10 -3
- data/lib/pact_broker/db/log_quietener.rb +7 -4
- data/lib/pact_broker/hash_refinements.rb +39 -0
- data/lib/pact_broker/logging.rb +11 -3
- data/lib/pact_broker/logging/default_formatter.rb +3 -1
- data/lib/pact_broker/version.rb +1 -1
- data/pact_broker.gemspec +2 -2
- data/spec/lib/pact_broker/api/contracts/verification_contract_spec.rb +18 -4
- data/spec/lib/pact_broker/db/log_quietener_spec.rb +10 -0
- data/spec/lib/pact_broker/hash_refinements_spec.rb +24 -0
- metadata +10 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9b3ca0a02cb3eb39138704d804ed6a9997aa044cf0729059175d24acf02794f
|
4
|
+
data.tar.gz: 619a828a1ab0f7b1d5677525c5d52b82ec785455a19c0603ce18a3981be81eb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80e5a6272e05b35ff82a5a08fc26cb8acc2729d64b969f3764dbd1bb6be4ed168722d884ca635fe85dc58946c085dc60d65b1d4c95cc0fc8d9437a9f8aaa3356
|
7
|
+
data.tar.gz: d094ef10bf315a635afd6c6ef52148ac25c2e03afafcbb5e53b411c4ff2e676fd01d9db45414be4354054396547ae182b4991beadf6e6f0de63045cb38b2ccde
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,19 @@
|
|
1
|
+
<a name="v2.58.0"></a>
|
2
|
+
### v2.58.0 (2020-06-19)
|
3
|
+
|
4
|
+
|
5
|
+
#### Features
|
6
|
+
|
7
|
+
* log foreign key constraint errors as warn as 99% of the time they are transitory and unreproducible and should not cause alarms to be raised ([71fd0270](/../../commit/71fd0270))
|
8
|
+
* use structured logs for logging errors ([1e097b37](/../../commit/1e097b37))
|
9
|
+
|
10
|
+
|
11
|
+
#### Bug Fixes
|
12
|
+
|
13
|
+
* fix: update sanitize gem for CVE-2020-4054 ([2af4bf9d](/../../commit/2af4bf9d))
|
14
|
+
* do not parse the provider version as a semantic version when order_versions_by_date is true ([bf30024f](/../../commit/bf30024f))
|
15
|
+
|
16
|
+
|
1
17
|
<a name="v2.57.0"></a>
|
2
18
|
### v2.57.0 (2020-06-16)
|
3
19
|
|
data/example/config.ru
CHANGED
@@ -8,7 +8,7 @@ ENV['RACK_ENV'] ||= 'production'
|
|
8
8
|
|
9
9
|
# Create a real database, and set the credentials for it here
|
10
10
|
# It is highly recommended to set the encoding to utf8
|
11
|
-
DATABASE_CREDENTIALS = {adapter: "sqlite", database: "pact_broker_database.sqlite3", :encoding => 'utf8'}
|
11
|
+
DATABASE_CREDENTIALS = { adapter: "sqlite", database: "pact_broker_database.sqlite3", :encoding => 'utf8', sql_log_level: :debug }
|
12
12
|
|
13
13
|
# For postgres:
|
14
14
|
#
|
@@ -8,13 +8,16 @@ module PactBroker
|
|
8
8
|
|
9
9
|
include PactBroker::Logging
|
10
10
|
|
11
|
+
WARNING_ERROR_CLASSES = [Sequel::ForeignKeyConstraintViolation]
|
12
|
+
|
11
13
|
def self.call e, request, response
|
12
14
|
error_reference = generate_error_reference
|
13
|
-
if
|
15
|
+
if log_as_warning?(e)
|
16
|
+
logger.warn("Error reference #{error_reference}", e)
|
17
|
+
elsif reportable?(e)
|
14
18
|
log_error(e, "Error reference #{error_reference}")
|
15
19
|
report(e, error_reference, request)
|
16
|
-
|
17
|
-
logger.info "Error reference #{error_reference} - #{e.class} #{e.message}\n#{e.backtrace.join("\n")}"
|
20
|
+
logger.info("Error reference #{error_reference}", e)
|
18
21
|
end
|
19
22
|
response.body = response_body_hash(e, error_reference).to_json
|
20
23
|
end
|
@@ -27,6 +30,10 @@ module PactBroker
|
|
27
30
|
!e.is_a?(PactBroker::Error) && !e.is_a?(JSON::GeneratorError)
|
28
31
|
end
|
29
32
|
|
33
|
+
def self.log_as_warning?(e)
|
34
|
+
WARNING_ERROR_CLASSES.any? { |clazz| e.is_a?(clazz) }
|
35
|
+
end
|
36
|
+
|
30
37
|
def self.display_message(e, error_reference)
|
31
38
|
if PactBroker.configuration.show_backtrace_in_error_response?
|
32
39
|
e.message || obfuscated_error_message(error_reference)
|
@@ -9,13 +9,11 @@ require 'delegate'
|
|
9
9
|
module PactBroker
|
10
10
|
module DB
|
11
11
|
class LogQuietener < SimpleDelegator
|
12
|
-
def info *args
|
13
|
-
__getobj__().debug(*args)
|
14
|
-
end
|
15
|
-
|
16
12
|
def error *args
|
17
13
|
if error_is_about_table_not_existing?(args)
|
18
14
|
__getobj__().debug(*reassure_people_that_this_is_expected(args))
|
15
|
+
elsif foreign_key_error?(args)
|
16
|
+
__getobj__().warn(*args)
|
19
17
|
else
|
20
18
|
__getobj__().error(*args)
|
21
19
|
end
|
@@ -28,6 +26,11 @@ module PactBroker
|
|
28
26
|
args.first.include?("no such view"))
|
29
27
|
end
|
30
28
|
|
29
|
+
# Foreign key exceptions are almost always transitory and unreproducible by this stage
|
30
|
+
def foreign_key_error?(args)
|
31
|
+
args.first.is_a?(String) && args.first.downcase.include?("foreign key")
|
32
|
+
end
|
33
|
+
|
31
34
|
def reassure_people_that_this_is_expected(args)
|
32
35
|
message = args.shift
|
33
36
|
message = message + " Don't panic. This happens when Sequel doesn't know if a table/view exists or not."
|
@@ -18,6 +18,10 @@ module PactBroker
|
|
18
18
|
symbolize_keys_private(self)
|
19
19
|
end
|
20
20
|
|
21
|
+
def stringify_keys
|
22
|
+
stringify_keys_private(self)
|
23
|
+
end
|
24
|
+
|
21
25
|
def snakecase_keys
|
22
26
|
snakecase_keys_private(self)
|
23
27
|
end
|
@@ -26,6 +30,10 @@ module PactBroker
|
|
26
30
|
keys.each_with_object(Hash.new) { |k, hash| hash[k] = self[k] if has_key?(k) }
|
27
31
|
end
|
28
32
|
|
33
|
+
def camelcase_keys
|
34
|
+
camelcase_keys_private(self)
|
35
|
+
end
|
36
|
+
|
29
37
|
private
|
30
38
|
|
31
39
|
def snakecase_keys_private(params)
|
@@ -45,7 +53,25 @@ module PactBroker
|
|
45
53
|
else
|
46
54
|
params
|
47
55
|
end
|
56
|
+
end
|
48
57
|
|
58
|
+
def camelcase_keys_private(params)
|
59
|
+
case params
|
60
|
+
when Hash
|
61
|
+
params.inject({}) do |result, (key, value)|
|
62
|
+
snake_key = case key
|
63
|
+
when String then key.camelcase
|
64
|
+
when Symbol then key.to_s.camelcase.to_sym
|
65
|
+
else
|
66
|
+
key
|
67
|
+
end
|
68
|
+
result.merge(snake_key => camelcase_keys_private(value))
|
69
|
+
end
|
70
|
+
when Array
|
71
|
+
params.collect { |value| camelcase_keys_private(value) }
|
72
|
+
else
|
73
|
+
params
|
74
|
+
end
|
49
75
|
end
|
50
76
|
|
51
77
|
def symbolize_keys_private(params)
|
@@ -60,6 +86,19 @@ module PactBroker
|
|
60
86
|
params
|
61
87
|
end
|
62
88
|
end
|
89
|
+
|
90
|
+
def stringify_keys_private(params)
|
91
|
+
case params
|
92
|
+
when Hash
|
93
|
+
params.inject({}) do |result, (key, value)|
|
94
|
+
result.merge(key.to_s => symbolize_keys_private(value))
|
95
|
+
end
|
96
|
+
when Array
|
97
|
+
params.collect { |value| symbolize_keys_private(value) }
|
98
|
+
else
|
99
|
+
params
|
100
|
+
end
|
101
|
+
end
|
63
102
|
end
|
64
103
|
end
|
65
104
|
end
|
data/lib/pact_broker/logging.rb
CHANGED
@@ -31,9 +31,17 @@ module PactBroker
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def log_error e, description = nil
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
if logger.instance_of?(SemanticLogger::Logger)
|
35
|
+
if description
|
36
|
+
logger.error(description, e)
|
37
|
+
else
|
38
|
+
logger.error(e)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
message = "#{e.class} #{e.message}\n#{e.backtrace.join("\n")}"
|
42
|
+
message = "#{description} - #{message}" if description
|
43
|
+
logger.error message
|
44
|
+
end
|
37
45
|
if ENV['PACT_BROKER_HIDE_PACTFLOW_MESSAGES'] != 'true'
|
38
46
|
logger.info "\n\n#{'*' * 80}\n\nPrefer it was someone else's job to deal with this error? Check out https://pactflow.io/oss for a hardened, fully supported SaaS version of the Pact Broker with an improved UI + more.\n\n#{'*' * 80}\n"
|
39
47
|
end
|
@@ -9,7 +9,9 @@ module PactBroker
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def call(log, output)
|
12
|
-
|
12
|
+
self.log = log
|
13
|
+
self.logger = logger
|
14
|
+
@formatter.call(log.level.upcase, log.time, nil, [tags, named_tags, duration, message, payload, exception].compact.join(" "))
|
13
15
|
end
|
14
16
|
end
|
15
17
|
end
|
data/lib/pact_broker/version.rb
CHANGED
data/pact_broker.gemspec
CHANGED
@@ -51,7 +51,7 @@ Gem::Specification.new do |gem|
|
|
51
51
|
gem.add_runtime_dependency 'sequel', '~> 5.28'
|
52
52
|
gem.add_runtime_dependency 'webmachine', '1.5.0'
|
53
53
|
gem.add_runtime_dependency 'semver2', '~> 3.4.2'
|
54
|
-
gem.add_runtime_dependency 'rack', '
|
54
|
+
gem.add_runtime_dependency 'rack', '>= 2.2.3', '~> 2.2'
|
55
55
|
gem.add_runtime_dependency 'redcarpet', '>=3.3.2', '~>3.3'
|
56
56
|
gem.add_runtime_dependency 'pact-support', '~> 1.14', '>= 1.14.1'
|
57
57
|
gem.add_runtime_dependency 'padrino-core', '>= 0.14.3', '~> 0.14'
|
@@ -63,7 +63,7 @@ Gem::Specification.new do |gem|
|
|
63
63
|
gem.add_runtime_dependency 'dry-logic', '0.4.2' # Later version cases ArgumentError: wrong number of arguments
|
64
64
|
gem.add_runtime_dependency 'table_print', '~> 1.5'
|
65
65
|
gem.add_runtime_dependency 'semantic_logger', '~> 4.3'
|
66
|
-
gem.add_runtime_dependency 'sanitize', '
|
66
|
+
gem.add_runtime_dependency 'sanitize', '>= 5.2.1', '~> 5.2'
|
67
67
|
|
68
68
|
gem.add_development_dependency 'pact', '~>1.14'
|
69
69
|
gem.add_development_dependency 'rspec-pact-matchers', '~>0.1'
|
@@ -15,6 +15,7 @@ module PactBroker
|
|
15
15
|
let(:success) { true }
|
16
16
|
let(:provider_version) { "4.5.6" }
|
17
17
|
let(:build_url) { 'http://foo' }
|
18
|
+
let(:order_versions_by_date) { false }
|
18
19
|
|
19
20
|
def modify hash, options
|
20
21
|
hash.delete(options.fetch(:without))
|
@@ -24,6 +25,7 @@ module PactBroker
|
|
24
25
|
describe "errors" do
|
25
26
|
|
26
27
|
before do
|
28
|
+
allow(PactBroker.configuration).to receive(:order_versions_by_date).and_return(order_versions_by_date)
|
27
29
|
subject.validate(params)
|
28
30
|
end
|
29
31
|
|
@@ -85,10 +87,22 @@ module PactBroker
|
|
85
87
|
end
|
86
88
|
end
|
87
89
|
|
88
|
-
context "when
|
89
|
-
let(:
|
90
|
-
|
91
|
-
|
90
|
+
context "when order_versions_by_date is true" do
|
91
|
+
let(:order_versions_by_date) { true }
|
92
|
+
|
93
|
+
context "when the providerApplicationVersion is not a semantic version" do
|
94
|
+
let(:provider_version) { "#" }
|
95
|
+
its(:errors) { is_expected.to be_empty }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when order_versions_by_date is false" do
|
100
|
+
context "when the providerApplicationVersion is not a semantic version" do
|
101
|
+
let(:provider_version) { "#" }
|
102
|
+
|
103
|
+
it "has an error" do
|
104
|
+
expect(subject.errors[:provider_version]).to include(match("#.*cannot be parsed"))
|
105
|
+
end
|
92
106
|
end
|
93
107
|
end
|
94
108
|
end
|
@@ -23,6 +23,16 @@ module PactBroker
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
context "when the error is a foreign key constraint violation" do
|
27
|
+
before do
|
28
|
+
subject.error("SQLite3::ConstraintException: FOREIGN KEY constraint failed: delete from pacticipants where id = 1")
|
29
|
+
end
|
30
|
+
|
31
|
+
it "logs the message at warn level" do
|
32
|
+
expect(logs.string).to include "WARN -- :"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
26
36
|
context "when the error is NOT for a table or view that does not exist" do
|
27
37
|
before do
|
28
38
|
subject.error("foo bar")
|
@@ -12,6 +12,30 @@ module PactBroker
|
|
12
12
|
expect(a.deep_merge(b)).to eq expected
|
13
13
|
end
|
14
14
|
|
15
|
+
describe "camelcase_keys" do
|
16
|
+
let(:hash_1) do
|
17
|
+
{
|
18
|
+
"foo_bar" => {
|
19
|
+
:meep_moop => "blahBlah",
|
20
|
+
"beepBoop" => ""
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
let(:expected) do
|
26
|
+
{
|
27
|
+
"fooBar" => {
|
28
|
+
:meepMoop => "blahBlah",
|
29
|
+
"beepBoop" => ""
|
30
|
+
}
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
it "camel cases the keys" do
|
35
|
+
expect(hash_1.camelcase_keys).to eq expected
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
15
39
|
describe "snakecase_keys" do
|
16
40
|
let(:hash_1) do
|
17
41
|
{
|
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.
|
4
|
+
version: 2.58.0
|
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: 2020-06-
|
13
|
+
date: 2020-06-25 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: httparty
|
@@ -340,14 +340,20 @@ dependencies:
|
|
340
340
|
requirements:
|
341
341
|
- - "~>"
|
342
342
|
- !ruby/object:Gem::Version
|
343
|
-
version: '5.
|
343
|
+
version: '5.2'
|
344
|
+
- - ">="
|
345
|
+
- !ruby/object:Gem::Version
|
346
|
+
version: 5.2.1
|
344
347
|
type: :runtime
|
345
348
|
prerelease: false
|
346
349
|
version_requirements: !ruby/object:Gem::Requirement
|
347
350
|
requirements:
|
348
351
|
- - "~>"
|
349
352
|
- !ruby/object:Gem::Version
|
350
|
-
version: '5.
|
353
|
+
version: '5.2'
|
354
|
+
- - ">="
|
355
|
+
- !ruby/object:Gem::Version
|
356
|
+
version: 5.2.1
|
351
357
|
- !ruby/object:Gem::Dependency
|
352
358
|
name: pact
|
353
359
|
requirement: !ruby/object:Gem::Requirement
|