pact_broker-client 0.0.6 → 1.0.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 +7 -0
- data/CHANGELOG.md +12 -0
- data/Gemfile.lock +57 -32
- data/README.md +47 -0
- data/doc/markdown/Pact Broker Client - Pact Broker.md +582 -0
- data/doc/markdown/README.md +3 -0
- data/lib/pact_broker/client/base_client.rb +3 -1
- data/lib/pact_broker/client/pact_broker_client.rb +4 -3
- data/lib/pact_broker/client/pacticipants.rb +1 -1
- data/lib/pact_broker/client/pacts.rb +22 -6
- data/lib/pact_broker/client/publish_pacts.rb +16 -6
- data/lib/pact_broker/client/retry.rb +26 -0
- data/lib/pact_broker/client/tasks/publication_task.rb +3 -2
- data/lib/pact_broker/client/version.rb +1 -1
- data/lib/pact_broker/client/versions.rb +1 -1
- data/spec/lib/pact_broker/client/base_client_spec.rb +51 -0
- data/spec/lib/pact_broker/client/pact_broker_client_spec.rb +28 -1
- data/spec/lib/pact_broker/client/pacticipants_spec.rb +18 -0
- data/spec/lib/pact_broker/client/publish_pacts_spec.rb +67 -5
- data/spec/lib/pact_broker/client/tasks/publication_task_spec.rb +4 -2
- data/spec/lib/pact_broker/client/versions_spec.rb +18 -0
- data/spec/pacts/pact_broker_client-pact_broker.json +87 -91
- data/spec/service_providers/pact_broker_client_pacticipant_version_spec.rb +56 -0
- data/spec/service_providers/pact_broker_client_publish_spec.rb +34 -12
- data/spec/service_providers/pact_broker_client_register_repository_spec.rb +2 -2
- data/spec/service_providers/pact_broker_client_retrive_pact_spec.rb +4 -47
- data/spec/service_providers/pact_broker_client_tags_spec.rb +3 -3
- data/spec/support/pacticipant_get.json +3 -3
- data/spec/support/pacticipants_list.json +1 -1
- data/spec/support/pacts_latest_list.json +2 -2
- metadata +34 -45
@@ -26,11 +26,13 @@ module PactBroker
|
|
26
26
|
include HTTParty
|
27
27
|
include StringToSymbol
|
28
28
|
|
29
|
-
attr_reader :base_url
|
29
|
+
attr_reader :base_url, :client_options
|
30
30
|
|
31
31
|
def initialize options
|
32
32
|
@base_url = options[:base_url]
|
33
|
+
@client_options = options[:client_options] || {}
|
33
34
|
self.class.base_uri base_url
|
35
|
+
self.class.basic_auth(client_options[:basic_auth][:username], client_options[:basic_auth][:password]) if client_options[:basic_auth]
|
34
36
|
end
|
35
37
|
|
36
38
|
def default_request_headers
|
@@ -14,19 +14,20 @@ module PactBroker
|
|
14
14
|
|
15
15
|
DEFAULT_OPTIONS = {base_url: DEFAULT_PACT_BROKER_BASE_URL}
|
16
16
|
|
17
|
-
attr_reader :base_url
|
17
|
+
attr_reader :base_url, :client_options
|
18
18
|
|
19
19
|
def initialize options = {}
|
20
20
|
merged_options = DEFAULT_OPTIONS.merge(options)
|
21
21
|
@base_url = merged_options[:base_url]
|
22
|
+
@client_options = merged_options[:client_options] || {}
|
22
23
|
end
|
23
24
|
|
24
25
|
def pacticipants
|
25
|
-
PactBroker::Client::Pacticipants.new base_url: base_url
|
26
|
+
PactBroker::Client::Pacticipants.new base_url: base_url, client_options: client_options
|
26
27
|
end
|
27
28
|
|
28
29
|
def pacts
|
29
|
-
PactBroker::Client::Pacts.new base_url: base_url
|
30
|
+
PactBroker::Client::Pacts.new base_url: base_url, client_options: client_options
|
30
31
|
end
|
31
32
|
|
32
33
|
end
|
@@ -13,7 +13,11 @@ module PactBroker
|
|
13
13
|
url = save_consumer_contract_url consumer_contract, consumer_version
|
14
14
|
response = self.class.put(url, body: pact_string, headers: default_put_headers)
|
15
15
|
handle_response(response) do
|
16
|
-
|
16
|
+
latest_link = find_latest_link JSON.parse(response.body)
|
17
|
+
if latest_link.nil?
|
18
|
+
"Please upgrade to the latest version of the pact broker to see the URL of the latest pact!"
|
19
|
+
end
|
20
|
+
latest_link
|
17
21
|
end
|
18
22
|
end
|
19
23
|
|
@@ -28,7 +32,7 @@ module PactBroker
|
|
28
32
|
def list_latest
|
29
33
|
response = self.class.get("/pacts/latest", headers: default_get_headers)
|
30
34
|
handle_response(response) do
|
31
|
-
|
35
|
+
map_pact_list_to_hash JSON.parse(response.body)["pacts"]
|
32
36
|
end
|
33
37
|
end
|
34
38
|
|
@@ -43,7 +47,7 @@ module PactBroker
|
|
43
47
|
private
|
44
48
|
|
45
49
|
#TODO Move into mapper class
|
46
|
-
def
|
50
|
+
def map_pact_list_to_hash pacts_list
|
47
51
|
pacts_list.collect do | pact_hash |
|
48
52
|
{
|
49
53
|
consumer: {
|
@@ -59,6 +63,18 @@ module PactBroker
|
|
59
63
|
end
|
60
64
|
end
|
61
65
|
|
66
|
+
def find_latest_link response
|
67
|
+
links = response['_links']
|
68
|
+
return nil unless links
|
69
|
+
key = links.keys.find{ | key | key =~ /latest/ && key =~ /pact/ && key =~ /version/ }
|
70
|
+
return links[key]['href'] if key
|
71
|
+
key = links.keys.find{ | key | key =~ /latest/ && key =~ /pact/ }
|
72
|
+
return links[key]['href'] if key
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
|
62
78
|
def find_latest_consumer_contract_query options
|
63
79
|
query = {:consumer => options[:consumer], :provider => options[:provider]}
|
64
80
|
query[:tag] = options[:tag] if options[:tag]
|
@@ -69,21 +85,21 @@ module PactBroker
|
|
69
85
|
consumer_name = encode_param(options[:consumer])
|
70
86
|
provider_name = encode_param(options[:provider])
|
71
87
|
tag = options[:tag] ? "/#{options[:tag]}" : ""
|
72
|
-
"/
|
88
|
+
"/pacts/provider/#{provider_name}/consumer/#{consumer_name}/latest#{tag}"
|
73
89
|
end
|
74
90
|
|
75
91
|
def get_consumer_contract_url options
|
76
92
|
consumer_name = encode_param(options[:consumer])
|
77
93
|
provider_name = encode_param(options[:provider])
|
78
94
|
consumer_version = encode_param(options[:consumer_version])
|
79
|
-
"/
|
95
|
+
"/pacts/provider/#{provider_name}/consumer/#{consumer_name}/version/#{consumer_version}"
|
80
96
|
end
|
81
97
|
|
82
98
|
def save_consumer_contract_url consumer_contract, consumer_version
|
83
99
|
consumer_name = encode_param(consumer_contract.consumer.name)
|
84
100
|
provider_name = encode_param(consumer_contract.provider.name)
|
85
101
|
version = encode_param(consumer_version)
|
86
|
-
"/
|
102
|
+
"/pacts/provider/#{provider_name}/consumer/#{consumer_name}/version/#{version}"
|
87
103
|
end
|
88
104
|
end
|
89
105
|
end
|
@@ -1,39 +1,49 @@
|
|
1
1
|
require 'pact_broker/client'
|
2
|
+
require 'pact_broker/client/retry'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Client
|
5
6
|
class PublishPacts
|
6
7
|
|
7
|
-
def initialize pact_broker_base_url, pact_files, consumer_version
|
8
|
+
def initialize pact_broker_base_url, pact_files, consumer_version, pact_broker_client_options={}
|
8
9
|
@pact_broker_base_url = pact_broker_base_url
|
9
10
|
@pact_files = pact_files
|
10
11
|
@consumer_version = consumer_version
|
12
|
+
@pact_broker_client_options = pact_broker_client_options
|
11
13
|
end
|
12
14
|
|
13
15
|
def call
|
14
16
|
validate
|
17
|
+
$stdout.puts("")
|
15
18
|
pact_files.collect{ | pact_file | publish_pact pact_file }.all?
|
16
19
|
end
|
17
20
|
|
18
21
|
private
|
19
22
|
|
20
|
-
attr_reader :pact_broker_base_url, :pact_files, :consumer_version
|
23
|
+
attr_reader :pact_broker_base_url, :pact_files, :consumer_version, :pact_broker_client_options
|
21
24
|
|
22
25
|
def pact_broker_client
|
23
|
-
@pact_broker_client ||= PactBroker::Client::PactBrokerClient.new(base_url: pact_broker_base_url)
|
26
|
+
@pact_broker_client ||= PactBroker::Client::PactBrokerClient.new(base_url: pact_broker_base_url, client_options: pact_broker_client_options)
|
24
27
|
end
|
25
28
|
|
26
29
|
def publish_pact pact_file
|
27
30
|
begin
|
28
|
-
puts "Publishing #{pact_file} to pact broker at #{pact_broker_base_url}"
|
29
|
-
|
30
|
-
true
|
31
|
+
$stdout.puts ">> Publishing #{pact_file} to pact broker at #{pact_broker_base_url}"
|
32
|
+
publish_pact_contents File.read(pact_file)
|
31
33
|
rescue => e
|
32
34
|
$stderr.puts "Failed to publish pact: #{pact_file} due to error: #{e.to_s}\n#{e.backtrace.join("\n")}"
|
33
35
|
false
|
34
36
|
end
|
35
37
|
end
|
36
38
|
|
39
|
+
def publish_pact_contents pact_file_contents
|
40
|
+
Retry.until_true do
|
41
|
+
latest_pact_url = pact_broker_client.pacticipants.versions.pacts.publish(pact_json: pact_file_contents, consumer_version: consumer_version)
|
42
|
+
$stdout.puts "The latest version of this pact can be accessed at the following URL (use this to configure the provider verification):\n#{latest_pact_url}\n\n"
|
43
|
+
true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
37
47
|
def validate
|
38
48
|
raise "Please specify the consumer_version" unless (consumer_version && consumer_version.to_s.strip.size > 0)
|
39
49
|
raise "Please specify the pact_broker_base_url" unless (pact_broker_base_url && pact_broker_base_url.to_s.strip.size > 0)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module PactBroker
|
2
|
+
module Client
|
3
|
+
class Retry
|
4
|
+
|
5
|
+
def self.until_true options = {}
|
6
|
+
max_tries = options.fetch(:times, 3)
|
7
|
+
tries = 0
|
8
|
+
while true
|
9
|
+
begin
|
10
|
+
return yield
|
11
|
+
rescue StandardError => e
|
12
|
+
tries += 1
|
13
|
+
$stderr.puts "Error publishing pact - #{e.message}, attempt #{tries} of #{max_tries}"
|
14
|
+
sleep options
|
15
|
+
raise e if max_tries == tries
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.sleep options
|
21
|
+
Kernel.sleep options.fetch(:sleep, 5)
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -15,7 +15,7 @@ module PactBroker
|
|
15
15
|
module Client
|
16
16
|
class PublicationTask < ::Rake::TaskLib
|
17
17
|
|
18
|
-
attr_accessor :pattern, :pact_broker_base_url, :consumer_version
|
18
|
+
attr_accessor :pattern, :pact_broker_base_url, :consumer_version, :pact_broker_basic_auth
|
19
19
|
|
20
20
|
def initialize name = nil, &block
|
21
21
|
@name = name
|
@@ -32,7 +32,8 @@ module PactBroker
|
|
32
32
|
task task_name do
|
33
33
|
block.call(self)
|
34
34
|
require 'pact_broker/client/publish_pacts'
|
35
|
-
|
35
|
+
pact_broker_client_options = pact_broker_basic_auth ? {basic_auth: pact_broker_basic_auth} :{}
|
36
|
+
success = PactBroker::Client::PublishPacts.new(pact_broker_base_url, FileList[pattern], consumer_version, pact_broker_client_options).call
|
36
37
|
raise "One or more pacts failed to be published" unless success
|
37
38
|
end
|
38
39
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'pact_broker/client/base_client'
|
2
|
+
module PactBroker
|
3
|
+
module Client
|
4
|
+
describe BaseClient do
|
5
|
+
describe '#initialize' do
|
6
|
+
let(:base_url) { 'http://pact_broker_base_url'}
|
7
|
+
let(:username) { 'pact_repo_username'}
|
8
|
+
let(:password) { 'pact_repo_password'}
|
9
|
+
let(:client_options) do
|
10
|
+
{
|
11
|
+
basic_auth: {
|
12
|
+
username: username,
|
13
|
+
password: password
|
14
|
+
}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
context 'with basic url' do
|
18
|
+
it 'should set base url' do
|
19
|
+
base_client = BaseClient.new(base_url: base_url)
|
20
|
+
expect(base_client.base_url).to eq(base_url)
|
21
|
+
expect(BaseClient.base_uri).to eq(base_url)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'with client options' do
|
26
|
+
subject { BaseClient.new(base_url: base_url, client_options: client_options) }
|
27
|
+
it 'should set client options ' do
|
28
|
+
expect(subject.client_options).to eq(client_options)
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should set httpparty basic auth when client options contains basic auth' do
|
32
|
+
expect(BaseClient).to receive(:basic_auth).with(username, password)
|
33
|
+
subject
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
context 'without client options' do
|
38
|
+
subject { BaseClient.new(base_url: base_url) }
|
39
|
+
it 'should set client options to empty hash ' do
|
40
|
+
expect(subject.client_options).to eq({})
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should not set httpparty basic auth' do
|
44
|
+
expect(BaseClient).to_not receive(:basic_auth).with(username, password)
|
45
|
+
subject
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -5,14 +5,41 @@ require 'pact_broker/client'
|
|
5
5
|
module PactBroker::Client
|
6
6
|
describe PactBrokerClient do
|
7
7
|
|
8
|
+
let(:client_options) do
|
9
|
+
{ some_option: 'option value'}
|
10
|
+
end
|
11
|
+
let(:base_url) { 'https://blah' }
|
12
|
+
|
8
13
|
describe 'initialize' do
|
9
14
|
subject { PactBrokerClient.new }
|
10
15
|
it 'sets the base_uri to http://pact-broker by default' do
|
11
16
|
expect(subject.base_url).to eq('http://pact-broker')
|
12
17
|
end
|
13
18
|
|
19
|
+
it 'sets the client options to empty hash by default' do
|
20
|
+
expect(subject.client_options).to eq({})
|
21
|
+
end
|
22
|
+
|
14
23
|
it 'allows configuration of the base_uri' do
|
15
|
-
expect(PactBrokerClient.new(base_url:
|
24
|
+
expect(PactBrokerClient.new(base_url: base_url).base_url).to eq(base_url)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'allows configuration of the client options' do
|
28
|
+
expect(PactBrokerClient.new(client_options: client_options).client_options).to eq(client_options)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'pacticipants' do
|
33
|
+
it 'initializes pacticipants with base url and client options' do
|
34
|
+
expect(PactBroker::Client::Pacticipants).to receive(:new).with(base_url: base_url, client_options: client_options)
|
35
|
+
PactBrokerClient.new(base_url: base_url, client_options: client_options).pacticipants
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'pacts' do
|
40
|
+
it 'initializes [act] with base url and client options' do
|
41
|
+
expect(PactBroker::Client::Pacts).to receive(:new).with(base_url: base_url, client_options: client_options)
|
42
|
+
PactBrokerClient.new(base_url: base_url, client_options: client_options).pacts
|
16
43
|
end
|
17
44
|
end
|
18
45
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'pact_broker/client/pacticipants'
|
2
|
+
module PactBroker
|
3
|
+
module Client
|
4
|
+
describe Pacticipants do
|
5
|
+
let(:client_options) do
|
6
|
+
{ some_option: 'option value'}
|
7
|
+
end
|
8
|
+
let(:base_url) { 'https://blah' }
|
9
|
+
|
10
|
+
describe 'versions' do
|
11
|
+
it 'initializes versions with base url and client options' do
|
12
|
+
expect(PactBroker::Client::Versions).to receive(:new).with(base_url: base_url, client_options: client_options)
|
13
|
+
Pacticipants.new(base_url: base_url, client_options: client_options).versions
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -9,22 +9,31 @@ module PactBroker
|
|
9
9
|
|
10
10
|
before do
|
11
11
|
FakeFS.activate!
|
12
|
-
pacts_client.stub(:publish)
|
13
|
-
PactBroker::Client::PactBrokerClient.stub(:new).with(base_url: pact_broker_base_url).and_return(pact_broker_client)
|
12
|
+
pacts_client.stub(:publish).and_return(latest_pact_url)
|
13
|
+
PactBroker::Client::PactBrokerClient.stub(:new).with(base_url: pact_broker_base_url, client_options: pact_broker_client_options).and_return(pact_broker_client)
|
14
14
|
end
|
15
15
|
|
16
16
|
after do
|
17
17
|
FakeFS.deactivate!
|
18
18
|
end
|
19
19
|
|
20
|
+
let(:latest_pact_url) { 'http://example.org/latest/pact' }
|
20
21
|
let(:pact_broker_client) { double("PactBroker::Client")}
|
21
22
|
let(:pact_files) { ['spec/pacts/consumer-provider.json']}
|
22
23
|
let(:consumer_version) { "1.2.3" }
|
23
24
|
let(:pact_hash) { {consumer: {name: 'Consumer'}, provider: {name: 'Provider'} } }
|
24
25
|
let(:pacts_client) { instance_double("PactBroker::ClientSupport::Pacts")}
|
25
26
|
let(:pact_broker_base_url) { 'http://some-host'}
|
27
|
+
let(:pact_broker_client_options) do
|
28
|
+
{
|
29
|
+
basic_auth: {
|
30
|
+
username: 'user',
|
31
|
+
password: 'pass'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
end
|
26
35
|
|
27
|
-
subject { PublishPacts.new(pact_broker_base_url, pact_files, consumer_version) }
|
36
|
+
subject { PublishPacts.new(pact_broker_base_url, pact_files, consumer_version, pact_broker_client_options) }
|
28
37
|
|
29
38
|
before do
|
30
39
|
FileUtils.mkdir_p "spec/pacts"
|
@@ -40,13 +49,20 @@ module PactBroker
|
|
40
49
|
end
|
41
50
|
|
42
51
|
context "when publishing is successful" do
|
52
|
+
|
53
|
+
it "puts the location of the latest pact" do
|
54
|
+
allow($stdout).to receive(:puts)
|
55
|
+
expect($stdout).to receive(:puts).with(/#{latest_pact_url}/)
|
56
|
+
subject.call
|
57
|
+
end
|
43
58
|
it "returns true" do
|
44
|
-
expect(subject.call).to
|
59
|
+
expect(subject.call).to be true
|
45
60
|
end
|
46
61
|
end
|
47
62
|
|
48
63
|
context "when publishing one or more pacts fails" do
|
49
64
|
let(:pact_files) { ['spec/pacts/doesnotexist.json','spec/pacts/consumer-provider.json']}
|
65
|
+
|
50
66
|
before do
|
51
67
|
$stderr.stub(:puts)
|
52
68
|
end
|
@@ -62,7 +78,7 @@ module PactBroker
|
|
62
78
|
end
|
63
79
|
|
64
80
|
it "returns false" do
|
65
|
-
expect(subject.call).to
|
81
|
+
expect(subject.call).to be false
|
66
82
|
end
|
67
83
|
end
|
68
84
|
|
@@ -86,6 +102,52 @@ module PactBroker
|
|
86
102
|
expect { subject.call }.to raise_error(/Please specify the pact_broker_base_url/)
|
87
103
|
end
|
88
104
|
end
|
105
|
+
|
106
|
+
context "when an error occurs every time while publishing a pact" do
|
107
|
+
|
108
|
+
before do
|
109
|
+
allow(Retry).to receive(:sleep)
|
110
|
+
allow(pacts_client).to receive(:publish).and_raise("an error")
|
111
|
+
allow($stderr).to receive(:puts)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "retries multiple times" do
|
115
|
+
expect(pacts_client).to receive(:publish).exactly(3).times
|
116
|
+
subject.call
|
117
|
+
end
|
118
|
+
|
119
|
+
it "returns false" do
|
120
|
+
expect(subject.call).to eq false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "when an error occurs less than the maximum number of retries" do
|
125
|
+
|
126
|
+
before do
|
127
|
+
allow(Retry).to receive(:sleep)
|
128
|
+
tries = 0
|
129
|
+
allow(pacts_client).to receive(:publish) do
|
130
|
+
if tries == 0
|
131
|
+
tries += 1
|
132
|
+
raise "an error"
|
133
|
+
else
|
134
|
+
latest_pact_url
|
135
|
+
end
|
136
|
+
end
|
137
|
+
allow($stderr).to receive(:puts)
|
138
|
+
end
|
139
|
+
|
140
|
+
it "retries multiple times" do
|
141
|
+
expect(pacts_client).to receive(:publish).exactly(2).times
|
142
|
+
subject.call
|
143
|
+
end
|
144
|
+
|
145
|
+
it "returns true" do
|
146
|
+
expect(subject.call).to eq true
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
89
151
|
end
|
90
152
|
end
|
91
153
|
end
|