local_ci 0.0.1 → 0.0.2
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +17 -4
- data/Rakefile +30 -21
- data/lib/local_ci/dsl.rb +30 -0
- data/lib/local_ci/exec_context.rb +44 -0
- data/lib/local_ci/failure.rb +7 -5
- data/lib/local_ci/flow.rb +75 -39
- data/lib/local_ci/helper.rb +10 -0
- data/lib/local_ci/job.rb +40 -0
- data/lib/local_ci/rake.rb +7 -0
- data/lib/local_ci/task.rb +37 -0
- data/lib/local_ci.rb +7 -6
- data/local_ci.gemspec +1 -1
- data/spec/spec_helper.rb +15 -0
- data/spec/support/dsl_klass.rb +5 -0
- data/spec/unit/local_ci/dsl_spec.rb +85 -0
- data/spec/unit/local_ci/exec_context_spec.rb +106 -0
- data/spec/unit/local_ci/failure_spec.rb +24 -0
- data/spec/unit/local_ci/flow_spec.rb +221 -0
- data/spec/unit/local_ci/helper_spec.rb +29 -0
- data/spec/unit/local_ci/job_spec.rb +126 -0
- data/spec/unit/local_ci/rake_spec.rb +16 -0
- data/spec/unit/local_ci/task_spec.rb +114 -0
- metadata +17 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 83a9843902d865aac3c8a3d995129379db5661f71fbece0537137f45fbed0b7e
|
|
4
|
+
data.tar.gz: 535d98f227e41f2aba8bbab39ec28b304d89cff2599cc2dc646cb103dc7ee465
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 60376c8a194767876646b90604047e387071f46e77742e6d26ccc5f53ae69e39aa61633511482b4b6a27f2d9ec98a6369862740fcff862e8e030b0a6c16a4f31
|
|
7
|
+
data.tar.gz: 261ed6fce994c12fc161fa8c8c86bd580fa5c4ae228364e83d786f2b5af2a9e53b75db96b2636956e078417d9b430dbfdbcc3e58f2551e452dbe69aa7a894519
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
local_ci (0.0.
|
|
4
|
+
local_ci (0.0.2)
|
|
5
5
|
logger
|
|
6
6
|
pastel
|
|
7
7
|
rake
|
|
@@ -12,11 +12,11 @@ GEM
|
|
|
12
12
|
remote: https://rubygems.org/
|
|
13
13
|
specs:
|
|
14
14
|
ast (2.4.3)
|
|
15
|
-
|
|
15
|
+
diff-lcs (1.6.2)
|
|
16
|
+
json (2.17.1)
|
|
16
17
|
language_server-protocol (3.17.0.5)
|
|
17
18
|
lint_roller (1.1.0)
|
|
18
19
|
logger (1.7.0)
|
|
19
|
-
neospec (0.0.1)
|
|
20
20
|
parallel (1.27.0)
|
|
21
21
|
parser (3.3.10.0)
|
|
22
22
|
ast (~> 2.4.1)
|
|
@@ -28,6 +28,19 @@ GEM
|
|
|
28
28
|
rainbow (3.1.1)
|
|
29
29
|
rake (13.3.1)
|
|
30
30
|
regexp_parser (2.11.3)
|
|
31
|
+
rspec (3.13.2)
|
|
32
|
+
rspec-core (~> 3.13.0)
|
|
33
|
+
rspec-expectations (~> 3.13.0)
|
|
34
|
+
rspec-mocks (~> 3.13.0)
|
|
35
|
+
rspec-core (3.13.6)
|
|
36
|
+
rspec-support (~> 3.13.0)
|
|
37
|
+
rspec-expectations (3.13.5)
|
|
38
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
39
|
+
rspec-support (~> 3.13.0)
|
|
40
|
+
rspec-mocks (3.13.7)
|
|
41
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
42
|
+
rspec-support (~> 3.13.0)
|
|
43
|
+
rspec-support (3.13.6)
|
|
31
44
|
rubocop (1.81.7)
|
|
32
45
|
json (~> 2.3)
|
|
33
46
|
language_server-protocol (~> 3.17.0.2)
|
|
@@ -77,7 +90,7 @@ PLATFORMS
|
|
|
77
90
|
|
|
78
91
|
DEPENDENCIES
|
|
79
92
|
local_ci!
|
|
80
|
-
|
|
93
|
+
rspec
|
|
81
94
|
standardrb
|
|
82
95
|
|
|
83
96
|
BUNDLED WITH
|
data/Rakefile
CHANGED
|
@@ -1,35 +1,44 @@
|
|
|
1
|
+
require "standard/rake"
|
|
1
2
|
require "local_ci"
|
|
2
3
|
|
|
3
|
-
|
|
4
|
+
LocalCI::Rake.setup(self)
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
setup do
|
|
7
|
+
job "Bundle", "bundle check | bundle install"
|
|
8
|
+
end
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
job "
|
|
10
|
-
run "bundle exec standardrb"
|
|
11
|
-
end
|
|
10
|
+
teardown do
|
|
11
|
+
job "Echo", "echo", "global teardown"
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
flow "Linting" do
|
|
15
|
+
job "StandardRB", "bundle exec rake standard"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
flow "Specs" do
|
|
19
|
+
setup do
|
|
20
|
+
job "Specs Setup", "echo specs setup"
|
|
19
21
|
end
|
|
22
|
+
|
|
23
|
+
teardown do
|
|
24
|
+
job "Specs Teardown", "echo specs teardown"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
job "RSpec", "bundle exec rspec"
|
|
20
28
|
end
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
job "
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
flow "Build" do
|
|
31
|
+
setup do
|
|
32
|
+
job "Start docker", "echo docker start"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
Dir.glob("*").each do |file|
|
|
36
|
+
job "Compile - #{file}" do
|
|
37
|
+
run "echo", "gcc", file
|
|
27
38
|
end
|
|
28
39
|
end
|
|
29
|
-
end
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
`bundle exec standardrb --fix-unsafely`
|
|
41
|
+
teardown do
|
|
42
|
+
job "Stop Docker", "echo docker stop"
|
|
34
43
|
end
|
|
35
44
|
end
|
data/lib/local_ci/dsl.rb
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module LocalCI
|
|
2
|
+
module DSL
|
|
3
|
+
def setup(heading = "Setup", parallel: false, &block)
|
|
4
|
+
LocalCI::Flow.new(
|
|
5
|
+
name: :setup,
|
|
6
|
+
heading: heading,
|
|
7
|
+
parallel: parallel,
|
|
8
|
+
actions: false,
|
|
9
|
+
block: block
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def teardown(heading = "Teardown", parallel: false, &block)
|
|
14
|
+
LocalCI::Flow.new(
|
|
15
|
+
name: :teardown,
|
|
16
|
+
heading: heading,
|
|
17
|
+
parallel: parallel,
|
|
18
|
+
actions: false,
|
|
19
|
+
block: block
|
|
20
|
+
)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def flow(name, heading = nil, parallel: true, &block)
|
|
24
|
+
heading ||= name
|
|
25
|
+
name = LocalCI::Helper.taskize(heading) unless name.is_a?(Symbol)
|
|
26
|
+
|
|
27
|
+
LocalCI::Flow.new(name: name, heading: heading, parallel: parallel, block: block)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module LocalCI
|
|
2
|
+
class ExecContext
|
|
3
|
+
attr_reader :flow
|
|
4
|
+
|
|
5
|
+
def initialize(flow:)
|
|
6
|
+
@flow = flow
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def run(command, *args)
|
|
10
|
+
LocalCI::Helper.runner.run command, *args
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def job(name, *args, &block)
|
|
14
|
+
LocalCI::Job.new(
|
|
15
|
+
flow: @flow,
|
|
16
|
+
name: name,
|
|
17
|
+
command: args,
|
|
18
|
+
block: block
|
|
19
|
+
)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def setup(heading = nil, parallel: false, &block)
|
|
23
|
+
heading ||= "#{@flow.heading} - Setup"
|
|
24
|
+
LocalCI::Flow.new(
|
|
25
|
+
name: "#{@flow.task}:setup",
|
|
26
|
+
heading: heading,
|
|
27
|
+
parallel: parallel,
|
|
28
|
+
actions: false,
|
|
29
|
+
block: block
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def teardown(heading = nil, parallel: false, &block)
|
|
34
|
+
heading ||= "#{@flow.heading} - Teardown"
|
|
35
|
+
LocalCI::Flow.new(
|
|
36
|
+
name: "#{@flow.task}:teardown",
|
|
37
|
+
heading: heading,
|
|
38
|
+
parallel: parallel,
|
|
39
|
+
actions: false,
|
|
40
|
+
block: block
|
|
41
|
+
)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
data/lib/local_ci/failure.rb
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
module LocalCI
|
|
2
2
|
class Failure
|
|
3
|
-
|
|
3
|
+
attr_reader :job
|
|
4
4
|
|
|
5
5
|
def initialize(job:, message:)
|
|
6
6
|
@job = job
|
|
7
7
|
@message = message
|
|
8
8
|
end
|
|
9
9
|
|
|
10
|
-
def
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
def message
|
|
11
|
+
<<~STR
|
|
12
|
+
#{LocalCI::Helper.pastel.bold.red("FAIL:")} #{@job}
|
|
13
|
+
#{@message}
|
|
14
|
+
|
|
15
|
+
STR
|
|
14
16
|
end
|
|
15
17
|
end
|
|
16
18
|
end
|
data/lib/local_ci/flow.rb
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
module LocalCI
|
|
2
2
|
class Flow
|
|
3
|
-
|
|
3
|
+
attr_accessor :task, :heading, :spinner, :failures
|
|
4
4
|
|
|
5
|
-
def
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
def initialize(name:, heading:, parallel:, block:, actions: true)
|
|
6
|
+
@task = name
|
|
7
|
+
@task = "ci:#{name}" unless @task.start_with?("ci:")
|
|
8
|
+
@parallel = parallel
|
|
9
9
|
@failures = []
|
|
10
|
-
@task = task
|
|
11
10
|
@heading = heading
|
|
12
|
-
@
|
|
13
|
-
|
|
11
|
+
@actions = actions
|
|
12
|
+
@spinner = TTY::Spinner::Multi.new(
|
|
13
|
+
"[:spinner] #{LocalCI::Helper.pastel.bold.blue(@heading)}",
|
|
14
14
|
format: :classic,
|
|
15
|
-
success_mark: pastel.green("✓"),
|
|
16
|
-
error_mark: pastel.red("✗"),
|
|
15
|
+
success_mark: LocalCI::Helper.pastel.green("✓"),
|
|
16
|
+
error_mark: LocalCI::Helper.pastel.red("✗"),
|
|
17
17
|
style: {
|
|
18
18
|
top: "",
|
|
19
19
|
middle: " ",
|
|
@@ -21,44 +21,80 @@ module LocalCI
|
|
|
21
21
|
}
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
abort pastel.red("#{@heading} failed, see CI.log for more.") if @failures.any?
|
|
24
|
+
setup_required_tasks
|
|
25
|
+
if actions?
|
|
26
|
+
setup_flow_tasks
|
|
27
|
+
else
|
|
28
|
+
setup_actionless_flow_tasks
|
|
31
29
|
end
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
Rake::Task[:local_ci].prerequisites << @task
|
|
31
|
+
after_jobs
|
|
35
32
|
|
|
36
|
-
instance_exec(&block)
|
|
33
|
+
LocalCI::ExecContext.new(flow: self).instance_exec(&block)
|
|
37
34
|
end
|
|
38
35
|
|
|
39
|
-
def
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
36
|
+
def actions? = !!@actions
|
|
37
|
+
|
|
38
|
+
def actionless? = !actions?
|
|
39
|
+
|
|
40
|
+
def isolated? = LocalCI::Task["ci"].already_invoked
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def setup_required_tasks
|
|
45
|
+
ci_task = LocalCI::Task["ci", "Run the CI suite"]
|
|
46
|
+
|
|
47
|
+
LocalCI::Task["ci:setup", "Setup the system to run CI"]
|
|
48
|
+
LocalCI::Task["ci:teardown", "Cleanup after the CI"]
|
|
49
|
+
|
|
50
|
+
ci_task.add_prerequisite "ci:setup"
|
|
51
|
+
ci_task.define do
|
|
52
|
+
LocalCI::Task["ci:teardown"].invoke
|
|
55
53
|
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def setup_flow_tasks
|
|
57
|
+
LocalCI::Task["#{@task}:setup"]
|
|
56
58
|
|
|
57
|
-
@
|
|
59
|
+
LocalCI::Task.new("#{@task}:jobs", parallel_prerequisites: @parallel)
|
|
60
|
+
|
|
61
|
+
LocalCI::Task["#{@task}:teardown"]
|
|
62
|
+
LocalCI::Task["#{@task}:failure_check"]
|
|
63
|
+
LocalCI::Task[@task, @heading]
|
|
64
|
+
|
|
65
|
+
LocalCI::Task["#{@task}:setup"]
|
|
66
|
+
LocalCI::Task["#{@task}:setup"].add_prerequisite "ci:setup"
|
|
67
|
+
|
|
68
|
+
LocalCI::Task[@task].add_prerequisite "#{@task}:teardown"
|
|
69
|
+
LocalCI::Task["#{@task}:failure_check"].add_prerequisite "#{@task}:teardown"
|
|
70
|
+
LocalCI::Task["#{@task}:teardown"].add_prerequisite "#{@task}:jobs"
|
|
71
|
+
LocalCI::Task["#{@task}:jobs"].add_prerequisite "#{@task}:setup"
|
|
72
|
+
|
|
73
|
+
LocalCI::Task["ci"].add_prerequisite @task
|
|
58
74
|
end
|
|
59
75
|
|
|
60
|
-
def
|
|
61
|
-
|
|
76
|
+
def setup_actionless_flow_tasks
|
|
77
|
+
LocalCI::Task.new("#{@task}:jobs", parallel_prerequisites: @parallel)
|
|
78
|
+
LocalCI::Task["#{@task}:failure_check"]
|
|
79
|
+
|
|
80
|
+
LocalCI::Task[@task].add_prerequisite "#{@task}:failure_check"
|
|
81
|
+
LocalCI::Task["#{@task}:failure_check"].add_prerequisite "#{@task}:jobs"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def after_jobs
|
|
85
|
+
LocalCI::Task[@task].define do
|
|
86
|
+
LocalCI::Task["#{@task}:teardown"].invoke
|
|
87
|
+
LocalCI::Task["ci:teardown"].invoke unless isolated? || actionless?
|
|
88
|
+
|
|
89
|
+
if @failures.any?
|
|
90
|
+
LocalCI::Task["ci:teardown"].invoke
|
|
91
|
+
@failures.each do |failure|
|
|
92
|
+
puts failure.display
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
abort LocalCI::Helper.pastel.red("#{@heading} failed, see CI.log for more.")
|
|
96
|
+
end
|
|
97
|
+
end
|
|
62
98
|
end
|
|
63
99
|
end
|
|
64
100
|
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module LocalCI
|
|
2
|
+
module Helper
|
|
3
|
+
def self.pastel = @pastel ||= Pastel.new(enabled: TTY::Color.support?)
|
|
4
|
+
def self.runner = @runner ||= TTY::Command.new(output: Logger.new("ci.log"))
|
|
5
|
+
|
|
6
|
+
def self.taskize(heading)
|
|
7
|
+
heading.downcase.gsub(/\s/, "_").gsub(/[^\w]/, "").to_sym
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
data/lib/local_ci/job.rb
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module LocalCI
|
|
2
|
+
class Job
|
|
3
|
+
attr_accessor :flow, :name, :command, :block, :task, :spinner
|
|
4
|
+
|
|
5
|
+
def initialize(flow:, name:, command:, block:)
|
|
6
|
+
@flow = flow
|
|
7
|
+
@name = name
|
|
8
|
+
@command = command
|
|
9
|
+
@block = block
|
|
10
|
+
@task = "#{@flow.task}:jobs:#{LocalCI::Helper.taskize(name)}"
|
|
11
|
+
|
|
12
|
+
raise ArgumentError, "Must specify a block or command" unless command || block
|
|
13
|
+
@spinner = flow.spinner.register("[:spinner] #{name}")
|
|
14
|
+
|
|
15
|
+
::Rake::Task.define_task(task) do
|
|
16
|
+
@spinner.auto_spin
|
|
17
|
+
start = Time.now
|
|
18
|
+
|
|
19
|
+
if block
|
|
20
|
+
LocalCI::ExecContext.new(flow: @flow).instance_exec(&block)
|
|
21
|
+
else
|
|
22
|
+
LocalCI::Helper.runner.run(*command)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
took = Time.now - start
|
|
26
|
+
@spinner.success("(#{took.round(2)}s)")
|
|
27
|
+
rescue TTY::Command::ExitError => e
|
|
28
|
+
spinner.error
|
|
29
|
+
@flow.failures << LocalCI::Failure.new(
|
|
30
|
+
job: @name,
|
|
31
|
+
message: e.message
|
|
32
|
+
)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
::Rake::Task["#{@flow.task}:jobs"].prerequisites << task
|
|
36
|
+
|
|
37
|
+
::Rake::Task[task].prerequisites << "#{@flow.task}:setup" if @flow.actions?
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
module LocalCI
|
|
2
|
+
class Task
|
|
3
|
+
extend Forwardable
|
|
4
|
+
|
|
5
|
+
def self.[](task, comment = nil)
|
|
6
|
+
new(task, comment: comment)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
attr_accessor :task
|
|
10
|
+
|
|
11
|
+
def_delegators :@task, :comment=, :invoke, :already_invoked, :prerequisites
|
|
12
|
+
|
|
13
|
+
def initialize(task, comment: nil, parallel_prerequisites: false)
|
|
14
|
+
@parallel_prerequisites = parallel_prerequisites
|
|
15
|
+
klass.define_task(task) unless klass.task_defined?(task)
|
|
16
|
+
@task = klass[task]
|
|
17
|
+
@task.comment = comment if comment
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def add_prerequisite(prerequisite)
|
|
21
|
+
return if prerequisites.include?(prerequisite)
|
|
22
|
+
prerequisites << prerequisite
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def define(&block)
|
|
26
|
+
::Rake::Task.define_task(@task.to_s) do
|
|
27
|
+
block.call
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def klass
|
|
34
|
+
@parallel_prerequisites ? ::Rake::MultiTask : ::Rake::Task
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/local_ci.rb
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
+
require "forwardable"
|
|
1
2
|
require "logger"
|
|
2
3
|
require "tty-command"
|
|
3
4
|
require "tty-spinner"
|
|
4
5
|
require "pastel"
|
|
5
6
|
|
|
7
|
+
require "local_ci/dsl"
|
|
8
|
+
require "local_ci/exec_context"
|
|
6
9
|
require "local_ci/failure"
|
|
7
10
|
require "local_ci/flow"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
end
|
|
13
|
-
end
|
|
11
|
+
require "local_ci/helper"
|
|
12
|
+
require "local_ci/job"
|
|
13
|
+
require "local_ci/rake"
|
|
14
|
+
require "local_ci/task"
|
data/local_ci.gemspec
CHANGED
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require "rspec"
|
|
2
|
+
require "rake"
|
|
3
|
+
|
|
4
|
+
require "local_ci"
|
|
5
|
+
|
|
6
|
+
require "support/dsl_klass"
|
|
7
|
+
|
|
8
|
+
RSpec.configure do |config|
|
|
9
|
+
config.after(:example) do
|
|
10
|
+
Rake::Task.clear
|
|
11
|
+
|
|
12
|
+
LocalCI::Helper.instance_variable_set(:@pastel, nil)
|
|
13
|
+
LocalCI::Helper.instance_variable_set(:@runner, nil)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe LocalCI::DSL do
|
|
4
|
+
before do
|
|
5
|
+
@block = -> {}
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe ".flow" do
|
|
9
|
+
it "calls LocalCI::Flow" do
|
|
10
|
+
expect(LocalCI::Flow).to receive(:new).with(
|
|
11
|
+
name: :name,
|
|
12
|
+
heading: "heading",
|
|
13
|
+
parallel: "parallel",
|
|
14
|
+
block: @block
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
Support::DSLKlass.new.flow(:name, "heading", parallel: "parallel", &@block)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
context "when only passed a heading" do
|
|
21
|
+
it "converts the heading to a sensible name name" do
|
|
22
|
+
expect(LocalCI::Flow).to receive(:new).with(
|
|
23
|
+
name: :my_cool_flow,
|
|
24
|
+
heading: "My Cool Flow!",
|
|
25
|
+
parallel: true,
|
|
26
|
+
block: @block
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
Support::DSLKlass.new.flow("My Cool Flow!", &@block)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
describe ".setup" do
|
|
35
|
+
it "calls LocalCI::Flow" do
|
|
36
|
+
expect(LocalCI::Flow).to receive(:new).with(
|
|
37
|
+
name: :setup,
|
|
38
|
+
heading: "Setup",
|
|
39
|
+
parallel: "parallel",
|
|
40
|
+
actions: false,
|
|
41
|
+
block: @block
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
Support::DSLKlass.new.setup(parallel: "parallel", &@block)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "passes through the heading" do
|
|
48
|
+
expect(LocalCI::Flow).to receive(:new).with(
|
|
49
|
+
name: :setup,
|
|
50
|
+
heading: "My Cool Setup",
|
|
51
|
+
parallel: "parallel",
|
|
52
|
+
actions: false,
|
|
53
|
+
block: @block
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
Support::DSLKlass.new.setup("My Cool Setup", parallel: "parallel", &@block)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe ".teardown" do
|
|
61
|
+
it "calls LocalCI::Flow" do
|
|
62
|
+
expect(LocalCI::Flow).to receive(:new).with(
|
|
63
|
+
name: :teardown,
|
|
64
|
+
heading: "Teardown",
|
|
65
|
+
parallel: "parallel",
|
|
66
|
+
actions: false,
|
|
67
|
+
block: @block
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
Support::DSLKlass.new.teardown(parallel: "parallel", &@block)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "passes through the heading" do
|
|
74
|
+
expect(LocalCI::Flow).to receive(:new).with(
|
|
75
|
+
name: :teardown,
|
|
76
|
+
heading: "My Cool Teardown",
|
|
77
|
+
parallel: "parallel",
|
|
78
|
+
actions: false,
|
|
79
|
+
block: @block
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
Support::DSLKlass.new.teardown("My Cool Teardown", parallel: "parallel", &@block)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe LocalCI::ExecContext do
|
|
4
|
+
before do
|
|
5
|
+
@block = -> {}
|
|
6
|
+
@flow = double(
|
|
7
|
+
:flow,
|
|
8
|
+
task: "flow-task",
|
|
9
|
+
heading: "flow-heading"
|
|
10
|
+
)
|
|
11
|
+
@context = LocalCI::ExecContext.new(flow: @flow)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "#initialize" do
|
|
15
|
+
it "assigns the flow" do
|
|
16
|
+
expect(@context.flow).to eq(@flow)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
describe "#run" do
|
|
21
|
+
it "runs the commands" do
|
|
22
|
+
expect(LocalCI::Helper.runner).to receive(:run)
|
|
23
|
+
.with("command", "arg1", "arg2")
|
|
24
|
+
|
|
25
|
+
@context.instance_exec {
|
|
26
|
+
run "command", "arg1", "arg2"
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
describe "#setup" do
|
|
32
|
+
it "creates a new flow" do
|
|
33
|
+
expect(LocalCI::Flow).to receive(:new)
|
|
34
|
+
.with(
|
|
35
|
+
name: "flow-task:setup",
|
|
36
|
+
heading: "flow-heading - Setup",
|
|
37
|
+
parallel: false,
|
|
38
|
+
actions: false,
|
|
39
|
+
block: @block
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
block = @block
|
|
43
|
+
@context.instance_exec {
|
|
44
|
+
setup(&block)
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "passes through heading and parallel" do
|
|
49
|
+
expect(LocalCI::Flow).to receive(:new)
|
|
50
|
+
.with(
|
|
51
|
+
name: "flow-task:setup",
|
|
52
|
+
heading: "Special Setup",
|
|
53
|
+
parallel: "parallel",
|
|
54
|
+
actions: false,
|
|
55
|
+
block: @block
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
block = @block
|
|
59
|
+
@context.instance_exec {
|
|
60
|
+
setup(
|
|
61
|
+
"Special Setup",
|
|
62
|
+
parallel: "parallel",
|
|
63
|
+
&block
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
describe "#teardown" do
|
|
70
|
+
it "creates a new flow" do
|
|
71
|
+
expect(LocalCI::Flow).to receive(:new)
|
|
72
|
+
.with(
|
|
73
|
+
name: "flow-task:teardown",
|
|
74
|
+
heading: "flow-heading - Teardown",
|
|
75
|
+
parallel: false,
|
|
76
|
+
actions: false,
|
|
77
|
+
block: @block
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
block = @block
|
|
81
|
+
@context.instance_exec {
|
|
82
|
+
teardown(&block)
|
|
83
|
+
}
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "passes through heading and parallel" do
|
|
87
|
+
expect(LocalCI::Flow).to receive(:new)
|
|
88
|
+
.with(
|
|
89
|
+
name: "flow-task:teardown",
|
|
90
|
+
heading: "Special Teardown",
|
|
91
|
+
parallel: "parallel",
|
|
92
|
+
actions: false,
|
|
93
|
+
block: @block
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
block = @block
|
|
97
|
+
@context.instance_exec {
|
|
98
|
+
teardown(
|
|
99
|
+
"Special Teardown",
|
|
100
|
+
parallel: "parallel",
|
|
101
|
+
&block
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe LocalCI::Failure do
|
|
4
|
+
describe "#message" do
|
|
5
|
+
it "returns information about the failure" do
|
|
6
|
+
pastel = double(:pastel)
|
|
7
|
+
expect(LocalCI::Helper).to receive(:pastel).and_return(pastel)
|
|
8
|
+
expect(pastel).to receive(:bold).and_return(pastel)
|
|
9
|
+
expect(pastel).to receive(:red).with("FAIL:")
|
|
10
|
+
.and_return("red")
|
|
11
|
+
|
|
12
|
+
failure = LocalCI::Failure.new(
|
|
13
|
+
job: "job",
|
|
14
|
+
message: "message"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
expect(failure.message).to eq(<<~STR)
|
|
18
|
+
red job
|
|
19
|
+
message
|
|
20
|
+
|
|
21
|
+
STR
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe LocalCI::Flow do
|
|
4
|
+
describe "#initialize" do
|
|
5
|
+
context "when creating parallel" do
|
|
6
|
+
it "call Rake::MultiTask" do
|
|
7
|
+
task = double(:task, prerequisites: [])
|
|
8
|
+
allow(task).to receive(:comment=)
|
|
9
|
+
allow(Rake::Task).to receive(:[]).and_return(task)
|
|
10
|
+
allow(Rake::Task).to receive(:define_task)
|
|
11
|
+
expect(Rake::MultiTask).to receive(:define_task).with("ci:parallel:jobs")
|
|
12
|
+
|
|
13
|
+
LocalCI::Flow.new(
|
|
14
|
+
name: "parallel",
|
|
15
|
+
heading: "heading",
|
|
16
|
+
parallel: true,
|
|
17
|
+
block: -> {}
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "when creating sequential" do
|
|
23
|
+
it "call Rake::Task" do
|
|
24
|
+
task = double(:task, prerequisites: [])
|
|
25
|
+
expect(task).to receive(:comment=).at_least(:once)
|
|
26
|
+
expect(Rake::Task).to receive(:[]).and_return(task).at_least(:once)
|
|
27
|
+
expect(Rake::Task).to receive(:define_task).with("ci:sequential:jobs").at_least(:once)
|
|
28
|
+
expect(Rake::Task).to receive(:define_task).at_least(:once)
|
|
29
|
+
|
|
30
|
+
LocalCI::Flow.new(
|
|
31
|
+
name: "sequential",
|
|
32
|
+
heading: "heading",
|
|
33
|
+
parallel: false,
|
|
34
|
+
block: -> {}
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context "when actions is true" do
|
|
40
|
+
it "creates the expected tasks" do
|
|
41
|
+
LocalCI::Flow.new(
|
|
42
|
+
name: "actions",
|
|
43
|
+
heading: "heading",
|
|
44
|
+
parallel: true,
|
|
45
|
+
actions: true,
|
|
46
|
+
block: -> {}
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
expect(Rake::Task.task_defined?("ci")).to be(true)
|
|
50
|
+
expect(Rake::Task.task_defined?("ci:setup")).to be(true)
|
|
51
|
+
expect(Rake::Task.task_defined?("ci:actions")).to be(true)
|
|
52
|
+
expect(Rake::Task.task_defined?("ci:actions:setup")).to be(true)
|
|
53
|
+
expect(Rake::Task.task_defined?("ci:actions:jobs")).to be(true)
|
|
54
|
+
expect(Rake::Task.task_defined?("ci:actions:teardown")).to be(true)
|
|
55
|
+
expect(Rake::Task.task_defined?("ci:teardown")).to be(true)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context "when actions is false" do
|
|
60
|
+
it "creates the expected tasks" do
|
|
61
|
+
LocalCI::Flow.new(
|
|
62
|
+
name: "actionless",
|
|
63
|
+
heading: "heading",
|
|
64
|
+
parallel: true,
|
|
65
|
+
actions: false,
|
|
66
|
+
block: -> {}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
expect(Rake::Task.task_defined?("ci")).to be(true)
|
|
70
|
+
expect(Rake::Task.task_defined?("ci:setup")).to be(true)
|
|
71
|
+
expect(Rake::Task.task_defined?("ci:actionless")).to be(true)
|
|
72
|
+
expect(Rake::Task.task_defined?("ci:actionless:setup")).to be(false)
|
|
73
|
+
expect(Rake::Task.task_defined?("ci:actionless:jobs")).to be(true)
|
|
74
|
+
expect(Rake::Task.task_defined?("ci:actionless:teardown")).to be(false)
|
|
75
|
+
expect(Rake::Task.task_defined?("ci:teardown")).to be(true)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "gives tasks the right comments" do
|
|
80
|
+
LocalCI::Flow.new(
|
|
81
|
+
name: "test",
|
|
82
|
+
heading: "heading",
|
|
83
|
+
parallel: true,
|
|
84
|
+
block: -> {}
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
expect(Rake::Task["ci"].comment).to eq("Run the CI suite")
|
|
88
|
+
expect(Rake::Task["ci:setup"].comment).to eq("Setup the system to run CI")
|
|
89
|
+
expect(Rake::Task["ci:teardown"].comment).to eq("Cleanup after the CI")
|
|
90
|
+
expect(Rake::Task["ci:test"].comment).to eq("heading")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "has the correct prerequisites for all tasks" do
|
|
94
|
+
LocalCI::Flow.new(
|
|
95
|
+
name: "test",
|
|
96
|
+
heading: "heading",
|
|
97
|
+
parallel: true,
|
|
98
|
+
block: -> {}
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
expect(Rake::Task["ci"].prerequisites).to eq(["ci:setup", "ci:test"])
|
|
102
|
+
expect(Rake::Task["ci:test"].prerequisites).to eq(["ci:test:teardown"])
|
|
103
|
+
expect(Rake::Task["ci:test:teardown"].prerequisites).to eq(["ci:test:jobs"])
|
|
104
|
+
expect(Rake::Task["ci:test:jobs"].prerequisites).to eq(["ci:test:setup"])
|
|
105
|
+
expect(Rake::Task["ci:test:setup"].prerequisites).to eq(["ci:setup"])
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "calls the expected jobs" do
|
|
109
|
+
allow(LocalCI::Job).to receive(:new)
|
|
110
|
+
|
|
111
|
+
job_1_block = -> {}
|
|
112
|
+
|
|
113
|
+
flow = LocalCI::Flow.new(
|
|
114
|
+
name: "test",
|
|
115
|
+
heading: "heading",
|
|
116
|
+
parallel: true,
|
|
117
|
+
block: -> {
|
|
118
|
+
job("Job 1", &job_1_block)
|
|
119
|
+
job("Job 2", "ls", "-la")
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
expect(LocalCI::Job).to have_received(:new).with(
|
|
124
|
+
flow: flow,
|
|
125
|
+
name: "Job 1",
|
|
126
|
+
command: [],
|
|
127
|
+
block: job_1_block
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
expect(LocalCI::Job).to have_received(:new).with(
|
|
131
|
+
flow: flow,
|
|
132
|
+
name: "Job 2",
|
|
133
|
+
command: ["ls", "-la"],
|
|
134
|
+
block: nil
|
|
135
|
+
)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
describe "#after_jobs" do
|
|
140
|
+
before do
|
|
141
|
+
@flow = LocalCI::Flow.new(
|
|
142
|
+
name: "flow",
|
|
143
|
+
heading: "heading",
|
|
144
|
+
parallel: true,
|
|
145
|
+
block: -> {}
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
@ci = double(:ci, already_invoked: false)
|
|
149
|
+
allow(LocalCI::Task).to receive(:[]).with("ci").and_return(@ci)
|
|
150
|
+
|
|
151
|
+
@flow_teardown = double(:flow_teardown)
|
|
152
|
+
allow(@flow_teardown).to receive(:invoke)
|
|
153
|
+
allow(LocalCI::Task).to receive(:[]).with("ci:flow:teardown").and_return(@flow_teardown)
|
|
154
|
+
|
|
155
|
+
@teardown = double(:teardown)
|
|
156
|
+
allow(@teardown).to receive(:invoke)
|
|
157
|
+
allow(LocalCI::Task).to receive(:[]).with("ci:teardown").and_return(@teardown)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
context "when there are no failures" do
|
|
161
|
+
it "runs ci:flow:teardown" do
|
|
162
|
+
expect(@flow_teardown).to receive(:invoke)
|
|
163
|
+
|
|
164
|
+
::Rake::Task["ci:flow"].invoke
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
context "when run in isolation" do
|
|
168
|
+
it "runs ci:teardown" do
|
|
169
|
+
expect(@teardown).to receive(:invoke)
|
|
170
|
+
|
|
171
|
+
::Rake::Task["ci:flow"].invoke
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context "when not run in isolation" do
|
|
176
|
+
before do
|
|
177
|
+
allow(@ci).to receive(:already_invoked).and_return(true)
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "does not run ci:teardown" do
|
|
181
|
+
expect(@teardown).not_to receive(:invoke)
|
|
182
|
+
|
|
183
|
+
::Rake::Task["ci:flow"].invoke
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
context "when there are failures" do
|
|
189
|
+
before do
|
|
190
|
+
@failure = double(:failure, display: "hi")
|
|
191
|
+
@flow.failures << @failure
|
|
192
|
+
|
|
193
|
+
allow(@flow).to receive(:abort)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it "runs ci:flow:teardown" do
|
|
197
|
+
expect(@flow_teardown).to receive(:invoke)
|
|
198
|
+
|
|
199
|
+
::Rake::Task["ci:flow"].invoke
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
it "invokes ci:teardown" do
|
|
203
|
+
expect(@teardown).to receive(:invoke)
|
|
204
|
+
|
|
205
|
+
::Rake::Task["ci:flow"].invoke
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it "displays the failures" do
|
|
209
|
+
expect(@failure).to receive(:display)
|
|
210
|
+
|
|
211
|
+
::Rake::Task["ci:flow"].invoke
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "aborts with a message" do
|
|
215
|
+
expect(@flow).to receive(:abort).with(/heading failed, see CI\.log for more\./)
|
|
216
|
+
|
|
217
|
+
::Rake::Task["ci:flow"].invoke
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe LocalCI::Helper do
|
|
4
|
+
describe ".pastel" do
|
|
5
|
+
it "returns a Pastel instance" do
|
|
6
|
+
expect(TTY::Color).to receive(:support?).and_return("support")
|
|
7
|
+
expect(Pastel).to receive(:new).with(enabled: "support")
|
|
8
|
+
.and_return("pastel")
|
|
9
|
+
|
|
10
|
+
expect(LocalCI::Helper.pastel).to eq("pastel")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe ".runner" do
|
|
15
|
+
it "returns a TTY::Command instance" do
|
|
16
|
+
expect(Logger).to receive(:new).with("ci.log").and_return("logger")
|
|
17
|
+
expect(TTY::Command).to receive(:new).with(output: "logger")
|
|
18
|
+
.and_return("tty-command")
|
|
19
|
+
|
|
20
|
+
expect(LocalCI::Helper.runner).to eq("tty-command")
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe ".taskize" do
|
|
25
|
+
it "returns a task-ized version of a string" do
|
|
26
|
+
expect(LocalCI::Helper.taskize("Hello There!")).to eq(:hello_there)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe LocalCI::Job do
|
|
4
|
+
before do
|
|
5
|
+
@flow = LocalCI::Flow.new(
|
|
6
|
+
name: "flow",
|
|
7
|
+
heading: "heading",
|
|
8
|
+
parallel: true,
|
|
9
|
+
block: -> {}
|
|
10
|
+
)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe "#initialize" do
|
|
14
|
+
it "creates a new job with the right arguments" do
|
|
15
|
+
job = LocalCI::Job.new(
|
|
16
|
+
flow: @flow,
|
|
17
|
+
name: "The Job Name!",
|
|
18
|
+
command: "command",
|
|
19
|
+
block: "block"
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
expect(job.flow).to eq(@flow)
|
|
23
|
+
expect(job.name).to eq("The Job Name!")
|
|
24
|
+
expect(job.command).to eq("command")
|
|
25
|
+
expect(job.block).to eq("block")
|
|
26
|
+
expect(job.task).to eq("ci:flow:jobs:the_job_name")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
context "when passed no block or command" do
|
|
30
|
+
it "raises an error" do
|
|
31
|
+
expect do
|
|
32
|
+
LocalCI::Job.new(
|
|
33
|
+
flow: @flow,
|
|
34
|
+
name: "name",
|
|
35
|
+
command: nil,
|
|
36
|
+
block: nil
|
|
37
|
+
)
|
|
38
|
+
end.to raise_error(ArgumentError, "Must specify a block or command")
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "defines a rake task" do
|
|
43
|
+
LocalCI::Job.new(
|
|
44
|
+
flow: @flow,
|
|
45
|
+
name: "The Job Name!",
|
|
46
|
+
command: "command",
|
|
47
|
+
block: "block"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
expect(Rake::Task.task_defined?("ci:flow:jobs:the_job_name")).to be(true)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "gives the rake task the right prerequisite" do
|
|
54
|
+
LocalCI::Job.new(
|
|
55
|
+
flow: @flow,
|
|
56
|
+
name: "The Job Name!",
|
|
57
|
+
command: "command",
|
|
58
|
+
block: "block"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
expect(Rake::Task["ci:flow:jobs"].prerequisites).to include("ci:flow:jobs:the_job_name")
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe "task" do
|
|
66
|
+
context "when running a block" do
|
|
67
|
+
it "runs all the commands from the block" do
|
|
68
|
+
expect(LocalCI::Helper.runner).to receive(:run).with("command 1")
|
|
69
|
+
expect(LocalCI::Helper.runner).to receive(:run).with("command", "2")
|
|
70
|
+
|
|
71
|
+
LocalCI::Job.new(
|
|
72
|
+
flow: @flow,
|
|
73
|
+
name: "block task",
|
|
74
|
+
command: nil,
|
|
75
|
+
block: -> {
|
|
76
|
+
run "command 1"
|
|
77
|
+
run "command", "2"
|
|
78
|
+
}
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
::Rake::Task["ci:flow:jobs:block_task"].invoke
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
context "when running one command inline" do
|
|
86
|
+
it "runs the commands" do
|
|
87
|
+
expect(LocalCI::Helper.runner).to receive(:run).with("command", "by", "argument")
|
|
88
|
+
|
|
89
|
+
LocalCI::Job.new(
|
|
90
|
+
flow: @flow,
|
|
91
|
+
name: "command task",
|
|
92
|
+
command: ["command", "by", "argument"],
|
|
93
|
+
block: nil
|
|
94
|
+
)
|
|
95
|
+
::Rake::Task["ci:flow:jobs:command_task"].invoke
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
context "when the job fails" do
|
|
100
|
+
it "is recorded against the flow" do
|
|
101
|
+
expect(LocalCI::Helper.runner).to receive(:run).with("exit 1")
|
|
102
|
+
.and_raise(
|
|
103
|
+
TTY::Command::ExitError.new(
|
|
104
|
+
"exit 1",
|
|
105
|
+
double(
|
|
106
|
+
exit_status: 1,
|
|
107
|
+
err: "oops!",
|
|
108
|
+
out: ""
|
|
109
|
+
)
|
|
110
|
+
)
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
LocalCI::Job.new(
|
|
114
|
+
flow: @flow,
|
|
115
|
+
name: "Raises an Error",
|
|
116
|
+
command: "exit 1",
|
|
117
|
+
block: nil
|
|
118
|
+
)
|
|
119
|
+
::Rake::Task["ci:flow:jobs:raises_an_error"].invoke
|
|
120
|
+
|
|
121
|
+
expect(@flow.failures.size).to eq(1)
|
|
122
|
+
expect(@flow.failures.first.job).to eq("Raises an Error")
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe LocalCI::Rake do
|
|
4
|
+
describe ".setup" do
|
|
5
|
+
before do
|
|
6
|
+
@klass = double(:klass)
|
|
7
|
+
allow(@klass).to receive(:send)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it "includes the DSL" do
|
|
11
|
+
expect(@klass).to receive(:send).with(:include, LocalCI::DSL)
|
|
12
|
+
|
|
13
|
+
LocalCI::Rake.setup(@klass)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
|
|
3
|
+
describe LocalCI::Task do
|
|
4
|
+
describe "#initialize" do
|
|
5
|
+
context "with parallel preqresuites" do
|
|
6
|
+
it "creates a MultiTask" do
|
|
7
|
+
expect(::Rake::MultiTask).to receive(:[]).with("task")
|
|
8
|
+
|
|
9
|
+
LocalCI::Task.new("task", parallel_prerequisites: true)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
context "with a comment" do
|
|
13
|
+
it "sets the comment" do
|
|
14
|
+
task = double(:task)
|
|
15
|
+
allow(::Rake::MultiTask).to receive(:[]).and_return(task)
|
|
16
|
+
expect(task).to receive(:comment=).with("comment")
|
|
17
|
+
|
|
18
|
+
LocalCI::Task.new("task", comment: "comment", parallel_prerequisites: true)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
context "without a comment" do
|
|
23
|
+
it "does not set the comment" do
|
|
24
|
+
task = double(:task)
|
|
25
|
+
allow(::Rake::MultiTask).to receive(:[]).and_return(task)
|
|
26
|
+
expect(task).not_to receive(:comment=)
|
|
27
|
+
|
|
28
|
+
LocalCI::Task.new("task", parallel_prerequisites: true)
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "with sequential preqresuites" do
|
|
34
|
+
it "creates a Task" do
|
|
35
|
+
expect(::Rake::Task).to receive(:[]).with("task")
|
|
36
|
+
|
|
37
|
+
LocalCI::Task.new("task", parallel_prerequisites: false)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "with a comment" do
|
|
41
|
+
it "sets the comment" do
|
|
42
|
+
task = double(:task)
|
|
43
|
+
allow(::Rake::Task).to receive(:[]).and_return(task)
|
|
44
|
+
expect(task).to receive(:comment=).with("comment")
|
|
45
|
+
|
|
46
|
+
LocalCI::Task.new("task", comment: "comment", parallel_prerequisites: false)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "without a comment" do
|
|
51
|
+
it "does not set the comment" do
|
|
52
|
+
task = double(:task)
|
|
53
|
+
allow(::Rake::Task).to receive(:[]).and_return(task)
|
|
54
|
+
expect(task).not_to receive(:comment=)
|
|
55
|
+
|
|
56
|
+
LocalCI::Task.new("task", parallel_prerequisites: false)
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe ".[]" do
|
|
63
|
+
it "creates a LocalCI::Task" do
|
|
64
|
+
expect(LocalCI::Task).to receive(:new).with(
|
|
65
|
+
"task",
|
|
66
|
+
comment: "comment"
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
LocalCI::Task["task", "comment"]
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe "#add_prerequisite" do
|
|
74
|
+
before do
|
|
75
|
+
@task = LocalCI::Task.new("task", parallel_prerequisites: true)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "adds the prerequisite" do
|
|
79
|
+
expect(@task.prerequisites).to receive(:<<).with("prereq")
|
|
80
|
+
|
|
81
|
+
@task.add_prerequisite("prereq")
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
context "When it already has that prerequisite" do
|
|
85
|
+
it "doesn't add it again" do
|
|
86
|
+
expect(@task.prerequisites).not_to receive(:<<)
|
|
87
|
+
expect(@task).to receive(:prerequisites).and_return(["prereq"])
|
|
88
|
+
|
|
89
|
+
@task.add_prerequisite("prereq")
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe "#define" do
|
|
95
|
+
before do
|
|
96
|
+
@task = LocalCI::Task.new("task", parallel_prerequisites: true)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "calls define_task" do
|
|
100
|
+
expect(::Rake::Task).to receive(:define_task).with("task")
|
|
101
|
+
|
|
102
|
+
@task.define {}
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "uses the passed in block as the task body" do
|
|
106
|
+
@block_run = false
|
|
107
|
+
|
|
108
|
+
@task.define { @block_run = true }
|
|
109
|
+
|
|
110
|
+
@task.invoke
|
|
111
|
+
expect(@block_run).to be(true)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: local_ci
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0.
|
|
4
|
+
version: 0.0.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Sean Earle
|
|
@@ -90,9 +90,25 @@ files:
|
|
|
90
90
|
- Gemfile.lock
|
|
91
91
|
- Rakefile
|
|
92
92
|
- lib/local_ci.rb
|
|
93
|
+
- lib/local_ci/dsl.rb
|
|
94
|
+
- lib/local_ci/exec_context.rb
|
|
93
95
|
- lib/local_ci/failure.rb
|
|
94
96
|
- lib/local_ci/flow.rb
|
|
97
|
+
- lib/local_ci/helper.rb
|
|
98
|
+
- lib/local_ci/job.rb
|
|
99
|
+
- lib/local_ci/rake.rb
|
|
100
|
+
- lib/local_ci/task.rb
|
|
95
101
|
- local_ci.gemspec
|
|
102
|
+
- spec/spec_helper.rb
|
|
103
|
+
- spec/support/dsl_klass.rb
|
|
104
|
+
- spec/unit/local_ci/dsl_spec.rb
|
|
105
|
+
- spec/unit/local_ci/exec_context_spec.rb
|
|
106
|
+
- spec/unit/local_ci/failure_spec.rb
|
|
107
|
+
- spec/unit/local_ci/flow_spec.rb
|
|
108
|
+
- spec/unit/local_ci/helper_spec.rb
|
|
109
|
+
- spec/unit/local_ci/job_spec.rb
|
|
110
|
+
- spec/unit/local_ci/rake_spec.rb
|
|
111
|
+
- spec/unit/local_ci/task_spec.rb
|
|
96
112
|
homepage: https://github.com/HellRok/local_ci
|
|
97
113
|
licenses:
|
|
98
114
|
- MIT
|