pact_broker 2.57.0 → 2.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +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
|