pact_broker-client 1.30.0 → 1.35.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/.github/workflows/test.yml +23 -0
- data/CHANGELOG.md +46 -0
- data/README.md +15 -3
- data/doc/pacts/markdown/Pact Broker Client - Pact Broker.md +48 -8
- 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/matrix/text_formatter.rb +44 -11
- data/lib/pact_broker/client/pacts/list_latest_versions.rb +1 -1
- data/lib/pact_broker/client/publish_pacts.rb +13 -5
- data/lib/pact_broker/client/version.rb +1 -1
- data/pact-broker-client.gemspec +3 -1
- data/spec/lib/pact_broker/client/base_client_spec.rb +62 -4
- data/spec/lib/pact_broker/client/matrix/text_formatter_spec.rb +29 -4
- data/spec/lib/pact_broker/client/publish_pacts_spec.rb +20 -1
- data/spec/pacts/pact_broker_client-pact_broker.json +48 -8
- data/spec/support/matrix.json +6 -1
- data/spec/support/matrix.txt +3 -3
- data/spec/support/matrix_error.txt +3 -3
- data/spec/support/matrix_with_results.txt +10 -0
- metadata +42 -6
- data/.travis.yml +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1bf1176c39519652e60c6aab383a941a2dd5a1c8e968b746741a290e68c736e9
|
4
|
+
data.tar.gz: 04b1f3aa9f25b353e61eb558d393d108750cd97b4645fe81313b1d04dca33ba5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cbb4fe27ce2979d3daea2c597ca7509b6d4136ac53d139a738fd672f30d114fcce23ce4f3ba3c108aef13ec88b9793715bf57ec05a2fda6255dfcd7ed9c99875
|
7
|
+
data.tar.gz: 443c3e2e5fb75bcbfa3850ce1498f859c45872145f813c50b260a9a7d28a32f5aa7618c1f55b0c798b34975ec7b35d7e44b0937c6bd2575dea1b86356eb8ca5b
|
@@ -0,0 +1,23 @@
|
|
1
|
+
name: Test
|
2
|
+
|
3
|
+
on: push
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: "ubuntu-latest"
|
8
|
+
continue-on-error: ${{ matrix.experimental }}
|
9
|
+
strategy:
|
10
|
+
fail-fast: false
|
11
|
+
matrix:
|
12
|
+
ruby_version: ["2.2", "2.7"]
|
13
|
+
experimental: [false]
|
14
|
+
include:
|
15
|
+
- ruby_version: "3.0"
|
16
|
+
experimental: true
|
17
|
+
steps:
|
18
|
+
- uses: actions/checkout@v2
|
19
|
+
- uses: ruby/setup-ruby@v1
|
20
|
+
with:
|
21
|
+
ruby-version: ${{ matrix.ruby_version }}
|
22
|
+
- run: "bundle install"
|
23
|
+
- run: "bundle exec rake"
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,49 @@
|
|
1
|
+
<a name="v1.35.0"></a>
|
2
|
+
### v1.35.0 (2021-01-21)
|
3
|
+
|
4
|
+
#### Features
|
5
|
+
|
6
|
+
* **can-i-deploy**
|
7
|
+
* display links to verification results in the output of can-i-deploy when using text format ([976950d](/../../commit/976950d))
|
8
|
+
|
9
|
+
<a name="v1.34.0"></a>
|
10
|
+
### v1.34.0 (2020-11-20)
|
11
|
+
|
12
|
+
#### Features
|
13
|
+
|
14
|
+
* **pact publish**
|
15
|
+
* strip new lines from version numbers and tags ([5842d24](/../../commit/5842d24))
|
16
|
+
|
17
|
+
* **publish**
|
18
|
+
* update output text when pact already exists and merging ([9b849d3](/../../commit/9b849d3))
|
19
|
+
|
20
|
+
<a name="v1.33.0"></a>
|
21
|
+
### v1.33.0 (2020-11-10)
|
22
|
+
|
23
|
+
#### Features
|
24
|
+
|
25
|
+
* **publish**
|
26
|
+
* allow pacts to be merged on the server side ([bd80f10](/../../commit/bd80f10))
|
27
|
+
|
28
|
+
<a name="v1.32.0"></a>
|
29
|
+
### v1.32.0 (2020-10-26)
|
30
|
+
|
31
|
+
#### Features
|
32
|
+
|
33
|
+
* Improve HTTP errors handling (#76) ([d8eaf16](/../../commit/d8eaf16))
|
34
|
+
|
35
|
+
#### Bug Fixes
|
36
|
+
|
37
|
+
* **list-latest-pact-versions**
|
38
|
+
* correct json output ([cf77666](/../../commit/cf77666))
|
39
|
+
|
40
|
+
<a name="v1.31.0"></a>
|
41
|
+
### v1.31.0 (2020-10-22)
|
42
|
+
|
43
|
+
#### Features
|
44
|
+
|
45
|
+
* update thor dependancy (#75) ([2078f31](/../../commit/2078f31))
|
46
|
+
|
1
47
|
<a name="v1.30.0"></a>
|
2
48
|
### v1.30.0 (2020-10-09)
|
3
49
|
|
data/README.md
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
A client for the Pact Broker. Publishes and retrieves pacts, verification results, pacticipants, pacticipant versions and tags. The functionality is available via a CLI, or via Ruby Rake tasks. You can also use the [Pact CLI Docker image](https://hub.docker.com/r/pactfoundation/pact-cli).
|
4
4
|
|
5
|
-
|
5
|
+

|
6
|
+
|
7
|
+
[](http://badge.fury.io/rb/pact_broker-client)
|
6
8
|
|
7
9
|

|
8
10
|
|
@@ -16,9 +18,19 @@ Download the latest [pact-ruby-standalone][pact-ruby-standalone] package. You do
|
|
16
18
|
|
17
19
|
Add `gem 'pact_broker-client'` to your Gemfile and run `bundle install`, or install the gem directly by running `gem install pact_broker-client`.
|
18
20
|
|
21
|
+
## Connecting to a Pact Broker with a self signed certificate
|
22
|
+
|
23
|
+
To connect to a Pact Broker that uses custom SSL cerificates, set the environment variable `$SSL_CERT_FILE` or `$SSL_CERT_DIR` to a path that contains the appropriate certificate. Read more at https://docs.pact.io/pact_broker/advanced_topics/using-tls#for-non-jvm
|
24
|
+
|
19
25
|
## Usage - CLI
|
20
26
|
|
21
|
-
|
27
|
+
The Pact Broker base URL can be specified either using the environment variable `$PACT_BROKER_BASE_URL` or the `-b` or `--broker-base-url` parameters.
|
28
|
+
|
29
|
+
Pact Broker authentication can be performed either using basic auth or a bearer token.
|
30
|
+
|
31
|
+
Basic auth parameters can be specified using the `$PACT_BROKER_USERNAME` and `$PACT_BROKER_PASSWORD` environment variables, or the `-u` or `--broker-username` and `-p` or `--broker-password` parameters.
|
32
|
+
|
33
|
+
Authentication using a bearer token can be specified using the environment variable `$PACT_BROKER_TOKEN` or the `-k` or `--broker-token` parameters. This authentication system is used by [Pactflow](pactflow.io).
|
22
34
|
|
23
35
|
### publish
|
24
36
|
|
@@ -188,7 +200,7 @@ Can I deploy all the applications in my monorepo to prod?
|
|
188
200
|
--pacticipant B --version a7e28207 \
|
189
201
|
--pacticipant C --version a7e28207 \
|
190
202
|
--to prod \
|
191
|
-
--broker-base-url BROKER_BASE_URL
|
203
|
+
--broker-base-url BROKER_BASE_URL
|
192
204
|
|
193
205
|
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.)
|
194
206
|
|
@@ -164,7 +164,12 @@ Pact Broker will respond with:
|
|
164
164
|
},
|
165
165
|
"verificationResult": {
|
166
166
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
167
|
-
"success": true
|
167
|
+
"success": true,
|
168
|
+
"_links": {
|
169
|
+
"self": {
|
170
|
+
"href": "http://result"
|
171
|
+
}
|
172
|
+
}
|
168
173
|
},
|
169
174
|
"pact": {
|
170
175
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -185,7 +190,12 @@ Pact Broker will respond with:
|
|
185
190
|
},
|
186
191
|
"verificationResult": {
|
187
192
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
188
|
-
"success": true
|
193
|
+
"success": true,
|
194
|
+
"_links": {
|
195
|
+
"self": {
|
196
|
+
"href": "http://result"
|
197
|
+
}
|
198
|
+
}
|
189
199
|
},
|
190
200
|
"pact": {
|
191
201
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -233,7 +243,12 @@ Pact Broker will respond with:
|
|
233
243
|
},
|
234
244
|
"verificationResult": {
|
235
245
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
236
|
-
"success": true
|
246
|
+
"success": true,
|
247
|
+
"_links": {
|
248
|
+
"self": {
|
249
|
+
"href": "http://result"
|
250
|
+
}
|
251
|
+
}
|
237
252
|
},
|
238
253
|
"pact": {
|
239
254
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -281,7 +296,12 @@ Pact Broker will respond with:
|
|
281
296
|
},
|
282
297
|
"verificationResult": {
|
283
298
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
284
|
-
"success": true
|
299
|
+
"success": true,
|
300
|
+
"_links": {
|
301
|
+
"self": {
|
302
|
+
"href": "http://result"
|
303
|
+
}
|
304
|
+
}
|
285
305
|
},
|
286
306
|
"pact": {
|
287
307
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -329,7 +349,12 @@ Pact Broker will respond with:
|
|
329
349
|
},
|
330
350
|
"verificationResult": {
|
331
351
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
332
|
-
"success": true
|
352
|
+
"success": true,
|
353
|
+
"_links": {
|
354
|
+
"self": {
|
355
|
+
"href": "http://result"
|
356
|
+
}
|
357
|
+
}
|
333
358
|
},
|
334
359
|
"pact": {
|
335
360
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -413,7 +438,12 @@ Pact Broker will respond with:
|
|
413
438
|
},
|
414
439
|
"verificationResult": {
|
415
440
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
416
|
-
"success": true
|
441
|
+
"success": true,
|
442
|
+
"_links": {
|
443
|
+
"self": {
|
444
|
+
"href": "http://result"
|
445
|
+
}
|
446
|
+
}
|
417
447
|
},
|
418
448
|
"pact": {
|
419
449
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -484,7 +514,12 @@ Pact Broker will respond with:
|
|
484
514
|
},
|
485
515
|
"verificationResult": {
|
486
516
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
487
|
-
"success": true
|
517
|
+
"success": true,
|
518
|
+
"_links": {
|
519
|
+
"self": {
|
520
|
+
"href": "http://result"
|
521
|
+
}
|
522
|
+
}
|
488
523
|
},
|
489
524
|
"pact": {
|
490
525
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -735,7 +770,12 @@ Pact Broker will respond with:
|
|
735
770
|
},
|
736
771
|
"verificationResult": {
|
737
772
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
738
|
-
"success": true
|
773
|
+
"success": true,
|
774
|
+
"_links": {
|
775
|
+
"self": {
|
776
|
+
"href": "http://result"
|
777
|
+
}
|
778
|
+
}
|
739
779
|
},
|
740
780
|
"pact": {
|
741
781
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -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
|
@@ -1,41 +1,74 @@
|
|
1
1
|
require 'table_print'
|
2
|
+
require 'dig_rb'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Client
|
5
6
|
class Matrix
|
6
7
|
class TextFormatter
|
7
8
|
|
8
|
-
Line = Struct.new(:consumer, :consumer_version, :provider, :provider_version, :success)
|
9
|
+
Line = Struct.new(:consumer, :consumer_version, :provider, :provider_version, :success, :ref)
|
9
10
|
|
10
11
|
OPTIONS = [
|
11
12
|
{ consumer: {} },
|
12
13
|
{ consumer_version: {display_name: 'C.VERSION'} },
|
13
14
|
{ provider: {} },
|
14
15
|
{ provider_version: {display_name: 'P.VERSION'} },
|
15
|
-
{ success: {display_name: 'SUCCESS?'} }
|
16
|
+
{ success: {display_name: 'SUCCESS?'} },
|
17
|
+
{ ref: { display_name: 'RESULT#' }}
|
16
18
|
]
|
17
19
|
|
18
20
|
def self.call(matrix)
|
19
21
|
matrix_rows = matrix[:matrix]
|
20
22
|
return "" if matrix_rows.size == 0
|
21
|
-
|
23
|
+
verification_result_number = 0
|
24
|
+
data = matrix_rows.each_with_index.collect do | line |
|
25
|
+
has_verification_result_url = lookup(line, nil, :verificationResult, :_links, :self, :href)
|
26
|
+
if has_verification_result_url
|
27
|
+
verification_result_number += 1
|
28
|
+
end
|
22
29
|
Line.new(
|
23
|
-
lookup(line, :consumer, :name),
|
24
|
-
lookup(line, :consumer, :version, :number),
|
25
|
-
lookup(line, :provider, :name),
|
26
|
-
lookup(line, :provider, :version, :number),
|
27
|
-
lookup(line, :verificationResult, :success).to_s
|
30
|
+
lookup(line, "???", :consumer, :name),
|
31
|
+
lookup(line, "???", :consumer, :version, :number),
|
32
|
+
lookup(line, "???", :provider, :name) ,
|
33
|
+
lookup(line, "???", :provider, :version, :number),
|
34
|
+
(lookup(line, "???", :verificationResult, :success)).to_s,
|
35
|
+
has_verification_result_url ? verification_result_number : ""
|
28
36
|
)
|
29
37
|
end
|
30
38
|
|
31
39
|
printer = TablePrint::Printer.new(data, OPTIONS)
|
32
|
-
printer.table_print
|
40
|
+
printer.table_print + verification_result_urls_text(matrix)
|
33
41
|
end
|
34
42
|
|
35
|
-
def self.lookup line, *keys
|
43
|
+
def self.lookup line, default, *keys
|
36
44
|
keys.reduce(line) { | line, key | line[key] }
|
37
45
|
rescue NoMethodError
|
38
|
-
|
46
|
+
default
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.verification_results_urls_and_successes(matrix)
|
50
|
+
(matrix[:matrix] || []).collect do | row |
|
51
|
+
url = row.dig(:verificationResult, :_links, :self, :href)
|
52
|
+
if url
|
53
|
+
success = row.dig(:verificationResult, :success)
|
54
|
+
[url, success]
|
55
|
+
else
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end.compact
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.verification_result_urls_text(matrix)
|
62
|
+
text = self.verification_results_urls_and_successes(matrix).each_with_index.collect do |(url, success), i|
|
63
|
+
status = success ? 'success' : 'failure'
|
64
|
+
"#{i+1}. #{url} (#{status})"
|
65
|
+
end.join("\n")
|
66
|
+
|
67
|
+
if text.size > 0
|
68
|
+
"\n\nVERIFICATION RESULTS\n--------------------\n#{text}"
|
69
|
+
else
|
70
|
+
text
|
71
|
+
end
|
39
72
|
end
|
40
73
|
end
|
41
74
|
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,7 +95,11 @@ 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)
|
data/pact-broker-client.gemspec
CHANGED
@@ -24,11 +24,13 @@ 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
|
+
gem.add_runtime_dependency 'dig_rb', '~> 1.0'
|
29
30
|
|
30
31
|
gem.add_development_dependency 'fakefs', '~> 0.4'
|
31
32
|
gem.add_development_dependency 'webmock', '~> 3.0'
|
32
33
|
gem.add_development_dependency 'conventional-changelog', '~>1.3'
|
33
34
|
gem.add_development_dependency 'pact', '~> 1.16'
|
35
|
+
gem.add_development_dependency 'pact-support', '1.15.0'
|
34
36
|
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
|
@@ -1,29 +1,54 @@
|
|
1
|
+
require 'pact_broker/client/matrix/resource'
|
1
2
|
require 'pact_broker/client/matrix/text_formatter'
|
2
3
|
|
3
4
|
module PactBroker
|
4
5
|
module Client
|
5
6
|
describe Matrix::TextFormatter do
|
6
|
-
let(:
|
7
|
+
let(:matrix) { PactBroker::Client::Matrix::Resource.new(JSON.parse(File.read('spec/support/matrix.json'), symbolize_names: true)) }
|
7
8
|
let(:expected_matrix_lines) { File.read('spec/support/matrix.txt') }
|
8
9
|
|
9
10
|
# SublimeText removes whitespace from the end of files when you save them,
|
10
11
|
# so removing trailing whitespace before comparing
|
11
|
-
|
12
|
+
def strip_trailing_whitespace(text)
|
13
|
+
text.split("\n").collect(&:strip).join("\n")
|
14
|
+
end
|
15
|
+
|
16
|
+
subject { strip_trailing_whitespace(Matrix::TextFormatter.call(matrix)) }
|
12
17
|
|
13
18
|
context "with valid data" do
|
14
19
|
it "it has the right text" do
|
15
|
-
expect(subject).to
|
20
|
+
expect(subject).to start_with expected_matrix_lines
|
16
21
|
end
|
17
22
|
end
|
18
23
|
|
19
24
|
context "with invalid data" do
|
20
25
|
let(:expected_matrix_lines) { File.read('spec/support/matrix_error.txt') }
|
21
|
-
let(:
|
26
|
+
let(:matrix) { PactBroker::Client::Matrix::Resource.new(matrix: [{}]) }
|
22
27
|
|
23
28
|
it "doesn't blow up" do
|
24
29
|
expect(subject).to eq expected_matrix_lines
|
25
30
|
end
|
26
31
|
end
|
32
|
+
|
33
|
+
context "when some rows have a verification result URL and some don't" do
|
34
|
+
let(:matrix_lines) do
|
35
|
+
line_creator = -> { JSON.parse(File.read('spec/support/matrix.json'), symbolize_names: true)[:matrix].first }
|
36
|
+
line_1 = line_creator.call
|
37
|
+
line_2 = line_creator.call
|
38
|
+
line_3 = line_creator.call
|
39
|
+
line_2[:verificationResult] = nil
|
40
|
+
line_3[:verificationResult][:success] = false
|
41
|
+
[line_1, line_2, line_3]
|
42
|
+
end
|
43
|
+
|
44
|
+
let(:matrix) { PactBroker::Client::Matrix::Resource.new(matrix: matrix_lines) }
|
45
|
+
|
46
|
+
let(:expected_matrix_lines) { File.read('spec/support/matrix_with_results.txt') }
|
47
|
+
|
48
|
+
it "only provides a result number for the lines that have a result URL" do
|
49
|
+
expect(subject).to eq expected_matrix_lines
|
50
|
+
end
|
51
|
+
end
|
27
52
|
end
|
28
53
|
end
|
29
54
|
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
|
@@ -221,7 +221,12 @@
|
|
221
221
|
},
|
222
222
|
"verificationResult": {
|
223
223
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
224
|
-
"success": true
|
224
|
+
"success": true,
|
225
|
+
"_links": {
|
226
|
+
"self": {
|
227
|
+
"href": "http://result"
|
228
|
+
}
|
229
|
+
}
|
225
230
|
},
|
226
231
|
"pact": {
|
227
232
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -271,7 +276,12 @@
|
|
271
276
|
},
|
272
277
|
"verificationResult": {
|
273
278
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
274
|
-
"success": true
|
279
|
+
"success": true,
|
280
|
+
"_links": {
|
281
|
+
"self": {
|
282
|
+
"href": "http://result"
|
283
|
+
}
|
284
|
+
}
|
275
285
|
},
|
276
286
|
"pact": {
|
277
287
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -321,7 +331,12 @@
|
|
321
331
|
},
|
322
332
|
"verificationResult": {
|
323
333
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
324
|
-
"success": true
|
334
|
+
"success": true,
|
335
|
+
"_links": {
|
336
|
+
"self": {
|
337
|
+
"href": "http://result"
|
338
|
+
}
|
339
|
+
}
|
325
340
|
},
|
326
341
|
"pact": {
|
327
342
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -418,7 +433,12 @@
|
|
418
433
|
},
|
419
434
|
"verificationResult": {
|
420
435
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
421
|
-
"success": true
|
436
|
+
"success": true,
|
437
|
+
"_links": {
|
438
|
+
"self": {
|
439
|
+
"href": "http://result"
|
440
|
+
}
|
441
|
+
}
|
422
442
|
},
|
423
443
|
"pact": {
|
424
444
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -439,7 +459,12 @@
|
|
439
459
|
},
|
440
460
|
"verificationResult": {
|
441
461
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
442
|
-
"success": true
|
462
|
+
"success": true,
|
463
|
+
"_links": {
|
464
|
+
"self": {
|
465
|
+
"href": "http://result"
|
466
|
+
}
|
467
|
+
}
|
443
468
|
},
|
444
469
|
"pact": {
|
445
470
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -492,7 +517,12 @@
|
|
492
517
|
},
|
493
518
|
"verificationResult": {
|
494
519
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
495
|
-
"success": true
|
520
|
+
"success": true,
|
521
|
+
"_links": {
|
522
|
+
"self": {
|
523
|
+
"href": "http://result"
|
524
|
+
}
|
525
|
+
}
|
496
526
|
},
|
497
527
|
"pact": {
|
498
528
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -542,7 +572,12 @@
|
|
542
572
|
},
|
543
573
|
"verificationResult": {
|
544
574
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
545
|
-
"success": true
|
575
|
+
"success": true,
|
576
|
+
"_links": {
|
577
|
+
"self": {
|
578
|
+
"href": "http://result"
|
579
|
+
}
|
580
|
+
}
|
546
581
|
},
|
547
582
|
"pact": {
|
548
583
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
@@ -592,7 +627,12 @@
|
|
592
627
|
},
|
593
628
|
"verificationResult": {
|
594
629
|
"verifiedAt": "2017-10-10T12:49:04+11:00",
|
595
|
-
"success": true
|
630
|
+
"success": true,
|
631
|
+
"_links": {
|
632
|
+
"self": {
|
633
|
+
"href": "http://result"
|
634
|
+
}
|
635
|
+
}
|
596
636
|
},
|
597
637
|
"pact": {
|
598
638
|
"createdAt": "2017-10-10T12:49:04+11:00"
|
data/spec/support/matrix.json
CHANGED
data/spec/support/matrix.txt
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
CONSUMER | C.VERSION | PROVIDER | P.VERSION | SUCCESS?
|
2
|
-
|
3
|
-
Foo | 4 | Bar | 5 | true
|
1
|
+
CONSUMER | C.VERSION | PROVIDER | P.VERSION | SUCCESS? | RESULT#
|
2
|
+
---------|-----------|----------|-----------|----------|--------
|
3
|
+
Foo | 4 | Bar | 5 | true | 1
|
@@ -1,3 +1,3 @@
|
|
1
|
-
CONSUMER | C.VERSION | PROVIDER | P.VERSION | SUCCESS?
|
2
|
-
|
3
|
-
??? | ??? | ??? | ??? | ???
|
1
|
+
CONSUMER | C.VERSION | PROVIDER | P.VERSION | SUCCESS? | RESULT#
|
2
|
+
---------|-----------|----------|-----------|----------|--------
|
3
|
+
??? | ??? | ??? | ??? | ??? |
|
@@ -0,0 +1,10 @@
|
|
1
|
+
CONSUMER | C.VERSION | PROVIDER | P.VERSION | SUCCESS? | RESULT#
|
2
|
+
---------|-----------|----------|-----------|----------|--------
|
3
|
+
Foo | 4 | Bar | 5 | true | 1
|
4
|
+
Foo | 4 | Bar | 5 | ??? |
|
5
|
+
Foo | 4 | Bar | 5 | false | 2
|
6
|
+
|
7
|
+
VERIFICATION RESULTS
|
8
|
+
--------------------
|
9
|
+
1. http://result (success)
|
10
|
+
2. http://result (failure)
|
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.35.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:
|
11
|
+
date: 2021-01-21 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
|
@@ -80,6 +86,20 @@ dependencies:
|
|
80
86
|
- - "~>"
|
81
87
|
- !ruby/object:Gem::Version
|
82
88
|
version: '13.0'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: dig_rb
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - "~>"
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '1.0'
|
96
|
+
type: :runtime
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - "~>"
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '1.0'
|
83
103
|
- !ruby/object:Gem::Dependency
|
84
104
|
name: fakefs
|
85
105
|
requirement: !ruby/object:Gem::Requirement
|
@@ -136,6 +156,20 @@ dependencies:
|
|
136
156
|
- - "~>"
|
137
157
|
- !ruby/object:Gem::Version
|
138
158
|
version: '1.16'
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: pact-support
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - '='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: 1.15.0
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - '='
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: 1.15.0
|
139
173
|
description: Client for the Pact Broker. Publish, retrieve and query pacts and verification
|
140
174
|
results.
|
141
175
|
email:
|
@@ -146,10 +180,10 @@ extensions: []
|
|
146
180
|
extra_rdoc_files: []
|
147
181
|
files:
|
148
182
|
- ".github/workflows/release_gem.yml"
|
183
|
+
- ".github/workflows/test.yml"
|
149
184
|
- ".github/workflows/trigger_pact_docs_update.yml"
|
150
185
|
- ".gitignore"
|
151
186
|
- ".rspec"
|
152
|
-
- ".travis.yml"
|
153
187
|
- CHANGELOG.md
|
154
188
|
- Dockerfile
|
155
189
|
- Gemfile
|
@@ -271,6 +305,7 @@ files:
|
|
271
305
|
- spec/support/matrix.json
|
272
306
|
- spec/support/matrix.txt
|
273
307
|
- spec/support/matrix_error.txt
|
308
|
+
- spec/support/matrix_with_results.txt
|
274
309
|
- spec/support/pacticipant_get.json
|
275
310
|
- spec/support/pacticipants_list.json
|
276
311
|
- spec/support/pacts_latest_list.json
|
@@ -295,7 +330,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
295
330
|
- !ruby/object:Gem::Version
|
296
331
|
version: '0'
|
297
332
|
requirements: []
|
298
|
-
rubygems_version: 3.
|
333
|
+
rubygems_version: 3.2.6
|
299
334
|
signing_key:
|
300
335
|
specification_version: 4
|
301
336
|
summary: See description
|
@@ -350,6 +385,7 @@ test_files:
|
|
350
385
|
- spec/support/matrix.json
|
351
386
|
- spec/support/matrix.txt
|
352
387
|
- spec/support/matrix_error.txt
|
388
|
+
- spec/support/matrix_with_results.txt
|
353
389
|
- spec/support/pacticipant_get.json
|
354
390
|
- spec/support/pacticipants_list.json
|
355
391
|
- spec/support/pacts_latest_list.json
|
data/.travis.yml
DELETED
@@ -1,11 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
rvm:
|
3
|
-
- 2.2.4
|
4
|
-
- 2.4.1
|
5
|
-
|
6
|
-
# before_install:
|
7
|
-
# - (git show-ref | grep $(git log --pretty=%h -1) | sed 's|.*/\(.*\)|\1|' | sort -u | grep -v HEAD) || true
|
8
|
-
# - (git show -s --pretty=%d HEAD) || true
|
9
|
-
# - (git for-each-ref --format='%(objectname) %(refname:short)' refs/heads | awk "/^$(git rev-parse HEAD)/ {print \$2}") || true
|
10
|
-
# - (git show -s --pretty=%D HEAD | tr -s ', ' '\n' | grep -v HEAD | head -n1) || true
|
11
|
-
# - (git name-rev --name-only HEAD) || true
|