scripted 0.0.1
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 +19 -0
- data/.rspec +3 -0
- data/.travis.yml +8 -0
- data/Gemfile +6 -0
- data/MIT-LICENSE +22 -0
- data/README.md +423 -0
- data/Rakefile +39 -0
- data/bin/scripted +67 -0
- data/cucumber.yml +3 -0
- data/examples/important.rb +31 -0
- data/examples/parallel.rb +30 -0
- data/examples/pride.rb +37 -0
- data/examples/websockets.png +0 -0
- data/examples/websockets.rb +37 -0
- data/examples/websockets/public/ansiparse.js +156 -0
- data/examples/websockets/server.rb +32 -0
- data/examples/websockets/server.ru +10 -0
- data/examples/websockets/views/_client.handlebars +47 -0
- data/examples/websockets/views/app.coffee +210 -0
- data/examples/websockets/views/index.erb +1 -0
- data/examples/websockets/views/layout.erb +14 -0
- data/examples/websockets/views/style.sass +61 -0
- data/features/controlling_exit_status.feature +124 -0
- data/features/formatters.feature +142 -0
- data/features/rake_integration.feature +86 -0
- data/features/running_commands_in_parallel.feature +27 -0
- data/features/running_from_command_line.feature +56 -0
- data/features/running_from_ruby.feature +38 -0
- data/features/running_groups.feature +39 -0
- data/features/specifying_which_commands_to_run.feature +122 -0
- data/features/steps/scripted_steps.rb +25 -0
- data/features/support/aruba.rb +5 -0
- data/features/support/env.rb +2 -0
- data/install +5 -0
- data/lib/scripted.rb +28 -0
- data/lib/scripted/command.rb +82 -0
- data/lib/scripted/commands/rake.rb +25 -0
- data/lib/scripted/commands/ruby.rb +22 -0
- data/lib/scripted/commands/shell.rb +28 -0
- data/lib/scripted/configuration.rb +103 -0
- data/lib/scripted/error.rb +13 -0
- data/lib/scripted/formatters/announcer.rb +39 -0
- data/lib/scripted/formatters/blank.rb +97 -0
- data/lib/scripted/formatters/default.rb +62 -0
- data/lib/scripted/formatters/human_status.rb +38 -0
- data/lib/scripted/formatters/stats.rb +38 -0
- data/lib/scripted/formatters/table.rb +99 -0
- data/lib/scripted/formatters/websocket.rb +137 -0
- data/lib/scripted/group.rb +49 -0
- data/lib/scripted/output/command_logger.rb +42 -0
- data/lib/scripted/output/logger.rb +139 -0
- data/lib/scripted/rake_task.rb +24 -0
- data/lib/scripted/runner.rb +19 -0
- data/lib/scripted/running/execute.rb +16 -0
- data/lib/scripted/running/run_command.rb +101 -0
- data/lib/scripted/running/run_commands.rb +98 -0
- data/lib/scripted/running/select_commands.rb +22 -0
- data/lib/scripted/version.rb +3 -0
- data/scripted.gemspec +35 -0
- data/scripted.rb +16 -0
- data/spec/scripted/command_spec.rb +72 -0
- data/spec/scripted/commands/ruby_spec.rb +10 -0
- data/spec/scripted/commands/shell_spec.rb +18 -0
- data/spec/scripted/configuration_spec.rb +50 -0
- data/spec/scripted/formatters/websocket_spec.rb +14 -0
- data/spec/scripted/group_spec.rb +49 -0
- data/spec/scripted/running/run_command_spec.rb +157 -0
- data/spec/scripted/running/run_commands_spec.rb +150 -0
- data/spec/scripted/running/select_commands_spec.rb +28 -0
- data/spec/spec_helper.rb +15 -0
- data/spec/support/expect_to_receive.rb +17 -0
- data/spec/support/io_capture.rb +50 -0
- metadata +340 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 iain
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,423 @@
|
|
1
|
+
# Scripted
|
2
|
+
|
3
|
+
[](http://travis-ci.org/iain/scripted)
|
4
|
+
|
5
|
+
Scripted is a framework for organizing scripts.
|
6
|
+
|
7
|
+
Among its features are:
|
8
|
+
|
9
|
+
* A convenient DSL to determine how and when to run scripts
|
10
|
+
* Determine which scripts in parallel with each other
|
11
|
+
* Manage the exit status of your scripts
|
12
|
+
* A variaty of output formatters, including one that exports the output of the
|
13
|
+
scripts via websockets!
|
14
|
+
* Specify groups of tasks
|
15
|
+
* Integration with Rake
|
16
|
+
|
17
|
+
See a video of [scripted running with websockets](http://www.youtube.com/watch?v=GMiN0dHtFkg).
|
18
|
+
|
19
|
+
## Reasoning
|
20
|
+
|
21
|
+
It is considered good practice to bundle all the tasks you need to do in one
|
22
|
+
script. This can be a setup script that installs your application, or a all
|
23
|
+
test scripts combined for your CI to use.
|
24
|
+
|
25
|
+
While it is very easy to make this with plain Bash scripts, I found myself
|
26
|
+
writing a lot of boiler code over and over again. I wanted to keep track of the
|
27
|
+
runtimes of each commands. Or I wanted to run certain scripts in parallel, but
|
28
|
+
still wait for them to finish.
|
29
|
+
|
30
|
+
This gem exists because I wanted to simply define which commands to run, and
|
31
|
+
not deal with all the boilerplate code every time.
|
32
|
+
|
33
|
+
## Examples
|
34
|
+
|
35
|
+
There are a number of examples included in the project. You can find them in
|
36
|
+
the `examples` directory.
|
37
|
+
|
38
|
+
* Clone the project
|
39
|
+
* Install via `./install`
|
40
|
+
* See which examples are avaibale: `rake -T examples`
|
41
|
+
* Run an example: `rake examples:websockets`
|
42
|
+
|
43
|
+
## Usage
|
44
|
+
|
45
|
+
You'll need to create a configuration file for scripted to run. By default this
|
46
|
+
file is called `scripted.rb`, but you can name it whatever you like.
|
47
|
+
|
48
|
+
After making the configuration, you can run it with the `scripted` executable.
|
49
|
+
|
50
|
+
Run `scripted --help` to get an overview of all the options.
|
51
|
+
|
52
|
+
### The Basic Command DSL
|
53
|
+
|
54
|
+
You can define "commands" via the `run`-method. For instance:
|
55
|
+
|
56
|
+
``` ruby
|
57
|
+
run "rspec"
|
58
|
+
run "cucumber"
|
59
|
+
```
|
60
|
+
|
61
|
+
The first argument to the `run`-method is the name of the command. If you don't
|
62
|
+
specify anything else, this will be the shell command run. You can change the
|
63
|
+
command further by supplying a block.
|
64
|
+
|
65
|
+
``` ruby
|
66
|
+
run "fast unit specs" do
|
67
|
+
`rspec spec/unit`
|
68
|
+
end
|
69
|
+
|
70
|
+
run "slow integration specs" do
|
71
|
+
`rspec spec/integration`
|
72
|
+
end
|
73
|
+
```
|
74
|
+
|
75
|
+
You can also specify Rake tasks and Ruby commands to run:
|
76
|
+
|
77
|
+
``` ruby
|
78
|
+
run "migrate the database" do
|
79
|
+
rake "db:migrate"
|
80
|
+
end
|
81
|
+
|
82
|
+
run "some ruby code" do
|
83
|
+
ruby { 1 + 1 }
|
84
|
+
end
|
85
|
+
```
|
86
|
+
|
87
|
+
Keep in mind that MRI has trouble running ruby and rake tasks in parallel due
|
88
|
+
to the GIL.
|
89
|
+
|
90
|
+
### Running scripts in parallel
|
91
|
+
|
92
|
+
You can really win some time by running certain commands in parallel. Doing
|
93
|
+
that is easy, just put them in a `parallel`-block:
|
94
|
+
|
95
|
+
``` ruby
|
96
|
+
run "bundle install"
|
97
|
+
|
98
|
+
parallel do
|
99
|
+
run "rspec"
|
100
|
+
run "cucumber"
|
101
|
+
end
|
102
|
+
|
103
|
+
run "something else"
|
104
|
+
```
|
105
|
+
|
106
|
+
Commands that come after the parallel block, will wait until all the commands
|
107
|
+
that run in parallel have finished.
|
108
|
+
|
109
|
+
There are only a few caveats to this. The scripts must be able to run
|
110
|
+
simultaniously. If they both access the same global data, like a database or
|
111
|
+
files on your hard disk, they will probably fail. Any output they produce
|
112
|
+
will appear at the same time, possibly making it unreadable.
|
113
|
+
|
114
|
+
You can specify multiple parallel blocks.
|
115
|
+
|
116
|
+
### Managing exit status
|
117
|
+
|
118
|
+
By default, all commands will run, even if one failed. The exit status of the
|
119
|
+
entire scripted run will hover reflect that one script has failed.
|
120
|
+
|
121
|
+
If one of your commands is so important that other commands cannot possibly
|
122
|
+
succeed afterwards, mark it with `important!`:
|
123
|
+
|
124
|
+
``` ruby
|
125
|
+
run "bundle install" do
|
126
|
+
important!
|
127
|
+
end
|
128
|
+
|
129
|
+
run "rspec"
|
130
|
+
```
|
131
|
+
|
132
|
+
If a command might fail, but you don't want the global exit status to change if
|
133
|
+
it happens, mark the command with `unimportant!`
|
134
|
+
|
135
|
+
``` ruby
|
136
|
+
run "flickering tests" do
|
137
|
+
unimportant!
|
138
|
+
end
|
139
|
+
```
|
140
|
+
|
141
|
+
If you have some clean up to do, that always must run, even if an important
|
142
|
+
command failed, mark it with `forced!`:
|
143
|
+
|
144
|
+
``` ruby
|
145
|
+
run "start xvfb" do
|
146
|
+
`/etc/init.d/xvfb start`
|
147
|
+
unimportant! # it might be on already
|
148
|
+
end
|
149
|
+
|
150
|
+
run "bundle install" do
|
151
|
+
important!
|
152
|
+
end
|
153
|
+
|
154
|
+
run "rspec"
|
155
|
+
|
156
|
+
run "stop xvfb" do
|
157
|
+
`/etc/init.d/xvfb stop`
|
158
|
+
forced!
|
159
|
+
end
|
160
|
+
```
|
161
|
+
|
162
|
+
And finally, to have a command run only if other commands have failed, mark it
|
163
|
+
with `only_when_failed!`:
|
164
|
+
|
165
|
+
``` ruby
|
166
|
+
run "mail me if build failed" do
|
167
|
+
only_when_failed!
|
168
|
+
end
|
169
|
+
```
|
170
|
+
|
171
|
+
### Formatters
|
172
|
+
|
173
|
+
Formatters determine what gets outputted. This can be to your screen, a file,
|
174
|
+
or a websocket. You can specify the formatters via the command line, or via
|
175
|
+
the configuration file.
|
176
|
+
|
177
|
+
Via the command line:
|
178
|
+
|
179
|
+
$ scripted --format my_formatter --out some_file.txt
|
180
|
+
|
181
|
+
Via the configuration file:
|
182
|
+
|
183
|
+
``` ruby
|
184
|
+
formatter :my_formatter, :out => "some_file.txt"
|
185
|
+
```
|
186
|
+
|
187
|
+
You can have multiple formatters. If you don't specify the `out` option, it
|
188
|
+
will send the output to `STDOUT`.
|
189
|
+
|
190
|
+
#### The default formatter
|
191
|
+
|
192
|
+
The formatter that is used if you don't specify anything is `default`. This
|
193
|
+
formatter will output the output of your scripts and display stacktraces. If
|
194
|
+
you specify different formatters, the default formatter will not be used. So if
|
195
|
+
you still want output to the terminal, you need to add this formatter.
|
196
|
+
|
197
|
+
$ scripted -f default -f some_other_formatter
|
198
|
+
|
199
|
+
#### Table formatter
|
200
|
+
|
201
|
+
The `table` formatter will display an ASCII table when it's done, giving an
|
202
|
+
overview of all commands.
|
203
|
+
|
204
|
+
It looks something like this:
|
205
|
+
|
206
|
+
```
|
207
|
+
┌─────────────────┬─────────┬─────────┐
|
208
|
+
│ Command │ Runtime │ Status │
|
209
|
+
├─────────────────┼─────────┼─────────┤
|
210
|
+
│ rspec │ 0.661s │ success │
|
211
|
+
│ cucumber │ 18.856s │ success │
|
212
|
+
│ cucumber -p wip │ 0.558s │ success │
|
213
|
+
└─────────────────┴─────────┴─────────┘
|
214
|
+
Total runtime: 19.527s
|
215
|
+
```
|
216
|
+
|
217
|
+
To use it:
|
218
|
+
|
219
|
+
$ scripted --format table
|
220
|
+
|
221
|
+
#### Announcer formatter
|
222
|
+
|
223
|
+
This will print a banner before each command, so you can easily see when a
|
224
|
+
command is executed.
|
225
|
+
|
226
|
+
It looks something like this:
|
227
|
+
|
228
|
+
```
|
229
|
+
┌────────────────────────────────────────────────┐
|
230
|
+
│ bundle update │
|
231
|
+
└────────────────────────────────────────────────┘
|
232
|
+
```
|
233
|
+
|
234
|
+
To use it:
|
235
|
+
|
236
|
+
$ scripted --format announcer
|
237
|
+
|
238
|
+
#### Stats formatter
|
239
|
+
|
240
|
+
The `stats` formatter will print a csv file with the same contents as the
|
241
|
+
`table`-formatter. This is handy if you want to keep track of how long your
|
242
|
+
test suite takes over time, for example.
|
243
|
+
|
244
|
+
Example:
|
245
|
+
|
246
|
+
``` csv
|
247
|
+
name,runtime,status
|
248
|
+
bundle update,5.583716,success
|
249
|
+
rspec,4.319095,success
|
250
|
+
cucumber,22.292316,failed
|
251
|
+
cucumber -p wip,0.649777,success
|
252
|
+
```
|
253
|
+
|
254
|
+
To use it:
|
255
|
+
|
256
|
+
$ scripted --format stats --out runtime.csv
|
257
|
+
|
258
|
+
Note: make sure you backup the file afterwars, because each time it runs, it
|
259
|
+
will override the file. Also, if you're running on Ruby 1.8, you'll have to
|
260
|
+
install FasterCSV.
|
261
|
+
|
262
|
+
#### Websocket formatter
|
263
|
+
|
264
|
+
And last, but not least, the `websocket` formatter. This awesome formatter will
|
265
|
+
publish the output of your commands directly to a websocket.
|
266
|
+
|
267
|
+
This is done via [Faye](http://faye.jcoglan.com/), a simple pub/sub messaging
|
268
|
+
system. It is tricky to implement this, so be sure to check out the example
|
269
|
+
code, which includes a fully functioning Ember.js application.
|
270
|
+
|
271
|
+
$ scripted -f websocket -o http://localhost:9292/faye
|
272
|
+
|
273
|
+
Make sure you have Faye running. The example does this for you.
|
274
|
+
|
275
|
+

|
276
|
+
|
277
|
+
#### Your own formatter
|
278
|
+
|
279
|
+
You can also make your own formatter. As the name of the formatter, just
|
280
|
+
specify the class name:
|
281
|
+
|
282
|
+
$ scripted -f MyAwesome::Formatter
|
283
|
+
|
284
|
+
Have a look at the existing formatters in `lib/scripted/formatters` to see how
|
285
|
+
to make one.
|
286
|
+
|
287
|
+
### Groups
|
288
|
+
|
289
|
+
You can specify different groups of commands by putting commands in a `group`
|
290
|
+
block:
|
291
|
+
|
292
|
+
``` ruby
|
293
|
+
group :test do
|
294
|
+
run "rspec"
|
295
|
+
run "cucumber"
|
296
|
+
end
|
297
|
+
|
298
|
+
group :install do
|
299
|
+
run "bundle install"
|
300
|
+
rake "db:setup"
|
301
|
+
end
|
302
|
+
```
|
303
|
+
|
304
|
+
Then you can specify one or many groups to run on the command line:
|
305
|
+
|
306
|
+
$ scripted --group install --group test
|
307
|
+
|
308
|
+
Commands that are not defined in any group are put in the `default` group.
|
309
|
+
|
310
|
+
### Rake integration
|
311
|
+
|
312
|
+
Besides calling Rake tasks from Scripted, you can also launch scripted via
|
313
|
+
Rake.
|
314
|
+
|
315
|
+
The simplest example is:
|
316
|
+
|
317
|
+
``` ruby
|
318
|
+
require 'scripted/rake_task'
|
319
|
+
Scripted::RakeTask.new(:scripted)
|
320
|
+
```
|
321
|
+
|
322
|
+
Then you can run `rake scripted`
|
323
|
+
|
324
|
+
You can pass a block to specify your commands in-line if you like:
|
325
|
+
|
326
|
+
``` ruby
|
327
|
+
require 'scripted/rake_task'
|
328
|
+
Scripted::RakeTask.new(:install) do
|
329
|
+
run "foo"
|
330
|
+
run "bar"
|
331
|
+
end
|
332
|
+
```
|
333
|
+
|
334
|
+
You can also supply different groups to run:
|
335
|
+
|
336
|
+
``` ruby
|
337
|
+
require 'scripted/rake_task'
|
338
|
+
Scripted::RakeTask.new(:ci, :install, :test)
|
339
|
+
```
|
340
|
+
|
341
|
+
Running `rake ci` will run both the `install` and `test` group.
|
342
|
+
|
343
|
+
### Ruby integration
|
344
|
+
|
345
|
+
Calling scripted from within another Ruby process is easy:
|
346
|
+
|
347
|
+
``` ruby
|
348
|
+
require 'scripted'
|
349
|
+
Scripted.run do
|
350
|
+
run "something"
|
351
|
+
end
|
352
|
+
```
|
353
|
+
|
354
|
+
## Some considerations
|
355
|
+
|
356
|
+
### Use cases
|
357
|
+
|
358
|
+
I first named this library "test_suite", and most examples show running test
|
359
|
+
suites. But Scripted isn't only for running tests. Here are some ideas:
|
360
|
+
|
361
|
+
* Installing stuff, like installing stuff you want
|
362
|
+
* Running a command perminantly and seeing the output via websockets. Like
|
363
|
+
ping, your server, or a tool that monitors your worker queues.
|
364
|
+
|
365
|
+
### Complicated setup
|
366
|
+
|
367
|
+
The beauty if plain bash scripts is that they can be run without having
|
368
|
+
anything installed. The problem with Scripted is that it is a gem and you might
|
369
|
+
need to `gem install scripted` or `bundle install` before it will work.
|
370
|
+
|
371
|
+
I prefer to have the README of my projects say, something along the lines of:
|
372
|
+
|
373
|
+
``` md
|
374
|
+
## How To
|
375
|
+
|
376
|
+
* Install: `script/install`
|
377
|
+
* Upgrade: `script/upgrade`
|
378
|
+
* Deploy: `script/deploy`
|
379
|
+
```
|
380
|
+
|
381
|
+
Nothing more. No complicated 10 step plan, just type one command and you're
|
382
|
+
good to go. You need a bash script for that.
|
383
|
+
|
384
|
+
So here is an example of how such a bash script might look like:
|
385
|
+
|
386
|
+
``` bash
|
387
|
+
#!/usr/bin/env bash
|
388
|
+
set -e
|
389
|
+
gem which scripted >/dev/null 2>&1 || gem install scripted
|
390
|
+
scripted --group install
|
391
|
+
```
|
392
|
+
|
393
|
+
### Status of the gem
|
394
|
+
|
395
|
+
This gem is in alpha state. YMMV. I believe I got the basic functionality, but
|
396
|
+
not everything is as cleanly implemented as it could be. For instance, there
|
397
|
+
are undoubtedly edge cases I didn't think of and error handling can probably be
|
398
|
+
more user friendly.
|
399
|
+
|
400
|
+
I'm putting this out there to get some feedback. Please don't hesitate to
|
401
|
+
contact me if you have any questions or ideas for improvements. Mention me on
|
402
|
+
[Twitter](https://twitter.com/iain_nl), or open an issue on Github.
|
403
|
+
|
404
|
+
### Known issues
|
405
|
+
|
406
|
+
* Works on MRI and Rubinius.
|
407
|
+
* JRuby might have problems running shell commands.
|
408
|
+
* JRuby doesn't always allow you to compile C extensions, so you cannot install
|
409
|
+
Faye. Use a different Ruby implementation or use the Node.js version.
|
410
|
+
* To get color in RSpec, use the `--tty` switch, or RSpec will not believe the
|
411
|
+
shell supports color.
|
412
|
+
* Use the `--color` switch for Cucumber.
|
413
|
+
|
414
|
+
## Contributing
|
415
|
+
|
416
|
+
To set it up, just run `./install`.
|
417
|
+
|
418
|
+
1. Fork it
|
419
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
420
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
421
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
422
|
+
5. Create new Pull Request
|
423
|
+
|