producer-core 0.1.10 → 0.1.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/features/recipes/ask.feature +22 -0
- data/features/steps/recipe_steps.rb +4 -0
- data/lib/producer/core.rb +1 -0
- data/lib/producer/core/action.rb +2 -2
- data/lib/producer/core/cli.rb +1 -2
- data/lib/producer/core/condition.rb +2 -0
- data/lib/producer/core/condition/dsl.rb +1 -1
- data/lib/producer/core/env.rb +4 -2
- data/lib/producer/core/prompter.rb +21 -0
- data/lib/producer/core/recipe/dsl.rb +1 -3
- data/lib/producer/core/remote.rb +1 -1
- data/lib/producer/core/remote/environment.rb +3 -1
- data/lib/producer/core/remote/fs.rb +2 -0
- data/lib/producer/core/task/dsl.rb +5 -1
- data/lib/producer/core/test.rb +6 -0
- data/lib/producer/core/tests/has_env.rb +1 -1
- data/lib/producer/core/tests/has_file.rb +1 -1
- data/lib/producer/core/version.rb +1 -1
- data/spec/producer/core/action_spec.rb +8 -1
- data/spec/producer/core/cli_spec.rb +3 -9
- data/spec/producer/core/condition/dsl_spec.rb +32 -40
- data/spec/producer/core/condition_spec.rb +15 -31
- data/spec/producer/core/env_spec.rb +16 -11
- data/spec/producer/core/prompter_spec.rb +41 -0
- data/spec/producer/core/recipe/dsl_spec.rb +34 -60
- data/spec/producer/core/remote/environment_spec.rb +20 -17
- data/spec/producer/core/remote/fs_spec.rb +1 -1
- data/spec/producer/core/remote_spec.rb +7 -19
- data/spec/producer/core/task/dsl_spec.rb +48 -54
- data/spec/producer/core/task_spec.rb +23 -51
- data/spec/producer/core/test_spec.rb +14 -14
- data/spec/spec_helper.rb +0 -1
- metadata +6 -3
- data/spec/support/tests_helpers.rb +0 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6a27039a047e17f8490bd070f3906b435939441
|
4
|
+
data.tar.gz: 7f1c4c346f1258e97f59454a6bcf3a20c6e02288
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b84f00106289af7baa8f57ab9aa336eaf2f4a9114a5a7553d5431e83ec8a04b8512ed37657c1599367bd75f41f8f99fabb241eada0c3bf4c9c88c2c5a88bc80
|
7
|
+
data.tar.gz: c3ed29fc5633c033e6f35f83d990325d0cdbce10a8a753cbc9f1e7f063795633ad9c465bc322327963ddeb096ec3e0e6c16f6919d2ffef6b753108a52016c7e9
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Feature: `ask' recipe keyword
|
2
|
+
|
3
|
+
Scenario: prompts user with a list of choices on standard output
|
4
|
+
Given a recipe with:
|
5
|
+
"""
|
6
|
+
task :ask_letter do
|
7
|
+
letter = ask 'Which letter?', [[:a, ?A], [:b, ?B]]
|
8
|
+
|
9
|
+
echo letter.inspect
|
10
|
+
end
|
11
|
+
"""
|
12
|
+
When I execute the recipe interactively
|
13
|
+
And I type "1"
|
14
|
+
Then the output must contain:
|
15
|
+
"""
|
16
|
+
Which letter?
|
17
|
+
0: A
|
18
|
+
1: B
|
19
|
+
Choice:
|
20
|
+
:b
|
21
|
+
"""
|
22
|
+
And the exit status must be 0
|
data/lib/producer/core.rb
CHANGED
@@ -14,6 +14,7 @@ require 'producer/core/condition'
|
|
14
14
|
require 'producer/core/condition/dsl'
|
15
15
|
require 'producer/core/env'
|
16
16
|
require 'producer/core/errors'
|
17
|
+
require 'producer/core/prompter'
|
17
18
|
require 'producer/core/recipe'
|
18
19
|
require 'producer/core/recipe/dsl'
|
19
20
|
require 'producer/core/remote'
|
data/lib/producer/core/action.rb
CHANGED
@@ -4,10 +4,10 @@ module Producer
|
|
4
4
|
require 'forwardable'
|
5
5
|
|
6
6
|
extend Forwardable
|
7
|
-
def_delegators :@env, :output, :remote
|
7
|
+
def_delegators :@env, :input, :output, :remote
|
8
8
|
def_delegators :remote, :fs
|
9
9
|
|
10
|
-
|
10
|
+
attr_reader :env, :arguments
|
11
11
|
|
12
12
|
def initialize(env, *args)
|
13
13
|
@env = env
|
data/lib/producer/core/cli.rb
CHANGED
data/lib/producer/core/env.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
module Producer
|
2
2
|
module Core
|
3
3
|
class Env
|
4
|
-
|
4
|
+
attr_reader :input, :output
|
5
|
+
attr_accessor :target
|
5
6
|
|
6
|
-
def initialize(output: $stdout)
|
7
|
+
def initialize(input: $stdin, output: $stdout)
|
8
|
+
@input = input
|
7
9
|
@output = output
|
8
10
|
@target = nil
|
9
11
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Producer
|
2
|
+
module Core
|
3
|
+
class Prompter
|
4
|
+
attr_reader :input, :output
|
5
|
+
|
6
|
+
def initialize(input, output)
|
7
|
+
@input = input
|
8
|
+
@output = output
|
9
|
+
end
|
10
|
+
|
11
|
+
def prompt(question, choices)
|
12
|
+
cs = choices.each_with_index.inject('') do |m, (c, i)|
|
13
|
+
m += "#{i}: #{c.last}\n"
|
14
|
+
end
|
15
|
+
output.puts "#{question}\n#{cs}Choice:"
|
16
|
+
choice = input.gets
|
17
|
+
choices[choice.to_i].first
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -2,7 +2,7 @@ module Producer
|
|
2
2
|
module Core
|
3
3
|
class Recipe
|
4
4
|
class DSL
|
5
|
-
attr_reader :env, :tasks
|
5
|
+
attr_reader :env, :code, :block, :tasks
|
6
6
|
|
7
7
|
def initialize(env, code = nil, &block)
|
8
8
|
@env = env
|
@@ -20,8 +20,6 @@ module Producer
|
|
20
20
|
self
|
21
21
|
end
|
22
22
|
|
23
|
-
private
|
24
|
-
|
25
23
|
def source(filepath)
|
26
24
|
instance_eval File.read("./#{filepath}.rb"), "#{filepath}.rb"
|
27
25
|
end
|
data/lib/producer/core/remote.rb
CHANGED
@@ -15,7 +15,7 @@ module Producer
|
|
15
15
|
|
16
16
|
define_action :file_write, Actions::FileWriter
|
17
17
|
|
18
|
-
|
18
|
+
attr_reader :env, :block, :actions
|
19
19
|
|
20
20
|
def initialize(env, &block)
|
21
21
|
@env = env
|
@@ -32,6 +32,10 @@ module Producer
|
|
32
32
|
@condition = Condition.evaluate(@env, &block) if block
|
33
33
|
@condition
|
34
34
|
end
|
35
|
+
|
36
|
+
def ask(question, choices, prompter: Prompter)
|
37
|
+
prompter.new(env.input, env.output).prompt(question, choices)
|
38
|
+
end
|
35
39
|
end
|
36
40
|
end
|
37
41
|
end
|
data/lib/producer/core/test.rb
CHANGED
@@ -2,8 +2,9 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Producer::Core
|
4
4
|
describe Action do
|
5
|
+
let(:input) { StringIO.new }
|
5
6
|
let(:output) { StringIO.new }
|
6
|
-
let(:env) { Env.new(output: output) }
|
7
|
+
let(:env) { Env.new(input: input, output: output) }
|
7
8
|
let(:arguments) { [:some, :arguments] }
|
8
9
|
subject(:action) { Action.new(env, *arguments) }
|
9
10
|
|
@@ -19,6 +20,12 @@ module Producer::Core
|
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
23
|
+
describe '#input' do
|
24
|
+
it 'returns env input' do
|
25
|
+
expect(action.input).to be input
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
22
29
|
describe '#output' do
|
23
30
|
it 'delegates to env output' do
|
24
31
|
action.output.puts 'some content'
|
@@ -53,7 +53,9 @@ module Producer::Core
|
|
53
53
|
context 'without arguments' do
|
54
54
|
let(:arguments) { [] }
|
55
55
|
|
56
|
-
|
56
|
+
it 'raises our ArgumentError exception' do
|
57
|
+
expect { cli }.to raise_error described_class::ArgumentError
|
58
|
+
end
|
57
59
|
end
|
58
60
|
end
|
59
61
|
|
@@ -69,14 +71,6 @@ module Producer::Core
|
|
69
71
|
end
|
70
72
|
end
|
71
73
|
|
72
|
-
describe '#recipe' do
|
73
|
-
it 'returns the assigned recipe' do
|
74
|
-
recipe = double 'recipe'
|
75
|
-
cli.recipe = recipe
|
76
|
-
expect(cli.recipe).to be recipe
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
74
|
describe '#run' do
|
81
75
|
it 'loads the recipe' do
|
82
76
|
cli.run
|
@@ -13,7 +13,7 @@ module Producer::Core
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '.define_test' do
|
16
|
-
let(:some_test_class) {
|
16
|
+
let(:some_test_class) { Test }
|
17
17
|
|
18
18
|
before { Condition::DSL.define_test(:some_test, some_test_class) }
|
19
19
|
|
@@ -24,15 +24,38 @@ module Producer::Core
|
|
24
24
|
it 'defines the negated test' do
|
25
25
|
expect(dsl).to respond_to :no_some_test
|
26
26
|
end
|
27
|
+
|
28
|
+
context 'when a test keyword is called' do
|
29
|
+
it 'registers the test' do
|
30
|
+
expect { dsl.some_test }.to change { dsl.tests.count }.by 1
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'registers the test with current env' do
|
34
|
+
dsl.some_test
|
35
|
+
expect(dsl.tests.first.env).to be env
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'registers the test with given arguments' do
|
39
|
+
dsl.some_test :some, :args
|
40
|
+
expect(dsl.tests.first.arguments).to eq [:some, :args]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when a negated test keyword is called' do
|
45
|
+
it 'registers a negated test' do
|
46
|
+
dsl.no_some_test
|
47
|
+
expect(dsl.tests.first).to be_negated
|
48
|
+
end
|
49
|
+
end
|
27
50
|
end
|
28
51
|
|
29
52
|
describe '#initialize' do
|
30
|
-
it 'assigns the
|
31
|
-
expect(dsl.
|
53
|
+
it 'assigns the env' do
|
54
|
+
expect(dsl.env).to be env
|
32
55
|
end
|
33
56
|
|
34
|
-
it 'assigns the
|
35
|
-
expect(dsl.
|
57
|
+
it 'assigns the code' do
|
58
|
+
expect(dsl.block).to be block
|
36
59
|
end
|
37
60
|
|
38
61
|
it 'assigns no test' do
|
@@ -40,46 +63,15 @@ module Producer::Core
|
|
40
63
|
end
|
41
64
|
end
|
42
65
|
|
43
|
-
describe '#
|
44
|
-
it '
|
45
|
-
dsl.
|
46
|
-
expect
|
66
|
+
describe '#evaluate' do
|
67
|
+
it 'evaluates its code' do
|
68
|
+
dsl = described_class.new(env) { throw :condition_code }
|
69
|
+
expect { dsl.evaluate }.to throw_symbol :condition_code
|
47
70
|
end
|
48
|
-
end
|
49
71
|
|
50
|
-
describe '#evaluate' do
|
51
72
|
it 'returns the value returned by the assigned block' do
|
52
73
|
expect(dsl.evaluate).to eq block.call
|
53
74
|
end
|
54
|
-
|
55
|
-
context 'when a defined test keyword is called' do
|
56
|
-
let(:some_test_class) { double 'SomeTest class' }
|
57
|
-
let(:block) { proc { some_test :some, :args } }
|
58
|
-
|
59
|
-
before { Condition::DSL.define_test(:some_test, some_test_class) }
|
60
|
-
|
61
|
-
it 'builds a new test with the env and given arguments' do
|
62
|
-
expect(some_test_class).to receive(:new).with(env, :some, :args)
|
63
|
-
dsl.evaluate
|
64
|
-
end
|
65
|
-
|
66
|
-
it 'registers the new test' do
|
67
|
-
some_test = double 'SomeTest instance'
|
68
|
-
allow(some_test_class).to receive(:new) { some_test }
|
69
|
-
dsl.evaluate
|
70
|
-
expect(dsl.tests).to include(some_test)
|
71
|
-
end
|
72
|
-
|
73
|
-
context 'when keyword is prefixed with "no_"' do
|
74
|
-
let(:block) { proc { no_some_test :some, :args } }
|
75
|
-
|
76
|
-
it 'builds a negated test' do
|
77
|
-
expect(some_test_class)
|
78
|
-
.to receive(:new).with(env, :some, :args, negated: true)
|
79
|
-
dsl.evaluate
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
75
|
end
|
84
76
|
end
|
85
77
|
end
|
@@ -2,56 +2,40 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Producer::Core
|
4
4
|
describe Condition do
|
5
|
-
|
6
|
-
|
5
|
+
let(:test_ok) { double 'test', pass?: true }
|
6
|
+
let(:test_ko) { double 'test', pass?: false }
|
7
7
|
let(:tests) { [test_ok, test_ko] }
|
8
8
|
subject(:condition) { Condition.new(tests) }
|
9
9
|
|
10
10
|
describe '.evaluate' do
|
11
|
-
let(:env)
|
12
|
-
let(:block)
|
13
|
-
|
14
|
-
|
15
|
-
expect(Condition::DSL)
|
16
|
-
.to receive(:new).with(env, &block).and_call_original
|
17
|
-
Condition.evaluate(env, &block)
|
18
|
-
end
|
11
|
+
let(:env) { double 'env' }
|
12
|
+
let(:block) { proc { some_test; :some_return_value } }
|
13
|
+
let(:some_test_class) { Class.new(Test) }
|
14
|
+
subject(:condition) { described_class.evaluate(env, &block) }
|
19
15
|
|
20
|
-
|
21
|
-
dsl = double('dsl').as_null_object
|
22
|
-
allow(Condition::DSL).to receive(:new) { dsl }
|
23
|
-
expect(dsl).to receive :evaluate
|
24
|
-
Condition.evaluate(env, &block)
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'builds a condition with its test and block return value' do
|
28
|
-
expect(Condition)
|
29
|
-
.to receive(:new).with([], :some_condition_code)
|
30
|
-
Condition.evaluate(env, &block)
|
31
|
-
end
|
16
|
+
before { Condition::DSL.define_test(:some_test, some_test_class) }
|
32
17
|
|
33
|
-
it 'returns
|
34
|
-
condition
|
35
|
-
|
36
|
-
expect(Condition.evaluate(env, &block)).to be condition
|
18
|
+
it 'returns an evaluated condition' do
|
19
|
+
expect(condition.tests.first).to be_a Test
|
20
|
+
expect(condition.return_value).to eq :some_return_value
|
37
21
|
end
|
38
22
|
end
|
39
23
|
|
40
24
|
describe '#initialize' do
|
41
25
|
it 'assigns the tests' do
|
42
|
-
expect(condition.
|
26
|
+
expect(condition.tests).to eq tests
|
43
27
|
end
|
44
28
|
|
45
29
|
it 'assigns nil as a default return value' do
|
46
|
-
expect(condition.
|
30
|
+
expect(condition.return_value).to be nil
|
47
31
|
end
|
48
32
|
|
49
33
|
context 'when a return value is given as argument' do
|
50
34
|
let(:return_value) { :some_return_value }
|
51
|
-
subject(:condition) {
|
35
|
+
subject(:condition) { described_class.new(tests, return_value) }
|
52
36
|
|
53
37
|
it 'assigns the return value' do
|
54
|
-
expect(condition.
|
38
|
+
expect(condition.return_value).to eq return_value
|
55
39
|
end
|
56
40
|
end
|
57
41
|
end
|
@@ -74,7 +58,7 @@ module Producer::Core
|
|
74
58
|
end
|
75
59
|
|
76
60
|
context 'when there are no test' do
|
77
|
-
subject(:condition) {
|
61
|
+
subject(:condition) { described_class.new([], return_value) }
|
78
62
|
|
79
63
|
context 'and return value is truthy' do
|
80
64
|
let(:return_value) { :some_truthy_value }
|
@@ -2,32 +2,37 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Producer::Core
|
4
4
|
describe Env do
|
5
|
-
let(:output) { double 'output' }
|
6
5
|
subject(:env) { Env.new }
|
7
6
|
|
8
7
|
describe '#initialize' do
|
8
|
+
it 'assigns $stdin as the default output' do
|
9
|
+
expect(env.input).to be $stdin
|
10
|
+
end
|
11
|
+
|
9
12
|
it 'assigns $stdout as the default output' do
|
10
|
-
expect(env.
|
13
|
+
expect(env.output).to be $stdout
|
11
14
|
end
|
12
15
|
|
13
16
|
it 'assigns no default target' do
|
14
17
|
expect(env.target).not_to be
|
15
18
|
end
|
16
19
|
|
17
|
-
context 'when
|
18
|
-
|
20
|
+
context 'when input is given as argument' do
|
21
|
+
let(:input) { double 'input' }
|
22
|
+
subject(:env) { described_class.new(input: input) }
|
19
23
|
|
20
|
-
it 'assigns the given
|
21
|
-
expect(env.
|
24
|
+
it 'assigns the given input' do
|
25
|
+
expect(env.input).to eq input
|
22
26
|
end
|
23
27
|
end
|
24
|
-
end
|
25
28
|
|
26
|
-
|
27
|
-
|
29
|
+
context 'when output is given as argument' do
|
30
|
+
let(:output) { double 'output' }
|
31
|
+
subject(:env) { described_class.new(output: output) }
|
28
32
|
|
29
|
-
|
30
|
-
|
33
|
+
it 'assigns the given output' do
|
34
|
+
expect(env.output).to eq output
|
35
|
+
end
|
31
36
|
end
|
32
37
|
end
|
33
38
|
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Producer::Core
|
4
|
+
describe Prompter do
|
5
|
+
let(:input) { StringIO.new }
|
6
|
+
let(:output) { StringIO.new }
|
7
|
+
let(:env) { Env.new(input: input, output: output) }
|
8
|
+
subject(:prompter) { Prompter.new(input, output) }
|
9
|
+
|
10
|
+
describe '#initialize' do
|
11
|
+
it 'assigns the given input' do
|
12
|
+
expect(prompter.input).to be input
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'assigns the given output' do
|
16
|
+
expect(prompter.output).to be output
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe '#prompt' do
|
21
|
+
let(:question) { 'Which letter?' }
|
22
|
+
let(:choices) { [[:a, ?A], [:b, ?B]] }
|
23
|
+
|
24
|
+
it 'prompts choices' do
|
25
|
+
prompter.prompt question, choices
|
26
|
+
expect(output.string).to eq <<-eoh.gsub /^\s+\|/, ''
|
27
|
+
|#{question}
|
28
|
+
|0: A
|
29
|
+
|1: B
|
30
|
+
|Choice:
|
31
|
+
eoh
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'returns value for entry chosen by user' do
|
35
|
+
input.puts '1'
|
36
|
+
input.rewind
|
37
|
+
expect(prompter.prompt question, choices).to eq :b
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -5,7 +5,7 @@ module Producer::Core
|
|
5
5
|
include FixturesHelpers
|
6
6
|
|
7
7
|
let(:code) { proc { :some_recipe_code } }
|
8
|
-
let(:env) {
|
8
|
+
let(:env) { Env.new }
|
9
9
|
subject(:dsl) { Recipe::DSL.new(env, &code) }
|
10
10
|
|
11
11
|
describe '#initialize' do
|
@@ -19,16 +19,16 @@ module Producer::Core
|
|
19
19
|
|
20
20
|
context 'when a string of code is given as argument' do
|
21
21
|
let(:code) { 'some_code' }
|
22
|
-
subject(:dsl) {
|
22
|
+
subject(:dsl) { described_class.new(env, code) }
|
23
23
|
|
24
24
|
it 'assigns the string of code' do
|
25
|
-
expect(dsl.
|
25
|
+
expect(dsl.code).to eq code
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
context 'when a code block is given as argument' do
|
30
30
|
it 'assigns the code block' do
|
31
|
-
expect(dsl.
|
31
|
+
expect(dsl.block).to be code
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -44,7 +44,7 @@ module Producer::Core
|
|
44
44
|
|
45
45
|
describe '#evaluate' do
|
46
46
|
it 'evaluates its code' do
|
47
|
-
dsl =
|
47
|
+
dsl = described_class.new(env) { throw :recipe_code }
|
48
48
|
expect { dsl.evaluate }.to throw_symbol :recipe_code
|
49
49
|
end
|
50
50
|
|
@@ -53,76 +53,50 @@ module Producer::Core
|
|
53
53
|
end
|
54
54
|
end
|
55
55
|
|
56
|
-
|
57
|
-
|
56
|
+
describe '#source' do
|
57
|
+
let(:filepath) { fixture_path_for 'recipes/throw' }
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
it 'returns the current environment' do
|
63
|
-
expect(env).to receive :some_message
|
64
|
-
dsl.evaluate
|
65
|
-
end
|
59
|
+
it 'sources the recipe given as argument' do
|
60
|
+
expect { dsl.source filepath }.to throw_symbol :recipe_code
|
66
61
|
end
|
62
|
+
end
|
67
63
|
|
68
|
-
|
69
|
-
|
70
|
-
let(:code) { "source '#{filepath}'" }
|
71
|
-
subject(:dsl) { Recipe::DSL.new(env, code) }
|
64
|
+
describe '#target' do
|
65
|
+
let(:host) { 'some_host.example' }
|
72
66
|
|
73
|
-
|
74
|
-
|
75
|
-
|
67
|
+
it 'registers the target host in the env' do
|
68
|
+
dsl.target host
|
69
|
+
expect(env.target).to eq host
|
76
70
|
end
|
71
|
+
end
|
77
72
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
expect(env).to receive(:target=).with('some_host.example')
|
83
|
-
dsl
|
84
|
-
end
|
73
|
+
describe '#task' do
|
74
|
+
it 'registers a new evaluated task' do
|
75
|
+
expect { dsl.task(:some_task) { :some_task_code } }
|
76
|
+
.to change { dsl.tasks.count }.by 1
|
85
77
|
end
|
78
|
+
end
|
86
79
|
|
87
|
-
|
88
|
-
|
80
|
+
describe '#macro' do
|
81
|
+
it 'defines the new recipe keyword' do
|
82
|
+
dsl.macro :hello
|
83
|
+
expect(dsl).to respond_to(:hello)
|
84
|
+
end
|
89
85
|
|
90
|
-
|
91
|
-
|
92
|
-
.to receive(:evaluate).with(:some_task, env, :some, :arg) do |&b|
|
93
|
-
expect(b.call).to eq :some_value
|
94
|
-
end
|
95
|
-
dsl
|
96
|
-
end
|
86
|
+
context 'when a defined macro is called' do
|
87
|
+
before { dsl.macro(:hello) { :some_macro_code } }
|
97
88
|
|
98
89
|
it 'registers the new task' do
|
99
|
-
|
100
|
-
allow(Task).to receive(:new) { task }
|
101
|
-
expect(dsl.tasks).to include(task)
|
90
|
+
expect { dsl.hello }.to change { dsl.tasks.count }.by 1
|
102
91
|
end
|
103
92
|
end
|
104
93
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
it 'defines the new recipe keyword' do
|
109
|
-
expect(dsl).to respond_to(:hello)
|
110
|
-
end
|
111
|
-
|
112
|
-
context 'when the new keyword is called' do
|
113
|
-
let(:code) { proc { macro(:hello) { echo 'hello' }; hello } }
|
114
|
-
|
115
|
-
it 'registers the new task' do
|
116
|
-
expect(dsl.tasks.first.actions.first).to be_an Actions::Echo
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
context 'when macro takes arguments' do
|
121
|
-
let(:code) { proc { macro(:hello) { |e| echo e }; hello :arg } }
|
94
|
+
context 'when a defined macro is called with arguments' do
|
95
|
+
before { dsl.macro(:hello) { |a, b| echo a, b } }
|
122
96
|
|
123
|
-
|
124
|
-
|
125
|
-
|
97
|
+
it 'evaluates task code with arguments' do
|
98
|
+
dsl.hello :some, :args
|
99
|
+
expect(dsl.tasks.first.actions.first.arguments).to eq [:some, :args]
|
126
100
|
end
|
127
101
|
end
|
128
102
|
end
|
@@ -9,37 +9,40 @@ module Producer::Core
|
|
9
9
|
|
10
10
|
describe '.string_to_hash' do
|
11
11
|
it 'converts key=value pairs separated by new lines to a hash' do
|
12
|
-
expect(
|
13
|
-
.to eq variables
|
12
|
+
expect(described_class.string_to_hash(string)).to eq variables
|
14
13
|
end
|
15
14
|
end
|
16
15
|
|
17
16
|
describe '.new_from_string' do
|
18
|
-
it '
|
19
|
-
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
it 'returns the instance' do
|
24
|
-
environment = double 'environment'
|
25
|
-
allow(Remote::Environment).to receive(:new) { environment }
|
26
|
-
expect(Remote::Environment.new_from_string(string)).to be environment
|
17
|
+
it 'returns a new instance with converted keys and values' do
|
18
|
+
environment = described_class.new_from_string string
|
19
|
+
expect(environment.variables).to eq variables
|
27
20
|
end
|
28
21
|
end
|
29
22
|
|
30
23
|
describe '#initialize' do
|
31
24
|
it 'assigns the key/value pairs' do
|
32
|
-
expect(environment.
|
25
|
+
expect(environment.variables).to eq variables
|
33
26
|
end
|
34
27
|
end
|
35
28
|
|
36
29
|
describe '#key?' do
|
37
|
-
|
30
|
+
context 'when key is defined' do
|
31
|
+
it 'returns true' do
|
32
|
+
expect(environment.key? 'FOO').to be true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'when key is not defined' do
|
37
|
+
it 'returns false' do
|
38
|
+
expect(environment.key? 'INEXISTENT_KEY').to be false
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
environment.key? key
|
43
|
+
describe '#[]' do
|
44
|
+
it 'returns the value indexed by given key' do
|
45
|
+
expect(environment['FOO']).to eq 'bar'
|
43
46
|
end
|
44
47
|
end
|
45
48
|
end
|
@@ -5,8 +5,8 @@ module Producer::Core
|
|
5
5
|
let(:hostname) { 'some_host.example' }
|
6
6
|
subject(:remote) { Remote.new(hostname) }
|
7
7
|
|
8
|
-
describe '#
|
9
|
-
it '
|
8
|
+
describe '#initialize' do
|
9
|
+
it 'assigns the given hostname' do
|
10
10
|
expect(remote.hostname).to eq hostname
|
11
11
|
end
|
12
12
|
end
|
@@ -116,26 +116,14 @@ module Producer::Core
|
|
116
116
|
end
|
117
117
|
end
|
118
118
|
|
119
|
-
describe '#environment'
|
119
|
+
describe '#environment' do
|
120
120
|
let(:command) { 'env' }
|
121
|
-
let(:output) {
|
121
|
+
let(:output) { 'FOO=bar' }
|
122
122
|
|
123
|
-
before
|
124
|
-
story_with_new_channel do |ch|
|
125
|
-
ch.sends_exec command
|
126
|
-
ch.gets_data output
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
it 'builds a remote environment with the result of `env` command' do
|
131
|
-
expect(Remote::Environment).to receive(:new_from_string).with(output)
|
132
|
-
remote.environment
|
133
|
-
end
|
123
|
+
before { allow(remote).to receive(:execute) { output } }
|
134
124
|
|
135
|
-
it 'returns
|
136
|
-
environment
|
137
|
-
allow(Remote::Environment).to receive(:new_from_string) { environment }
|
138
|
-
expect(remote.environment).to be environment
|
125
|
+
it 'returns a remote environment' do
|
126
|
+
expect(remote.environment['FOO']).to eq 'bar'
|
139
127
|
end
|
140
128
|
end
|
141
129
|
end
|
@@ -3,7 +3,7 @@ require 'spec_helper'
|
|
3
3
|
module Producer::Core
|
4
4
|
describe Task::DSL do
|
5
5
|
let(:block) { proc {} }
|
6
|
-
let(:env) {
|
6
|
+
let(:env) { Env.new }
|
7
7
|
subject(:dsl) { Task::DSL.new(env, &block) }
|
8
8
|
|
9
9
|
%w[echo sh file_write].each do |action|
|
@@ -13,10 +13,29 @@ module Producer::Core
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe '.define_action' do
|
16
|
+
let(:some_action_class) { Class.new(Action) }
|
17
|
+
|
18
|
+
before { described_class.define_action(:some_action, some_action_class) }
|
19
|
+
|
16
20
|
it 'defines a new action keyword' do
|
17
|
-
Task::DSL.define_action(:some_action, Object)
|
18
21
|
expect(dsl).to respond_to :some_action
|
19
22
|
end
|
23
|
+
|
24
|
+
context 'when an action keyword is called' do
|
25
|
+
it 'registers the action' do
|
26
|
+
expect { dsl.some_action }.to change { dsl.actions.count }.by 1
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'registers the action with current env' do
|
30
|
+
dsl.some_action
|
31
|
+
expect(dsl.actions.first.env).to be env
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'registers the action with given arguments' do
|
35
|
+
dsl.some_action :some, :args
|
36
|
+
expect(dsl.actions.first.arguments).to eq [:some, :args]
|
37
|
+
end
|
38
|
+
end
|
20
39
|
end
|
21
40
|
|
22
41
|
describe '#initialize' do
|
@@ -24,28 +43,16 @@ module Producer::Core
|
|
24
43
|
expect(dsl.env).to be env
|
25
44
|
end
|
26
45
|
|
46
|
+
it 'assigns the given block' do
|
47
|
+
expect(dsl.block).to be block
|
48
|
+
end
|
49
|
+
|
27
50
|
it 'assigns no action' do
|
28
51
|
expect(dsl.actions).to be_empty
|
29
52
|
end
|
30
53
|
|
31
54
|
it 'assigns true as the condition' do
|
32
|
-
expect(dsl.
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
describe '#actions' do
|
37
|
-
it 'returns the assigned actions' do
|
38
|
-
dsl.instance_eval { @actions = [:some_action] }
|
39
|
-
expect(dsl.actions).to eq [:some_action]
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe '#condition' do
|
44
|
-
context 'without block' do
|
45
|
-
it 'returns the assigned condition' do
|
46
|
-
dsl.instance_eval { @condition = :some_condition }
|
47
|
-
expect(dsl.condition).to be :some_condition
|
48
|
-
end
|
55
|
+
expect(dsl.condition).to be true
|
49
56
|
end
|
50
57
|
end
|
51
58
|
|
@@ -65,47 +72,34 @@ module Producer::Core
|
|
65
72
|
.to throw_symbol :some_argument
|
66
73
|
end
|
67
74
|
end
|
75
|
+
end
|
68
76
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
Task::DSL.define_action(:some_action, some_action_class)
|
75
|
-
dsl.evaluate
|
77
|
+
describe '#condition' do
|
78
|
+
context 'when a block is given' do
|
79
|
+
it 'assigns a new evaluated condition' do
|
80
|
+
dsl.condition { :some_return_value }
|
81
|
+
expect(dsl.condition.return_value).to eq :some_return_value
|
76
82
|
end
|
83
|
+
end
|
84
|
+
end
|
77
85
|
|
78
|
-
|
79
|
-
|
80
|
-
|
86
|
+
describe '#ask' do
|
87
|
+
let(:question) { 'Which letter?' }
|
88
|
+
let(:choices) { [[:a, ?A], [:b, ?B]] }
|
89
|
+
let(:prompter_class) { double('prompter class').as_null_object }
|
90
|
+
subject(:ask) { dsl.ask question, choices,
|
91
|
+
prompter: prompter_class }
|
81
92
|
|
82
|
-
|
83
|
-
|
84
|
-
|
93
|
+
it 'builds a prompter' do
|
94
|
+
expect(prompter_class).to receive(:new).with(env.input, env.output)
|
95
|
+
ask
|
85
96
|
end
|
86
|
-
end
|
87
97
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
let(:block) { proc { condition { :some_value } } }
|
94
|
-
|
95
|
-
it 'builds a new evaluated condition' do
|
96
|
-
expect(Condition)
|
97
|
-
.to receive :evaluate do |&b|
|
98
|
-
expect(b.call).to eq :some_value
|
99
|
-
end
|
100
|
-
dsl
|
101
|
-
end
|
102
|
-
|
103
|
-
it 'assigns the new condition' do
|
104
|
-
condition = double('condition').as_null_object
|
105
|
-
allow(Condition).to receive(:evaluate) { condition }
|
106
|
-
expect(dsl.condition).to be condition
|
107
|
-
end
|
108
|
-
end
|
98
|
+
it 'prompts and returns the choice' do
|
99
|
+
prompter = double 'prompter'
|
100
|
+
allow(prompter_class).to receive(:new) { prompter }
|
101
|
+
allow(prompter).to receive(:prompt) { :choice }
|
102
|
+
expect(ask).to eq :choice
|
109
103
|
end
|
110
104
|
end
|
111
105
|
end
|
@@ -8,54 +8,44 @@ module Producer::Core
|
|
8
8
|
subject(:task) { Task.new(name, [action], condition) }
|
9
9
|
|
10
10
|
describe '.evaluate' do
|
11
|
-
let(:
|
12
|
-
let(:
|
13
|
-
let(:block)
|
14
|
-
|
15
|
-
|
16
|
-
dsl = double('dsl').as_null_object
|
17
|
-
expect(Task::DSL).to receive(:new).with(env) do |&b|
|
18
|
-
expect(b).to be block
|
19
|
-
dsl
|
20
|
-
end
|
21
|
-
Task.evaluate(name, env, *args, &block)
|
22
|
-
end
|
11
|
+
let(:name) { :some_task }
|
12
|
+
let(:env) { double 'env' }
|
13
|
+
let(:block) { proc { condition { :condition }; some_action } }
|
14
|
+
let(:some_action_class) { Class.new(Action) }
|
15
|
+
subject(:task) { Task.evaluate(name, env, :some, :args, &block) }
|
23
16
|
|
24
|
-
|
25
|
-
dsl = double('dsl').as_null_object
|
26
|
-
allow(Task::DSL).to receive(:new) { dsl }
|
27
|
-
expect(dsl).to receive(:evaluate).with(*args)
|
28
|
-
Task.evaluate(name, env, *args, &block)
|
29
|
-
end
|
17
|
+
before { Task::DSL.define_action(:some_action, some_action_class) }
|
30
18
|
|
31
|
-
it '
|
32
|
-
|
33
|
-
'dsl', actions: [:some_action], condition: :some_condition
|
34
|
-
).as_null_object
|
35
|
-
allow(Task::DSL).to receive(:new) { dsl }
|
36
|
-
expect(Task)
|
37
|
-
.to receive(:new).with(:some_task, [:some_action], :some_condition)
|
38
|
-
Task.evaluate(name, env, *args, &block)
|
19
|
+
it 'returns an evaluated task' do
|
20
|
+
expect(task).to be_kind_of Task
|
39
21
|
end
|
40
22
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
23
|
+
context 'evaluated task' do
|
24
|
+
it 'has the requested name' do
|
25
|
+
expect(task.name).to eq name
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'has the requested actions' do
|
29
|
+
expect(task.actions.first).to be_kind_of some_action_class
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'has the requested condition' do
|
33
|
+
expect(task.condition.return_value).to be :condition
|
34
|
+
end
|
45
35
|
end
|
46
36
|
end
|
47
37
|
|
48
38
|
describe '#initialize' do
|
49
39
|
it 'assigns the name' do
|
50
|
-
expect(task.
|
40
|
+
expect(task.name).to eq name
|
51
41
|
end
|
52
42
|
|
53
43
|
it 'assigns the actions' do
|
54
|
-
expect(task.
|
44
|
+
expect(task.actions).to eq [action]
|
55
45
|
end
|
56
46
|
|
57
47
|
it 'assigns the condition' do
|
58
|
-
expect(task.
|
48
|
+
expect(task.condition).to eq condition
|
59
49
|
end
|
60
50
|
|
61
51
|
context 'when only the name is given as argument' do
|
@@ -71,24 +61,6 @@ module Producer::Core
|
|
71
61
|
end
|
72
62
|
end
|
73
63
|
|
74
|
-
describe '#name' do
|
75
|
-
it 'returns its name' do
|
76
|
-
expect(task.name).to eq name
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
describe '#actions' do
|
81
|
-
it 'returns the assigned actions' do
|
82
|
-
expect(task.actions).to eq [action]
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
describe '#condition' do
|
87
|
-
it 'returns the assigned condition' do
|
88
|
-
expect(task.condition).to be condition
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
64
|
describe '#condition_met?' do
|
93
65
|
context 'when condition is truthy' do
|
94
66
|
let(:condition) { Condition.new([], true) }
|
@@ -2,41 +2,41 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
module Producer::Core
|
4
4
|
describe Test do
|
5
|
-
let(:env) {
|
5
|
+
let(:env) { Env.new }
|
6
6
|
let(:arguments) { [:some, :arguments] }
|
7
7
|
subject(:test) { Test.new(env, *arguments) }
|
8
8
|
|
9
9
|
describe '#initialize' do
|
10
10
|
it 'assigns the env' do
|
11
|
-
expect(test.
|
11
|
+
expect(test.env).to be env
|
12
12
|
end
|
13
13
|
|
14
14
|
it 'assigns the arguments' do
|
15
|
-
expect(test.
|
15
|
+
expect(test.arguments).to eq arguments
|
16
16
|
end
|
17
17
|
|
18
18
|
it 'assigns negated as false by default' do
|
19
|
-
expect(test
|
19
|
+
expect(test).to_not be_negated
|
20
20
|
end
|
21
21
|
|
22
22
|
context 'when negated option is true' do
|
23
|
-
subject(:test) {
|
23
|
+
subject(:test) { described_class.new(env, *arguments, negated: true) }
|
24
24
|
|
25
25
|
it 'assigns negated as true' do
|
26
|
-
expect(test
|
26
|
+
expect(test).to be_negated
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
describe '#
|
32
|
-
it 'returns
|
33
|
-
expect(test.
|
31
|
+
describe '#remote' do
|
32
|
+
it 'returns env remote' do
|
33
|
+
expect(test.remote).to be test.env.remote
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
describe '#
|
38
|
-
it 'returns
|
39
|
-
expect(test.
|
37
|
+
describe '#fs' do
|
38
|
+
it 'returns env remote fs' do
|
39
|
+
expect(test.fs).to be test.env.remote.fs
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -46,7 +46,7 @@ module Producer::Core
|
|
46
46
|
end
|
47
47
|
|
48
48
|
context 'when test is negated' do
|
49
|
-
subject(:test) {
|
49
|
+
subject(:test) { described_class.new(env, *arguments, negated: true) }
|
50
50
|
|
51
51
|
it 'returns true' do
|
52
52
|
expect(test.negated?).to be true
|
@@ -66,7 +66,7 @@ module Producer::Core
|
|
66
66
|
end
|
67
67
|
|
68
68
|
context 'when test is negated' do
|
69
|
-
subject(:test) {
|
69
|
+
subject(:test) { described_class.new(env, *arguments, negated: true) }
|
70
70
|
|
71
71
|
it 'returns false when #verify is true' do
|
72
72
|
allow(test).to receive(:verify) { true }
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: producer-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thibault Jouan
|
@@ -112,6 +112,7 @@ files:
|
|
112
112
|
- features/actions/file_write.feature
|
113
113
|
- features/actions/sh.feature
|
114
114
|
- features/cli/usage.feature
|
115
|
+
- features/recipes/ask.feature
|
115
116
|
- features/recipes/env.feature
|
116
117
|
- features/recipes/evaluation.feature
|
117
118
|
- features/recipes/macro.feature
|
@@ -140,6 +141,7 @@ files:
|
|
140
141
|
- lib/producer/core/condition/dsl.rb
|
141
142
|
- lib/producer/core/env.rb
|
142
143
|
- lib/producer/core/errors.rb
|
144
|
+
- lib/producer/core/prompter.rb
|
143
145
|
- lib/producer/core/recipe.rb
|
144
146
|
- lib/producer/core/recipe/dsl.rb
|
145
147
|
- lib/producer/core/remote.rb
|
@@ -164,6 +166,7 @@ files:
|
|
164
166
|
- spec/producer/core/condition/dsl_spec.rb
|
165
167
|
- spec/producer/core/condition_spec.rb
|
166
168
|
- spec/producer/core/env_spec.rb
|
169
|
+
- spec/producer/core/prompter_spec.rb
|
167
170
|
- spec/producer/core/recipe/dsl_spec.rb
|
168
171
|
- spec/producer/core/recipe_spec.rb
|
169
172
|
- spec/producer/core/remote/environment_spec.rb
|
@@ -179,7 +182,6 @@ files:
|
|
179
182
|
- spec/support/exit_helpers.rb
|
180
183
|
- spec/support/fixtures_helpers.rb
|
181
184
|
- spec/support/net_ssh_story_helpers.rb
|
182
|
-
- spec/support/tests_helpers.rb
|
183
185
|
homepage: https://rubygems.org/gems/producer-core
|
184
186
|
licenses: []
|
185
187
|
metadata: {}
|
@@ -208,6 +210,7 @@ test_files:
|
|
208
210
|
- features/actions/file_write.feature
|
209
211
|
- features/actions/sh.feature
|
210
212
|
- features/cli/usage.feature
|
213
|
+
- features/recipes/ask.feature
|
211
214
|
- features/recipes/env.feature
|
212
215
|
- features/recipes/evaluation.feature
|
213
216
|
- features/recipes/macro.feature
|
@@ -237,6 +240,7 @@ test_files:
|
|
237
240
|
- spec/producer/core/condition/dsl_spec.rb
|
238
241
|
- spec/producer/core/condition_spec.rb
|
239
242
|
- spec/producer/core/env_spec.rb
|
243
|
+
- spec/producer/core/prompter_spec.rb
|
240
244
|
- spec/producer/core/recipe/dsl_spec.rb
|
241
245
|
- spec/producer/core/recipe_spec.rb
|
242
246
|
- spec/producer/core/remote/environment_spec.rb
|
@@ -252,5 +256,4 @@ test_files:
|
|
252
256
|
- spec/support/exit_helpers.rb
|
253
257
|
- spec/support/fixtures_helpers.rb
|
254
258
|
- spec/support/net_ssh_story_helpers.rb
|
255
|
-
- spec/support/tests_helpers.rb
|
256
259
|
has_rdoc:
|