dynflow 0.5.0 → 0.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/dynflow/action.rb +13 -0
- data/lib/dynflow/executors/parallel/worker.rb +1 -0
- data/lib/dynflow/testing/assertions.rb +10 -0
- data/lib/dynflow/testing/dummy_execution_plan.rb +22 -7
- data/lib/dynflow/version.rb +1 -1
- data/lib/dynflow/web_console.rb +7 -3
- data/test/action_test.rb +21 -0
- data/test/testing_test.rb +18 -7
- data/web/views/flow_step.erb +12 -2
- data/web/views/show.erb +10 -0
- metadata +2 -2
data/lib/dynflow/action.rb
CHANGED
@@ -395,6 +395,8 @@ module Dynflow
|
|
395
395
|
end
|
396
396
|
end
|
397
397
|
end
|
398
|
+
|
399
|
+
check_serializable :input
|
398
400
|
end
|
399
401
|
end
|
400
402
|
|
@@ -422,6 +424,8 @@ module Dynflow
|
|
422
424
|
if result == SUSPEND
|
423
425
|
self.state = :suspended
|
424
426
|
end
|
427
|
+
|
428
|
+
check_serializable :output
|
425
429
|
end
|
426
430
|
|
427
431
|
else
|
@@ -440,5 +444,14 @@ module Dynflow
|
|
440
444
|
end
|
441
445
|
end
|
442
446
|
end
|
447
|
+
|
448
|
+
def check_serializable(what)
|
449
|
+
Match! what, :input, :output
|
450
|
+
value = send what
|
451
|
+
recursive_to_hash value # it raises when not serializable
|
452
|
+
rescue => e
|
453
|
+
value.replace not_serializable: true
|
454
|
+
raise e
|
455
|
+
end
|
443
456
|
end
|
444
457
|
end
|
@@ -30,6 +30,16 @@ module Dynflow
|
|
30
30
|
found
|
31
31
|
end
|
32
32
|
|
33
|
+
def refute_action_planed(action, planned_action_class)
|
34
|
+
Match! action.phase, Action::Plan
|
35
|
+
Match! action.state, :success
|
36
|
+
found = action.execution_plan.planned_plan_steps.
|
37
|
+
select { |a| a.is_a?(planned_action_class) }
|
38
|
+
|
39
|
+
assert(found.empty?, "Action #{planned_action_class} was planned")
|
40
|
+
found
|
41
|
+
end
|
42
|
+
|
33
43
|
# assert that +action+ has run-phase planned
|
34
44
|
def assert_run_phase(action, input = nil, &block)
|
35
45
|
Match! action.phase, Action::Plan
|
@@ -7,16 +7,28 @@ module Dynflow
|
|
7
7
|
attr_reader :id, :planned_plan_steps, :planned_run_steps, :planned_finalize_steps
|
8
8
|
|
9
9
|
def initialize
|
10
|
-
@id
|
11
|
-
@planned_plan_steps
|
12
|
-
@planned_run_steps
|
13
|
-
@planned_finalize_steps
|
10
|
+
@id = Testing.get_id.to_s
|
11
|
+
@planned_plan_steps = []
|
12
|
+
@planned_run_steps = []
|
13
|
+
@planned_finalize_steps = []
|
14
|
+
@planned_action_stubbers = {}
|
14
15
|
end
|
15
16
|
|
16
17
|
def world
|
17
18
|
@world ||= DummyWorld.new
|
18
19
|
end
|
19
20
|
|
21
|
+
# Allows modify the DummyPlannedAction returned by plan_action
|
22
|
+
def stub_planned_action(klass, &block)
|
23
|
+
@planned_action_stubbers[klass] = block
|
24
|
+
end
|
25
|
+
|
26
|
+
def add_plan_step(klass, _)
|
27
|
+
dummy_planned_action(klass).tap do |action|
|
28
|
+
@planned_plan_steps << action
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
20
32
|
def add_run_step(action)
|
21
33
|
@planned_run_steps << action
|
22
34
|
action
|
@@ -27,9 +39,12 @@ module Dynflow
|
|
27
39
|
action
|
28
40
|
end
|
29
41
|
|
30
|
-
def
|
31
|
-
|
32
|
-
|
42
|
+
def dummy_planned_action(klass)
|
43
|
+
DummyPlannedAction.new(klass).tap do |action|
|
44
|
+
if planned_action_stubber = @planned_action_stubbers[klass]
|
45
|
+
planned_action_stubber.call(action)
|
46
|
+
end
|
47
|
+
end
|
33
48
|
end
|
34
49
|
|
35
50
|
def switch_flow(*args, &block)
|
data/lib/dynflow/version.rb
CHANGED
data/lib/dynflow/web_console.rb
CHANGED
@@ -56,6 +56,10 @@ module Dynflow
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
def duration_to_s(duration)
|
60
|
+
h("%0.2fs" % duration)
|
61
|
+
end
|
62
|
+
|
59
63
|
def load_action(step)
|
60
64
|
world.persistence.load_action(step)
|
61
65
|
end
|
@@ -74,7 +78,7 @@ module Dynflow
|
|
74
78
|
if !value_html.empty?
|
75
79
|
<<-HTML
|
76
80
|
<p>
|
77
|
-
|
81
|
+
<b>#{h(label)}</b>
|
78
82
|
#{value_html}
|
79
83
|
</p>
|
80
84
|
HTML
|
@@ -139,11 +143,11 @@ module Dynflow
|
|
139
143
|
end
|
140
144
|
|
141
145
|
def updated_url(new_params)
|
142
|
-
url("?" + Rack::Utils.
|
146
|
+
url("?" + Rack::Utils.build_nested_query(params.merge(new_params.stringify_keys)))
|
143
147
|
end
|
144
148
|
|
145
149
|
def paginated_url(delta)
|
146
|
-
h(updated_url(page: [0, page + delta].max))
|
150
|
+
h(updated_url(page: [0, page + delta].max.to_s))
|
147
151
|
end
|
148
152
|
|
149
153
|
def pagination_options
|
data/test/action_test.rb
CHANGED
@@ -70,5 +70,26 @@ module Dynflow
|
|
70
70
|
presenter.summary.must_equal(assignees: ["John Doe"])
|
71
71
|
end
|
72
72
|
end
|
73
|
+
|
74
|
+
describe 'serialization' do
|
75
|
+
|
76
|
+
include Testing
|
77
|
+
|
78
|
+
it 'fails when input is not serializable' do
|
79
|
+
klass = Class.new(Dynflow::Action)
|
80
|
+
-> { create_and_plan_action klass, key: Object.new }.must_raise NoMethodError
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'fails when output is not serializable' do
|
84
|
+
klass = Class.new(Dynflow::Action) do
|
85
|
+
def run
|
86
|
+
output.update key: Object.new
|
87
|
+
end
|
88
|
+
end
|
89
|
+
action = create_and_plan_action klass, {}
|
90
|
+
-> { run_action action }.must_raise NoMethodError
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
73
94
|
end
|
74
95
|
end
|
data/test/testing_test.rb
CHANGED
@@ -9,7 +9,7 @@ module Dynflow
|
|
9
9
|
|
10
10
|
describe 'testing' do
|
11
11
|
|
12
|
-
|
12
|
+
specify '#plan_action' do
|
13
13
|
input = { 'input' => 'input' }
|
14
14
|
action = create_and_plan_action CWE::DummyHeavyProgress, input
|
15
15
|
|
@@ -21,9 +21,20 @@ module Dynflow
|
|
21
21
|
assert_run_phase action
|
22
22
|
assert_finalize_phase action
|
23
23
|
assert_action_planed action, CWE::DummySuspended
|
24
|
+
refute_action_planed action, CWE::DummyAnotherTrigger
|
24
25
|
end
|
25
26
|
|
26
|
-
|
27
|
+
specify 'stub_plan_action' do
|
28
|
+
action = create_action CWE::DummyHeavyProgress
|
29
|
+
action.execution_plan.stub_planned_action(CWE::DummySuspended) do |sub_action|
|
30
|
+
sub_action.define_singleton_method(:test) { "test" }
|
31
|
+
end
|
32
|
+
plan_action(action, {})
|
33
|
+
stubbed_action = action.execution_plan.planned_plan_steps.first
|
34
|
+
stubbed_action.test.must_equal "test"
|
35
|
+
end
|
36
|
+
|
37
|
+
specify '#run_action without suspend' do
|
27
38
|
input = { 'input' => 'input' }
|
28
39
|
plan = create_and_plan_action CWE::DummyHeavyProgress, input
|
29
40
|
action = run_action plan
|
@@ -37,7 +48,7 @@ module Dynflow
|
|
37
48
|
action.progress_done.must_equal 1
|
38
49
|
end
|
39
50
|
|
40
|
-
|
51
|
+
specify '#run_action with suspend' do
|
41
52
|
input = { 'input' => 'input' }
|
42
53
|
plan = create_and_plan_action CWE::DummySuspended, input
|
43
54
|
action = run_action plan
|
@@ -59,7 +70,7 @@ module Dynflow
|
|
59
70
|
action.progress_done.must_equal 1
|
60
71
|
end
|
61
72
|
|
62
|
-
|
73
|
+
specify '#finalize_action' do
|
63
74
|
input = { 'input' => 'input' }
|
64
75
|
plan = create_and_plan_action CWE::DummyHeavyProgress, input
|
65
76
|
run = run_action plan
|
@@ -122,14 +133,14 @@ module Dynflow
|
|
122
133
|
let(:planned_action) { create_and_plan_action CWE::Merge, plan_input }
|
123
134
|
let(:runned_action) { run_action planned_action }
|
124
135
|
|
125
|
-
it '
|
136
|
+
it 'plans' do
|
126
137
|
assert_run_phase planned_action
|
127
138
|
refute_finalize_phase planned_action
|
128
139
|
|
129
140
|
planned_action.execution_plan.planned_plan_steps.must_be_empty
|
130
141
|
end
|
131
142
|
|
132
|
-
it '
|
143
|
+
it 'runs' do
|
133
144
|
runned_action.output.fetch(:passed).must_equal true
|
134
145
|
end
|
135
146
|
|
@@ -138,7 +149,7 @@ module Dynflow
|
|
138
149
|
super.update review_results: [true, false]
|
139
150
|
end
|
140
151
|
|
141
|
-
it '
|
152
|
+
it 'runs' do
|
142
153
|
runned_action.output.fetch(:passed).must_equal false
|
143
154
|
end
|
144
155
|
end
|
data/web/views/flow_step.erb
CHANGED
@@ -5,17 +5,27 @@
|
|
5
5
|
<% end %>
|
6
6
|
|
7
7
|
<span class="step-label">
|
8
|
-
<%= h(step.id) %>: <%= h(step.action_class.name) %>
|
8
|
+
<%= h(step.id) %>: <%= h(step.action_class.name) %>
|
9
|
+
(<%= h(step.state) %>)
|
10
|
+
<% unless step.state == :pending %>
|
11
|
+
[ <%= duration_to_s(step.real_time) %> / <%= duration_to_s(step.execution_time) %> ]
|
12
|
+
<% end %>
|
9
13
|
</span>
|
10
14
|
<% if @plan.state == :paused && step.state == :error %>
|
11
15
|
<a href="<%= url("/#{@plan.id}/skip/#{step.id}") %>" class="postlink">Skip</a>
|
12
16
|
<% end %>
|
13
17
|
<div class="action">
|
18
|
+
<% unless @plan.state == :pending %>
|
19
|
+
<p><b>Started at:</b> <%= h(step.started_at) %></p>
|
20
|
+
<p><b>Ended at:</b> <%= h(step.ended_at) %></p>
|
21
|
+
<p><b>Real time:</b> <%= duration_to_s(step.real_time) %></p>
|
22
|
+
<p><b>Execution time (excluding suspended state):</b> <%= duration_to_s(step.execution_time) %></p>
|
23
|
+
<% end %>
|
14
24
|
<%= show_action_data("Input:", action.input) %>
|
15
25
|
<%= show_action_data("Output:", action.output) %>
|
16
26
|
<% if step.error %>
|
17
27
|
<p>
|
18
|
-
Error
|
28
|
+
<b>Error:</b>
|
19
29
|
</p>
|
20
30
|
<p>
|
21
31
|
<%= h(step.error.exception_class) %>
|
data/web/views/show.erb
CHANGED
@@ -14,6 +14,16 @@
|
|
14
14
|
<%= h(@plan.result) %>
|
15
15
|
</p>
|
16
16
|
|
17
|
+
<p>
|
18
|
+
<b>Started at:</b>
|
19
|
+
<%= h(@plan.started_at) %>
|
20
|
+
</p>
|
21
|
+
|
22
|
+
<p>
|
23
|
+
<b>Ended at:</b>
|
24
|
+
<%= h(@plan.ended_at) %>
|
25
|
+
</p>
|
26
|
+
|
17
27
|
<ul class="phases nav nav-tabs" id="myTab">
|
18
28
|
<li><a href="#plan">Plan</a></li>
|
19
29
|
<li class="active"><a href="#run">Run</a></li>
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dynflow
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-03-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|