pact 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +14 -1
- data/lib/pact/cli.rb +5 -98
- data/lib/pact/cli/run_pact_verification.rb +74 -0
- data/lib/pact/cli/spec_criteria.rb +23 -0
- data/lib/pact/consumer/configuration/configuration_extensions.rb +12 -0
- data/lib/pact/doc/interaction_view_model.rb +2 -1
- data/lib/pact/provider/configuration/configuration_extension.rb +0 -8
- data/lib/pact/provider/configuration/pact_verification.rb +2 -1
- data/lib/pact/provider/help/console_text.rb +80 -0
- data/lib/pact/provider/help/content.rb +38 -0
- data/lib/pact/provider/help/pact_diff.rb +67 -0
- data/lib/pact/provider/help/prompt_text.rb +51 -0
- data/lib/pact/provider/help/write.rb +55 -0
- data/lib/pact/provider/pact_source.rb +19 -0
- data/lib/pact/provider/pact_spec_runner.rb +33 -14
- data/lib/pact/provider/print_missing_provider_states.rb +10 -3
- data/lib/pact/provider/rspec.rb +8 -11
- data/lib/pact/provider/rspec/formatter_rspec_2.rb +3 -4
- data/lib/pact/provider/rspec/formatter_rspec_3.rb +10 -11
- data/lib/pact/provider/world.rb +12 -0
- data/lib/pact/tasks/task_helper.rb +6 -2
- data/lib/pact/templates/help.erb +22 -0
- data/lib/pact/version.rb +1 -1
- data/lib/tasks/pact.rake +6 -0
- data/pact.gemspec +2 -2
- metadata +17 -8
data/CHANGELOG.md
CHANGED
@@ -2,7 +2,20 @@ Do this to generate your change history
|
|
2
2
|
|
3
3
|
git log --pretty=format:' * %h - %s (%an, %ad)'
|
4
4
|
|
5
|
-
|
5
|
+
### 1.5.0 (25 November 2014)
|
6
|
+
|
7
|
+
* 9a5ab1c - Allow path to be specified as a Pact::Term (Beth, Wed Jan 21 07:56:19 2015 +1100)
|
8
|
+
* cdec8bd - Prepended rake commands in output with 'bundle exec' (Beth, Mon Dec 22 17:27:12 2014 +1100)
|
9
|
+
* 6dfb16e - Added line to print pact verify command to stdout (Beth, Mon Dec 22 17:19:00 2014 +1100)
|
10
|
+
* b507f50 - Changed colours of missing provider state templates (Beth, Tue Dec 16 21:50:00 2014 +1100)
|
11
|
+
* d61769c - Added prompt for rake pact:verify:help on test failure. (Beth, Tue Dec 16 21:34:51 2014 +1100)
|
12
|
+
* c5377a1 - Created rake pact:verify:help task to display help text (Beth, Tue Dec 16 20:38:45 2014 +1100)
|
13
|
+
* c9d1189 - Write help to file after pact:verify (Beth, Tue Dec 16 19:49:20 2014 +1100)
|
14
|
+
* c7d8c35 - Added pact diff to help text (Beth, Tue Dec 16 13:14:35 2014 +1100)
|
15
|
+
* c877b94 - Moved interaction filter to command line argument from ENV (Beth, Sun Dec 14 22:05:44 2014 +1100)
|
16
|
+
* cd077ec - Added message to show diff between current pact and previous version when pact:verify fails. This relies on the 'diff-previous-distinct' relation being present in the pact resource, so will only work when the pact is retrieved from a pact broker (Beth, Fri Dec 12 11:25:59 2014 +1100)
|
17
|
+
* 43aa930 - Added command line option to show full backtrace for pact:verify failures (Beth, Thu Dec 4 08:45:28 2014 +1100)
|
18
|
+
* 5667874 - Ensure markdown doc rendering doesn't blow up if there is a nil description (Beth, Wed Dec 3 21:35:42 2014 +1100)
|
6
19
|
|
7
20
|
### 1.4.0 (25 November 2014)
|
8
21
|
|
data/lib/pact/cli.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
|
-
require 'find_a_port'
|
2
1
|
require 'thor'
|
3
|
-
require '
|
4
|
-
require 'pact/consumer'
|
5
|
-
require 'rack/handler/webrick'
|
2
|
+
require 'pact/cli/run_pact_verification'
|
6
3
|
|
7
4
|
module Pact
|
8
5
|
class CLI < Thor
|
@@ -10,103 +7,13 @@ module Pact
|
|
10
7
|
desc 'verify', "Verify a pact"
|
11
8
|
method_option :pact_helper, aliases: "-h", desc: "Pact helper file", :required => true
|
12
9
|
method_option :pact_uri, aliases: "-p", desc: "Pact URI"
|
10
|
+
method_option :backtrace, aliases: "-b", desc: "Show full backtrace", :default => false, :type => :boolean
|
11
|
+
method_option :description, aliases: "-d", desc: "Interaction description filter"
|
12
|
+
method_option :provider_state, aliases: "-s", desc: "Provider state filter"
|
13
13
|
|
14
14
|
def verify
|
15
|
-
RunPactVerification.call(options)
|
15
|
+
Cli::RunPactVerification.call(options)
|
16
16
|
end
|
17
17
|
|
18
|
-
private
|
19
|
-
|
20
|
-
def log message
|
21
|
-
puts message unless options[:quiet]
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
class RunPactVerification
|
26
|
-
|
27
|
-
attr_reader :options
|
28
|
-
|
29
|
-
def initialize options
|
30
|
-
@options = options
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.call options
|
34
|
-
new(options).call
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
def call
|
39
|
-
initialize_rspec
|
40
|
-
setup_load_path
|
41
|
-
load_pact_helper
|
42
|
-
run_specs
|
43
|
-
end
|
44
|
-
|
45
|
-
private
|
46
|
-
|
47
|
-
def initialize_rspec
|
48
|
-
# With RSpec3, if the pact_helper loads a library that adds its own formatter before we set one,
|
49
|
-
# we will get a ProgressFormatter too, and get little dots sprinkled throughout our output.
|
50
|
-
require 'pact/rspec'
|
51
|
-
::RSpec.configuration.add_formatter Pact::RSpec.formatter_class
|
52
|
-
end
|
53
|
-
|
54
|
-
def setup_load_path
|
55
|
-
require 'pact/provider/pact_spec_runner'
|
56
|
-
lib = File.join(Dir.pwd, "lib") # Assume we are running from within the project root. RSpec is smarter about this.
|
57
|
-
spec = File.join(Dir.pwd, "spec")
|
58
|
-
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
59
|
-
$LOAD_PATH.unshift(spec) if Dir.exist?(spec) && !$LOAD_PATH.include?(spec)
|
60
|
-
end
|
61
|
-
|
62
|
-
def load_pact_helper
|
63
|
-
load options[:pact_helper]
|
64
|
-
end
|
65
|
-
|
66
|
-
def run_specs
|
67
|
-
exit_code = if options[:pact_uri]
|
68
|
-
run_with_pact_uri
|
69
|
-
else
|
70
|
-
run_with_configured_pacts
|
71
|
-
end
|
72
|
-
exit 1 unless exit_code == 0
|
73
|
-
end
|
74
|
-
|
75
|
-
def run_with_pact_uri
|
76
|
-
Pact::Provider::PactSpecRunner.new([{uri: options[:pact_uri]}], pact_spec_options).run
|
77
|
-
end
|
78
|
-
|
79
|
-
def run_with_configured_pacts
|
80
|
-
pact_verifications = Pact.configuration.pact_verifications
|
81
|
-
verification_configs = pact_verifications.collect { | pact_verification | { :uri => pact_verification.uri }}
|
82
|
-
raise "Please configure a pact to verify" if verification_configs.empty?
|
83
|
-
Pact::Provider::PactSpecRunner.new(verification_configs, options).run
|
84
|
-
end
|
85
|
-
|
86
|
-
def pact_spec_options
|
87
|
-
{criteria: SpecCriteria.call}
|
88
|
-
end
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
class SpecCriteria
|
93
|
-
|
94
|
-
def self.call
|
95
|
-
criteria = {}
|
96
|
-
|
97
|
-
description = ENV["PACT_DESCRIPTION"]
|
98
|
-
criteria[:description] = Regexp.new(description) if description
|
99
|
-
|
100
|
-
provider_state = ENV["PACT_PROVIDER_STATE"]
|
101
|
-
if provider_state
|
102
|
-
if provider_state.length == 0
|
103
|
-
criteria[:provider_state] = nil #Allow PACT_PROVIDER_STATE="" to mean no provider state
|
104
|
-
else
|
105
|
-
criteria[:provider_state] = Regexp.new(provider_state)
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
criteria
|
110
|
-
end
|
111
18
|
end
|
112
19
|
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'pact/cli/spec_criteria'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module Cli
|
5
|
+
class RunPactVerification
|
6
|
+
|
7
|
+
attr_reader :options
|
8
|
+
|
9
|
+
def initialize options
|
10
|
+
@options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.call options
|
14
|
+
new(options).call
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
def call
|
19
|
+
initialize_rspec
|
20
|
+
setup_load_path
|
21
|
+
load_pact_helper
|
22
|
+
run_specs
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def initialize_rspec
|
28
|
+
# With RSpec3, if the pact_helper loads a library that adds its own formatter before we set one,
|
29
|
+
# we will get a ProgressFormatter too, and get little dots sprinkled throughout our output.
|
30
|
+
require 'pact/rspec'
|
31
|
+
::RSpec.configuration.add_formatter Pact::RSpec.formatter_class
|
32
|
+
end
|
33
|
+
|
34
|
+
def setup_load_path
|
35
|
+
require 'pact/provider/pact_spec_runner'
|
36
|
+
lib = File.join(Dir.pwd, "lib") # Assume we are running from within the project root. RSpec is smarter about this.
|
37
|
+
spec = File.join(Dir.pwd, "spec")
|
38
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
39
|
+
$LOAD_PATH.unshift(spec) if Dir.exist?(spec) && !$LOAD_PATH.include?(spec)
|
40
|
+
end
|
41
|
+
|
42
|
+
def load_pact_helper
|
43
|
+
load options[:pact_helper]
|
44
|
+
end
|
45
|
+
|
46
|
+
def run_specs
|
47
|
+
exit_code = if options[:pact_uri]
|
48
|
+
run_with_pact_uri
|
49
|
+
else
|
50
|
+
run_with_configured_pacts
|
51
|
+
end
|
52
|
+
exit exit_code
|
53
|
+
end
|
54
|
+
|
55
|
+
def run_with_pact_uri
|
56
|
+
Pact::Provider::PactSpecRunner.new([options[:pact_uri]], pact_spec_options).run
|
57
|
+
end
|
58
|
+
|
59
|
+
def run_with_configured_pacts
|
60
|
+
pact_urls = Pact.provider_world.pact_urls
|
61
|
+
raise "Please configure a pact to verify" if pact_urls.empty?
|
62
|
+
Pact::Provider::PactSpecRunner.new(pact_urls, pact_spec_options).run
|
63
|
+
end
|
64
|
+
|
65
|
+
def pact_spec_options
|
66
|
+
{
|
67
|
+
full_backtrace: options[:backtrace],
|
68
|
+
criteria: SpecCriteria.call(options)
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Pact
|
2
|
+
module Cli
|
3
|
+
class SpecCriteria
|
4
|
+
|
5
|
+
def self.call options
|
6
|
+
criteria = {}
|
7
|
+
|
8
|
+
criteria[:description] = Regexp.new(options[:description]) if options[:description]
|
9
|
+
|
10
|
+
provider_state = options[:provider_state]
|
11
|
+
if provider_state
|
12
|
+
if provider_state.length == 0
|
13
|
+
criteria[:provider_state] = nil #Allow PACT_PROVIDER_STATE="" to mean no provider state
|
14
|
+
else
|
15
|
+
criteria[:provider_state] = Regexp.new(provider_state)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
criteria
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -17,6 +17,18 @@ module Pact
|
|
17
17
|
@doc_dir = doc_dir
|
18
18
|
end
|
19
19
|
|
20
|
+
def reports_dir
|
21
|
+
@reports_dir ||= default_reports_dir
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_reports_dir
|
25
|
+
File.expand_path("./reports/pacts")
|
26
|
+
end
|
27
|
+
|
28
|
+
def reports_dir= reports_dir
|
29
|
+
@reports_dir = reports_dir
|
30
|
+
end
|
31
|
+
|
20
32
|
def add_provider_verification &block
|
21
33
|
provider_verifications << block
|
22
34
|
end
|
@@ -17,7 +17,7 @@ module Pact
|
|
17
17
|
if has_provider_state?
|
18
18
|
"#{description} given #{interaction.provider_state}"
|
19
19
|
else
|
20
|
-
|
20
|
+
description
|
21
21
|
end.gsub(/\s+/,'_')
|
22
22
|
end
|
23
23
|
end
|
@@ -51,6 +51,7 @@ module Pact
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def description start_of_sentence = false
|
54
|
+
return '' unless @interaction.description
|
54
55
|
apply_capitals(@interaction.description.strip, start_of_sentence)
|
55
56
|
end
|
56
57
|
|
@@ -21,14 +21,6 @@ module Pact
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
def add_pact_verification verification
|
25
|
-
pact_verifications << verification
|
26
|
-
end
|
27
|
-
|
28
|
-
def pact_verifications
|
29
|
-
@pact_verifications ||= []
|
30
|
-
end
|
31
|
-
|
32
24
|
def config_ru_path
|
33
25
|
@config_ru_path ||= './config.ru'
|
34
26
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'pact/provider/pact_verification'
|
2
2
|
require 'pact/shared/dsl'
|
3
|
+
require 'pact/provider/world'
|
3
4
|
|
4
5
|
module Pact
|
5
6
|
module Provider
|
@@ -33,7 +34,7 @@ module Pact
|
|
33
34
|
|
34
35
|
def create_pact_verification
|
35
36
|
verification = Pact::Provider::PactVerification.new(consumer_name, pact_uri, ref)
|
36
|
-
Pact.
|
37
|
+
Pact.provider_world.add_pact_verification verification
|
37
38
|
end
|
38
39
|
|
39
40
|
def validate
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'pact/provider/help/content'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pact/consumer/configuration'
|
4
|
+
require 'pact/provider/help/write'
|
5
|
+
require 'term/ansicolor'
|
6
|
+
|
7
|
+
module Pact
|
8
|
+
module Provider
|
9
|
+
module Help
|
10
|
+
class ConsoleText
|
11
|
+
|
12
|
+
C = ::Term::ANSIColor
|
13
|
+
|
14
|
+
def self.call reports_dir = Pact.configuration.reports_dir, options = {color: true}
|
15
|
+
new(reports_dir || Pact.configuration.reports_dir, options).call
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize reports_dir, options
|
19
|
+
@reports_dir = File.expand_path(reports_dir)
|
20
|
+
@options = options
|
21
|
+
end
|
22
|
+
|
23
|
+
def call
|
24
|
+
begin
|
25
|
+
options[:color] ? ColorizeMarkdown.(help_text) : help_text
|
26
|
+
rescue Errno::ENOENT
|
27
|
+
options[:color] ? error_text_coloured : error_text_plain
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
attr_reader :reports_dir, :options
|
34
|
+
|
35
|
+
def help_text
|
36
|
+
File.read(help_file_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
def help_file_path
|
40
|
+
File.join(reports_dir, Write::HELP_FILE_NAME)
|
41
|
+
end
|
42
|
+
|
43
|
+
def error_text_plain
|
44
|
+
"Sorry, could not find help file at #{help_file_path}. Please ensure you have run `rake pact:verify`.\n" +
|
45
|
+
"If this does not fix the problem, please raise a github issues for this bug."
|
46
|
+
end
|
47
|
+
|
48
|
+
def error_text_coloured
|
49
|
+
C.red(error_text_plain)
|
50
|
+
end
|
51
|
+
|
52
|
+
class ColorizeMarkdown
|
53
|
+
|
54
|
+
C = ::Term::ANSIColor
|
55
|
+
|
56
|
+
def self.call markdown
|
57
|
+
markdown.split("\n").collect do | line |
|
58
|
+
if line.start_with?("# ")
|
59
|
+
yellow_underling line.gsub(/^# /, '')
|
60
|
+
elsif line.start_with?("* ")
|
61
|
+
green("* ") + line.gsub(/^\* /, '')
|
62
|
+
else
|
63
|
+
line
|
64
|
+
end
|
65
|
+
end.join("\n")
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.yellow_underling string
|
69
|
+
C.underline(C.yellow(string))
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.green string
|
73
|
+
C.green(string)
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'pact/provider/help/pact_diff'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module Provider
|
5
|
+
module Help
|
6
|
+
class Content
|
7
|
+
|
8
|
+
def initialize pact_jsons
|
9
|
+
@pact_jsons = pact_jsons
|
10
|
+
end
|
11
|
+
|
12
|
+
def text
|
13
|
+
help_text + "\n\n" + pact_diffs
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
attr_reader :pact_jsons
|
19
|
+
|
20
|
+
def help_text
|
21
|
+
temp_dir = Pact.configuration.tmp_dir
|
22
|
+
log_path = Pact.configuration.log_path
|
23
|
+
ERB.new(template_string).result(binding)
|
24
|
+
end
|
25
|
+
|
26
|
+
def template_string
|
27
|
+
File.read(File.expand_path( '../../../templates/help.erb', __FILE__))
|
28
|
+
end
|
29
|
+
|
30
|
+
def pact_diffs
|
31
|
+
pact_jsons.collect do | pact_json |
|
32
|
+
PactDiff.call(pact_json)
|
33
|
+
end.compact.join("\n")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module Pact
|
2
|
+
module Provider
|
3
|
+
module Help
|
4
|
+
|
5
|
+
class PactDiff
|
6
|
+
|
7
|
+
class PrintPactDiffError < StandardError; end
|
8
|
+
|
9
|
+
attr_reader :pact_json, :output
|
10
|
+
|
11
|
+
def initialize pact_json
|
12
|
+
@pact_json = pact_json
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.call pact_json
|
16
|
+
new(pact_json).call
|
17
|
+
end
|
18
|
+
|
19
|
+
def call
|
20
|
+
begin
|
21
|
+
if diff_rel && diff_url
|
22
|
+
header + "\n" + get_diff
|
23
|
+
end
|
24
|
+
rescue PrintPactDiffError => e
|
25
|
+
return e.message
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def header
|
32
|
+
"The following changes have been made since the previous distinct version of this pact, and may be responsible for verification failure:\n"
|
33
|
+
end
|
34
|
+
|
35
|
+
def pact_hash
|
36
|
+
@pact_hash ||= json_load(pact_json)
|
37
|
+
end
|
38
|
+
|
39
|
+
def links
|
40
|
+
pact_hash['_links'] || pact_hash['links']
|
41
|
+
end
|
42
|
+
|
43
|
+
def diff_rel
|
44
|
+
return nil unless links
|
45
|
+
key = links.keys.find { | key | key =~ /diff/ && key =~ /distinct/ && key =~ /previous/}
|
46
|
+
key ? links[key] : nil
|
47
|
+
end
|
48
|
+
|
49
|
+
def diff_url
|
50
|
+
diff_rel['href']
|
51
|
+
end
|
52
|
+
|
53
|
+
def get_diff
|
54
|
+
begin
|
55
|
+
open(diff_url) { | file | file.read }
|
56
|
+
rescue StandardError => e
|
57
|
+
raise PrintPactDiffError.new("Tried to retrieve diff with previous pact from #{diff_url}, but received response code #{e}.")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def json_load json
|
62
|
+
JSON.load(json, nil, { max_nesting: 50 })
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'pact/consumer/configuration'
|
2
|
+
require 'term/ansicolor'
|
3
|
+
require 'pathname'
|
4
|
+
|
5
|
+
module Pact
|
6
|
+
module Provider
|
7
|
+
module Help
|
8
|
+
class PromptText
|
9
|
+
|
10
|
+
C = ::Term::ANSIColor
|
11
|
+
|
12
|
+
def self.call reports_dir = Pact.configuration.reports_dir, options = {color: Pact.configuration.color_enabled}
|
13
|
+
new(reports_dir, options).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize reports_dir, options
|
17
|
+
@reports_dir = File.expand_path(reports_dir)
|
18
|
+
@options = options
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
options[:color] ? prompt_text_colored : prompt_text_plain
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :reports_dir, :options
|
28
|
+
|
29
|
+
def prompt_text_plain
|
30
|
+
"For assistance debugging failures, run `bundle exec rake pact:verify:help#{rake_args}`\n"
|
31
|
+
end
|
32
|
+
|
33
|
+
def prompt_text_colored
|
34
|
+
C.yellow(prompt_text_plain)
|
35
|
+
end
|
36
|
+
|
37
|
+
def rake_args
|
38
|
+
if reports_dir == Pact.configuration.default_reports_dir
|
39
|
+
''
|
40
|
+
else
|
41
|
+
"[#{relative_reports_dir}]"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def relative_reports_dir
|
46
|
+
Pathname.new(reports_dir).relative_path_from(Pathname.new(Dir.pwd))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'pact/provider/help/content'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'pact/consumer/configuration'
|
4
|
+
|
5
|
+
module Pact
|
6
|
+
module Provider
|
7
|
+
module Help
|
8
|
+
class Write
|
9
|
+
|
10
|
+
HELP_FILE_NAME = 'help.md'
|
11
|
+
|
12
|
+
def self.call pact_jsons, reports_dir = Pact.configuration.reports_dir
|
13
|
+
new(pact_jsons, reports_dir).call
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize pact_jsons, reports_dir
|
17
|
+
@pact_jsons = pact_jsons
|
18
|
+
@reports_dir = File.expand_path(reports_dir)
|
19
|
+
end
|
20
|
+
|
21
|
+
def call
|
22
|
+
clean_reports_dir
|
23
|
+
write
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :reports_dir, :pact_jsons
|
29
|
+
|
30
|
+
def clean_reports_dir
|
31
|
+
raise "Cleaning report dir #{reports_dir} would delete project!" if reports_dir_contains_pwd
|
32
|
+
FileUtils.rm_rf reports_dir
|
33
|
+
FileUtils.mkdir_p reports_dir
|
34
|
+
end
|
35
|
+
|
36
|
+
def reports_dir_contains_pwd
|
37
|
+
Dir.pwd.start_with?(reports_dir)
|
38
|
+
end
|
39
|
+
|
40
|
+
def write
|
41
|
+
File.open(help_path, "w") { |file| file << help_text }
|
42
|
+
end
|
43
|
+
|
44
|
+
def help_path
|
45
|
+
File.join(reports_dir, 'help.md')
|
46
|
+
end
|
47
|
+
|
48
|
+
def help_text
|
49
|
+
Content.new(pact_jsons).text
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'pact/consumer_contract/pact_file'
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Provider
|
5
|
+
class PactSource
|
6
|
+
|
7
|
+
attr_reader :uri
|
8
|
+
|
9
|
+
def initialize uri
|
10
|
+
@uri = uri
|
11
|
+
end
|
12
|
+
|
13
|
+
def pact_json
|
14
|
+
@pact_json ||= Pact::PactFile.read(uri, {})
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -5,6 +5,8 @@ require 'rspec/core/formatters/documentation_formatter'
|
|
5
5
|
require 'pact/provider/pact_helper_locator'
|
6
6
|
require 'pact/project_root'
|
7
7
|
require 'pact/rspec'
|
8
|
+
require 'pact/provider/pact_source'
|
9
|
+
require 'pact/provider/help/write'
|
8
10
|
|
9
11
|
require_relative 'rspec'
|
10
12
|
|
@@ -15,12 +17,12 @@ module Pact
|
|
15
17
|
|
16
18
|
include Pact::Provider::RSpec::ClassMethods
|
17
19
|
|
18
|
-
attr_reader :
|
20
|
+
attr_reader :pact_urls
|
19
21
|
attr_reader :options
|
20
22
|
attr_reader :output
|
21
23
|
|
22
|
-
def initialize
|
23
|
-
@
|
24
|
+
def initialize pact_urls, options = {}
|
25
|
+
@pact_urls = pact_urls
|
24
26
|
@options = options
|
25
27
|
@results = nil
|
26
28
|
end
|
@@ -38,17 +40,6 @@ module Pact
|
|
38
40
|
|
39
41
|
private
|
40
42
|
|
41
|
-
def initialize_specs
|
42
|
-
spec_definitions.each do | spec_definition |
|
43
|
-
options = {
|
44
|
-
consumer: spec_definition[:consumer],
|
45
|
-
save_pactfile_to_tmp: true,
|
46
|
-
criteria: @options[:criteria]
|
47
|
-
}
|
48
|
-
honour_pactfile spec_definition[:uri], options
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
43
|
def configure_rspec
|
53
44
|
monkey_patch_backtrace_formatter
|
54
45
|
|
@@ -74,6 +65,7 @@ module Pact
|
|
74
65
|
formatter_class = Pact::RSpec.formatter_class
|
75
66
|
pact_formatter = ::RSpec.configuration.formatters.find {|f| f.class == formatter_class && f.output == ::RSpec.configuration.output_stream}
|
76
67
|
::RSpec.configuration.add_formatter formatter_class unless pact_formatter
|
68
|
+
::RSpec.configuration.full_backtrace = @options[:full_backtrace]
|
77
69
|
|
78
70
|
config.before(:suite) do
|
79
71
|
# Preload app before suite so the classes loaded in memory are consistent for
|
@@ -84,6 +76,12 @@ module Pact
|
|
84
76
|
Pact.configuration.provider.app
|
85
77
|
end
|
86
78
|
|
79
|
+
jsons = pact_jsons
|
80
|
+
|
81
|
+
config.after(:suite) do
|
82
|
+
Pact::Provider::Help::Write.call(jsons)
|
83
|
+
end
|
84
|
+
|
87
85
|
end
|
88
86
|
|
89
87
|
def run_specs
|
@@ -106,6 +104,27 @@ module Pact
|
|
106
104
|
end
|
107
105
|
end
|
108
106
|
|
107
|
+
def pact_sources
|
108
|
+
@pact_sources ||= begin
|
109
|
+
pact_urls.collect do | pact_url |
|
110
|
+
PactBroker::Provider::PactSource.new(pact_url)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def pact_jsons
|
116
|
+
pact_sources.collect(&:pact_json)
|
117
|
+
end
|
118
|
+
|
119
|
+
def initialize_specs
|
120
|
+
pact_sources.each do | pact_source |
|
121
|
+
options = {
|
122
|
+
criteria: @options[:criteria]
|
123
|
+
}
|
124
|
+
honour_pactfile pact_source.uri, pact_source.pact_json, options
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
109
128
|
def class_exists? name
|
110
129
|
Kernel.const_get name
|
111
130
|
rescue NameError
|
@@ -1,16 +1,23 @@
|
|
1
|
+
require 'term/ansicolor'
|
2
|
+
|
1
3
|
module Pact
|
2
4
|
module Provider
|
3
5
|
class PrintMissingProviderStates
|
4
6
|
|
7
|
+
C = ::Term::ANSIColor
|
8
|
+
|
5
9
|
# Hash of consumer names to array of names of missing provider states
|
6
10
|
def self.call missing_provider_states, output
|
7
11
|
if missing_provider_states.any?
|
8
|
-
output.puts
|
12
|
+
output.puts colorize(text(missing_provider_states))
|
9
13
|
end
|
10
14
|
end
|
11
15
|
|
12
|
-
def self.
|
13
|
-
"\
|
16
|
+
def self.colorize string
|
17
|
+
lines = string.split("\n")
|
18
|
+
first_line = C.cyan(C.underline(lines[0]))
|
19
|
+
other_lines = C.cyan(lines[1..-1].join("\n"))
|
20
|
+
first_line + "\n" + other_lines
|
14
21
|
end
|
15
22
|
|
16
23
|
def self.text missing_provider_states
|
data/lib/pact/provider/rspec.rb
CHANGED
@@ -18,18 +18,18 @@ module Pact
|
|
18
18
|
|
19
19
|
include ::RSpec::Core::DSL
|
20
20
|
|
21
|
-
def honour_pactfile
|
21
|
+
def honour_pactfile pact_uri, pact_json, options
|
22
22
|
#TODO change puts to use output stream
|
23
|
-
puts "Reading pact at #{
|
23
|
+
puts "Reading pact at #{pact_uri}"
|
24
24
|
puts "Filtering interactions by: #{options[:criteria]}" if options[:criteria] && options[:criteria].any?
|
25
|
-
consumer_contract = Pact::ConsumerContract.from_json(
|
26
|
-
::RSpec.describe "Verifying a pact between #{consumer_contract.consumer.name} and #{consumer_contract.provider.name}", :pactfile_uri =>
|
27
|
-
honour_consumer_contract consumer_contract, options
|
25
|
+
consumer_contract = Pact::ConsumerContract.from_json(pact_json)
|
26
|
+
::RSpec.describe "Verifying a pact between #{consumer_contract.consumer.name} and #{consumer_contract.provider.name}", :pactfile_uri => pact_uri do
|
27
|
+
honour_consumer_contract consumer_contract, options.merge(pact_json: pact_json)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
31
|
def honour_consumer_contract consumer_contract, options = {}
|
32
|
-
describe_consumer_contract consumer_contract, options.merge(
|
32
|
+
describe_consumer_contract consumer_contract, options.merge(:consumer => consumer_contract.consumer.name)
|
33
33
|
end
|
34
34
|
|
35
35
|
private
|
@@ -63,7 +63,8 @@ module Pact
|
|
63
63
|
metadata = {
|
64
64
|
:pact => :verify,
|
65
65
|
:pact_interaction => interaction,
|
66
|
-
:pact_interaction_example_description => interaction_description_for_rerun_command(interaction)
|
66
|
+
:pact_interaction_example_description => interaction_description_for_rerun_command(interaction),
|
67
|
+
:pact_json => options[:pact_json]
|
67
68
|
}
|
68
69
|
|
69
70
|
describe description_for(interaction), metadata do
|
@@ -148,10 +149,6 @@ module Pact
|
|
148
149
|
description_for(interaction).capitalize + ( interaction.provider_state ? " given #{interaction.provider_state}" : "")
|
149
150
|
end
|
150
151
|
|
151
|
-
def read_pact_from uri, options = {}
|
152
|
-
Pact::PactFile.read(uri, options)
|
153
|
-
end
|
154
|
-
|
155
152
|
end
|
156
153
|
|
157
154
|
# The "arrange" and "act" parts of the test really only need to be run once,
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'pact/provider/print_missing_provider_states'
|
2
2
|
require 'rspec/core/formatters/documentation_formatter'
|
3
3
|
require 'term/ansicolor'
|
4
|
+
require 'pact/provider/help/prompt_text'
|
4
5
|
|
5
6
|
module Pact
|
6
7
|
module Provider
|
@@ -42,7 +43,7 @@ module Pact
|
|
42
43
|
description = example.metadata[:pact_interaction].description
|
43
44
|
pactfile_uri = example.metadata[:pactfile_uri]
|
44
45
|
example_description = example.metadata[:pact_interaction_example_description]
|
45
|
-
failure_color("rake pact:verify:at[#{pactfile_uri}] PACT_DESCRIPTION=\"#{description}\" PACT_PROVIDER_STATE=\"#{provider_state}\"") + " " + detail_color("# #{example_description}")
|
46
|
+
failure_color("bundle exec rake pact:verify:at[#{pactfile_uri}] PACT_DESCRIPTION=\"#{description}\" PACT_PROVIDER_STATE=\"#{provider_state}\"") + " " + detail_color("# #{example_description}")
|
46
47
|
end
|
47
48
|
|
48
49
|
def print_failure_message
|
@@ -50,9 +51,7 @@ module Pact
|
|
50
51
|
end
|
51
52
|
|
52
53
|
def failure_message
|
53
|
-
"\n" +
|
54
|
-
"The pact files have been stored locally in the following temp directory:\n #{Pact.configuration.tmp_dir}\n\n" +
|
55
|
-
"The requests and responses are logged in the following log file:\n #{Pact.configuration.log_path}\n\n"
|
54
|
+
"\n" + Pact::Provider::Help::PromptText.() + "\n"
|
56
55
|
end
|
57
56
|
|
58
57
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'pact/provider/print_missing_provider_states'
|
2
2
|
require 'rspec/core/formatters'
|
3
3
|
require 'term/ansicolor'
|
4
|
+
require 'pact/provider/help/prompt_text'
|
4
5
|
|
5
6
|
module Pact
|
6
7
|
module Provider
|
@@ -25,11 +26,11 @@ module Pact
|
|
25
26
|
private
|
26
27
|
|
27
28
|
def interactions_count(summary)
|
28
|
-
summary.examples.collect{ |e|e.metadata[:pact_interaction_example_description]}.uniq.size
|
29
|
+
summary.examples.collect{ |e| e.metadata[:pact_interaction_example_description] }.uniq.size
|
29
30
|
end
|
30
31
|
|
31
32
|
def failed_interactions_count(summary)
|
32
|
-
summary.failed_examples.collect{ |e|e.metadata[:pact_interaction_example_description]}.uniq.size
|
33
|
+
summary.failed_examples.collect{ |e| e.metadata[:pact_interaction_example_description] }.uniq.size
|
33
34
|
end
|
34
35
|
|
35
36
|
def totals_line summary
|
@@ -39,11 +40,11 @@ module Pact
|
|
39
40
|
end
|
40
41
|
|
41
42
|
def colorized_totals_line(summary)
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
colorizer.wrap(totals_line(summary), color_for_summary(summary))
|
44
|
+
end
|
45
|
+
|
46
|
+
def color_for_summary summary
|
47
|
+
summary.failure_count > 0 ? ::RSpec.configuration.failure_color : ::RSpec.configuration.success_color
|
47
48
|
end
|
48
49
|
|
49
50
|
def print_rerun_commands summary
|
@@ -68,7 +69,7 @@ module Pact
|
|
68
69
|
description = example.metadata[:pact_interaction].description
|
69
70
|
pactfile_uri = example.metadata[:pactfile_uri]
|
70
71
|
example_description = example.metadata[:pact_interaction_example_description]
|
71
|
-
colorizer.wrap("rake pact:verify:at[#{pactfile_uri}] PACT_DESCRIPTION=\"#{description}\" PACT_PROVIDER_STATE=\"#{provider_state}\" ", ::RSpec.configuration.failure_color) +
|
72
|
+
colorizer.wrap("bundle exec rake pact:verify:at[#{pactfile_uri}] PACT_DESCRIPTION=\"#{description}\" PACT_PROVIDER_STATE=\"#{provider_state}\" ", ::RSpec.configuration.failure_color) +
|
72
73
|
colorizer.wrap("# #{example_description}", ::RSpec.configuration.detail_color)
|
73
74
|
end
|
74
75
|
|
@@ -77,9 +78,7 @@ module Pact
|
|
77
78
|
end
|
78
79
|
|
79
80
|
def failure_message
|
80
|
-
"\n" +
|
81
|
-
"The pact files have been stored locally in the following temp directory:\n #{Pact.configuration.tmp_dir}\n\n" +
|
82
|
-
"The requests and responses are logged in the following log file:\n #{Pact.configuration.log_path}\n\n"
|
81
|
+
"\n" + Pact::Provider::Help::PromptText.() + "\n"
|
83
82
|
end
|
84
83
|
|
85
84
|
def colorizer
|
data/lib/pact/provider/world.rb
CHANGED
@@ -18,6 +18,18 @@ module Pact
|
|
18
18
|
@provider_states_proxy ||= Pact::Provider::State::ProviderStateProxy.new
|
19
19
|
end
|
20
20
|
|
21
|
+
def add_pact_verification verification
|
22
|
+
pact_verifications << verification
|
23
|
+
end
|
24
|
+
|
25
|
+
def pact_verifications
|
26
|
+
@pact_verifications ||= []
|
27
|
+
end
|
28
|
+
|
29
|
+
def pact_urls
|
30
|
+
pact_verifications.collect(&:uri)
|
31
|
+
end
|
32
|
+
|
21
33
|
end
|
22
34
|
end
|
23
35
|
end
|
@@ -23,12 +23,16 @@ module Pact
|
|
23
23
|
command_parts << "SPEC_OPTS=#{Shellwords.escape(rspec_opts || '')}"
|
24
24
|
command_parts << FileUtils::RUBY
|
25
25
|
command_parts << "-S pact verify"
|
26
|
-
command_parts << "-
|
27
|
-
(command_parts << "-
|
26
|
+
command_parts << "--pact-helper" << (pact_helper.end_with?(".rb") ? pact_helper : pact_helper + ".rb")
|
27
|
+
(command_parts << "--pact-uri" << pact_uri) if pact_uri
|
28
|
+
command_parts << "--backtrace" if ENV['BACKTRACE'] == 'true'
|
29
|
+
command_parts << "--description #{Shellwords.escape(ENV['PACT_DESCRIPTION'])}" if ENV['PACT_DESCRIPTION']
|
30
|
+
command_parts << "--provider-state #{Shellwords.escape(ENV['PACT_PROVIDER_STATE'])}" if ENV['PACT_PROVIDER_STATE']
|
28
31
|
command_parts.flatten.join(" ")
|
29
32
|
end
|
30
33
|
|
31
34
|
def execute_cmd command
|
35
|
+
$stdout.puts command
|
32
36
|
system(command) ? 0 : 1
|
33
37
|
end
|
34
38
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# For assistance debugging failures
|
2
|
+
|
3
|
+
* The pact files have been stored locally in the following temp directory:
|
4
|
+
<%= temp_dir %>
|
5
|
+
|
6
|
+
* The requests and responses are logged in the following log file:
|
7
|
+
<%= log_path %>
|
8
|
+
|
9
|
+
* Add BACKTRACE=true to the `rake pact:verify` command to see the full backtrace
|
10
|
+
|
11
|
+
* If the diff output is confusing, try using another diff formatter.
|
12
|
+
The options are :unix, :embedded and :list
|
13
|
+
|
14
|
+
Pact.configure do | config |
|
15
|
+
config.diff_formatter = :embedded
|
16
|
+
end
|
17
|
+
|
18
|
+
See https://github.com/realestate-com-au/pact/blob/master/documentation/configuration.md#diff_formatter for examples and more information.
|
19
|
+
|
20
|
+
* Check out https://github.com/realestate-com-au/pact/wiki/Troubleshooting
|
21
|
+
|
22
|
+
* Ask a question in the google users' group https://groups.google.com/forum/#!forum/pact-support
|
data/lib/pact/version.rb
CHANGED
data/lib/tasks/pact.rake
CHANGED
@@ -26,4 +26,10 @@ namespace :pact do
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
desc "Get help debugging pact:verify failures."
|
30
|
+
task 'verify:help', :reports_dir do | t, args |
|
31
|
+
require 'pact/provider/help/console_text'
|
32
|
+
puts Pact::Provider::Help::ConsoleText.(args[:reports_dir])
|
33
|
+
end
|
34
|
+
|
29
35
|
end
|
data/pact.gemspec
CHANGED
@@ -28,8 +28,8 @@ Gem::Specification.new do |gem|
|
|
28
28
|
gem.add_runtime_dependency 'webrick'
|
29
29
|
gem.add_runtime_dependency 'term-ansicolor', '~> 1.0'
|
30
30
|
|
31
|
-
gem.add_runtime_dependency 'pact-support', '~> 0.1
|
32
|
-
gem.add_runtime_dependency 'pact-mock_service', '~> 0.2.
|
31
|
+
gem.add_runtime_dependency 'pact-support', '~> 0.2.1'
|
32
|
+
gem.add_runtime_dependency 'pact-mock_service', '~> 0.2.3'
|
33
33
|
|
34
34
|
gem.add_development_dependency 'rake', '~> 10.0.3'
|
35
35
|
gem.add_development_dependency 'webmock', '~> 1.18.0'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pact
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date:
|
16
|
+
date: 2015-01-20 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: randexp
|
@@ -166,7 +166,7 @@ dependencies:
|
|
166
166
|
requirements:
|
167
167
|
- - ~>
|
168
168
|
- !ruby/object:Gem::Version
|
169
|
-
version: 0.1
|
169
|
+
version: 0.2.1
|
170
170
|
type: :runtime
|
171
171
|
prerelease: false
|
172
172
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -174,7 +174,7 @@ dependencies:
|
|
174
174
|
requirements:
|
175
175
|
- - ~>
|
176
176
|
- !ruby/object:Gem::Version
|
177
|
-
version: 0.1
|
177
|
+
version: 0.2.1
|
178
178
|
- !ruby/object:Gem::Dependency
|
179
179
|
name: pact-mock_service
|
180
180
|
requirement: !ruby/object:Gem::Requirement
|
@@ -182,7 +182,7 @@ dependencies:
|
|
182
182
|
requirements:
|
183
183
|
- - ~>
|
184
184
|
- !ruby/object:Gem::Version
|
185
|
-
version: 0.2.
|
185
|
+
version: 0.2.3
|
186
186
|
type: :runtime
|
187
187
|
prerelease: false
|
188
188
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -190,7 +190,7 @@ dependencies:
|
|
190
190
|
requirements:
|
191
191
|
- - ~>
|
192
192
|
- !ruby/object:Gem::Version
|
193
|
-
version: 0.2.
|
193
|
+
version: 0.2.3
|
194
194
|
- !ruby/object:Gem::Dependency
|
195
195
|
name: rake
|
196
196
|
requirement: !ruby/object:Gem::Requirement
|
@@ -338,6 +338,8 @@ files:
|
|
338
338
|
- bin/pact
|
339
339
|
- lib/pact.rb
|
340
340
|
- lib/pact/cli.rb
|
341
|
+
- lib/pact/cli/run_pact_verification.rb
|
342
|
+
- lib/pact/cli/spec_criteria.rb
|
341
343
|
- lib/pact/consumer.rb
|
342
344
|
- lib/pact/consumer/configuration.rb
|
343
345
|
- lib/pact/consumer/configuration/configuration_extensions.rb
|
@@ -370,8 +372,14 @@ files:
|
|
370
372
|
- lib/pact/provider/configuration/service_provider_config.rb
|
371
373
|
- lib/pact/provider/configuration/service_provider_dsl.rb
|
372
374
|
- lib/pact/provider/context.rb
|
375
|
+
- lib/pact/provider/help/console_text.rb
|
376
|
+
- lib/pact/provider/help/content.rb
|
377
|
+
- lib/pact/provider/help/pact_diff.rb
|
378
|
+
- lib/pact/provider/help/prompt_text.rb
|
379
|
+
- lib/pact/provider/help/write.rb
|
373
380
|
- lib/pact/provider/matchers/messages.rb
|
374
381
|
- lib/pact/provider/pact_helper_locator.rb
|
382
|
+
- lib/pact/provider/pact_source.rb
|
375
383
|
- lib/pact/provider/pact_spec_runner.rb
|
376
384
|
- lib/pact/provider/pact_verification.rb
|
377
385
|
- lib/pact/provider/print_missing_provider_states.rb
|
@@ -392,6 +400,7 @@ files:
|
|
392
400
|
- lib/pact/tasks.rb
|
393
401
|
- lib/pact/tasks/task_helper.rb
|
394
402
|
- lib/pact/tasks/verification_task.rb
|
403
|
+
- lib/pact/templates/help.erb
|
395
404
|
- lib/pact/templates/provider_state.erb
|
396
405
|
- lib/pact/version.rb
|
397
406
|
- lib/tasks/pact.rake
|
@@ -411,7 +420,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
411
420
|
version: '0'
|
412
421
|
segments:
|
413
422
|
- 0
|
414
|
-
hash: -
|
423
|
+
hash: -4361813118953471608
|
415
424
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
416
425
|
none: false
|
417
426
|
requirements:
|
@@ -420,7 +429,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
420
429
|
version: '0'
|
421
430
|
segments:
|
422
431
|
- 0
|
423
|
-
hash: -
|
432
|
+
hash: -4361813118953471608
|
424
433
|
requirements: []
|
425
434
|
rubyforge_project:
|
426
435
|
rubygems_version: 1.8.23
|