pact_broker 2.27.2 → 2.27.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +1 -1
- data/CHANGELOG.md +32 -0
- data/DEVELOPER_SETUP.md +1 -0
- data/example/config.ru +1 -1
- data/lib/pact_broker.rb +1 -0
- data/lib/pact_broker/api.rb +1 -0
- data/lib/pact_broker/api/decorators/pact_version_decorator.rb +0 -5
- data/lib/pact_broker/api/decorators/tagged_pact_versions_decorator.rb +46 -0
- data/lib/pact_broker/api/renderers/html_pact_renderer.rb +1 -1
- data/lib/pact_broker/api/resources/error_handler.rb +1 -0
- data/lib/pact_broker/api/resources/index.rb +6 -0
- data/lib/pact_broker/api/resources/tagged_pact_versions.rb +38 -0
- data/lib/pact_broker/app.rb +12 -6
- data/lib/pact_broker/certificates/service.rb +1 -0
- data/lib/pact_broker/configuration.rb +11 -16
- data/lib/pact_broker/db/log_quietener.rb +38 -0
- data/lib/pact_broker/doc/views/index/tagged-pact-versions.markdown +7 -0
- data/lib/pact_broker/logging.rb +25 -20
- data/lib/pact_broker/logging/default_formatter.rb +16 -0
- data/lib/pact_broker/matrix/deployment_status_summary.rb +3 -1
- data/lib/pact_broker/pacticipants/service.rb +1 -1
- data/lib/pact_broker/pacts/all_pact_publications.rb +1 -1
- data/lib/pact_broker/pacts/repository.rb +18 -4
- data/lib/pact_broker/pacts/service.rb +4 -0
- data/lib/pact_broker/ui/views/index/show-with-tags.haml +34 -33
- data/lib/pact_broker/ui/views/index/show.haml +28 -27
- data/lib/pact_broker/ui/views/layouts/main.haml +2 -2
- data/lib/pact_broker/ui/views/matrix/show.haml +126 -127
- data/lib/pact_broker/verifications/service.rb +3 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/repository.rb +3 -1
- data/lib/pact_broker/webhooks/job.rb +1 -0
- data/pact_broker.gemspec +1 -0
- data/script/db-spec.sh +2 -0
- data/spec/features/delete_tagged_pact_versions_spec.rb +28 -0
- data/spec/features/get_tagged_pact_versions_spec.rb +26 -0
- data/spec/integration/ui/index_spec.rb +2 -2
- data/spec/lib/pact_broker/api/decorators/pact_version_decorator_spec.rb +0 -3
- data/spec/lib/pact_broker/api/decorators/tagged_pact_versions_decorator_spec.rb +79 -0
- data/spec/lib/pact_broker/api/renderers/html_pact_renderer_spec.rb +5 -6
- data/spec/lib/pact_broker/api/resources/error_handler_spec.rb +7 -1
- data/spec/lib/pact_broker/api/resources/tagged_pact_versions_spec.rb +88 -0
- data/spec/lib/pact_broker/badges/service_spec.rb +3 -2
- data/spec/lib/pact_broker/certificates/service_spec.rb +8 -3
- data/spec/lib/pact_broker/db/log_quietener_spec.rb +42 -0
- data/spec/lib/pact_broker/domain/webhook_request_spec.rb +17 -12
- data/spec/lib/pact_broker/domain/webhook_spec.rb +7 -2
- data/spec/lib/pact_broker/matrix/deployment_status_summary_spec.rb +8 -1
- data/spec/lib/pact_broker/pacticipants/service_spec.rb +5 -3
- data/spec/lib/pact_broker/pacts/repository_spec.rb +44 -3
- data/spec/lib/pact_broker/verifications/service_spec.rb +6 -2
- data/spec/lib/pact_broker/webhooks/job_spec.rb +2 -0
- data/spec/lib/pact_broker/webhooks/service_spec.rb +6 -1
- data/spec/spec_helper.rb +13 -13
- data/spec/support/database.rb +5 -0
- data/spec/support/fixture_pact.rb +34 -0
- data/spec/support/logging.rb +5 -0
- data/spec/support/shared_context.rb +10 -0
- data/tasks/development.rake +12 -3
- metadata +40 -3
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'pact_broker/repositories'
|
2
2
|
require 'pact_broker/api/decorators/verification_decorator'
|
3
3
|
require 'pact_broker/verifications/summary_for_consumer_version'
|
4
|
+
require 'pact_broker/logging'
|
4
5
|
|
5
6
|
module PactBroker
|
6
7
|
|
@@ -11,13 +12,14 @@ module PactBroker
|
|
11
12
|
|
12
13
|
extend PactBroker::Repositories
|
13
14
|
extend PactBroker::Services
|
15
|
+
include PactBroker::Logging
|
14
16
|
|
15
17
|
def next_number
|
16
18
|
verification_repository.next_number
|
17
19
|
end
|
18
20
|
|
19
21
|
def create next_verification_number, params, pact
|
20
|
-
|
22
|
+
logger.info "Creating verification #{next_verification_number} for pact_id=#{pact.id} from params #{params}"
|
21
23
|
verification = PactBroker::Domain::Verification.new
|
22
24
|
provider_version_number = params.fetch('providerApplicationVersion')
|
23
25
|
PactBroker::Api::Decorators::VerificationDecorator.new(verification).from_hash(params)
|
data/lib/pact_broker/version.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'sequel'
|
2
|
+
require 'pact_broker/logging'
|
2
3
|
require 'pact_broker/domain/version'
|
3
4
|
require 'pact_broker/tags/repository'
|
4
5
|
|
@@ -6,6 +7,7 @@ module PactBroker
|
|
6
7
|
module Versions
|
7
8
|
class Repository
|
8
9
|
|
10
|
+
include PactBroker::Logging
|
9
11
|
include PactBroker::Repositories::Helpers
|
10
12
|
|
11
13
|
def find_by_pacticipant_id_and_number pacticipant_id, number
|
@@ -53,7 +55,7 @@ module PactBroker
|
|
53
55
|
|
54
56
|
# There may be a race condition if two simultaneous requests come in to create the same version
|
55
57
|
def create args
|
56
|
-
|
58
|
+
logger.info "Upserting version #{args[:number]} for pacticipant_id=#{args[:pacticipant_id]}"
|
57
59
|
version_params = {
|
58
60
|
number: args[:number],
|
59
61
|
pacticipant_id: args[:pacticipant_id],
|
data/pact_broker.gemspec
CHANGED
@@ -39,6 +39,7 @@ Gem::Specification.new do |gem|
|
|
39
39
|
gem.add_runtime_dependency 'rack-protection', '~>2.0'
|
40
40
|
gem.add_runtime_dependency 'dry-types', '~> 0.10.3' # https://travis-ci.org/pact-foundation/pact_broker/jobs/249448621
|
41
41
|
gem.add_runtime_dependency 'table_print', '~> 1.5'
|
42
|
+
gem.add_runtime_dependency 'semantic_logger', '~> 4.3'
|
42
43
|
|
43
44
|
gem.add_development_dependency 'pact', '~>1.14'
|
44
45
|
gem.add_development_dependency 'rspec-pact-matchers', '~>0.1'
|
data/script/db-spec.sh
CHANGED
@@ -0,0 +1,28 @@
|
|
1
|
+
describe "Deleting tagged pact versions" do
|
2
|
+
|
3
|
+
let(:path) { "/pacts/provider/Bar/consumer/Foo/tag/prod" }
|
4
|
+
|
5
|
+
subject { delete(path) }
|
6
|
+
|
7
|
+
context "when the pact exists" do
|
8
|
+
before do
|
9
|
+
TestDataBuilder.new
|
10
|
+
.create_pact_with_hierarchy("Foo", "1.2.3", "Bar")
|
11
|
+
.create_consumer_version_tag("prod")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "deletes the pact" do
|
15
|
+
expect{ subject }.to change{ PactBroker::Pacts::PactPublication.count }.by(-1)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns a 204" do
|
19
|
+
expect(subject.status).to be 204
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context "when the pact does not exist" do
|
24
|
+
it "returns a 404 Not Found" do
|
25
|
+
expect(subject.status).to be 404
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
describe "retrieving tagged pact versions" do
|
2
|
+
|
3
|
+
let(:path) { "/pacts/provider/Provider/consumer/Consumer/tag/prod"}
|
4
|
+
|
5
|
+
subject { get(path) }
|
6
|
+
let(:json_response_body) { JSON.parse(subject.body) }
|
7
|
+
|
8
|
+
before do
|
9
|
+
TestDataBuilder.new
|
10
|
+
.create_consumer("Consumer")
|
11
|
+
.create_provider("Provider")
|
12
|
+
.create_consumer_version("1.2.3")
|
13
|
+
.create_consumer_version_tag("prod")
|
14
|
+
.create_pact
|
15
|
+
.create_consumer_version("4.5.6")
|
16
|
+
.create_pact
|
17
|
+
end
|
18
|
+
|
19
|
+
it "returns a 200 HAL JSON response" do
|
20
|
+
expect(subject).to be_a_hal_json_success_response
|
21
|
+
end
|
22
|
+
|
23
|
+
it "returns the list of tagged pact versions" do
|
24
|
+
expect(json_response_body['_links']['pb:pact-versions']).to be_a Array
|
25
|
+
end
|
26
|
+
end
|
@@ -22,14 +22,14 @@ describe "UI index" do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it "returns a table of pacts" do
|
25
|
-
expect(subject.body.scan('<tr').to_a.count).to eq
|
25
|
+
expect(subject.body.scan('<tr').to_a.count).to eq 2
|
26
26
|
end
|
27
27
|
|
28
28
|
context "with an array of tags" do
|
29
29
|
let(:params) { { tags: ['prod'] } }
|
30
30
|
|
31
31
|
it "returns a table of pacts with the specfied tags" do
|
32
|
-
expect(subject.body.scan('<tr').to_a.count).to eq
|
32
|
+
expect(subject.body.scan('<tr').to_a.count).to eq 3
|
33
33
|
end
|
34
34
|
end
|
35
35
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'pact_broker/api/decorators/tagged_pact_versions_decorator'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Decorators
|
6
|
+
describe TaggedPactVersionsDecorator do
|
7
|
+
before do
|
8
|
+
allow(PactBroker::Api::Decorators::PactVersionDecorator).to receive(:new).and_return(_version_decorator)
|
9
|
+
allow_any_instance_of(TaggedPactVersionsDecorator).to receive(:pact_url).and_return('pact_url')
|
10
|
+
allow_any_instance_of(TaggedPactVersionsDecorator).to receive(:pacticipant_url).and_return('pacticipant_url')
|
11
|
+
allow_any_instance_of(TaggedPactVersionsDecorator).to receive(:pacticipant_url).and_return('pacticipant_url')
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:user_options) do
|
15
|
+
register_fixture(:tagged_pact_versions_decorator_user_options) do
|
16
|
+
{
|
17
|
+
base_url: "http://example.org",
|
18
|
+
resource_url: "http://example.org/pacts/provider/Bar/consumer/Foo/tag/prod",
|
19
|
+
consumer_name: "Foo",
|
20
|
+
provider_name: "Bar",
|
21
|
+
tag: "prod"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:_version_decorator) do
|
27
|
+
instance_double(PactBroker::Api::Decorators::VersionDecorator, to_hash: { some: "pact" } )
|
28
|
+
end
|
29
|
+
let(:pact_versions) { [pact_version] }
|
30
|
+
let(:pact_version) do
|
31
|
+
instance_double("PactBroker::Domain::Pact").as_null_object
|
32
|
+
end
|
33
|
+
|
34
|
+
let(:decorator) { TaggedPactVersionsDecorator.new(pact_versions) }
|
35
|
+
let(:json) { decorator.to_json(user_options: user_options) }
|
36
|
+
subject { JSON.parse(json) }
|
37
|
+
|
38
|
+
let(:expected) do
|
39
|
+
{
|
40
|
+
"_embedded" => {
|
41
|
+
"pacts" => [
|
42
|
+
{
|
43
|
+
"some" => "pact"
|
44
|
+
}
|
45
|
+
]
|
46
|
+
},
|
47
|
+
"_links" => {
|
48
|
+
"self" => {
|
49
|
+
"href" => "http://example.org/pacts/provider/Bar/consumer/Foo/tag/prod",
|
50
|
+
"title" => "All versions of the pact between Foo and Bar with tag prod"
|
51
|
+
},
|
52
|
+
"pb:consumer" => {
|
53
|
+
"href" => "pacticipant_url",
|
54
|
+
"title" => "Consumer",
|
55
|
+
"name" => "Foo"
|
56
|
+
},
|
57
|
+
"pb:provider" => {
|
58
|
+
"href" => "pacticipant_url",
|
59
|
+
"title" => "Provider",
|
60
|
+
"name" => "Bar"
|
61
|
+
},
|
62
|
+
"pb:pact-versions" => [
|
63
|
+
{
|
64
|
+
"href" => "pact_url",
|
65
|
+
"title" => "Pact version",
|
66
|
+
"name" => "#[InstanceDouble(PactBroker::Domain::Pact) (anonymous)]"
|
67
|
+
}
|
68
|
+
]
|
69
|
+
}
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
it "matches the expected JSON" do
|
74
|
+
expect(subject).to match_pact(expected, allow_unexpected_keys: false)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -11,6 +11,8 @@ module PactBroker
|
|
11
11
|
ENV['BACKUP_TZ'] = ENV['TZ']
|
12
12
|
ENV['TZ'] = "Australia/Melbourne"
|
13
13
|
PactBroker.configuration.enable_public_badge_access = true
|
14
|
+
allow(PactBroker::Api::PactBrokerUrls).to receive(:pact_url).with('', pact).and_return(pact_url)
|
15
|
+
allow_any_instance_of(HtmlPactRenderer).to receive(:logger).and_return(logger)
|
14
16
|
|
15
17
|
Timecop.freeze(created_at + 3)
|
16
18
|
end
|
@@ -32,10 +34,7 @@ module PactBroker
|
|
32
34
|
badge_url: 'http://badge'
|
33
35
|
}
|
34
36
|
end
|
35
|
-
|
36
|
-
before do
|
37
|
-
allow(PactBroker::Api::PactBrokerUrls).to receive(:pact_url).with('', pact).and_return(pact_url)
|
38
|
-
end
|
37
|
+
let(:logger) { double('logger').as_null_object }
|
39
38
|
|
40
39
|
subject { HtmlPactRenderer.call pact, options }
|
41
40
|
|
@@ -95,8 +94,8 @@ module PactBroker
|
|
95
94
|
end
|
96
95
|
|
97
96
|
it "logs a warning" do
|
98
|
-
allow(
|
99
|
-
expect(
|
97
|
+
allow(logger).to receive(:warn).with(/Error/)
|
98
|
+
expect(logger).to receive(:warn).with(/Could not parse/)
|
100
99
|
subject
|
101
100
|
end
|
102
101
|
end
|
@@ -5,6 +5,12 @@ module PactBroker
|
|
5
5
|
module Resources
|
6
6
|
describe ErrorHandler do
|
7
7
|
describe "call" do
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(ErrorHandler).to receive(:logger).and_return(logger)
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:logger) { double('logger').as_null_object }
|
8
14
|
let(:error) { StandardError.new('test error') }
|
9
15
|
let(:thing) { double('thing', call: nil, another_call: nil) }
|
10
16
|
let(:options) { { env: env } }
|
@@ -91,7 +97,7 @@ module PactBroker
|
|
91
97
|
end
|
92
98
|
|
93
99
|
it "logs the error" do
|
94
|
-
expect(
|
100
|
+
expect(logger).to receive(:error).at_least(1).times
|
95
101
|
subject
|
96
102
|
end
|
97
103
|
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'pact_broker/api/resources/tagged_pact_versions'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Api
|
5
|
+
module Resources
|
6
|
+
describe TaggedPactVersions do
|
7
|
+
include_context "stubbed services"
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(pacticipant_service).to receive(:find_pacticipant_by_name).with("Foo").and_return(consumer)
|
11
|
+
allow(pacticipant_service).to receive(:find_pacticipant_by_name).with("Bar").and_return(provider)
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:path) { "/pacts/provider/Bar/consumer/Foo/tag/prod" }
|
15
|
+
let(:consumer) { double('Bar') }
|
16
|
+
let(:provider) { double('Foo') }
|
17
|
+
|
18
|
+
context "GET" do
|
19
|
+
before do
|
20
|
+
allow(PactBroker::Api::Decorators::TaggedPactVersionsDecorator).to receive(:new).and_return(decorator)
|
21
|
+
allow(pact_service).to receive(:find_all_pact_versions_between).and_return(pact_versions)
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:decorator) { instance_double(PactBroker::Api::Decorators::TaggedPactVersionsDecorator, to_json: 'json') }
|
25
|
+
let(:pact_versions) { double('pacts') }
|
26
|
+
|
27
|
+
subject { get(path) }
|
28
|
+
|
29
|
+
let(:user_options) do
|
30
|
+
register_fixture(:tagged_pact_versions_decorator_user_options) do
|
31
|
+
{
|
32
|
+
base_url: "http://example.org",
|
33
|
+
resource_url: "http://example.org/pacts/provider/Bar/consumer/Foo/tag/prod",
|
34
|
+
consumer_name: "Foo",
|
35
|
+
provider_name: "Bar",
|
36
|
+
tag: "prod"
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it "finds all the pacts with the given consumer/provider/tag" do
|
42
|
+
expect(pact_service).to receive(:find_all_pact_versions_between).with("Foo", and: "Bar", tag: "prod")
|
43
|
+
subject
|
44
|
+
end
|
45
|
+
|
46
|
+
it "returns a 200 OK hal+json response" do
|
47
|
+
expect(subject).to be_a_hal_json_success_response
|
48
|
+
end
|
49
|
+
|
50
|
+
it "creates a JSON representation of the pact versions" do
|
51
|
+
expect(PactBroker::Api::Decorators::TaggedPactVersionsDecorator).to receive(:new).with(pact_versions)
|
52
|
+
expect(decorator).to receive(:to_json).with(user_options: hash_including(user_options))
|
53
|
+
subject
|
54
|
+
end
|
55
|
+
|
56
|
+
it "returns the JSON representation of the pact versions" do
|
57
|
+
expect(subject.body).to eq 'json'
|
58
|
+
end
|
59
|
+
|
60
|
+
context "with the consumer or provider do not exist" do
|
61
|
+
let(:consumer) { nil }
|
62
|
+
|
63
|
+
it "returns a 404" do
|
64
|
+
expect(subject).to be_a_404_response
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "DELETE" do
|
70
|
+
before do
|
71
|
+
allow(pact_service).to receive(:delete_all_pact_versions_between)
|
72
|
+
end
|
73
|
+
|
74
|
+
subject { delete(path) }
|
75
|
+
|
76
|
+
it "deletes all the pacts with the given consumer/provider/tag" do
|
77
|
+
expect(pact_service).to receive(:delete_all_pact_versions_between).with("Foo", and: "Bar", tag: "prod")
|
78
|
+
subject
|
79
|
+
end
|
80
|
+
|
81
|
+
it "returns a 204" do
|
82
|
+
expect(subject.status).to eq 204
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -10,7 +10,7 @@ module PactBroker
|
|
10
10
|
let(:label) { nil }
|
11
11
|
let(:initials) { false }
|
12
12
|
let(:verification_status) { :success }
|
13
|
-
|
13
|
+
let(:logger) { double('logger').as_null_object }
|
14
14
|
let(:expected_url) { "https://img.shields.io/badge/#{expected_left_text}-#{expected_right_text}-#{expected_color}.svg" }
|
15
15
|
let(:expected_color) { "brightgreen" }
|
16
16
|
let(:expected_right_text) { "verified" }
|
@@ -24,6 +24,7 @@ module PactBroker
|
|
24
24
|
|
25
25
|
before do
|
26
26
|
Service.clear_cache
|
27
|
+
allow(Service).to receive(:logger).and_return(logger)
|
27
28
|
end
|
28
29
|
|
29
30
|
it "returns the svg file" do
|
@@ -224,7 +225,7 @@ module PactBroker
|
|
224
225
|
end
|
225
226
|
|
226
227
|
it "logs the error" do
|
227
|
-
expect(
|
228
|
+
expect(logger).to receive(:error).with(/Error retrieving badge from.*shield.*an error/)
|
228
229
|
subject
|
229
230
|
end
|
230
231
|
|
@@ -4,6 +4,11 @@ module PactBroker
|
|
4
4
|
module Certificates
|
5
5
|
describe Service do
|
6
6
|
let(:certificate_content) { File.read('spec/fixtures/certificate.pem') }
|
7
|
+
let(:logger) { double('logger').as_null_object }
|
8
|
+
|
9
|
+
before do
|
10
|
+
allow(Service).to receive(:logger).and_return(logger)
|
11
|
+
end
|
7
12
|
|
8
13
|
describe "#cert_store" do
|
9
14
|
subject { Service.cert_store }
|
@@ -19,7 +24,7 @@ module PactBroker
|
|
19
24
|
end
|
20
25
|
|
21
26
|
it "logs the error" do
|
22
|
-
expect(
|
27
|
+
expect(Service).to receive(:log_error).with(anything, /Error adding certificate/).at_least(1).times
|
23
28
|
subject
|
24
29
|
end
|
25
30
|
|
@@ -46,7 +51,7 @@ module PactBroker
|
|
46
51
|
let(:certificate_content) { File.read('spec/fixtures/certificates/cacert.pem') }
|
47
52
|
|
48
53
|
it "returns all the X509 Certificate objects" do
|
49
|
-
expect(
|
54
|
+
expect(logger).to_not receive(:error).with(/Error.*1234/)
|
50
55
|
expect(subject.size).to eq 1
|
51
56
|
end
|
52
57
|
end
|
@@ -55,7 +60,7 @@ module PactBroker
|
|
55
60
|
let(:certificate_content) { File.read('spec/fixtures/certificate-invalid.pem') }
|
56
61
|
|
57
62
|
it "logs an error" do
|
58
|
-
expect(
|
63
|
+
expect(logger).to receive(:error).with(/Error.*1234/)
|
59
64
|
subject
|
60
65
|
end
|
61
66
|
|