buildem 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.autotest +13 -0
- data/EXAMPLES.md +34 -0
- data/Gemfile +7 -0
- data/README.md +54 -0
- data/lib/buildem/base.rb +10 -0
- data/lib/buildem/condition_matcher.rb +15 -0
- data/lib/buildem/executor.rb +24 -6
- data/lib/buildem/runner.rb +8 -5
- data/lib/buildem/version.rb +1 -1
- data/spec/helper.rb +13 -2
- data/spec/unit/condition_matcher_spec.rb +44 -0
- data/spec/unit/executor_spec.rb +66 -0
- data/spec/unit/version_spec.rb +1 -1
- metadata +12 -6
- data/EXAMPLE +0 -16
- data/README +0 -46
data/.autotest
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'autotest/growl'
|
2
|
+
require 'autotest/fsevent'
|
3
|
+
|
4
|
+
Autotest.add_hook(:initialize) {|at|
|
5
|
+
at.add_exception %r{^\.git}
|
6
|
+
at.add_exception %r{^./tmp}
|
7
|
+
at.clear_mappings
|
8
|
+
at.add_mapping(%r{^lib/buildem/.*\.rb$}) {|f, _|
|
9
|
+
item = f.split("/").last.gsub(".rb","")
|
10
|
+
Dir["spec/unit/#{item}_spec.rb"]
|
11
|
+
}
|
12
|
+
nil
|
13
|
+
}
|
data/EXAMPLES.md
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
Worker configuration, and unordered tasks
|
2
|
+
-----------------------------------------
|
3
|
+
|
4
|
+
$configuration.workers = 2
|
5
|
+
|
6
|
+
run "initialize.sh"
|
7
|
+
run "clean.sh"
|
8
|
+
|
9
|
+
unorderd do
|
10
|
+
queued_run "job1.sh"
|
11
|
+
queued_run "job2.sh"
|
12
|
+
queued_run "job3.sh"
|
13
|
+
run "some_task_in_the_middle_of_queue.sh" # this will block all of the queued_run calls after this
|
14
|
+
queued_run "job4.sh"
|
15
|
+
queued_run "job5.sh"
|
16
|
+
queued_run "job6.sh"
|
17
|
+
end
|
18
|
+
|
19
|
+
run "do_something_at_the_end.sh"
|
20
|
+
This example will execute job 1 - 3 in any order two at a time, hit some\_task\_in\_the\_middle\_of\_queue run that wait for it to complete and then continue executing job 4 - 6 two at a time.
|
21
|
+
|
22
|
+
---
|
23
|
+
|
24
|
+
|
25
|
+
Worker configuration, and unordered tasks with options
|
26
|
+
------------------------------------------------------
|
27
|
+
|
28
|
+
run "initialize.sh"
|
29
|
+
run "clean.sh", :retry_amount => 10 # The default exitstatus for commands is 0, when specifying retry amount of 10 if the run command does not return 0 it will retry up to 10 times.
|
30
|
+
run "do_something_at_the_end.sh", {:retry_amount => 10, :retry_condition => 99} # Same as above, but is considered successful if the exitstatus is 99 due to the supplied retry_condition.
|
31
|
+
run "danger_danger_danger", :quit_on_error => false # If a task has explosive behavior (It causes an exception) :quit_on_error => false can be supplied as an option to continue execution
|
32
|
+
# regardless of problems.
|
33
|
+
|
34
|
+
These options can be applied to both queued_run, and run jobs.
|
data/Gemfile
CHANGED
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
Build'em quick, Build'em right
|
2
|
+
==============================
|
3
|
+
|
4
|
+
Build'em is a small little script parser that is intended for large build systems.
|
5
|
+
Build'em is still very young :) so be careful using it. Input is always welcome and if there is a feature that you just half to have i'd probably do it.
|
6
|
+
|
7
|
+
|
8
|
+
Features:
|
9
|
+
---------
|
10
|
+
|
11
|
+
Execution:
|
12
|
+
Scripts go in a plain text file, I use my\_very\_important\_task.buildem
|
13
|
+
and then simply call buildem my\_very\_important\_task.buildem
|
14
|
+
|
15
|
+
* Build'em supports sequential tasks (tasks that go in order)
|
16
|
+
|
17
|
+
Example:
|
18
|
+
run "./task.sh"
|
19
|
+
run "./another.sh" #another.sh waits for task.sh to complete
|
20
|
+
|
21
|
+
* Build'em supports a work queue, what does this mean?
|
22
|
+
This means that you can run tasks concurrently, easily.
|
23
|
+
|
24
|
+
Example:
|
25
|
+
|
26
|
+
unorderd do
|
27
|
+
queued_run "./some_task.sh"
|
28
|
+
queued_run "./some_task1.sh" # All of these items will be executed at the same time
|
29
|
+
queued_run "./some_task2.sh"
|
30
|
+
end
|
31
|
+
|
32
|
+
*IMPORTANT* All queued\_run tasks must be inside of an unorderd block if you want them to run at the same time. If you use run for a task, it will block to complete.
|
33
|
+
That being said you can inject ordered tasks in the middle of unorderd tasks by using run instead of using qeueued_run if you wish to.
|
34
|
+
|
35
|
+
* Configuration
|
36
|
+
To set the worker amount for unorderd tasks before the unorderd block do $configuration.workers = 10 to get 10 nano-bots working for you.
|
37
|
+
|
38
|
+
Example:
|
39
|
+
|
40
|
+
$configuration.workers = 5
|
41
|
+
unorderd do
|
42
|
+
....
|
43
|
+
end
|
44
|
+
|
45
|
+
This will give you 5 nano-bots for your unordered tasks
|
46
|
+
|
47
|
+
|
48
|
+
optional run and queued_run options
|
49
|
+
--------------------------
|
50
|
+
* :retry\_amount (Integer that specifies that you want to retry the execution of the provided command. Default is 1 execution.)
|
51
|
+
* :retry\_condition (Integer, regular expression, or string that specifies what a good execution is. Default is 0 if not specified.)
|
52
|
+
* :quit\_on\_error (Boolean that specifies if build'em should quit when an exception happens executing the provided command. Default is true)
|
53
|
+
|
54
|
+
|
data/lib/buildem/base.rb
CHANGED
@@ -3,6 +3,16 @@ require 'buildem'
|
|
3
3
|
require 'fileutils'
|
4
4
|
include FileUtils
|
5
5
|
|
6
|
+
module Kernel
|
7
|
+
def exitstatus
|
8
|
+
$?
|
9
|
+
end
|
10
|
+
|
11
|
+
def run_command(cmd)
|
12
|
+
`#{cmd}`
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
6
16
|
def windows?
|
7
17
|
return java.lang.System.get_property("os.name")[/windows/i] if RUBY_PLATFORM == "java"
|
8
18
|
return RUBY_PLATFORM[/mswin/]
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class BuildEm::ConditionMatcher
|
2
|
+
def match(return_code, output, condition)
|
3
|
+
case condition
|
4
|
+
when Regexp
|
5
|
+
return false unless output =~ condition
|
6
|
+
when String
|
7
|
+
return false unless output == condition
|
8
|
+
when Fixnum
|
9
|
+
return false unless return_code == condition
|
10
|
+
else
|
11
|
+
raise "unsupported type for condition"
|
12
|
+
end
|
13
|
+
return true
|
14
|
+
end
|
15
|
+
end
|
data/lib/buildem/executor.rb
CHANGED
@@ -1,11 +1,14 @@
|
|
1
1
|
require "buildem/base"
|
2
|
+
require "buildem/condition_matcher"
|
2
3
|
|
3
4
|
class BuildEm::Executor
|
4
5
|
|
5
6
|
attr_accessor :argz
|
6
7
|
|
7
|
-
def initialize(args)
|
8
|
+
def initialize(args, kernel=Kernel, matcher=BuildEm::ConditionMatcher.new)
|
9
|
+
@kernel = kernel
|
8
10
|
@argz ||= args
|
11
|
+
@matcher = matcher
|
9
12
|
end
|
10
13
|
|
11
14
|
def name
|
@@ -13,17 +16,32 @@ class BuildEm::Executor
|
|
13
16
|
end
|
14
17
|
|
15
18
|
def run
|
16
|
-
|
19
|
+
optz = argz[1]
|
20
|
+
quit_on_error = (optz[:quit_on_error].nil? ? true : optz[:quit_on_error])
|
21
|
+
retry_amount = (optz[:retry_amount].nil? ? 1 : optz[:retry_amount])
|
22
|
+
condition = (optz[:retry_condition].nil? ? 0 : optz[:retry_condition])
|
23
|
+
executions = 0
|
17
24
|
begin
|
18
|
-
puts
|
25
|
+
puts "retrying command [#{argz[0]}]" if executions > 0
|
26
|
+
executions += 1
|
27
|
+
@comamnd_output = @kernel.run_command("#{argz[0]}")
|
28
|
+
@command_exitstatus = @kernel.exitstatus
|
29
|
+
match = @matcher.match(@command_exitstatus, @comamnd_output, condition)
|
30
|
+
puts @comamnd_output if match
|
31
|
+
return @command_exitstatus if match
|
19
32
|
rescue Exception => e
|
20
|
-
|
21
|
-
|
33
|
+
if quit_on_error
|
34
|
+
raise e
|
35
|
+
else
|
36
|
+
#put to output log or specified log
|
37
|
+
end
|
38
|
+
end while executions < retry_amount
|
39
|
+
@command_exitstatus
|
22
40
|
end
|
23
41
|
|
24
42
|
private
|
25
43
|
|
26
|
-
def
|
44
|
+
def redirect_standard_error_and_out
|
27
45
|
""
|
28
46
|
end
|
29
47
|
|
data/lib/buildem/runner.rb
CHANGED
@@ -15,10 +15,10 @@ module Kernel
|
|
15
15
|
end
|
16
16
|
$pool.start
|
17
17
|
$pool.shutdown
|
18
|
+
puts "Finished #{$jobs.size} unordered jobs"
|
18
19
|
end
|
19
20
|
|
20
21
|
def queued_run(command, optz = {})
|
21
|
-
optz = {:foo => "bar", :moo => "cow"}
|
22
22
|
$jobs << BuildEm::Executor.new([command,optz])
|
23
23
|
end
|
24
24
|
|
@@ -31,10 +31,13 @@ class BuildEm::Runner
|
|
31
31
|
$jobs = []
|
32
32
|
def self.start
|
33
33
|
if ARGV.size == 1
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
begin
|
35
|
+
puts "running #{ARGV[0]}"
|
36
|
+
$configuration = BuildEm::Configuration.new
|
37
|
+
load ARGV[0]
|
38
|
+
ensure
|
39
|
+
puts "finished #{ARGV[0]}"
|
40
|
+
end
|
38
41
|
else
|
39
42
|
puts usage
|
40
43
|
end
|
data/lib/buildem/version.rb
CHANGED
data/spec/helper.rb
CHANGED
@@ -5,6 +5,8 @@ require 'rspec'
|
|
5
5
|
|
6
6
|
$SPEC_ROOT = File.expand_path(File.dirname(__FILE__))
|
7
7
|
|
8
|
+
require "bundler/setup"
|
9
|
+
|
8
10
|
def require_files filename
|
9
11
|
filename.each do |file|
|
10
12
|
require "#{$SPEC_ROOT}/../lib/buildem/#{file}"
|
@@ -24,8 +26,17 @@ RSpec.configure do |config|
|
|
24
26
|
begin
|
25
27
|
yield
|
26
28
|
rescue Exception => e
|
27
|
-
|
28
|
-
|
29
|
+
case clazz
|
30
|
+
when String
|
31
|
+
e.message.should == clazz
|
32
|
+
return
|
33
|
+
when Regexp
|
34
|
+
e.message.should =~ clazz
|
35
|
+
return
|
36
|
+
else
|
37
|
+
e.class.should == clazz
|
38
|
+
return
|
39
|
+
end
|
29
40
|
end
|
30
41
|
fail "Did not throw an exception like intended"
|
31
42
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+"/../helper.rb")
|
2
|
+
require_files "condition_matcher"
|
3
|
+
|
4
|
+
describe BuildEm::ConditionMatcher, "match" do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@matcher = BuildEm::ConditionMatcher.new
|
8
|
+
end
|
9
|
+
|
10
|
+
# match(return_code, output, condition)
|
11
|
+
|
12
|
+
it "raises an exception when an unsupported condition is supplied" do
|
13
|
+
unsupported_type = 1.00
|
14
|
+
expecting_exception("unsupported type for condition") { @matcher.match(0,"foo", unsupported_type) }
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "output with string matching" do
|
18
|
+
it "returns true when it finds a match" do
|
19
|
+
@matcher.match(0,"foo", "foo").should == true
|
20
|
+
end
|
21
|
+
it "returns true when it can not find a match" do
|
22
|
+
@matcher.match(0,"foo", "bar").should == false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "output with regexp matching" do
|
27
|
+
it "returns true when it finds a match" do
|
28
|
+
@matcher.match(0,"very complex output", /\w+\s+complex\s+\w+/).should == true
|
29
|
+
end
|
30
|
+
it "returns true when it can not find a match" do
|
31
|
+
@matcher.match(0,"more [complex] output", /\w+\s+complex\s+\w+/).should == false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "return code matching" do
|
36
|
+
it "returns true when it finds a match" do
|
37
|
+
@matcher.match(0,"SUCCESS", 0).should == true
|
38
|
+
end
|
39
|
+
it "returns true when it can not find a match" do
|
40
|
+
@matcher.match(0,"FAILURE", 1).should == false
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)+"/../helper.rb")
|
2
|
+
require_files "executor"
|
3
|
+
|
4
|
+
describe BuildEm::Executor, "run" do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@mock_kernel = mock(Kernel)
|
8
|
+
@matcher = mock(BuildEm::ConditionMatcher)
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "runs with default options" do
|
12
|
+
|
13
|
+
it "executes the provided command and quits if no retries supplied" do
|
14
|
+
command = "pinky and the brain"
|
15
|
+
executor = BuildEm::Executor.new([command,{}], @mock_kernel)
|
16
|
+
run_and_exitstatus_with(command, "FAILURE", 8675308)
|
17
|
+
executor.run.should == 8675308
|
18
|
+
end
|
19
|
+
|
20
|
+
it "raises an exception when something bad goes on" do
|
21
|
+
command = "foo bar"
|
22
|
+
executor = BuildEm::Executor.new([command, {}], @mock_kernel)
|
23
|
+
@mock_kernel.should_receive("run_command").with(command).and_raise("KA BOOM")
|
24
|
+
expecting_exception("KA BOOM") { executor.run }
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "runs command with options" do
|
30
|
+
|
31
|
+
it "executes the provided command 10 times when condition is not met" do
|
32
|
+
command = "some really cool command"
|
33
|
+
executor = BuildEm::Executor.new([command, {:retry_amount => 10}], @mock_kernel)
|
34
|
+
10.times do
|
35
|
+
run_and_exitstatus_with(command, "FAILURE", -1)
|
36
|
+
end
|
37
|
+
executor.run.should == -1
|
38
|
+
end
|
39
|
+
|
40
|
+
it "executes the provided command 3 times out of 10 when condition is met after 3 tries" do
|
41
|
+
command = "command_to_run"
|
42
|
+
executor = BuildEm::Executor.new([command, {:retry_amount => 10}], @mock_kernel)
|
43
|
+
2.times do
|
44
|
+
run_and_exitstatus_with(command, "FAILURE", -1)
|
45
|
+
end
|
46
|
+
run_and_exitstatus_with(command, "WINNER", 0)
|
47
|
+
executor.run.should == 0
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not raise an exception when something bad goes on if :quit_on_error is false" do
|
51
|
+
argz = ["command_to_run", {:quit_on_error => false}]
|
52
|
+
executor = BuildEm::Executor.new(argz, @mock_kernel)
|
53
|
+
@mock_kernel.should_receive("run_command").with("command_to_run").and_raise("KA BOOM")
|
54
|
+
executor.run.should == nil
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def run_and_exitstatus_with(command, output, exitstatus)
|
61
|
+
@mock_kernel.should_receive("run_command").with(command).and_return(output)
|
62
|
+
@mock_kernel.should_receive(:exitstatus).and_return(exitstatus)
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
end
|
data/spec/unit/version_spec.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: buildem
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jeremy W. Rowe
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-04-02 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -58,15 +58,17 @@ extensions: []
|
|
58
58
|
extra_rdoc_files: []
|
59
59
|
|
60
60
|
files:
|
61
|
+
- .autotest
|
61
62
|
- .gitignore
|
62
|
-
-
|
63
|
+
- EXAMPLES.md
|
63
64
|
- Gemfile
|
64
|
-
- README
|
65
|
+
- README.md
|
65
66
|
- Rakefile
|
66
67
|
- bin/buildem
|
67
68
|
- buildem.gemspec
|
68
69
|
- lib/buildem.rb
|
69
70
|
- lib/buildem/base.rb
|
71
|
+
- lib/buildem/condition_matcher.rb
|
70
72
|
- lib/buildem/configuration.rb
|
71
73
|
- lib/buildem/executor.rb
|
72
74
|
- lib/buildem/runner.rb
|
@@ -74,7 +76,9 @@ files:
|
|
74
76
|
- lib/buildem/version.rb
|
75
77
|
- spec/helper.rb
|
76
78
|
- spec/unit/base_spec.rb
|
79
|
+
- spec/unit/condition_matcher_spec.rb
|
77
80
|
- spec/unit/configuration_spec.rb
|
81
|
+
- spec/unit/executor_spec.rb
|
78
82
|
- spec/unit/helper/examples/blank_file.buildem
|
79
83
|
- spec/unit/helper/examples/everything.buildem
|
80
84
|
- spec/unit/helper/examples/nonsequential.buildem
|
@@ -121,7 +125,9 @@ summary: A simple build script wrapper that allows for concurent tasks
|
|
121
125
|
test_files:
|
122
126
|
- spec/helper.rb
|
123
127
|
- spec/unit/base_spec.rb
|
128
|
+
- spec/unit/condition_matcher_spec.rb
|
124
129
|
- spec/unit/configuration_spec.rb
|
130
|
+
- spec/unit/executor_spec.rb
|
125
131
|
- spec/unit/helper/examples/blank_file.buildem
|
126
132
|
- spec/unit/helper/examples/everything.buildem
|
127
133
|
- spec/unit/helper/examples/nonsequential.buildem
|
data/EXAMPLE
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
$configuration.workers = 2
|
2
|
-
|
3
|
-
run "initialize.sh"
|
4
|
-
run "clean.sh"
|
5
|
-
|
6
|
-
unorderd do
|
7
|
-
queued_run "build.sh"
|
8
|
-
queued_run "checkin.sh"
|
9
|
-
queued_run "publish.sh"
|
10
|
-
run "some_task_in_the_middle_of_queue.sh" # this will block all of the queued_run calls after this
|
11
|
-
queued_run "build.sh"
|
12
|
-
queued_run "checkin.sh"
|
13
|
-
queued_run "publish.sh"
|
14
|
-
end
|
15
|
-
|
16
|
-
run "do_something_at_the_end.sh"
|
data/README
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
Build'em quick, Build'em right
|
2
|
-
|
3
|
-
Build'em is a small little script parser that is intended for large build systems.
|
4
|
-
Build'em is still very young :) so be careful using it. Input is always welcome and if there is a feature that you just half to have i'd probably do it.
|
5
|
-
|
6
|
-
|
7
|
-
Features:
|
8
|
-
|
9
|
-
Execution:
|
10
|
-
Scripts go in a plain text file, I use my_very_important_task.buildem
|
11
|
-
and then simply call buildem my_very_important_task.buildem
|
12
|
-
|
13
|
-
1) Build'em supports sequential tasks (tasks that go in order)
|
14
|
-
|
15
|
-
Example:
|
16
|
-
run "./task.sh"
|
17
|
-
run "./another.sh" #another.sh waits for task.sh to complete
|
18
|
-
|
19
|
-
2) Build'em supports a work queue, what does this mean?
|
20
|
-
This means that you can run tasks concurrently, easily.
|
21
|
-
|
22
|
-
Example:
|
23
|
-
|
24
|
-
unorderd do
|
25
|
-
queued_run "./some_task.sh"
|
26
|
-
queued_run "./some_task1.sh" # All of these items will be executed at the same time
|
27
|
-
queued_run "./some_task2.sh"
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
*IMPORTANT* All queued_run tasks must be inside of an unorderd block if you want them to run at the same time. If you use run for a task, it will block to complete.
|
32
|
-
That being said you can inject ordered tasks in the middle of unorderd tasks by using run instead of using qeueued_run if you wish to.
|
33
|
-
|
34
|
-
|
35
|
-
3) Configuration
|
36
|
-
To set the worker amount for unorderd tasks before the unorderd block do $configuration.workers = 10 to get 10 nano-bots working for you.
|
37
|
-
|
38
|
-
Example:
|
39
|
-
$configuration.workers = 5
|
40
|
-
unorderd do
|
41
|
-
....
|
42
|
-
end
|
43
|
-
|
44
|
-
This will give you 5 nano-bots for your unordered tasks
|
45
|
-
|
46
|
-
|