stairs 0.6.1 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 33b582fd2fb33082959934152985b5fde210cb23
4
- data.tar.gz: 283a59e20d7e5eb6730553b305f1632a58723789
3
+ metadata.gz: d00a852f658b8f3191f7ae6c5f7edf56823ecc38
4
+ data.tar.gz: 424bc1126fe1cb6757b735a3b72a95032e225518
5
5
  SHA512:
6
- metadata.gz: 79a9879b665d47712c18bd84622f896f99d3ac78ae247c0a7daf841463ec6e29dac0d523847c02593780e440a249cc36285af8eb8fd364aa7499eadfb2e0f58c
7
- data.tar.gz: add58a9fd0211cc3ff9518805b6f474043848f37af26e793bbebb5c1021c2fe9a9fb1d8e3d7c3920f13005429c016b065296f672f786d95154bfe09154d18abf
6
+ metadata.gz: 4b7faabcf3e3168c77a3e3afb2d9da5d1cdb020ab71dd4f8a3a90870e4605b39ef37f496e5243e05fb26f4b7cb53a0d6af87d6ea939474892efeb64faefbf59e
7
+ data.tar.gz: 53e273c0bf8ed61bc395cae6b366e9d9e32f12f54741f021dbf3dff5d6a645ae93e7d092156a079746d46abee344fea28b87622247281b330f5cd8359283b427
data/.rubocop.yml CHANGED
@@ -8,10 +8,6 @@ LineLength:
8
8
  CaseIndentation:
9
9
  Enabled: false
10
10
 
11
- # This was offending when it shouldn't have been, like in util/file_mutation:21
12
- UselessAssignment:
13
- Enabled: false
14
-
15
11
  # Seems unnecessary?
16
12
  ReduceArguments:
17
13
  Enabled: false
data/README.md CHANGED
@@ -20,6 +20,21 @@ interactive prompts for everything else.
20
20
  [![Build Status](https://travis-ci.org/patbenatar/stairs.png?branch=master)](https://travis-ci.org/patbenatar/stairs)
21
21
  [![Code Climate](https://codeclimate.com/github/patbenatar/stairs.png)](https://codeclimate.com/github/patbenatar/stairs)
22
22
 
23
+ ## Table of Contents
24
+
25
+ * [Setup](#setup)
26
+ * [Running Scripts](#running-scripts)
27
+ * [Command Line Utility](#advanced)
28
+ * [Defining Scripts](#defining-scripts)
29
+ * [Collecting Input](#collecting-values)
30
+ * [Asking Questions](#asking-questions)
31
+ * [Setting ENV vars](#setting-env-vars)
32
+ * [Writing to Files](#writing-files)
33
+ * [Miscellaneous](#misc-helpers)
34
+ * [Steps](#steps)
35
+ * [Groups](#groups)
36
+ * [Plugins](#plugins)
37
+
23
38
  ## Setup
24
39
 
25
40
  ### Rails
@@ -42,7 +57,7 @@ Same as above, but you'll have to manually add the Stairs Rake tasks to your
42
57
  require "stairs/tasks"
43
58
  ```
44
59
 
45
- ## Usage
60
+ ## Running Scripts
46
61
 
47
62
  ### Basic
48
63
 
@@ -60,6 +75,7 @@ If you want more control, use the `stairs` command line utility:
60
75
  $ stairs --help
61
76
  Usage: stairs [options]
62
77
  --use-defaults Use defaults when available
78
+ -g, --groups GROUPS Specify groups to run. e.g. init,reset
63
79
  ```
64
80
 
65
81
  ## Defining scripts
@@ -99,8 +115,9 @@ end
99
115
  dinner = choice "Meat or vegetables?", ["Meat", "Vegetables"]
100
116
  ```
101
117
 
102
- ### Setting env vars
103
- Stairs currently supports writing environment variables for rbenv-vars, RVM, and dotenv.
118
+ ### Setting ENV vars
119
+ Stairs currently supports writing environment variables for rbenv-vars, RVM, and
120
+ dotenv.
104
121
 
105
122
  ```ruby
106
123
  env "NAME", value
@@ -124,7 +141,9 @@ Display a message when setup completes
124
141
  finish "Now that you're done, go have a drink!"
125
142
  ```
126
143
 
127
- ### Defining setup steps
144
+ ### Steps
145
+
146
+ Group related setup procedures into named steps using `setup`:
128
147
 
129
148
  ```ruby
130
149
  setup :a_cool_service do
@@ -133,12 +152,48 @@ end
133
152
  ```
134
153
 
135
154
  #### Using predefined steps (aka plugins)
155
+
136
156
  ```ruby
137
157
  setup :s3
138
158
  setup :facebook, required: false
139
159
  ```
140
160
 
141
- ## Plugins for common setups
161
+ [Available Plugins](#plugins)
162
+
163
+ ### Groups
164
+
165
+ Stairs supports organizing your script into groups in a way similar to what you
166
+ may be used to with Bundler. With groups you can target specific steps to run
167
+ for different use cases (see `-g` option in the [command line utility](#advanced)).
168
+
169
+ Anything outside of a group will always be executed. Anything within a group
170
+ will only be executed when its group is run. By default, Stairs runs the `newb`
171
+ group with `$ rake newb`.
172
+
173
+ For example, you may want to run different steps on a brand new setup than you
174
+ would when resetting an existing setup:
175
+
176
+ ```ruby
177
+ group :newb do
178
+ setup :s3
179
+ end
180
+
181
+ group :newb, :reset do
182
+ setup :balanced
183
+ rake "db:setup"
184
+ end
185
+ ```
186
+
187
+ And then run your reset like so:
188
+
189
+ ```bash
190
+ $ stairs -g reset
191
+ ```
192
+
193
+ ## Plugins
194
+
195
+ Many projects share dependencies. Plugins are predefined setup steps for common
196
+ use cases.
142
197
 
143
198
  Some steps support options. Options are specified as a hash like so:
144
199
 
data/bin/stairs CHANGED
@@ -3,6 +3,8 @@
3
3
  require "optparse"
4
4
  require "stairs"
5
5
 
6
+ groups = nil
7
+
6
8
  Stairs.configure do |config|
7
9
  OptionParser.new do |options|
8
10
  options.banner = "Usage: stairs [options]"
@@ -10,6 +12,14 @@ Stairs.configure do |config|
10
12
  options.on("--use-defaults", "Use defaults when available") do |value|
11
13
  config.use_defaults = value
12
14
  end
15
+
16
+ options.on(
17
+ "-g",
18
+ "--groups GROUPS",
19
+ "Specify groups to run. e.g. init,reset"
20
+ ) do |value|
21
+ groups = value.split(",").map { |g| g.to_sym } if value
22
+ end
13
23
  end.parse!
14
24
  end
15
25
 
@@ -17,4 +27,4 @@ end
17
27
  rails_application = File.expand_path("./config/application.rb")
18
28
  require rails_application if File.exists?(rails_application)
19
29
 
20
- Stairs::Runner.new.run!
30
+ Stairs::Runner.new(groups).run!
data/lib/stairs/runner.rb CHANGED
@@ -1,8 +1,16 @@
1
1
  module Stairs
2
2
  class Runner
3
+ def initialize(groups=nil)
4
+ @groups = groups
5
+ end
6
+
3
7
  def run!
4
8
  Stairs::InteractiveConfiguration.new.run!
5
- Stairs::Script.new("setup.rb").run!
9
+ Stairs::Script.new("setup.rb", groups).run!
6
10
  end
11
+
12
+ private
13
+
14
+ attr_reader :groups
7
15
  end
8
16
  end
data/lib/stairs/script.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  module Stairs
2
2
  class Script
3
- def initialize(filename)
3
+ def initialize(filename, groups)
4
4
  @filename = filename
5
5
  @script = File.read(@filename)
6
+ @groups = groups
6
7
  end
7
8
 
8
9
  def run!
@@ -13,9 +14,9 @@ module Stairs
13
14
  private
14
15
 
15
16
  def run
16
- Step.new.instance_eval(script)
17
+ Step.new(groups).instance_eval(script)
17
18
  end
18
19
 
19
- attr_reader :script, :filename
20
+ attr_reader :script, :filename, :groups
20
21
  end
21
22
  end
data/lib/stairs/step.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  module Stairs
2
2
  class Step
3
- attr_reader :options
3
+ attr_reader :options, :groups
4
4
 
5
- def initialize(options={})
5
+ def initialize(*args)
6
+ options = args.extract_options!
6
7
  @options = options.reverse_merge required: true
8
+
9
+ @groups = args.first
7
10
  end
8
11
 
9
12
  def run!
@@ -85,16 +88,20 @@ module Stairs
85
88
  # of Step
86
89
  def setup(step_name, options={}, &block)
87
90
  if block_given?
88
- Step.new(options).tap do |step|
91
+ Step.new(groups, options).tap do |step|
89
92
  step.define_singleton_method :run, &block
90
93
  step.step_title = step_name.to_s.titleize
91
94
  end.run!
92
95
  else
93
96
  klass = "Stairs::Steps::#{step_name.to_s.camelize}".constantize
94
- klass.new(options).run!
97
+ klass.new(groups, options).run!
95
98
  end
96
99
  end
97
100
 
101
+ def group(*names)
102
+ yield if !groups || (names & groups).any?
103
+ end
104
+
98
105
  def finish(message)
99
106
  puts "== All done!".green
100
107
  puts message.green
data/lib/stairs/tasks.rb CHANGED
@@ -7,7 +7,7 @@ module Stairs
7
7
  def install!
8
8
  desc "Setup the project"
9
9
  task :newb do
10
- Stairs::Runner.new.run!
10
+ Stairs::Runner.new([:newb]).run!
11
11
  end
12
12
  end
13
13
  end
@@ -28,7 +28,7 @@ module Stairs
28
28
  def write_line(string, filename)
29
29
  File.open filename, "a+" do |file|
30
30
  # ensure file ends with newline before appending
31
- last_line = file.each_line.reduce("") { |m, l| m = l }
31
+ last_line = file.each_line.reduce("") { |m, l| l }
32
32
  file.puts "" unless last_line == "" || last_line =~ /(.*)\n/
33
33
 
34
34
  file.puts string
@@ -1,3 +1,3 @@
1
1
  module Stairs
2
- VERSION = "0.6.1"
2
+ VERSION = "0.7.0"
3
3
  end
@@ -1,6 +1,9 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Stairs::Runner do
4
+ let(:groups) { nil }
5
+ let(:subject) { described_class.new(groups) }
6
+
4
7
  describe "#run!" do
5
8
  let(:script_double) { double("script", run!: true) }
6
9
 
@@ -16,11 +19,20 @@ describe Stairs::Runner do
16
19
  subject.run!
17
20
  end
18
21
 
19
- it "runs the setup.rb script" do
20
- Stairs::Script.should_receive(:new).with("setup.rb").and_return(script_double)
22
+ it "runs all groups in the setup.rb script" do
23
+ Stairs::Script.should_receive(:new).with("setup.rb", groups).and_return(script_double)
21
24
  script_double.should_receive(:run!)
22
25
 
23
26
  subject.run!
24
27
  end
28
+
29
+ context "with groups provided" do
30
+ let(:groups) { [:reset] }
31
+
32
+ it "passes the specified groups to the script" do
33
+ Stairs::Script.should_receive(:new).with("setup.rb", groups)
34
+ subject.run!
35
+ end
36
+ end
25
37
  end
26
38
  end
@@ -2,7 +2,9 @@ require "spec_helper"
2
2
 
3
3
  describe Stairs::Script do
4
4
  let(:filename) { "setup.rb" }
5
- subject { described_class.new(filename) }
5
+ let(:groups) { [:reset] }
6
+ subject { described_class.new(filename, groups) }
7
+
6
8
 
7
9
  context "with a script present" do
8
10
  before do
@@ -13,12 +15,23 @@ describe Stairs::Script do
13
15
 
14
16
  after { File.delete(filename) }
15
17
 
18
+ describe "initialize" do
19
+ it "receives groups" do
20
+ expect { described_class.new(filename, groups) }.not_to raise_error
21
+ end
22
+ end
23
+
16
24
  describe "#run!" do
17
25
  it "outputs running message" do
18
26
  output = capture_stdout { subject.run! }
19
27
  expect(output).to include "= Running script setup.rb"
20
28
  end
21
29
 
30
+ it "passes groups to the new instance of Step" do
31
+ Stairs::Step.should_receive(:new).with(groups)
32
+ subject.run!
33
+ end
34
+
22
35
  it "evaluates the script in the context of an instance of Step" do
23
36
  # because our test setup.rb only contains `self.class` we can check
24
37
  # this way:
@@ -26,4 +39,4 @@ describe Stairs::Script do
26
39
  end
27
40
  end
28
41
  end
29
- end
42
+ end
@@ -2,7 +2,8 @@ require "spec_helper"
2
2
 
3
3
  describe Stairs::Step do
4
4
  let(:anon_step) { Class.new(described_class) }
5
- subject { anon_step.new }
5
+ let(:groups) { nil }
6
+ subject { anon_step.new(groups) }
6
7
 
7
8
  describe "metadata" do
8
9
  describe "step_title" do
@@ -42,21 +43,27 @@ describe Stairs::Step do
42
43
  end
43
44
  end
44
45
 
45
- describe "options" do
46
- describe "default options" do
47
- it "is required" do
48
- expect(subject.options[:required]).to be_true
46
+ describe "#initialize" do
47
+ describe "options" do
48
+ describe "default options" do
49
+ it "is required" do
50
+ expect(subject.options[:required]).to be_true
51
+ end
49
52
  end
50
- end
51
53
 
52
- context "with options" do
53
- let(:options) { { something: "cool" } }
54
- subject { anon_step.new(options) }
54
+ context "with options" do
55
+ let(:options) { { something: "cool" } }
56
+ subject { anon_step.new(options) }
55
57
 
56
- it "exposes options on the instance" do
57
- expect(subject.options[:something]).to eq "cool"
58
+ it "exposes options on the instance" do
59
+ expect(subject.options[:something]).to eq "cool"
60
+ end
58
61
  end
59
62
  end
63
+
64
+ it "exposes supplied groups on the instance" do
65
+ expect(subject.groups).to eq groups
66
+ end
60
67
  end
61
68
 
62
69
  describe "#run!" do
@@ -314,18 +321,23 @@ describe Stairs::Step do
314
321
 
315
322
  context "with a valid step_name" do
316
323
  let!(:mock_step_class) { Stairs::Steps::MockStep = Class.new(Stairs::Step) }
324
+ before { mock_step_class.any_instance.stub run!: true }
317
325
 
318
326
  it "instantiates and runs the step" do
319
327
  mock_step_class.any_instance.should_receive(:run!)
320
328
  subject.setup :mock_step
321
329
  end
322
330
 
331
+ it "passes groups to the step" do
332
+ mock_step_class.should_receive(:new).with(groups, {}).and_call_original
333
+ subject.setup :mock_step
334
+ end
335
+
323
336
  context "with options" do
324
337
  let(:options) { { something: "cool" } }
325
- before { mock_step_class.any_instance.stub run!: true }
326
338
 
327
339
  it "passes options to the step" do
328
- mock_step_class.should_receive(:new).with(options).and_call_original
340
+ mock_step_class.should_receive(:new).with(groups, options).and_call_original
329
341
  subject.setup :mock_step, options
330
342
  end
331
343
  end
@@ -336,6 +348,12 @@ describe Stairs::Step do
336
348
  subject.setup(:custom_step) { puts "I'm running in #{self.class}" }
337
349
  end
338
350
 
351
+ # Initialize primary subject before asserting against #new for the Step
352
+ # it initializes
353
+ def initialize_primary_subject
354
+ instance = subject
355
+ end
356
+
339
357
  it "sets the new step's title to a titleized version of step_name" do
340
358
  output = capture_stdout { call_method }
341
359
  expect(output).to include "Custom Step"
@@ -346,17 +364,52 @@ describe Stairs::Step do
346
364
  expect(output).to include "I'm running in Stairs::Step"
347
365
  end
348
366
 
367
+ it "passes groups to the step" do
368
+ initialize_primary_subject
369
+
370
+ described_class.should_receive(:new).with(groups, {}).and_call_original
371
+ call_method
372
+ end
373
+
349
374
  context "with options" do
350
375
  let(:options) { { something: "cool" } }
351
376
  before { described_class.any_instance.stub run!: true }
352
377
 
353
378
  it "passes options to the step" do
354
- instance = subject # Initialize class before asserting against #new
379
+ initialize_primary_subject
355
380
 
356
- described_class.should_receive(:new).with(options).and_call_original
381
+ described_class.should_receive(:new).with(groups, options).and_call_original
357
382
  subject.setup(:custom_step, options) { true }
358
383
  end
359
384
  end
360
385
  end
361
386
  end
387
+
388
+ describe "#group" do
389
+ let(:name) { :reset }
390
+
391
+ context "when the name is in the groups to run" do
392
+ let(:groups) { [:reset, :init] }
393
+
394
+ it "calls the supplied block" do
395
+ expect { |b| subject.group(name, &b) }.to yield_control
396
+ end
397
+ end
398
+
399
+ context "when the name is not in the groups to run" do
400
+ let(:groups) { [:init] }
401
+
402
+ it "does not call the supplied block" do
403
+ expect { |b| subject.group(name, &b) }.not_to yield_control
404
+ end
405
+
406
+ context "but no groups to run are provided" do
407
+ let(:groups) { nil }
408
+
409
+ it "calls the supplied block" do
410
+ expect { |b| subject.group(name, &b) }.to yield_control
411
+ end
412
+ end
413
+ end
414
+ end
362
415
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stairs
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - patbenatar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-11-27 00:00:00.000000000 Z
11
+ date: 2013-12-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler