pact_broker-client 1.4.0 → 1.5.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 +11 -0
- data/RELEASING.md +1 -1
- data/Rakefile +8 -2
- data/bin/pact-publish +4 -0
- data/gemfiles/default.gemfile.lock +11 -11
- data/gemfiles/ruby_under_22.gemfile.lock +11 -11
- data/lib/pact_broker/client/cli/custom_thor.rb +71 -0
- data/lib/pact_broker/client/cli/publish.rb +82 -0
- data/lib/pact_broker/client/error.rb +5 -0
- data/lib/pact_broker/client/merge_pacts.rb +57 -0
- data/lib/pact_broker/client/pact_file.rb +36 -0
- data/lib/pact_broker/client/pact_hash.rb +19 -0
- data/lib/pact_broker/client/pacts.rb +7 -8
- data/lib/pact_broker/client/publish_pacts.rb +35 -23
- data/lib/pact_broker/client/version.rb +1 -1
- data/pact-broker-client.gemspec +1 -1
- data/spec/lib/pact_broker/client/cli/custom_thor_spec.rb +105 -0
- data/spec/lib/pact_broker/client/cli/publish_spec.rb +128 -0
- data/spec/lib/pact_broker/client/merge_pacts_spec.rb +69 -0
- data/spec/lib/pact_broker/client/publish_pacts_spec.rb +38 -17
- data/spec/service_providers/pact_broker_client_publish_spec.rb +1 -1
- data/spec/support/cli_test_pacts/bar.json +0 -0
- data/spec/support/cli_test_pacts/foo.json +0 -0
- data/spec/support/shared_context.rb +2 -1
- metadata +35 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a630ec3051f4b51d5a8acb1ca7365bf47742eecd
|
4
|
+
data.tar.gz: 73f384f4e4609e169e54b4bcc464cc670c43b483
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7f0803e0421cf2499da988d58e6de8156fc2bfcd8c8ffab89e139431b51907c3c42d32293c754f98a64051c878dc942b17915038b6d563a155be5f3c5d5cbf90
|
7
|
+
data.tar.gz: 9ccc081095706def8781febb131ee1d85616e33eede87f554dc4c9d7e34728e427f4babe6f2f97b8ddb18a03e7cdac99259d93926d025c68d6fb288c1140343c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,14 @@
|
|
1
|
+
<a name="v1.5.0"></a>
|
2
|
+
### v1.5.0 (2017-09-28)
|
3
|
+
|
4
|
+
#### Features
|
5
|
+
|
6
|
+
* **cli**
|
7
|
+
* add command line tool to publish pacts ([d031b98](/../../commit/d031b98))
|
8
|
+
|
9
|
+
* **publish pacts**
|
10
|
+
* merge pact files with same consumer/provider before publishing ([1c039a0](/../../commit/1c039a0))
|
11
|
+
|
1
12
|
<a name="v1.4.0"></a>
|
2
13
|
### v1.4.0 (2017-09-07)
|
3
14
|
|
data/RELEASING.md
CHANGED
@@ -8,7 +8,7 @@
|
|
8
8
|
|
9
9
|
4. Add files to git
|
10
10
|
|
11
|
-
$ git add CHANGELOG.md lib/pact_broker/client/version.rb
|
11
|
+
$ git add CHANGELOG.md lib/pact_broker/client/version.rb gemfiles
|
12
12
|
$ git commit -m "Releasing version $(ruby -r ./lib/pact_broker/client/version.rb -e "puts PactBroker::Client::VERSION")"
|
13
13
|
|
14
14
|
5. Release:
|
data/Rakefile
CHANGED
@@ -4,9 +4,15 @@ require 'conventional_changelog'
|
|
4
4
|
|
5
5
|
Dir.glob('lib/tasks/**/*.rake').each { |task| load "#{Dir.pwd}/#{task}" }
|
6
6
|
Dir.glob('tasks/**/*.rake').each { |task| load "#{Dir.pwd}/#{task}" }
|
7
|
-
RSpec::Core::RakeTask.new(:spec)
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do | task |
|
8
|
+
task.rspec_opts = "--pattern spec/lib/**/*_spec.rb"
|
9
|
+
end
|
10
|
+
|
11
|
+
RSpec::Core::RakeTask.new('spec:providers') do | task |
|
12
|
+
task.rspec_opts = "--pattern spec/service_providers/**/*_spec.rb"
|
13
|
+
end
|
8
14
|
|
9
|
-
task :default => [:spec]
|
15
|
+
task :default => [:spec, 'spec:providers']
|
10
16
|
|
11
17
|
task :generate_changelog do
|
12
18
|
require 'pact_broker/client/version'
|
data/bin/pact-publish
ADDED
@@ -1,10 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
pact_broker-client (1.
|
4
|
+
pact_broker-client (1.5.0)
|
5
5
|
httparty
|
6
6
|
json
|
7
|
-
pact
|
8
7
|
term-ansicolor
|
9
8
|
|
10
9
|
GEM
|
@@ -18,21 +17,22 @@ GEM
|
|
18
17
|
thor (>= 0.14.0)
|
19
18
|
awesome_print (1.8.0)
|
20
19
|
coderay (1.1.2)
|
20
|
+
conventional-changelog (1.3.0)
|
21
21
|
crack (0.4.3)
|
22
22
|
safe_yaml (~> 1.0.0)
|
23
23
|
diff-lcs (1.3)
|
24
|
-
fakefs (0.11.
|
24
|
+
fakefs (0.11.2)
|
25
25
|
find_a_port (1.0.1)
|
26
26
|
hashdiff (0.3.6)
|
27
27
|
httparty (0.15.6)
|
28
28
|
multi_xml (>= 0.5.2)
|
29
29
|
json (2.1.0)
|
30
|
-
method_source (0.
|
30
|
+
method_source (0.9.0)
|
31
31
|
multi_xml (0.6.0)
|
32
|
-
pact (1.
|
32
|
+
pact (1.16.0)
|
33
33
|
json (> 1.8.5)
|
34
34
|
pact-mock_service (~> 2.0)
|
35
|
-
pact-support (~> 1.1)
|
35
|
+
pact-support (~> 1.1, >= 1.1.8)
|
36
36
|
rack-test (~> 0.6.2)
|
37
37
|
randexp (~> 0.1.7)
|
38
38
|
rspec (>= 2.14)
|
@@ -49,7 +49,7 @@ GEM
|
|
49
49
|
term-ansicolor (~> 1.0)
|
50
50
|
thor
|
51
51
|
webrick
|
52
|
-
pact-support (1.
|
52
|
+
pact-support (1.2.0)
|
53
53
|
awesome_print (~> 1.1)
|
54
54
|
find_a_port (~> 1.0.1)
|
55
55
|
json
|
@@ -58,10 +58,9 @@ GEM
|
|
58
58
|
rspec (>= 2.14)
|
59
59
|
term-ansicolor (~> 1.0)
|
60
60
|
thor
|
61
|
-
pry (0.
|
61
|
+
pry (0.11.1)
|
62
62
|
coderay (~> 1.1.0)
|
63
|
-
method_source (~> 0.
|
64
|
-
slop (~> 3.4)
|
63
|
+
method_source (~> 0.9.0)
|
65
64
|
public_suffix (3.0.0)
|
66
65
|
rack (2.0.3)
|
67
66
|
rack-test (0.6.3)
|
@@ -84,7 +83,6 @@ GEM
|
|
84
83
|
rspec-support (~> 3.6.0)
|
85
84
|
rspec-support (3.6.0)
|
86
85
|
safe_yaml (1.0.4)
|
87
|
-
slop (3.6.0)
|
88
86
|
term-ansicolor (1.6.0)
|
89
87
|
tins (~> 1.0)
|
90
88
|
thor (0.20.0)
|
@@ -100,7 +98,9 @@ PLATFORMS
|
|
100
98
|
|
101
99
|
DEPENDENCIES
|
102
100
|
appraisal
|
101
|
+
conventional-changelog
|
103
102
|
fakefs (~> 0.4)
|
103
|
+
pact (~> 1.16)
|
104
104
|
pact_broker-client!
|
105
105
|
pry
|
106
106
|
rake (~> 10.0.3)
|
@@ -1,10 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
pact_broker-client (1.
|
4
|
+
pact_broker-client (1.5.0)
|
5
5
|
httparty
|
6
6
|
json
|
7
|
-
pact
|
8
7
|
term-ansicolor
|
9
8
|
|
10
9
|
GEM
|
@@ -18,21 +17,22 @@ GEM
|
|
18
17
|
thor (>= 0.14.0)
|
19
18
|
awesome_print (1.8.0)
|
20
19
|
coderay (1.1.2)
|
20
|
+
conventional-changelog (1.3.0)
|
21
21
|
crack (0.4.3)
|
22
22
|
safe_yaml (~> 1.0.0)
|
23
23
|
diff-lcs (1.3)
|
24
|
-
fakefs (0.11.
|
24
|
+
fakefs (0.11.2)
|
25
25
|
find_a_port (1.0.1)
|
26
26
|
hashdiff (0.3.6)
|
27
27
|
httparty (0.15.6)
|
28
28
|
multi_xml (>= 0.5.2)
|
29
29
|
json (2.1.0)
|
30
|
-
method_source (0.
|
30
|
+
method_source (0.9.0)
|
31
31
|
multi_xml (0.6.0)
|
32
|
-
pact (1.
|
32
|
+
pact (1.16.0)
|
33
33
|
json (> 1.8.5)
|
34
34
|
pact-mock_service (~> 2.0)
|
35
|
-
pact-support (~> 1.1)
|
35
|
+
pact-support (~> 1.1, >= 1.1.8)
|
36
36
|
rack-test (~> 0.6.2)
|
37
37
|
randexp (~> 0.1.7)
|
38
38
|
rspec (>= 2.14)
|
@@ -49,7 +49,7 @@ GEM
|
|
49
49
|
term-ansicolor (~> 1.0)
|
50
50
|
thor
|
51
51
|
webrick
|
52
|
-
pact-support (1.
|
52
|
+
pact-support (1.2.0)
|
53
53
|
awesome_print (~> 1.1)
|
54
54
|
find_a_port (~> 1.0.1)
|
55
55
|
json
|
@@ -58,10 +58,9 @@ GEM
|
|
58
58
|
rspec (>= 2.14)
|
59
59
|
term-ansicolor (~> 1.0)
|
60
60
|
thor
|
61
|
-
pry (0.
|
61
|
+
pry (0.11.1)
|
62
62
|
coderay (~> 1.1.0)
|
63
|
-
method_source (~> 0.
|
64
|
-
slop (~> 3.4)
|
63
|
+
method_source (~> 0.9.0)
|
65
64
|
public_suffix (3.0.0)
|
66
65
|
rack (1.6.8)
|
67
66
|
rack-test (0.6.3)
|
@@ -84,7 +83,6 @@ GEM
|
|
84
83
|
rspec-support (~> 3.6.0)
|
85
84
|
rspec-support (3.6.0)
|
86
85
|
safe_yaml (1.0.4)
|
87
|
-
slop (3.6.0)
|
88
86
|
term-ansicolor (1.6.0)
|
89
87
|
tins (~> 1.0)
|
90
88
|
thor (0.20.0)
|
@@ -100,7 +98,9 @@ PLATFORMS
|
|
100
98
|
|
101
99
|
DEPENDENCIES
|
102
100
|
appraisal
|
101
|
+
conventional-changelog
|
103
102
|
fakefs (~> 0.4)
|
103
|
+
pact (~> 1.16)
|
104
104
|
pact_broker-client!
|
105
105
|
pry
|
106
106
|
rack (< 2.0)
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Client
|
5
|
+
module CLI
|
6
|
+
##
|
7
|
+
# Custom Thor task allows the following:
|
8
|
+
#
|
9
|
+
# `script arg1 arg2` to be interpreted as `script <default_task> arg1 arg2`
|
10
|
+
# `--option 1 --option 2` to be interpreted as `--option 1 2` (the standard Thor format for multiple value options)
|
11
|
+
# `script --help` to display the help for the default task instead of the command list
|
12
|
+
#
|
13
|
+
class CustomThor < ::Thor
|
14
|
+
|
15
|
+
no_commands do
|
16
|
+
def self.start given_args = ARGV, config = {}
|
17
|
+
super(massage_args(given_args))
|
18
|
+
end
|
19
|
+
|
20
|
+
def help *args
|
21
|
+
if args.empty?
|
22
|
+
super(self.class.default_task)
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.massage_args argv
|
29
|
+
prepend_default_task_name(turn_muliple_tag_options_into_array(argv))
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.prepend_default_task_name argv
|
33
|
+
if known_first_arguments.include?(argv[0])
|
34
|
+
argv
|
35
|
+
else
|
36
|
+
[default_command] + argv
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# other task names, help, and the help shortcuts
|
41
|
+
def self.known_first_arguments
|
42
|
+
@known_first_arguments ||= tasks.keys + ::Thor::HELP_MAPPINGS + ['help']
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.turn_muliple_tag_options_into_array argv
|
46
|
+
new_argv = []
|
47
|
+
opt_name = nil
|
48
|
+
argv.each_with_index do | arg, i |
|
49
|
+
if arg.start_with?('-')
|
50
|
+
opt_name = arg
|
51
|
+
existing = new_argv.find { | a | a.first == opt_name }
|
52
|
+
if !existing
|
53
|
+
new_argv << [arg]
|
54
|
+
end
|
55
|
+
else
|
56
|
+
if opt_name
|
57
|
+
existing = new_argv.find { | a | a.first == opt_name }
|
58
|
+
existing << arg
|
59
|
+
opt_name = nil
|
60
|
+
else
|
61
|
+
new_argv << [arg]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
new_argv.flatten
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'pact_broker/client/cli/custom_thor'
|
2
|
+
require 'pact_broker/client/publish_pacts'
|
3
|
+
require 'pact_broker/client/version'
|
4
|
+
require 'rake/file_list'
|
5
|
+
|
6
|
+
module PactBroker
|
7
|
+
module Client
|
8
|
+
module CLI
|
9
|
+
|
10
|
+
# Thor::Error will have its backtrace hidden
|
11
|
+
class PactPublicationError < ::Thor::Error; end
|
12
|
+
|
13
|
+
class Publish < CustomThor
|
14
|
+
desc 'PACT_DIRS_OR_FILES ...', "Publish pacts to a Pact Broker."
|
15
|
+
method_option :consumer_version, required: true, aliases: "-v", desc: "The consumer application version"
|
16
|
+
method_option :broker_base_url, required: true, aliases: "-b", desc: "The base URL of the Pact Broker"
|
17
|
+
method_option :username, aliases: "-u", desc: "Basic auth username for Pact Broker"
|
18
|
+
method_option :password, aliases: "-p", desc: "Basic auth password for Pact Broker"
|
19
|
+
method_option :tag, aliases: "-t", type: :array, banner: "TAG", desc: "Tag name for consumer version. Can be specified multiple times."
|
20
|
+
|
21
|
+
def broker(*pact_files)
|
22
|
+
validate(pact_files)
|
23
|
+
success = publish_pacts(pact_files)
|
24
|
+
raise PactPublicationError, "One or more pacts failed to be published" unless success
|
25
|
+
rescue PactBroker::Client::Error => e
|
26
|
+
raise PactPublicationError, "#{e.class} - #{e.message}"
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'version', "Show the pact_broker-client gem version"
|
30
|
+
def version
|
31
|
+
$stdout.puts PactBroker::Client::VERSION
|
32
|
+
end
|
33
|
+
|
34
|
+
default_task :broker
|
35
|
+
|
36
|
+
no_commands do
|
37
|
+
|
38
|
+
def validate pact_files
|
39
|
+
unless pact_files && pact_files.any?
|
40
|
+
raise RequiredArgumentMissingError, "No value provided for required pact_files"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def publish_pacts pact_files
|
45
|
+
PactBroker::Client::PublishPacts.call(
|
46
|
+
options[:broker_base_url],
|
47
|
+
file_list(pact_files),
|
48
|
+
options[:consumer_version],
|
49
|
+
tags,
|
50
|
+
pact_broker_client_options
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
def file_list pact_files
|
55
|
+
Rake::FileList[pact_files].collect do | path |
|
56
|
+
if File.directory?(path)
|
57
|
+
Rake::FileList[File.join(path, "*.json")]
|
58
|
+
else
|
59
|
+
path
|
60
|
+
end
|
61
|
+
end.flatten
|
62
|
+
end
|
63
|
+
|
64
|
+
def tags
|
65
|
+
[*options[:tag]].compact
|
66
|
+
end
|
67
|
+
|
68
|
+
def pact_broker_client_options
|
69
|
+
if options[:username]
|
70
|
+
{
|
71
|
+
username: options[:username],
|
72
|
+
password: options[:password]
|
73
|
+
}
|
74
|
+
else
|
75
|
+
{}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'pact_broker/client/error'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Client
|
6
|
+
|
7
|
+
class PactMergeError < PactBroker::Client::Error; end
|
8
|
+
|
9
|
+
module MergePacts
|
10
|
+
extend self
|
11
|
+
|
12
|
+
def call pact_hashes
|
13
|
+
pact_hashes.reduce{|p1, p2| merge(p1, p2) }
|
14
|
+
end
|
15
|
+
|
16
|
+
# Accepts two hashes representing pacts, outputs a merged hash
|
17
|
+
# Does not make any guarantees about order of interactions
|
18
|
+
def merge original, additional
|
19
|
+
new_pact = JSON.parse(original.to_json, symbolize_names: true)
|
20
|
+
|
21
|
+
additional[:interactions].each do |new_interaction|
|
22
|
+
# check to see if this interaction matches an existing interaction
|
23
|
+
overwrite_index = original[:interactions].find_index do |original_interaction|
|
24
|
+
same_description_and_state?(original_interaction, new_interaction)
|
25
|
+
end
|
26
|
+
|
27
|
+
# overwrite existing interaction if a match is found, otherwise appends the new interaction
|
28
|
+
if overwrite_index
|
29
|
+
if new_interaction == original[:interactions][overwrite_index]
|
30
|
+
new_pact[:interactions][overwrite_index] = new_interaction
|
31
|
+
else
|
32
|
+
raise PactMergeError, almost_duplicate_message(original[:interactions][overwrite_index], new_interaction)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
new_pact[:interactions] << new_interaction
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
new_pact
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def almost_duplicate_message(original, new_interaction)
|
45
|
+
"An interaction with same description (#{new_interaction[:description].inspect}) and provider state (#{new_interaction[:providerState].inspect}) but a different request or response has already been used. " +
|
46
|
+
"Please use a different description or provider state, or hard-code any random data.\n" +
|
47
|
+
original.to_json + "\n\n"
|
48
|
+
new_interaction.to_json
|
49
|
+
end
|
50
|
+
|
51
|
+
def same_description_and_state? original, additional
|
52
|
+
original[:description] == additional[:description] &&
|
53
|
+
original[:providerState] == additional[:providerState]
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'pact_broker/client/pact_hash'
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Client
|
6
|
+
class PactFile
|
7
|
+
def initialize path
|
8
|
+
@path = path
|
9
|
+
end
|
10
|
+
|
11
|
+
def path
|
12
|
+
@path
|
13
|
+
end
|
14
|
+
|
15
|
+
def pact_name
|
16
|
+
pact_hash.pact_name
|
17
|
+
end
|
18
|
+
|
19
|
+
def consumer_name
|
20
|
+
pact_hash.consumer_name
|
21
|
+
end
|
22
|
+
|
23
|
+
def provider_name
|
24
|
+
pact_hash.provider_name
|
25
|
+
end
|
26
|
+
|
27
|
+
def pact_hash
|
28
|
+
@pact_hash ||= PactHash[JSON.parse(read, symbolize_names: true)]
|
29
|
+
end
|
30
|
+
|
31
|
+
def read
|
32
|
+
@read ||= File.read(@path)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Client
|
5
|
+
class PactHash < ::Hash
|
6
|
+
def pact_name
|
7
|
+
"#{consumer_name}/#{provider_name} pact"
|
8
|
+
end
|
9
|
+
|
10
|
+
def consumer_name
|
11
|
+
self[:consumer][:name]
|
12
|
+
end
|
13
|
+
|
14
|
+
def provider_name
|
15
|
+
self[:provider][:name]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,6 +1,5 @@
|
|
1
|
-
require 'pact/consumer_contract'
|
2
1
|
require_relative 'base_client'
|
3
|
-
|
2
|
+
require 'pact_broker/client/pact_hash'
|
4
3
|
|
5
4
|
module PactBroker
|
6
5
|
module Client
|
@@ -8,9 +7,9 @@ module PactBroker
|
|
8
7
|
|
9
8
|
def publish options
|
10
9
|
consumer_version = options[:consumer_version]
|
11
|
-
|
12
|
-
|
13
|
-
url = save_consumer_contract_url
|
10
|
+
pact_hash = options[:pact_hash]
|
11
|
+
pact_string = pact_hash.to_json
|
12
|
+
url = save_consumer_contract_url pact_hash, consumer_version
|
14
13
|
|
15
14
|
if @client_options[:write] == :merge
|
16
15
|
response = self.class.patch(url, body: pact_string, headers: default_patch_headers)
|
@@ -128,9 +127,9 @@ module PactBroker
|
|
128
127
|
"/pacts/provider/#{provider_name}/consumer/#{consumer_name}/version/#{consumer_version}"
|
129
128
|
end
|
130
129
|
|
131
|
-
def save_consumer_contract_url
|
132
|
-
consumer_name = encode_param(
|
133
|
-
provider_name = encode_param(
|
130
|
+
def save_consumer_contract_url pact_hash, consumer_version
|
131
|
+
consumer_name = encode_param(pact_hash.consumer_name)
|
132
|
+
provider_name = encode_param(pact_hash.provider_name)
|
134
133
|
version = encode_param(consumer_version)
|
135
134
|
"/pacts/provider/#{provider_name}/consumer/#{consumer_name}/version/#{version}"
|
136
135
|
end
|
@@ -1,14 +1,21 @@
|
|
1
1
|
require 'term/ansicolor'
|
2
2
|
require 'pact_broker/client'
|
3
3
|
require 'pact_broker/client/retry'
|
4
|
+
require 'pact_broker/client/pact_file'
|
5
|
+
require 'pact_broker/client/pact_hash'
|
6
|
+
require 'pact_broker/client/merge_pacts'
|
4
7
|
|
5
8
|
module PactBroker
|
6
9
|
module Client
|
7
10
|
class PublishPacts
|
8
11
|
|
9
|
-
def
|
12
|
+
def self.call(pact_broker_base_url, pact_file_paths, consumer_version, tags, pact_broker_client_options={})
|
13
|
+
new(pact_broker_base_url, pact_file_paths, consumer_version, tags, pact_broker_client_options).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize pact_broker_base_url, pact_file_paths, consumer_version, tags, pact_broker_client_options={}
|
10
17
|
@pact_broker_base_url = pact_broker_base_url
|
11
|
-
@
|
18
|
+
@pact_file_paths = pact_file_paths
|
12
19
|
@consumer_version = consumer_version
|
13
20
|
@tags = tags
|
14
21
|
@pact_broker_client_options = pact_broker_client_options
|
@@ -24,22 +31,33 @@ module PactBroker
|
|
24
31
|
|
25
32
|
private
|
26
33
|
|
27
|
-
attr_reader :pact_broker_base_url, :
|
34
|
+
attr_reader :pact_broker_base_url, :pact_file_paths, :consumer_version, :tags, :pact_broker_client_options
|
28
35
|
|
29
36
|
def pact_broker_client
|
30
37
|
@pact_broker_client ||= PactBroker::Client::PactBrokerClient.new(base_url: pact_broker_base_url, client_options: pact_broker_client_options)
|
31
38
|
end
|
32
39
|
|
33
40
|
def publish_pacts
|
34
|
-
pact_files.collect
|
41
|
+
pact_files.group_by(&:pact_name).collect do | pact_name, pact_files |
|
42
|
+
$stdout.puts "Merging #{pact_files.collect(&:path).join(", ")}" if pact_files.size > 1
|
43
|
+
publish_pact(PactHash[merge_contents(pact_files)])
|
44
|
+
end.all?
|
35
45
|
end
|
36
46
|
|
37
|
-
def
|
47
|
+
def merge_contents(pact_files)
|
48
|
+
MergePacts.call(pact_files.collect(&:pact_hash))
|
49
|
+
end
|
50
|
+
|
51
|
+
def pact_files
|
52
|
+
@pact_files ||= pact_file_paths.collect{ |pact_file_path| PactFile.new(pact_file_path) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def publish_pact pact
|
38
56
|
begin
|
39
|
-
$stdout.puts "
|
40
|
-
publish_pact_contents
|
57
|
+
$stdout.puts "Publishing #{pact.pact_name} to pact broker at #{pact_broker_base_url}"
|
58
|
+
publish_pact_contents pact
|
41
59
|
rescue => e
|
42
|
-
$stderr.puts "Failed to publish
|
60
|
+
$stderr.puts "Failed to publish #{pact.pact_name} due to error: #{e.class} - #{e}"
|
43
61
|
false
|
44
62
|
end
|
45
63
|
end
|
@@ -59,38 +77,32 @@ module PactBroker
|
|
59
77
|
true
|
60
78
|
end
|
61
79
|
rescue => e
|
62
|
-
$stderr.puts "Failed to tag version #{consumer_version} of #{consumer_name} due to error: #{e.
|
80
|
+
$stderr.puts "Failed to tag version #{consumer_version} of #{consumer_name} due to error: #{e.class} - #{e}}"
|
63
81
|
false
|
64
82
|
end
|
65
83
|
|
66
|
-
def publish_pact_contents(
|
84
|
+
def publish_pact_contents(pact)
|
67
85
|
Retry.until_true do
|
68
|
-
contract = contract_from_file(pact_file_contents)
|
69
86
|
pacts = pact_broker_client.pacticipants.versions.pacts
|
70
|
-
if pacts.version_published?(consumer:
|
71
|
-
$stdout.puts ::Term::ANSIColor.yellow("The given version of pact is already published.
|
87
|
+
if pacts.version_published?(consumer: pact.consumer_name, provider: pact.provider_name, consumer_version: consumer_version)
|
88
|
+
$stdout.puts ::Term::ANSIColor.yellow("The given version of pact is already published. Overwriting...")
|
72
89
|
end
|
73
90
|
|
74
|
-
latest_pact_url = pacts.publish(
|
91
|
+
latest_pact_url = pacts.publish(pact_hash: pact, consumer_version: consumer_version)
|
75
92
|
$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}"
|
76
93
|
true
|
77
94
|
end
|
78
95
|
end
|
79
96
|
|
80
97
|
def consumer_name
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
def contract_from_file pact_file_contents
|
85
|
-
::Pact::ConsumerContract.from_json(pact_file_contents)
|
98
|
+
pact_files.first.consumer_name
|
86
99
|
end
|
87
100
|
|
88
101
|
def validate
|
89
|
-
raise "Please specify the consumer_version" unless (consumer_version && consumer_version.to_s.strip.size > 0)
|
90
|
-
raise "Please specify the pact_broker_base_url" unless (pact_broker_base_url && pact_broker_base_url.to_s.strip.size > 0)
|
91
|
-
raise "No pact files found" unless (
|
102
|
+
raise PactBroker::Client::Error.new("Please specify the consumer_version") unless (consumer_version && consumer_version.to_s.strip.size > 0)
|
103
|
+
raise PactBroker::Client::Error.new("Please specify the pact_broker_base_url") unless (pact_broker_base_url && pact_broker_base_url.to_s.strip.size > 0)
|
104
|
+
raise PactBroker::Client::Error.new("No pact files found") unless (pact_file_paths && pact_file_paths.any?)
|
92
105
|
end
|
93
|
-
|
94
106
|
end
|
95
107
|
end
|
96
108
|
end
|
data/pact-broker-client.gemspec
CHANGED
@@ -21,7 +21,6 @@ Gem::Specification.new do |gem|
|
|
21
21
|
gem.require_paths = ["lib"]
|
22
22
|
gem.license = 'MIT'
|
23
23
|
|
24
|
-
gem.add_runtime_dependency 'pact'
|
25
24
|
gem.add_runtime_dependency 'httparty'
|
26
25
|
gem.add_runtime_dependency 'json'
|
27
26
|
gem.add_runtime_dependency 'term-ansicolor'
|
@@ -32,4 +31,5 @@ Gem::Specification.new do |gem|
|
|
32
31
|
gem.add_development_dependency 'appraisal'
|
33
32
|
gem.add_development_dependency 'webmock', '~> 3.0'
|
34
33
|
gem.add_development_dependency 'conventional-changelog'
|
34
|
+
gem.add_development_dependency 'pact', '~> 1.16'
|
35
35
|
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'pact_broker/client/cli/custom_thor'
|
2
|
+
|
3
|
+
module PactBroker::Client::CLI
|
4
|
+
|
5
|
+
class Delegate
|
6
|
+
def self.call options; end
|
7
|
+
end
|
8
|
+
|
9
|
+
class TestThor < CustomThor
|
10
|
+
desc 'ARGUMENT', 'This is the description'
|
11
|
+
def test_default(argument)
|
12
|
+
Delegate.call(argument: argument)
|
13
|
+
end
|
14
|
+
|
15
|
+
desc '', ''
|
16
|
+
method_option :multi, type: :array
|
17
|
+
def test_multiple_options
|
18
|
+
Delegate.call(options)
|
19
|
+
end
|
20
|
+
|
21
|
+
default_command :test_default
|
22
|
+
end
|
23
|
+
|
24
|
+
describe CustomThor do
|
25
|
+
subject { TestThor.new }
|
26
|
+
|
27
|
+
it "invokes the default task when aguments are given without specifying a task" do
|
28
|
+
expect(Delegate).to receive(:call).with(argument: 'foo')
|
29
|
+
TestThor.start(%w{foo})
|
30
|
+
end
|
31
|
+
|
32
|
+
it "converts options that are specified multiple times into a single array" do
|
33
|
+
expect(Delegate).to receive(:call).with({'multi' => ['one', 'two']})
|
34
|
+
TestThor.start(%w{test_multiple_options --multi one --multi two})
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".prepend_default_task_name" do
|
38
|
+
let(:argv_with) { [TestThor.default_command, 'foo'] }
|
39
|
+
|
40
|
+
context "when the default task name is given" do
|
41
|
+
it "does not prepend the default task name" do
|
42
|
+
expect(TestThor.prepend_default_task_name(argv_with)).to eq(argv_with)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "when the first argument is --help" do
|
47
|
+
let(:argv) { ['--help', 'foo'] }
|
48
|
+
|
49
|
+
it "does not prepend the default task name" do
|
50
|
+
expect(TestThor.prepend_default_task_name(argv)).to eq(argv)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when the default task name is not given" do
|
55
|
+
let(:argv) { ['foo'] }
|
56
|
+
|
57
|
+
it "prepends the default task name" do
|
58
|
+
expect(TestThor.prepend_default_task_name(argv)).to eq(argv_with)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe ".turn_muliple_tag_options_into_array" do
|
64
|
+
it "turns '--tag foo --tag bar' into '--tag foo bar'" do
|
65
|
+
input = %w{--ignore this --tag foo --tag bar --wiffle --that}
|
66
|
+
output = %w{--ignore this --tag foo bar --wiffle --that }
|
67
|
+
expect(TestThor.turn_muliple_tag_options_into_array(input)).to eq output
|
68
|
+
end
|
69
|
+
|
70
|
+
it "turns '--tag foo bar --tag meep' into '--tag foo meep bar'" do
|
71
|
+
input = %w{--ignore this --tag foo bar --tag meep --wiffle --that}
|
72
|
+
output = %w{--ignore this --tag foo meep bar --wiffle --that}
|
73
|
+
expect(TestThor.turn_muliple_tag_options_into_array(input)).to eq output
|
74
|
+
end
|
75
|
+
|
76
|
+
it "turns '--tag foo --tag bar wiffle' into '--tag foo bar wiffle' which is silly" do
|
77
|
+
input = %w{--ignore this --tag foo --tag bar wiffle}
|
78
|
+
output = %w{--ignore this --tag foo bar wiffle}
|
79
|
+
expect(TestThor.turn_muliple_tag_options_into_array(input)).to eq output
|
80
|
+
end
|
81
|
+
|
82
|
+
it "maintains '--tag foo bar wiffle'" do
|
83
|
+
input = %w{--ignore this --tag foo bar wiffle --meep}
|
84
|
+
output = %w{--ignore this --tag foo bar wiffle --meep}
|
85
|
+
expect(TestThor.turn_muliple_tag_options_into_array(input)).to eq output
|
86
|
+
end
|
87
|
+
|
88
|
+
it "turns '-t foo -t bar' into '-t foo bar'" do
|
89
|
+
input = %w{--ignore this -t foo -t bar --meep --that 1 2 3}
|
90
|
+
output = %w{--ignore this -t foo bar --meep --that 1 2 3}
|
91
|
+
expect(TestThor.turn_muliple_tag_options_into_array(input)).to eq output
|
92
|
+
end
|
93
|
+
|
94
|
+
it "doesn't change anything when there are no duplicate options" do
|
95
|
+
input = %w{--ignore this --taggy foo --blah bar --wiffle --that}
|
96
|
+
expect(TestThor.turn_muliple_tag_options_into_array(input)).to eq input
|
97
|
+
end
|
98
|
+
|
99
|
+
it "return an empty array when given an empty array" do
|
100
|
+
input = []
|
101
|
+
expect(TestThor.turn_muliple_tag_options_into_array(input)).to eq input
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'pact_broker/client/cli/publish'
|
2
|
+
|
3
|
+
module PactBroker::Client::CLI
|
4
|
+
describe Publish do
|
5
|
+
describe ".broker" do
|
6
|
+
before do
|
7
|
+
allow(PactBroker::Client::PublishPacts).to receive(:call).and_return(true)
|
8
|
+
subject.options = minimum_valid_options
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:file_list) { ["spec/support/cli_test_pacts/foo.json"] }
|
12
|
+
let(:minimum_valid_options) do
|
13
|
+
{
|
14
|
+
pact_dir: 'spec/pacts',
|
15
|
+
consumer_version: '1.2.3',
|
16
|
+
broker_base_url: 'http://pact-broker'
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:invoke_broker) { subject.broker(*file_list) }
|
21
|
+
|
22
|
+
context "with minimum valid options" do
|
23
|
+
it "invokes the PublishPacts command" do
|
24
|
+
expect(PactBroker::Client::PublishPacts).to receive(:call).with(
|
25
|
+
"http://pact-broker",
|
26
|
+
["spec/support/cli_test_pacts/foo.json"],
|
27
|
+
"1.2.3",
|
28
|
+
[],
|
29
|
+
{}
|
30
|
+
)
|
31
|
+
invoke_broker
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "with a file pattern specified" do
|
36
|
+
let(:file_list) { ["spec/support/cli_test_pacts/*.json"] }
|
37
|
+
|
38
|
+
it "invokes the PublishPacts command with the expanded list of files" do
|
39
|
+
expect(PactBroker::Client::PublishPacts).to receive(:call).with(
|
40
|
+
anything,
|
41
|
+
["spec/support/cli_test_pacts/bar.json", "spec/support/cli_test_pacts/foo.json"],
|
42
|
+
anything,
|
43
|
+
anything,
|
44
|
+
anything
|
45
|
+
)
|
46
|
+
invoke_broker
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "with a pact directory specified" do
|
51
|
+
let(:file_list) { ["spec/support/cli_test_pacts"] }
|
52
|
+
|
53
|
+
it "invokes the PublishPacts command with the list of files in the directory" do
|
54
|
+
expect(PactBroker::Client::PublishPacts).to receive(:call).with(
|
55
|
+
anything,
|
56
|
+
["spec/support/cli_test_pacts/bar.json", "spec/support/cli_test_pacts/foo.json"],
|
57
|
+
anything,
|
58
|
+
anything,
|
59
|
+
anything
|
60
|
+
)
|
61
|
+
invoke_broker
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "with a tag" do
|
66
|
+
before do
|
67
|
+
subject.options = minimum_valid_options.merge(tag: ['foo'])
|
68
|
+
end
|
69
|
+
|
70
|
+
it "passes in the tag" do
|
71
|
+
expect(PactBroker::Client::PublishPacts).to receive(:call).with(
|
72
|
+
anything,
|
73
|
+
anything,
|
74
|
+
anything,
|
75
|
+
['foo'],
|
76
|
+
anything
|
77
|
+
)
|
78
|
+
invoke_broker
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "with basic auth options specified" do
|
83
|
+
before do
|
84
|
+
subject.options = minimum_valid_options.merge(username: 'foo', password: 'bar')
|
85
|
+
end
|
86
|
+
|
87
|
+
it "passes in the basic auth options" do
|
88
|
+
expect(PactBroker::Client::PublishPacts).to receive(:call).with(
|
89
|
+
anything,
|
90
|
+
anything,
|
91
|
+
anything,
|
92
|
+
anything,
|
93
|
+
{username: 'foo', password: 'bar'}
|
94
|
+
)
|
95
|
+
invoke_broker
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when no pact files are specified" do
|
100
|
+
let(:file_list) { [] }
|
101
|
+
|
102
|
+
it "raises an error" do
|
103
|
+
expect { invoke_broker }.to raise_error ::Thor::RequiredArgumentMissingError, "No value provided for required pact_files"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context "when an error is raised publishing" do
|
108
|
+
before do
|
109
|
+
allow(PactBroker::Client::PublishPacts).to receive(:call).and_raise(PactBroker::Client::Error.new('foo'))
|
110
|
+
end
|
111
|
+
|
112
|
+
it "raises a PactPublicationError" do
|
113
|
+
expect { invoke_broker }.to raise_error PactPublicationError, /foo/
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "when the publish command is not successful" do
|
118
|
+
before do
|
119
|
+
allow(PactBroker::Client::PublishPacts).to receive(:call).and_return(false)
|
120
|
+
end
|
121
|
+
|
122
|
+
it "raises a PactPublicationError" do
|
123
|
+
expect { invoke_broker }.to raise_error PactPublicationError
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'pact_broker/client/merge_pacts'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Client
|
5
|
+
describe MergePacts do
|
6
|
+
describe ".call" do
|
7
|
+
let(:pact_hash_1) do
|
8
|
+
{
|
9
|
+
other: 'info',
|
10
|
+
interactions: [
|
11
|
+
{providerState: 1, description: 1, foo: 'bar' }
|
12
|
+
]
|
13
|
+
}
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:pact_hash_2) do
|
17
|
+
{
|
18
|
+
interactions: [
|
19
|
+
{providerState: 2, description: 2, foo: 'wiffle' }
|
20
|
+
]
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:pact_hash_3) do
|
25
|
+
{
|
26
|
+
interactions: [
|
27
|
+
{providerState: 3, description: 3, foo: 'meep' },
|
28
|
+
{providerState: 1, description: 1, foo: 'bar' }
|
29
|
+
]
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:pact_hashes) { [pact_hash_1, pact_hash_2, pact_hash_3] }
|
34
|
+
|
35
|
+
let(:expected_merge) do
|
36
|
+
{
|
37
|
+
other: 'info',
|
38
|
+
interactions: [
|
39
|
+
{providerState: 1, description: 1, foo: 'bar' },
|
40
|
+
{providerState: 2, description: 2, foo: 'wiffle' },
|
41
|
+
{providerState: 3, description: 3, foo: 'meep' }
|
42
|
+
]
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
subject { MergePacts.call(pact_hashes) }
|
47
|
+
|
48
|
+
it "merges the interactions by consumer/provider" do
|
49
|
+
expect(subject).to eq expected_merge
|
50
|
+
end
|
51
|
+
|
52
|
+
context "when an interaction is found with the same state and description but has a difference elsewhere" do
|
53
|
+
let(:pact_hash_3) do
|
54
|
+
{
|
55
|
+
interactions: [
|
56
|
+
{providerState: 3, description: 3, foo: 'meep' },
|
57
|
+
{providerState: 1, description: 1, foo: 'different' }
|
58
|
+
]
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
it "raises an error" do
|
63
|
+
expect { subject }.to raise_error PactMergeError
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -7,11 +7,24 @@ module PactBroker
|
|
7
7
|
module Client
|
8
8
|
describe PublishPacts do
|
9
9
|
|
10
|
+
# The amount of stubbing that we have to do here indicates this class is doing
|
11
|
+
# TOO MUCH and needs to be split up!
|
10
12
|
before do
|
11
13
|
FakeFS.activate!
|
12
14
|
allow(pacts_client).to receive(:publish).and_return(latest_pact_url)
|
13
|
-
allow(PactBroker::Client::PactBrokerClient).to receive(:new)
|
15
|
+
allow(PactBroker::Client::PactBrokerClient).to receive(:new)
|
16
|
+
.with(base_url: pact_broker_base_url, client_options: pact_broker_client_options)
|
17
|
+
.and_return(pact_broker_client)
|
18
|
+
allow(pact_broker_client).to receive_message_chain(:pacticipants, :versions).and_return(pact_versions_client)
|
19
|
+
allow(pact_broker_client).to receive_message_chain(:pacticipants, :versions, :pacts).and_return(pacts_client)
|
20
|
+
allow(pacts_client).to receive(:version_published?).and_return(false)
|
14
21
|
allow($stdout).to receive(:puts)
|
22
|
+
allow(Retry).to receive(:sleep)
|
23
|
+
allow(MergePacts).to receive(:call) { | pact_hashes | pact_hashes[0] }
|
24
|
+
FileUtils.mkdir_p "spec/pacts"
|
25
|
+
File.open("spec/pacts/consumer-provider.json", "w") { |file| file << pact_hash.to_json }
|
26
|
+
File.open("spec/pacts/consumer-provider-2.json", "w") { |file| file << pact_hash.to_json }
|
27
|
+
File.open("spec/pacts/foo-bar.json", "w") { |file| file << pact_hash_2.to_json }
|
15
28
|
end
|
16
29
|
|
17
30
|
after do
|
@@ -20,10 +33,11 @@ module PactBroker
|
|
20
33
|
|
21
34
|
let(:latest_pact_url) { 'http://example.org/latest/pact' }
|
22
35
|
let(:pact_broker_client) { double("PactBroker::Client")}
|
23
|
-
let(:
|
36
|
+
let(:pact_file_paths) { ['spec/pacts/consumer-provider.json']}
|
24
37
|
let(:consumer_version) { "1.2.3" }
|
25
38
|
let(:tags) { nil }
|
26
39
|
let(:pact_hash) { {consumer: {name: 'Consumer'}, provider: {name: 'Provider'}, interactions: [] } }
|
40
|
+
let(:pact_hash_2) { {consumer: {name: 'Foo'}, provider: {name: 'Bar'}, interactions: [] } }
|
27
41
|
let(:pacts_client) { instance_double("PactBroker::ClientSupport::Pacts")}
|
28
42
|
let(:pact_versions_client) { instance_double("PactBroker::Client::Versions", tag: false) }
|
29
43
|
let(:pact_broker_base_url) { 'http://some-host'}
|
@@ -36,20 +50,12 @@ module PactBroker
|
|
36
50
|
}
|
37
51
|
end
|
38
52
|
|
39
|
-
subject { PublishPacts.new(pact_broker_base_url,
|
40
|
-
|
41
|
-
before do
|
42
|
-
FileUtils.mkdir_p "spec/pacts"
|
43
|
-
File.open("spec/pacts/consumer-provider.json", "w") { |file| file << pact_hash.to_json }
|
44
|
-
allow(pact_broker_client).to receive_message_chain(:pacticipants, :versions).and_return(pact_versions_client)
|
45
|
-
allow(pact_broker_client).to receive_message_chain(:pacticipants, :versions, :pacts).and_return(pacts_client)
|
46
|
-
allow(pacts_client).to receive(:version_published?).and_return(false)
|
47
|
-
end
|
53
|
+
subject { PublishPacts.new(pact_broker_base_url, pact_file_paths, consumer_version, tags, pact_broker_client_options) }
|
48
54
|
|
49
55
|
describe "call" do
|
50
56
|
|
51
57
|
it "uses the pact_broker client to publish the given pact" do
|
52
|
-
expect(pacts_client).to receive(:publish).with(
|
58
|
+
expect(pacts_client).to receive(:publish).with(pact_hash: pact_hash, consumer_version: consumer_version)
|
53
59
|
subject.call
|
54
60
|
end
|
55
61
|
|
@@ -65,20 +71,34 @@ module PactBroker
|
|
65
71
|
end
|
66
72
|
end
|
67
73
|
|
74
|
+
context "when publishing multiple files with the same consumer/provider" do
|
75
|
+
let(:pact_file_paths) { ['spec/pacts/consumer-provider.json','spec/pacts/consumer-provider-2.json']}
|
76
|
+
it "merges the files" do
|
77
|
+
expect(MergePacts).to receive(:call).with([pact_hash, pact_hash])
|
78
|
+
subject.call
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
68
82
|
context "when publishing one or more pacts fails" do
|
69
|
-
let(:
|
83
|
+
let(:pact_file_paths) { ['spec/pacts/consumer-provider.json','spec/pacts/foo-bar.json']}
|
70
84
|
|
71
85
|
before do
|
86
|
+
allow(pacts_client).to receive(:publish).with(
|
87
|
+
pact_hash: pact_hash,
|
88
|
+
consumer_version: consumer_version
|
89
|
+
).and_raise("an error")
|
90
|
+
|
72
91
|
allow($stderr).to receive(:puts)
|
73
92
|
end
|
74
93
|
|
75
94
|
it "logs an message to stderr" do
|
76
|
-
expect($stderr).to receive(:puts).with(/Failed to publish pact/)
|
95
|
+
expect($stderr).to receive(:puts).with(/Failed to publish Consumer\/Provider pact/)
|
77
96
|
subject.call
|
78
97
|
end
|
79
98
|
|
80
99
|
it "continues publishing the rest" do
|
81
|
-
expect(pacts_client).to receive(:publish).with(
|
100
|
+
expect(pacts_client).to receive(:publish).with(
|
101
|
+
pact_hash: pact_hash_2, consumer_version: consumer_version)
|
82
102
|
subject.call
|
83
103
|
end
|
84
104
|
|
@@ -88,7 +108,7 @@ module PactBroker
|
|
88
108
|
end
|
89
109
|
|
90
110
|
context "when no pact files are specified" do
|
91
|
-
let(:
|
111
|
+
let(:pact_file_paths) { [] }
|
92
112
|
it "raises a validation error" do
|
93
113
|
expect { subject.call }.to raise_error(/No pact files found/)
|
94
114
|
end
|
@@ -112,7 +132,8 @@ module PactBroker
|
|
112
132
|
let(:tags) { ["dev"] }
|
113
133
|
|
114
134
|
it "tags the consumer version" do
|
115
|
-
expect(pact_versions_client).to receive(:tag).with({pacticipant: "Consumer",
|
135
|
+
expect(pact_versions_client).to receive(:tag).with({pacticipant: "Consumer",
|
136
|
+
version: consumer_version, tag: "dev"})
|
116
137
|
subject.call
|
117
138
|
end
|
118
139
|
|
@@ -5,7 +5,7 @@ module PactBroker::Client
|
|
5
5
|
|
6
6
|
describe "publishing a pact" do
|
7
7
|
|
8
|
-
let(:options) { {
|
8
|
+
let(:options) { { pact_hash: pact_hash, consumer_version: consumer_version }}
|
9
9
|
let(:location) { 'http://example.org/pacts/provider/Pricing%20Service/consumer/Condor/latest' }
|
10
10
|
context "when the provider already exists in the pact-broker" do
|
11
11
|
|
File without changes
|
File without changes
|
@@ -1,6 +1,7 @@
|
|
1
|
+
require 'pact_broker/client/pact_hash'
|
1
2
|
shared_context "pact broker" do
|
2
3
|
|
3
|
-
let(:pact_hash) {
|
4
|
+
let(:pact_hash) { PactBroker::Client::PactHash[consumer: {name: 'Condor'}, provider: {name: 'Pricing Service'}, interactions: []] }
|
4
5
|
let(:consumer_contract) { Pact::ConsumerContract.from_hash pact_hash }
|
5
6
|
let(:pact_json) { pact_hash.to_json }
|
6
7
|
let(:pact_broker_client) { PactBroker::Client::PactBrokerClient.new(client_config) }
|
metadata
CHANGED
@@ -1,29 +1,15 @@
|
|
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.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bethany Skurrie
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-09-
|
11
|
+
date: 2017-09-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
-
- !ruby/object:Gem::Dependency
|
14
|
-
name: pact
|
15
|
-
requirement: !ruby/object:Gem::Requirement
|
16
|
-
requirements:
|
17
|
-
- - ">="
|
18
|
-
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
20
|
-
type: :runtime
|
21
|
-
prerelease: false
|
22
|
-
version_requirements: !ruby/object:Gem::Requirement
|
23
|
-
requirements:
|
24
|
-
- - ">="
|
25
|
-
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
27
13
|
- !ruby/object:Gem::Dependency
|
28
14
|
name: httparty
|
29
15
|
requirement: !ruby/object:Gem::Requirement
|
@@ -150,10 +136,25 @@ dependencies:
|
|
150
136
|
- - ">="
|
151
137
|
- !ruby/object:Gem::Version
|
152
138
|
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: pact
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '1.16'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '1.16'
|
153
153
|
description: Publishes pacts to, and retrieves pacts from, the pact broker server.
|
154
154
|
email:
|
155
155
|
- bskurrie@dius.com.au
|
156
|
-
executables:
|
156
|
+
executables:
|
157
|
+
- pact-publish
|
157
158
|
extensions: []
|
158
159
|
extra_rdoc_files: []
|
159
160
|
files:
|
@@ -166,6 +167,7 @@ files:
|
|
166
167
|
- README.md
|
167
168
|
- RELEASING.md
|
168
169
|
- Rakefile
|
170
|
+
- bin/pact-publish
|
169
171
|
- ci.sh
|
170
172
|
- doc/markdown/Pact Broker Client - Pact Broker.md
|
171
173
|
- doc/markdown/README.md
|
@@ -175,7 +177,13 @@ files:
|
|
175
177
|
- gemfiles/ruby_under_22.gemfile.lock
|
176
178
|
- lib/pact_broker/client.rb
|
177
179
|
- lib/pact_broker/client/base_client.rb
|
180
|
+
- lib/pact_broker/client/cli/custom_thor.rb
|
181
|
+
- lib/pact_broker/client/cli/publish.rb
|
182
|
+
- lib/pact_broker/client/error.rb
|
183
|
+
- lib/pact_broker/client/merge_pacts.rb
|
178
184
|
- lib/pact_broker/client/pact_broker_client.rb
|
185
|
+
- lib/pact_broker/client/pact_file.rb
|
186
|
+
- lib/pact_broker/client/pact_hash.rb
|
179
187
|
- lib/pact_broker/client/pacticipants.rb
|
180
188
|
- lib/pact_broker/client/pacts.rb
|
181
189
|
- lib/pact_broker/client/publish_pacts.rb
|
@@ -187,6 +195,9 @@ files:
|
|
187
195
|
- lib/pact_broker_client.rb
|
188
196
|
- pact-broker-client.gemspec
|
189
197
|
- spec/lib/pact_broker/client/base_client_spec.rb
|
198
|
+
- spec/lib/pact_broker/client/cli/custom_thor_spec.rb
|
199
|
+
- spec/lib/pact_broker/client/cli/publish_spec.rb
|
200
|
+
- spec/lib/pact_broker/client/merge_pacts_spec.rb
|
190
201
|
- spec/lib/pact_broker/client/pact_broker_client_spec.rb
|
191
202
|
- spec/lib/pact_broker/client/pacticipants_spec.rb
|
192
203
|
- spec/lib/pact_broker/client/publish_pacts_spec.rb
|
@@ -202,6 +213,8 @@ files:
|
|
202
213
|
- spec/service_providers/pact_broker_client_tags_spec.rb
|
203
214
|
- spec/service_providers/pact_helper.rb
|
204
215
|
- spec/spec_helper.rb
|
216
|
+
- spec/support/cli_test_pacts/bar.json
|
217
|
+
- spec/support/cli_test_pacts/foo.json
|
205
218
|
- spec/support/latest_pacts_for_provider.json
|
206
219
|
- spec/support/pacticipant_get.json
|
207
220
|
- spec/support/pacticipants_list.json
|
@@ -234,6 +247,9 @@ specification_version: 4
|
|
234
247
|
summary: See description
|
235
248
|
test_files:
|
236
249
|
- spec/lib/pact_broker/client/base_client_spec.rb
|
250
|
+
- spec/lib/pact_broker/client/cli/custom_thor_spec.rb
|
251
|
+
- spec/lib/pact_broker/client/cli/publish_spec.rb
|
252
|
+
- spec/lib/pact_broker/client/merge_pacts_spec.rb
|
237
253
|
- spec/lib/pact_broker/client/pact_broker_client_spec.rb
|
238
254
|
- spec/lib/pact_broker/client/pacticipants_spec.rb
|
239
255
|
- spec/lib/pact_broker/client/publish_pacts_spec.rb
|
@@ -249,6 +265,8 @@ test_files:
|
|
249
265
|
- spec/service_providers/pact_broker_client_tags_spec.rb
|
250
266
|
- spec/service_providers/pact_helper.rb
|
251
267
|
- spec/spec_helper.rb
|
268
|
+
- spec/support/cli_test_pacts/bar.json
|
269
|
+
- spec/support/cli_test_pacts/foo.json
|
252
270
|
- spec/support/latest_pacts_for_provider.json
|
253
271
|
- spec/support/pacticipant_get.json
|
254
272
|
- spec/support/pacticipants_list.json
|