pact_broker-client 1.29.1 → 1.34.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 +45 -0
- data/Gemfile +0 -4
- data/README.md +8 -1
- data/lib/pact_broker/client/base_client.rb +11 -9
- data/lib/pact_broker/client/cli/broker.rb +3 -1
- data/lib/pact_broker/client/matrix.rb +3 -1
- data/lib/pact_broker/client/pacts/list_latest_versions.rb +1 -1
- data/lib/pact_broker/client/publish_pacts.rb +14 -6
- data/lib/pact_broker/client/version.rb +1 -1
- data/pact-broker-client.gemspec +2 -1
- data/spec/lib/pact_broker/client/base_client_spec.rb +62 -4
- data/spec/lib/pact_broker/client/publish_pacts_spec.rb +20 -1
- metadata +24 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 108c1ab15ca6e36cc62cd630bdd73e716d83ed78ae9cdf718edb5abc7741ac3b
|
4
|
+
data.tar.gz: fa0e07f37153ce67e4b76a9e2ed32635e613d38972b60687e4eeff659e8d6dff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3a851164b96ca422c7c3e683c389f5731c86e85fa8a7fe29501fb9b0719b4ac20fc8caed19654324765c2f29e1b253dfd12055268b45e59d75eef73507c834f
|
7
|
+
data.tar.gz: c9f836d70e375a8a6205855184fefaf0712cfeb4c46a14bd71433406ddf6aa445c50d76a3d36044d4427ac63b4ad14b2eab5890a16d502e68a4704a4b3cac540
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,48 @@
|
|
1
|
+
<a name="v1.34.0"></a>
|
2
|
+
### v1.34.0 (2020-11-20)
|
3
|
+
|
4
|
+
#### Features
|
5
|
+
|
6
|
+
* **pact publish**
|
7
|
+
* strip new lines from version numbers and tags ([5842d24](/../../commit/5842d24))
|
8
|
+
|
9
|
+
* **publish**
|
10
|
+
* update output text when pact already exists and merging ([9b849d3](/../../commit/9b849d3))
|
11
|
+
|
12
|
+
<a name="v1.33.0"></a>
|
13
|
+
### v1.33.0 (2020-11-10)
|
14
|
+
|
15
|
+
#### Features
|
16
|
+
|
17
|
+
* **publish**
|
18
|
+
* allow pacts to be merged on the server side ([bd80f10](/../../commit/bd80f10))
|
19
|
+
|
20
|
+
<a name="v1.32.0"></a>
|
21
|
+
### v1.32.0 (2020-10-26)
|
22
|
+
|
23
|
+
#### Features
|
24
|
+
|
25
|
+
* Improve HTTP errors handling (#76) ([d8eaf16](/../../commit/d8eaf16))
|
26
|
+
|
27
|
+
#### Bug Fixes
|
28
|
+
|
29
|
+
* **list-latest-pact-versions**
|
30
|
+
* correct json output ([cf77666](/../../commit/cf77666))
|
31
|
+
|
32
|
+
<a name="v1.31.0"></a>
|
33
|
+
### v1.31.0 (2020-10-22)
|
34
|
+
|
35
|
+
#### Features
|
36
|
+
|
37
|
+
* update thor dependancy (#75) ([2078f31](/../../commit/2078f31))
|
38
|
+
|
39
|
+
<a name="v1.30.0"></a>
|
40
|
+
### v1.30.0 (2020-10-09)
|
41
|
+
|
42
|
+
#### Features
|
43
|
+
|
44
|
+
* remove outdated comment from pact publishing output ([251b4df](/../../commit/251b4df))
|
45
|
+
|
1
46
|
<a name="v1.29.1"></a>
|
2
47
|
### v1.29.1 (2020-08-07)
|
3
48
|
|
data/Gemfile
CHANGED
@@ -6,10 +6,6 @@ gemspec
|
|
6
6
|
# even thought it's in the development dependencies. Trying it here.
|
7
7
|
gem 'rake', '~> 13.0'
|
8
8
|
|
9
|
-
group :release do
|
10
|
-
gem 'bump', git: 'https://github.com/bethesque/bump.git'
|
11
|
-
end
|
12
|
-
|
13
9
|
if ENV['X_PACT_DEVELOPMENT'] == 'true'
|
14
10
|
gem 'pact-mock_service', path: '../pact-mock_service'
|
15
11
|
gem 'pact-support', path: '../pact-support'
|
data/README.md
CHANGED
@@ -153,7 +153,7 @@ Can I deploy the latest version of the application Foo that has the tag "test" t
|
|
153
153
|
|
154
154
|
If you are unable to use tags, or there is some other limitation that stops you from using the recommended approach, you can specify one or more of the dependencies explictly. You must also do this if you want to use the `--all TAG` option for any of the pacticipants.
|
155
155
|
|
156
|
-
You can specify as many application versions as you like, and you can even specify multiple versions of the same application (repeat the `--pacticipant` name and supply a different version.
|
156
|
+
You can specify as many application versions as you like, and you can even specify multiple versions of the same application (repeat the `--pacticipant` name and supply a different version). If you have a monorepo and you deploy a group of applications together, you can either call `can-i-deploy` once for each application, or you can group them all together by specifying a `--pacticipant` and `--version` for each sub-application.
|
157
157
|
|
158
158
|
You can use explictly declared dependencies with or without the `--to ENVIRONMENT`. For example, if you declare two (or more) application versions with no `--to ENVIRONMENT`, then only the applications you specify will be taken into account when determining if it is safe to deploy. If you declare two (or more) application versions _as well as_ a `--to ENVIRONMENT`, then the Pact Broker will work out what integrations your declared applications will have in that environment when determining if it safe to deploy. When using this script for a production release, and you are using tags, it is always the most future-proof option to use the `--to` if possible, as it will catch any newly added consumers or providers.
|
159
159
|
|
@@ -182,6 +182,13 @@ Can I deploy the latest version of Foo with tag "master" and the latest version
|
|
182
182
|
--pacticipant Bar --latest master \
|
183
183
|
--broker-base-url BROKER_BASE_URL
|
184
184
|
|
185
|
+
Can I deploy all the applications in my monorepo to prod?
|
186
|
+
|
187
|
+
$ pact-broker can-i-deploy --pacticipant A --version a7e28207 \
|
188
|
+
--pacticipant B --version a7e28207 \
|
189
|
+
--pacticipant C --version a7e28207 \
|
190
|
+
--to prod \
|
191
|
+
--broker-base-url BROKER_BASE_URL
|
185
192
|
|
186
193
|
Mobile provider use case - can I deploy version b80e7b1b of Bar, all versions of Foo with tag "prod", and the latest version tagged "prod" of any other automatically calculated dependencies together? (Eg. where Bar is a provider and Foo is a mobile consumer with multiple versions in production, and Bar also has its own providers it needs to be compatible with.)
|
187
194
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'erb'
|
2
4
|
require 'httparty'
|
3
5
|
require 'pact_broker/client/error'
|
@@ -30,6 +32,12 @@ module PactBroker
|
|
30
32
|
end
|
31
33
|
|
32
34
|
class BaseClient
|
35
|
+
ERROR_CODE_MAPPING = {
|
36
|
+
401 => "Authentication failed",
|
37
|
+
403 => "Authorization failed (insufficient permissions)",
|
38
|
+
409 => "Potential duplicate pacticipants"
|
39
|
+
}.freeze
|
40
|
+
|
33
41
|
include UrlHelpers
|
34
42
|
include HTTParty
|
35
43
|
include StringToSymbol
|
@@ -69,14 +77,8 @@ module PactBroker
|
|
69
77
|
yield response
|
70
78
|
elsif response.code == 404
|
71
79
|
nil
|
72
|
-
elsif response.code
|
73
|
-
message =
|
74
|
-
if response.body && response.body.size > 0
|
75
|
-
message = message + ": #{response.body}"
|
76
|
-
end
|
77
|
-
raise Error.new(message)
|
78
|
-
elsif response.code == 401
|
79
|
-
message = "Authentication failed"
|
80
|
+
elsif ERROR_CODE_MAPPING.key?(response.code)
|
81
|
+
message = ERROR_CODE_MAPPING.fetch(response.code)
|
80
82
|
if response.body && response.body.size > 0
|
81
83
|
message = message + ": #{response.body}"
|
82
84
|
end
|
@@ -93,7 +95,7 @@ module PactBroker
|
|
93
95
|
response.body
|
94
96
|
end
|
95
97
|
rescue
|
96
|
-
raise Error.new(response.body)
|
98
|
+
raise Error.new("status=#{response.code} #{response.body}")
|
97
99
|
end
|
98
100
|
raise Error.new(error_message)
|
99
101
|
end
|
@@ -50,6 +50,7 @@ module PactBroker
|
|
50
50
|
method_option :broker_token, aliases: "-k", desc: "Pact Broker bearer token"
|
51
51
|
method_option :tag, aliases: "-t", type: :array, banner: "TAG", desc: "Tag name for consumer version. Can be specified multiple times."
|
52
52
|
method_option :tag_with_git_branch, aliases: "-g", type: :boolean, default: false, required: false, desc: "Tag consumer version with the name of the current git branch. Default: false"
|
53
|
+
method_option :merge, type: :boolean, default: false, require: false, desc: "If a pact already exists for this consumer version and provider, merge the contents. Useful when running Pact tests concurrently on different build nodes."
|
53
54
|
method_option :verbose, aliases: "-v", type: :boolean, default: false, required: false, desc: "Verbose output. Default: false"
|
54
55
|
|
55
56
|
def publish(*pact_files)
|
@@ -209,13 +210,14 @@ module PactBroker
|
|
209
210
|
|
210
211
|
def publish_pacts pact_files
|
211
212
|
require 'pact_broker/client/publish_pacts'
|
213
|
+
write_options = options[:merge] ? { write: :merge } : {}
|
212
214
|
|
213
215
|
PactBroker::Client::PublishPacts.call(
|
214
216
|
options.broker_base_url,
|
215
217
|
file_list(pact_files),
|
216
218
|
options.consumer_app_version,
|
217
219
|
tags,
|
218
|
-
pact_broker_client_options
|
220
|
+
pact_broker_client_options.merge(write_options)
|
219
221
|
)
|
220
222
|
end
|
221
223
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'base_client'
|
2
4
|
require 'pact_broker/client/matrix/resource'
|
3
5
|
|
@@ -39,7 +41,7 @@ module PactBroker
|
|
39
41
|
response.body
|
40
42
|
end
|
41
43
|
rescue
|
42
|
-
raise Error.new(response.body)
|
44
|
+
raise Error.new("status=#{response.code} #{response.body}")
|
43
45
|
end
|
44
46
|
raise Error.new(error_message)
|
45
47
|
end
|
@@ -16,8 +16,8 @@ module PactBroker
|
|
16
16
|
def initialize pact_broker_base_url, pact_file_paths, consumer_version, tags, pact_broker_client_options={}
|
17
17
|
@pact_broker_base_url = pact_broker_base_url
|
18
18
|
@pact_file_paths = pact_file_paths
|
19
|
-
@consumer_version = consumer_version
|
20
|
-
@tags = tags
|
19
|
+
@consumer_version = consumer_version.respond_to?(:strip) ? consumer_version.strip : consumer_version
|
20
|
+
@tags = tags ? tags.collect{ |tag| tag.respond_to?(:strip) ? tag.strip : tag } : tags
|
21
21
|
@pact_broker_client_options = pact_broker_client_options
|
22
22
|
end
|
23
23
|
|
@@ -37,6 +37,10 @@ module PactBroker
|
|
37
37
|
@pact_broker_client ||= PactBroker::Client::PactBrokerClient.new(base_url: pact_broker_base_url, client_options: pact_broker_client_options)
|
38
38
|
end
|
39
39
|
|
40
|
+
def merge_on_server?
|
41
|
+
pact_broker_client_options[:write] == :merge
|
42
|
+
end
|
43
|
+
|
40
44
|
def publish_pacts
|
41
45
|
pact_files.group_by(&:pact_name).collect do | pact_name, pact_files |
|
42
46
|
$stdout.puts "Merging #{pact_files.collect(&:path).join(", ")}" if pact_files.size > 1
|
@@ -77,13 +81,13 @@ module PactBroker
|
|
77
81
|
versions = pact_broker_client.pacticipants.versions
|
78
82
|
Retry.while_error do
|
79
83
|
consumer_names.collect do | consumer_name |
|
80
|
-
$stdout.puts "Tagging version #{consumer_version} of #{consumer_name} as #{tag.inspect}"
|
81
84
|
versions.tag(pacticipant: consumer_name, version: consumer_version, tag: tag)
|
85
|
+
$stdout.puts "Tagged version #{consumer_version} of #{consumer_name} as #{tag.inspect}"
|
82
86
|
true
|
83
87
|
end
|
84
88
|
end
|
85
89
|
rescue => e
|
86
|
-
$stderr.puts "Failed to tag
|
90
|
+
$stderr.puts "Failed to tag version due to error: #{e.class} - #{e}"
|
87
91
|
false
|
88
92
|
end
|
89
93
|
|
@@ -91,11 +95,15 @@ module PactBroker
|
|
91
95
|
Retry.while_error do
|
92
96
|
pacts = pact_broker_client.pacticipants.versions.pacts
|
93
97
|
if pacts.version_published?(consumer: pact.consumer_name, provider: pact.provider_name, consumer_version: consumer_version)
|
94
|
-
|
98
|
+
if merge_on_server?
|
99
|
+
$stdout.puts "A pact for this consumer version is already published. Merging contents."
|
100
|
+
else
|
101
|
+
$stdout.puts ::Term::ANSIColor.yellow("A pact for this consumer version is already published. Overwriting. (Note: Overwriting pacts is not recommended as it can lead to race conditions. Best practice is to provide a unique consumer version number for each publication.)")
|
102
|
+
end
|
95
103
|
end
|
96
104
|
|
97
105
|
latest_pact_url = pacts.publish(pact_hash: pact, consumer_version: consumer_version)
|
98
|
-
$stdout.puts "The latest version of this pact can be accessed at the following URL
|
106
|
+
$stdout.puts "The latest version of this pact can be accessed at the following URL:\n#{latest_pact_url}"
|
99
107
|
true
|
100
108
|
end
|
101
109
|
end
|
data/pact-broker-client.gemspec
CHANGED
@@ -24,11 +24,12 @@ Gem::Specification.new do |gem|
|
|
24
24
|
gem.add_runtime_dependency 'httparty', '~>0.18'
|
25
25
|
gem.add_runtime_dependency 'term-ansicolor', '~> 1.7'
|
26
26
|
gem.add_runtime_dependency 'table_print', '~> 1.5'
|
27
|
-
gem.add_runtime_dependency 'thor', '
|
27
|
+
gem.add_runtime_dependency 'thor', '>= 0.20', '< 2.0'
|
28
28
|
gem.add_runtime_dependency 'rake', '~> 13.0' #For FileList
|
29
29
|
|
30
30
|
gem.add_development_dependency 'fakefs', '~> 0.4'
|
31
31
|
gem.add_development_dependency 'webmock', '~> 3.0'
|
32
32
|
gem.add_development_dependency 'conventional-changelog', '~>1.3'
|
33
33
|
gem.add_development_dependency 'pact', '~> 1.16'
|
34
|
+
gem.add_development_dependency 'pact-support', '1.15.0'
|
34
35
|
end
|
@@ -2,10 +2,11 @@ require 'pact_broker/client/base_client'
|
|
2
2
|
module PactBroker
|
3
3
|
module Client
|
4
4
|
describe BaseClient do
|
5
|
-
|
6
|
-
|
5
|
+
subject { BaseClient.new(base_url: base_url) }
|
6
|
+
|
7
|
+
let(:base_url) { 'http://pact_broker_base_url'}
|
7
8
|
|
8
|
-
|
9
|
+
describe '#initialize' do
|
9
10
|
let(:username) { 'pact_repo_username'}
|
10
11
|
let(:password) { 'pact_repo_password'}
|
11
12
|
let(:token) { '123456789' }
|
@@ -119,6 +120,63 @@ module PactBroker
|
|
119
120
|
end
|
120
121
|
end
|
121
122
|
end
|
123
|
+
|
124
|
+
describe '#handle_response' do
|
125
|
+
let(:response) { double('Response', success?: true) }
|
126
|
+
|
127
|
+
it 'yields response object' do
|
128
|
+
expect { |block| subject.handle_response(response, &block) }.to yield_with_args(response)
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'with 404 response' do
|
132
|
+
let(:response) { double('Response', success?: false, code: 404) }
|
133
|
+
it 'returns nil' do
|
134
|
+
expect(subject.handle_response(response)).to be_nil
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
context 'with 401 response' do
|
139
|
+
let(:response) { double('Response', success?: false, code: 401, body: 'body') }
|
140
|
+
it 'raise an exception with meaningful message' do
|
141
|
+
expect { subject.handle_response(response) }
|
142
|
+
.to raise_error(PactBroker::Client::Error, "Authentication failed: body")
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context 'with 403 response' do
|
147
|
+
let(:response) { double('Response', success?: false, code: 403, body: 'body') }
|
148
|
+
it 'raise an exception with meaningful message' do
|
149
|
+
expect { subject.handle_response(response) }
|
150
|
+
.to raise_error(PactBroker::Client::Error, "Authorization failed (insufficient permissions): body")
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context 'with 409 response' do
|
155
|
+
let(:response) { double('Response', success?: false, code: 409, body: 'body') }
|
156
|
+
it 'raise an exception with meaningful message' do
|
157
|
+
expect { subject.handle_response(response) }
|
158
|
+
.to raise_error(PactBroker::Client::Error, "Potential duplicate pacticipants: body")
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
context 'with unsuccessful JSON response' do
|
163
|
+
let(:response) do
|
164
|
+
double('Response', success?: false, code: 500, body: '{"errors": ["Internal server error"]}')
|
165
|
+
end
|
166
|
+
it 'raise an exception with meaningful message' do
|
167
|
+
expect { subject.handle_response(response) }
|
168
|
+
.to raise_error(PactBroker::Client::Error, "Internal server error")
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'with unsucessful nono-JSON response ' do
|
173
|
+
let(:response) { double('Response', success?: false, code: 500, body: 'Internal server error') }
|
174
|
+
it 'raise an exception with meaningful message' do
|
175
|
+
expect { subject.handle_response(response) }
|
176
|
+
.to raise_error(PactBroker::Client::Error, "status=500 Internal server error")
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
122
180
|
end
|
123
181
|
end
|
124
|
-
end
|
182
|
+
end
|
@@ -62,12 +62,12 @@ module PactBroker
|
|
62
62
|
end
|
63
63
|
|
64
64
|
context "when publishing is successful" do
|
65
|
-
|
66
65
|
it "puts the location of the latest pact" do
|
67
66
|
allow($stdout).to receive(:puts)
|
68
67
|
expect($stdout).to receive(:puts).with(/#{latest_pact_url}/)
|
69
68
|
subject.call
|
70
69
|
end
|
70
|
+
|
71
71
|
it "returns true" do
|
72
72
|
expect(subject.call).to be true
|
73
73
|
end
|
@@ -142,6 +142,15 @@ module PactBroker
|
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
145
|
+
context "when consumer_version has a new line" do
|
146
|
+
let(:consumer_version) { "1\n" }
|
147
|
+
|
148
|
+
it "strips the new line" do
|
149
|
+
expect(pacts_client).to receive(:publish).with(pact_hash: pact_hash, consumer_version: "1")
|
150
|
+
subject.call
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
145
154
|
context "when pact_broker_base_url is blank" do
|
146
155
|
let(:pact_broker_base_url) { " " }
|
147
156
|
it "raises a validation errror" do
|
@@ -164,6 +173,16 @@ module PactBroker
|
|
164
173
|
subject.call
|
165
174
|
end
|
166
175
|
|
176
|
+
context "when the tag has a new line on the end of it" do
|
177
|
+
let(:tags) { ["foo\n"] }
|
178
|
+
|
179
|
+
it "strips the newline" do
|
180
|
+
expect(pact_versions_client).to receive(:tag).with({pacticipant: "Consumer",
|
181
|
+
version: consumer_version, tag: "foo"})
|
182
|
+
subject.call
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
167
186
|
context "when an error occurs tagging the pact" do
|
168
187
|
|
169
188
|
before do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact_broker-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.34.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Beth Skurrie
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-11-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: httparty
|
@@ -56,16 +56,22 @@ dependencies:
|
|
56
56
|
name: thor
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0.20'
|
62
|
+
- - "<"
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '2.0'
|
62
65
|
type: :runtime
|
63
66
|
prerelease: false
|
64
67
|
version_requirements: !ruby/object:Gem::Requirement
|
65
68
|
requirements:
|
66
|
-
- - "
|
69
|
+
- - ">="
|
67
70
|
- !ruby/object:Gem::Version
|
68
71
|
version: '0.20'
|
72
|
+
- - "<"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '2.0'
|
69
75
|
- !ruby/object:Gem::Dependency
|
70
76
|
name: rake
|
71
77
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +142,20 @@ dependencies:
|
|
136
142
|
- - "~>"
|
137
143
|
- !ruby/object:Gem::Version
|
138
144
|
version: '1.16'
|
145
|
+
- !ruby/object:Gem::Dependency
|
146
|
+
name: pact-support
|
147
|
+
requirement: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - '='
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: 1.15.0
|
152
|
+
type: :development
|
153
|
+
prerelease: false
|
154
|
+
version_requirements: !ruby/object:Gem::Requirement
|
155
|
+
requirements:
|
156
|
+
- - '='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: 1.15.0
|
139
159
|
description: Client for the Pact Broker. Publish, retrieve and query pacts and verification
|
140
160
|
results.
|
141
161
|
email:
|