tddium-preview 0.5.6 → 0.6.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.
data/.gitignore CHANGED
@@ -49,3 +49,5 @@ nbproject
49
49
  #
50
50
  # For vim:
51
51
  *.swp
52
+ *.swo
53
+ .tddium.staging
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tddium-preview (0.5.5)
4
+ tddium-preview (0.5.6)
5
5
  bundler
6
6
  highline
7
7
  json
@@ -13,6 +13,7 @@ module TddiumConstant
13
13
  ENVIRONMENT = "production"
14
14
  SSH_FILE = "~/.ssh/id_rsa.pub"
15
15
  TEST_PATTERN = "spec/**/*_spec.rb"
16
+ SUITE_TEST_PATTERN = "features/*.feature, spec/**/*_spec.rb, test/**/test_*.rb"
16
17
  end
17
18
 
18
19
  module Git
@@ -57,6 +58,15 @@ module TddiumConstant
57
58
  PASSWORD_CONFIRMATION = "Confirm your password: "
58
59
  INVITATION_TOKEN = "Enter your invitation token:"
59
60
  USE_EXISTING_SUITE = "A suite exists '%%s' (branch %s). Enter '#{Response::YES}' to use it, or enter a new repo name:"
61
+ TEST_PATTERN = "Default test pattern: "
62
+ ENABLE_CI = "Do you want to configure Hosted Continuous Integration?"
63
+ UPDATE_SUITE = "Do you want to edit settings for this suite?"
64
+ CI_PULL_URL = "git URL to pull from:"
65
+ CI_PUSH_URL = "git URL to push on passing tests (blank to disable):"
66
+ ENABLE_CAMPFIRE = "Setup Campfire CI notifications?"
67
+ CAMPFIRE_SUBDOMAIN = "Campfire Subdomain:"
68
+ CAMPFIRE_ROOM = "Campfire Room:"
69
+ CAMPFIRE_TOKEN = "Campfire API Token:"
60
70
  end
61
71
 
62
72
  module Process
@@ -67,8 +77,9 @@ module TddiumConstant
67
77
  CHECK_TEST_STATUS = "Use 'tddium status' to check on pending jobs"
68
78
  FINISHED_TEST = "Finished in %s seconds"
69
79
  CHECK_TEST_REPORT = "Test report: %s"
70
- EXISTING_SUITE = "Current suite: %s"
71
- CREATING_SUITE = "Creating suite '%s'. This will take a few seconds."
80
+ EXISTING_SUITE = "Current suite...\n\n%s"
81
+ CREATING_SUITE = "Creating suite '%s/%s'. This will take a few seconds."
82
+ CREATED_SUITE = "Created suite...\n\n%s"
72
83
  PASSWORD_CONFIRMATION_INCORRECT = "Password confirmation incorrect"
73
84
  PASSWORD_CHANGED = "Your password has been changed."
74
85
  ACCOUNT_CREATED = "
@@ -116,7 +127,15 @@ with Tddium.
116
127
  SESSION_TITLE = " Session %s:"
117
128
  ATTRIBUTE_DETAIL = " %s: %s"
118
129
  SEPARATOR = "====="
119
- USING_SUITE = "Using suite: '%s' on branch: '%s'"
130
+ USING_SUITE = "Using suite...\n\n%s"
131
+ USER_DETAILS =<<EOF;
132
+ Username: <%=user["email"]%>
133
+ Account Created: <%=user["created_at"]%>
134
+ Recurly Management URL: <%=user["recurly_url"]%>
135
+ <% if user["heroku"] %>
136
+ Heroku Account Linked: <%=user["heroku_activation_done"]%>
137
+ <% end %>
138
+ EOF
120
139
  HEROKU_CONFIG = "
121
140
  Tddium is configured to work with your Heroku app.
122
141
 
@@ -131,6 +150,27 @@ $ tddium suite
131
150
  $ tddium spec
132
151
 
133
152
  "
153
+ SUITE_DETAILS =<<EOF;
154
+ Repo: <%=suite["repo_name"]%>/<%=suite["branch"]%>
155
+ Default Test Pattern: <%=suite["test_pattern"]%>
156
+ <% if suite["ci_pull_url"] %>
157
+ Tddium Hosted CI is enabled with the following parameters:
158
+
159
+ Pull URL: <%=suite["ci_pull_url"]%>
160
+ Push URL: <%=suite["ci_push_url"]%>
161
+
162
+ Notifications:
163
+ <%=suite["ci_notifications"]%>
164
+
165
+ Authorize the following SSH key to let Tddium's pulls and pushes through:
166
+
167
+ <%=suite["ci_ssh_pubkey"]%>
168
+
169
+ To trigger CI builds, POST to the following URL from a post-commit hook:
170
+
171
+ <%=suite["hook_uri"]%>
172
+ <% end %>
173
+ EOF
134
174
  end
135
175
 
136
176
  module Error
@@ -3,5 +3,5 @@ Copyright (c) 2011 Solano Labs All Rights Reserved
3
3
  =end
4
4
 
5
5
  module TddiumVersion
6
- VERSION = "0.5.6"
6
+ VERSION = "0.6.0"
7
7
  end
data/lib/tddium.rb CHANGED
@@ -8,6 +8,7 @@ require "highline/import"
8
8
  require "json"
9
9
  require "tddium_client"
10
10
  require "base64"
11
+ require 'erb'
11
12
  require File.expand_path("../tddium/constant", __FILE__)
12
13
  require File.expand_path("../tddium/heroku", __FILE__)
13
14
 
@@ -297,6 +298,9 @@ class Tddium < Thor
297
298
 
298
299
  desc "suite", "Register the suite for this project, or manage its settings"
299
300
  method_option :name, :type => :string, :default => nil
301
+ method_option :pull_url, :type => :string, :default => nil
302
+ method_option :push_url, :type => :string, :default => nil
303
+ method_option :test_pattern, :type => :string, :default => nil
300
304
  method_option :environment, :type => :string, :default => nil
301
305
  def suite
302
306
  set_default_environment(options[:environment])
@@ -307,45 +311,20 @@ class Tddium < Thor
307
311
  if current_suite_id
308
312
  current_suite = call_api(:get, current_suite_path)["suite"]
309
313
 
310
- say Text::Process::EXISTING_SUITE % "#{current_suite["repo_name"]}/#{current_suite["branch"]}"
314
+ say Text::Process::EXISTING_SUITE % format_suite_details(current_suite)
315
+ #prompt_update_suite(current_suite, options)
311
316
  else
312
317
  params[:branch] = current_git_branch
313
318
  default_suite_name = File.basename(Dir.pwd)
314
319
  params[:repo_name] = options[:name] || default_suite_name
315
320
 
316
- existing_suite = nil
317
- use_existing_suite = false
318
- suite_name_resolved = false
319
- while !suite_name_resolved
320
- # Check to see if there is an existing suite
321
- current_suites = call_api(:get, Api::Path::SUITES, params)
322
- existing_suite = current_suites["suites"].first
323
-
324
- # Get the suite name
325
- current_suite_name = params[:repo_name]
326
- if existing_suite
327
- # Prompt for using existing suite (unless suite name is passed from command line) or entering new one
328
- params[:repo_name] = prompt(Text::Prompt::USE_EXISTING_SUITE % params[:branch], options[:name], current_suite_name)
329
- if options[:name] || params[:repo_name] == Text::Prompt::Response::YES
330
- # Use the existing suite, so assign the value back and exit the loop
331
- params[:repo_name] = current_suite_name
332
- use_existing_suite = true
333
- suite_name_resolved = true
334
- end
335
- elsif current_suite_name == default_suite_name
336
- # Prompt for using default suite name or entering new one
337
- params[:repo_name] = prompt(Text::Prompt::SUITE_NAME, options[:name], current_suite_name)
338
- suite_name_resolved = true if params[:repo_name] == default_suite_name
339
- else
340
- # Suite name does not exist yet and already prompted
341
- suite_name_resolved = true
342
- end
343
- end
321
+ use_existing_suite, existing_suite = resolve_suite_name(options, params, default_suite_name)
344
322
 
345
323
  if use_existing_suite
346
324
  # Write to file and exit when using the existing suite
347
325
  write_suite(existing_suite["id"])
348
- say Text::Status::USING_SUITE % [existing_suite["repo_name"], existing_suite["branch"]]
326
+ say Text::Status::USING_SUITE % format_suite_details(existing_suite)
327
+ #prompt_update_suite(existing_suite, options)
349
328
  return
350
329
  end
351
330
 
@@ -353,17 +332,21 @@ class Tddium < Thor
353
332
  params[:bundler_version] = dependency_version(:bundle)
354
333
  params[:rubygems_version] = dependency_version(:gem)
355
334
 
335
+ prompt_suite_params(options, params)
356
336
 
357
337
  # Create new suite if it does not exist yet
358
- say Text::Process::CREATING_SUITE % params[:repo_name]
338
+ say Text::Process::CREATING_SUITE % [params[:repo_name], params[:branch]]
359
339
  new_suite = call_api(:post, Api::Path::SUITES, {:suite => params})
360
340
  # Save the created suite
361
341
  write_suite(new_suite["suite"]["id"])
362
342
 
363
343
  # Manage git
364
344
  update_git_remote_and_push(new_suite)
345
+
346
+ say Text::Process::CREATED_SUITE % format_suite_details(new_suite["suite"])
365
347
  end
366
348
  rescue TddiumClient::Error::Base
349
+ exit_failure
367
350
  end
368
351
  end
369
352
 
@@ -517,6 +500,55 @@ class Tddium < Thor
517
500
  data
518
501
  end
519
502
 
503
+ def prompt_suite_params(options, params)
504
+ params[:test_pattern] = prompt(Text::Prompt::TEST_PATTERN, options[:test_pattern], Default::SUITE_TEST_PATTERN)
505
+ if prompt(Text::Prompt::ENABLE_CI, options[:pull_url] ? 'y' : nil, 'n') == Text::Prompt::Response::YES
506
+ params[:ci_pull_url] = prompt(Text::Prompt::CI_PULL_URL, options[:pull_url], nil)
507
+ params[:ci_push_url] = prompt(Text::Prompt::CI_PUSH_URL, options[:push_url], nil)
508
+ if prompt(Text::Prompt::ENABLE_CAMPFIRE, nil, 'n') == Text::Prompt::Response::YES
509
+ params[:campfire_subdomain] = prompt(Text::Prompt::CAMPFIRE_SUBDOMAIN, options[:campfire_subdomain], nil)
510
+ params[:campfire_token] = prompt(Text::Prompt::CAMPFIRE_TOKEN, options[:campfire_token], nil)
511
+ params[:campfire_room] = prompt(Text::Prompt::CAMPFIRE_ROOM, options[:campfire_room], nil)
512
+ end
513
+ end
514
+ end
515
+
516
+ def prompt_update_suite(api_response, options)
517
+ say Text::Prompt::UPDATE_SUITE
518
+ end
519
+
520
+ def resolve_suite_name(options, params, default_suite_name)
521
+ # XXX updates params
522
+ existing_suite = nil
523
+ use_existing_suite = false
524
+ suite_name_resolved = false
525
+ while !suite_name_resolved
526
+ # Check to see if there is an existing suite
527
+ current_suites = call_api(:get, Api::Path::SUITES, params)
528
+ existing_suite = current_suites["suites"].first
529
+
530
+ # Get the suite name
531
+ current_suite_name = params[:repo_name]
532
+ if existing_suite
533
+ # Prompt for using existing suite (unless suite name is passed from command line) or entering new one
534
+ params[:repo_name] = prompt(Text::Prompt::USE_EXISTING_SUITE % params[:branch], options[:name], current_suite_name)
535
+ if options[:name] || params[:repo_name] == Text::Prompt::Response::YES
536
+ # Use the existing suite, so assign the value back and exit the loop
537
+ params[:repo_name] = current_suite_name
538
+ use_existing_suite = true
539
+ suite_name_resolved = true
540
+ end
541
+ elsif current_suite_name == default_suite_name
542
+ # Prompt for using default suite name or entering new one
543
+ params[:repo_name] = prompt(Text::Prompt::SUITE_NAME, options[:name], current_suite_name)
544
+ suite_name_resolved = true if params[:repo_name] == default_suite_name
545
+ else
546
+ # Suite name does not exist yet and already prompted
547
+ suite_name_resolved = true
548
+ end
549
+ end
550
+ [use_existing_suite, existing_suite]
551
+ end
520
552
 
521
553
  def set_default_environment(env)
522
554
  if env.nil?
@@ -549,15 +581,15 @@ class Tddium < Thor
549
581
  # Given the user is logged in, she should be able to use "tddium account" to display information about her account:
550
582
  # Email address
551
583
  # Account creation date
552
- say "Username: "+api_response["user"]["email"]
553
- say "Account Created: " + api_response["user"]["created_at"]
554
- say "Recurly Management URL: " + api_response["user"]["recurly_url"]
555
- say "CI Public Key: " + api_response["user"]["ci_ssh_pubkey"] if api_response["user"]["ci_ssh_pubkey"]
556
- say "Suites: " + api_response["user"]["suites"] if api_response["user"]["suites"]
557
- say "Heroku Account Linked: #{api_response["user"]["heroku_activation_done"]}" if api_response["user"]["heroku"]
584
+ user = api_response["user"]
585
+ say ERB.new(Text::Status::USER_DETAILS).result(binding)
558
586
  end
559
587
 
560
- def show_ci_info(api_response)
588
+ def format_suite_details(suite)
589
+ # Given an API response containing a "suite" key, compose a string with
590
+ # important information about the suite
591
+ details = ERB.new(Text::Status::SUITE_DETAILS).result(binding)
592
+ details
561
593
  end
562
594
 
563
595
  def suite_for_current_branch?
data/spec/tddium_spec.rb CHANGED
@@ -33,9 +33,16 @@ describe Tddium do
33
33
  SAMPLE_SUITE_ID = 1
34
34
  SAMPLE_USER_ID = 1
35
35
  DEFAULT_TEST_PATTERN = Tddium::Default::TEST_PATTERN
36
+ SAMPLE_SUITE_PATTERN = "features/*.feature, spec/**/*_spec.rb"
36
37
  CUSTOM_TEST_PATTERN = "**/cat_spec.rb"
37
- SAMPLE_SUITE_RESPONSE = {"repo_name" => SAMPLE_APP_NAME, "branch" => SAMPLE_BRANCH_NAME, "id" => SAMPLE_SUITE_ID, "ruby_version"=>SAMPLE_RUBY_VERSION, "git_repo_uri" => SAMPLE_GIT_REPO_URI}
38
+ SAMPLE_SUITE_RESPONSE = {"repo_name" => SAMPLE_APP_NAME,
39
+ "branch" => SAMPLE_BRANCH_NAME,
40
+ "id" => SAMPLE_SUITE_ID,
41
+ "ruby_version"=>SAMPLE_RUBY_VERSION,
42
+ "git_repo_uri" => SAMPLE_GIT_REPO_URI,
43
+ "test_pattern" => SAMPLE_SUITE_PATTERN}
38
44
  SAMPLE_SUITES_RESPONSE = {"suites" => [SAMPLE_SUITE_RESPONSE]}
45
+ SAMPLE_SUITE_OUTPUT = "Repo: #{SAMPLE_APP_NAME}/#{SAMPLE_BRANCH_NAME}\nDefault Test Pattern: #{SAMPLE_SUITE_PATTERN}\n\n"
39
46
  SAMPLE_TDDIUM_CONFIG_FILE = ".tddium.test"
40
47
  SAMPLE_TEST_EXECUTION_STATS = "total 1, notstarted 0, started 1, passed 0, failed 0, pending 0, error 0", "start_time"
41
48
  SAMPLE_USER_RESPONSE = {"status"=>0, "user"=>
@@ -1439,8 +1446,8 @@ describe Tddium do
1439
1446
 
1440
1447
  it_should_behave_like "writing the suite to file"
1441
1448
 
1442
- it "should show the user: '#{Tddium::Text::Status::USING_SUITE % [SAMPLE_APP_NAME, SAMPLE_BRANCH_NAME]}'" do
1443
- tddium.should_receive(:say).with(Tddium::Text::Status::USING_SUITE % [SAMPLE_APP_NAME, SAMPLE_BRANCH_NAME])
1449
+ it "should show the user: '#{Tddium::Text::Status::USING_SUITE % SAMPLE_SUITE_OUTPUT}'" do
1450
+ tddium.should_receive(:say).with(Tddium::Text::Status::USING_SUITE % SAMPLE_SUITE_OUTPUT)
1444
1451
  run_suite(tddium)
1445
1452
  end
1446
1453
  end
@@ -1481,13 +1488,36 @@ describe Tddium do
1481
1488
  context "interactive mode" do
1482
1489
  before do
1483
1490
  tddium.stub(:ask).with(Tddium::Text::Prompt::USE_EXISTING_SUITE % SAMPLE_BRANCH_NAME % SAMPLE_APP_NAME).and_return("foobar")
1491
+ tddium.stub(:ask).with(Tddium::Text::Prompt::TEST_PATTERN).and_return(SAMPLE_SUITE_PATTERN)
1484
1492
  stub_default_suite_name
1485
1493
  end
1486
1494
 
1487
- it "should POST the user's entered values to the API" do
1488
- tddium.should_receive(:say).with(Tddium::Text::Process::CREATING_SUITE % "foobar")
1489
- call_api_should_receive(:method => :post, :params => {:suite => hash_including(:repo_name => "foobar")})
1490
- run_suite(tddium)
1495
+ context "no ci url" do
1496
+ it "should POST the user's entered values to the API" do
1497
+ tddium.should_receive(:say).with(Tddium::Text::Process::CREATING_SUITE % ["foobar", SAMPLE_BRANCH_NAME])
1498
+ call_api_should_receive(:method => :post, :params => {:suite => hash_including(:repo_name => "foobar", :test_pattern=>SAMPLE_SUITE_PATTERN)})
1499
+ run_suite(tddium)
1500
+ end
1501
+ end
1502
+
1503
+ context "enable ci and campfire" do
1504
+ before do
1505
+ tddium.stub(:ask).with(Tddium::Text::Prompt::ENABLE_CI).and_return(Tddium::Text::Prompt::Response::YES)
1506
+ tddium.stub(:ask).with(Tddium::Text::Prompt::ENABLE_CAMPFIRE).and_return(Tddium::Text::Prompt::Response::YES)
1507
+ end
1508
+
1509
+ it "should prompt for URLs" do
1510
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::CI_PULL_URL)
1511
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::CI_PUSH_URL)
1512
+ run_suite(tddium)
1513
+ end
1514
+
1515
+ it "should prompt for campfire" do
1516
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::CAMPFIRE_SUBDOMAIN)
1517
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::CAMPFIRE_TOKEN)
1518
+ tddium.should_receive(:ask).with(Tddium::Text::Prompt::CAMPFIRE_ROOM)
1519
+ run_suite(tddium)
1520
+ end
1491
1521
  end
1492
1522
  end
1493
1523
 
@@ -1513,14 +1543,7 @@ describe Tddium do
1513
1543
 
1514
1544
  context "'GET #{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}' is successful" do
1515
1545
  before(:each) do
1516
- response = {
1517
- "suite" => {
1518
- "id" => SAMPLE_SUITE_ID,
1519
- "repo_name" => SAMPLE_APP_NAME,
1520
- "branch" => SAMPLE_BRANCH_NAME
1521
- }
1522
- }
1523
- stub_call_api_response(:get, "#{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}", response)
1546
+ stub_call_api_response(:get, "#{Tddium::Api::Path::SUITES}/#{SAMPLE_SUITE_ID}", {"suite"=>SAMPLE_SUITE_RESPONSE})
1524
1547
  end
1525
1548
 
1526
1549
  it "should not ask for a suite name" do
@@ -1535,7 +1558,7 @@ describe Tddium do
1535
1558
  end
1536
1559
 
1537
1560
  it "should display '#{Tddium::Text::Process::EXISTING_SUITE}'" do
1538
- tddium.should_receive(:say).with(Tddium::Text::Process::EXISTING_SUITE % "#{SAMPLE_APP_NAME}/#{SAMPLE_BRANCH_NAME}")
1561
+ tddium.should_receive(:say).with(Tddium::Text::Process::EXISTING_SUITE % SAMPLE_SUITE_OUTPUT)
1539
1562
  run_suite(tddium)
1540
1563
  end
1541
1564
 
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tddium-preview
3
3
  version: !ruby/object:Gem::Version
4
- hash: 7
5
4
  prerelease:
6
- segments:
7
- - 0
8
- - 5
9
- - 6
10
- version: 0.5.6
5
+ version: 0.6.0
11
6
  platform: ruby
12
7
  authors:
13
8
  - Solano Labs
@@ -15,7 +10,7 @@ autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
12
 
18
- date: 2011-06-14 00:00:00 -07:00
13
+ date: 2011-06-15 00:00:00 -07:00
19
14
  default_executable:
20
15
  dependencies:
21
16
  - !ruby/object:Gem::Dependency
@@ -26,9 +21,6 @@ dependencies:
26
21
  requirements:
27
22
  - - ">="
28
23
  - !ruby/object:Gem::Version
29
- hash: 3
30
- segments:
31
- - 0
32
24
  version: "0"
33
25
  type: :runtime
34
26
  version_requirements: *id001
@@ -40,9 +32,6 @@ dependencies:
40
32
  requirements:
41
33
  - - ">="
42
34
  - !ruby/object:Gem::Version
43
- hash: 3
44
- segments:
45
- - 0
46
35
  version: "0"
47
36
  type: :runtime
48
37
  version_requirements: *id002
@@ -54,9 +43,6 @@ dependencies:
54
43
  requirements:
55
44
  - - ">="
56
45
  - !ruby/object:Gem::Version
57
- hash: 3
58
- segments:
59
- - 0
60
46
  version: "0"
61
47
  type: :runtime
62
48
  version_requirements: *id003
@@ -68,11 +54,6 @@ dependencies:
68
54
  requirements:
69
55
  - - ">="
70
56
  - !ruby/object:Gem::Version
71
- hash: 19
72
- segments:
73
- - 0
74
- - 0
75
- - 6
76
57
  version: 0.0.6
77
58
  type: :runtime
78
59
  version_requirements: *id004
@@ -84,9 +65,6 @@ dependencies:
84
65
  requirements:
85
66
  - - ">="
86
67
  - !ruby/object:Gem::Version
87
- hash: 3
88
- segments:
89
- - 0
90
68
  version: "0"
91
69
  type: :runtime
92
70
  version_requirements: *id005
@@ -98,9 +76,6 @@ dependencies:
98
76
  requirements:
99
77
  - - ">="
100
78
  - !ruby/object:Gem::Version
101
- hash: 3
102
- segments:
103
- - 0
104
79
  version: "0"
105
80
  type: :development
106
81
  version_requirements: *id006
@@ -112,9 +87,6 @@ dependencies:
112
87
  requirements:
113
88
  - - ">="
114
89
  - !ruby/object:Gem::Version
115
- hash: 3
116
- segments:
117
- - 0
118
90
  version: "0"
119
91
  type: :development
120
92
  version_requirements: *id007
@@ -126,9 +98,6 @@ dependencies:
126
98
  requirements:
127
99
  - - ">="
128
100
  - !ruby/object:Gem::Version
129
- hash: 3
130
- segments:
131
- - 0
132
101
  version: "0"
133
102
  type: :development
134
103
  version_requirements: *id008
@@ -140,9 +109,6 @@ dependencies:
140
109
  requirements:
141
110
  - - ">="
142
111
  - !ruby/object:Gem::Version
143
- hash: 3
144
- segments:
145
- - 0
146
112
  version: "0"
147
113
  type: :development
148
114
  version_requirements: *id009
@@ -192,18 +158,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
192
158
  requirements:
193
159
  - - ">="
194
160
  - !ruby/object:Gem::Version
195
- hash: 3
196
- segments:
197
- - 0
198
161
  version: "0"
199
162
  required_rubygems_version: !ruby/object:Gem::Requirement
200
163
  none: false
201
164
  requirements:
202
165
  - - ">="
203
166
  - !ruby/object:Gem::Version
204
- hash: 3
205
- segments:
206
- - 0
207
167
  version: "0"
208
168
  requirements: []
209
169