Skip to content

Commit 342cb79

Browse files
dersamjuniper-shopify
authored andcommitted
DSL: passing output data between steps
1 parent 4571b58 commit 342cb79

File tree

8 files changed

+92
-24
lines changed

8 files changed

+92
-24
lines changed

dsl/step_communication.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# typed: false
2+
# frozen_string_literal: true
3+
4+
# How do we pass information between steps?
5+
# Demonstrate by passing result of a command output to another step
6+
7+
config do
8+
cmd(:echo) { display! }
9+
end
10+
11+
execute do
12+
cmd(:ls) { "ls -al" }
13+
cmd(:echo) do
14+
# TODO: this is a bespoke output object for cmd, is there a generic one we can offer
15+
first_line = cmd(:ls).command_output.split("\n").second
16+
"echo '#{first_line}'"
17+
end
18+
end

lib/roast/dsl/cog.rb

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
module Roast
55
module DSL
66
class Cog
7+
class CogAlreadyRanError < StandardError; end
8+
79
class << self
810
def on_create
911
eigen = self
1012
proc do |instance_name = Random.uuid, &action|
11-
#: self as Roast::DSL::ExecutionContext
12-
add_cog_instance(instance_name, eigen.new(action))
13+
#: self as Roast::DSL::WorkflowExecutionContext
14+
add_cog_instance(instance_name, eigen.new(instance_name, action))
1315
end
1416
end
1517

@@ -39,23 +41,28 @@ def find_child_config_or_default
3941
end
4042
end
4143

42-
attr_reader :output
44+
attr_reader :name, :output
4345

44-
def initialize(cog_input_proc)
46+
def initialize(name, cog_input_proc)
47+
@name = name
4548
@cog_input_proc = cog_input_proc
49+
@finished = false
4650
end
4751

48-
def input
49-
@cog_input_proc.call
50-
end
52+
def run!(config, cog_execution_context)
53+
raise CogAlreadyRanError if ran?
5154

52-
def run!(config)
5355
@config = config
54-
@output = execute
56+
@output = execute(cog_execution_context.instance_exec(&@cog_input_proc))
57+
@finished = true
58+
end
59+
60+
def ran?
61+
@finished
5562
end
5663

5764
# Inheriting cog must implement this
58-
def execute
65+
def execute(input)
5966
raise NotImplementedError
6067
end
6168
end

lib/roast/dsl/cog/store.rb

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@ class Cog
77
class Store
88
class CogAlreadyDefinedError < Roast::Error; end
99

10-
#: (Symbol) -> Roast::DSL::Cog?
11-
def find(id)
12-
store[id]
13-
end
10+
delegate :[], to: :store
1411

1512
#: (Symbol, Roast::DSL::Cog) -> Roast::DSL::Cog
1613
def insert(id, inst)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# typed: true
2+
# frozen_string_literal: true
3+
4+
module Roast
5+
module DSL
6+
# Contains the cogs already executed in this run.
7+
class CogExecutionContext
8+
# Raises if you access a cog in an execution block that hasn't already been run.
9+
class IncompleteCogExecutionAccessError < StandardError; end
10+
11+
def initialize(cogs, bound_names)
12+
@cogs = cogs
13+
bind_cog_methods(bound_names)
14+
end
15+
16+
private
17+
18+
def bind_cog_methods(bound_names)
19+
bound_names.map do |name|
20+
define_singleton_method(name.to_sym, ->(name) do
21+
@cogs[name].tap do |cog|
22+
raise IncompleteCogExecutionAccessError unless cog.ran?
23+
end.output
24+
end)
25+
end
26+
end
27+
end
28+
end
29+
end

lib/roast/dsl/cogs/cmd.rb

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module Cogs
77
class Cmd < Cog
88
class Output
99
#: String?
10-
attr_reader :output
10+
attr_reader :command_output
1111

1212
#: String?
1313
attr_reader :err
@@ -21,7 +21,7 @@ class Output
2121
#| Process::Status? status
2222
#| ) -> void
2323
def initialize(output, error, status)
24-
@output = output
24+
@command_output = output
2525
@err = error
2626
@status = status
2727
end
@@ -37,12 +37,16 @@ def print_all!
3737
def print_all?
3838
!!@values[:print_all]
3939
end
40+
41+
def display!
42+
print_all!
43+
end
4044
end
4145

42-
#: () -> Output
43-
def execute
46+
#: (String) -> Output
47+
def execute(input)
4448
result = Output.new(*Roast::Helpers::CmdRunner.capture3(input))
45-
puts result.output if @config.print_all?
49+
puts result.command_output if @config.print_all?
4650
result
4751
end
4852
end

lib/roast/dsl/executor.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def prepare!(input)
3232

3333
@config_context = ConfigContext.new(@cogs, @config_proc)
3434
@config_context.prepare!
35-
@execution_context = ExecutionContext.new(@cogs, @cog_stack, @execution_proc)
35+
@execution_context = WorkflowExecutionContext.new(@cogs, @cog_stack, @execution_proc)
3636
@execution_context.prepare!
3737

3838
@prepared = true
@@ -44,7 +44,10 @@ def start!
4444
raise ExecutorAlreadyCompletedError if @completed
4545

4646
@cog_stack.map do |name, cog|
47-
cog.run!(@config_context.fetch_merged_config(cog.class, name.to_sym))
47+
cog.run!(
48+
@config_context.fetch_merged_config(cog.class, name.to_sym),
49+
@execution_context.cog_execution_context,
50+
)
4851
end
4952

5053
@completed = true
@@ -63,7 +66,7 @@ def config(&block)
6366
@config_proc = block
6467
end
6568

66-
#: { () [self: ExecutionContext] -> void} -> void
69+
#: { () [self: WorkflowExecutionContext] -> void} -> void
6770
def execute(&block)
6871
@execution_proc = block
6972
end

lib/roast/dsl/execution_context.rb renamed to lib/roast/dsl/workflow_execution_context.rb

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,41 @@
33

44
module Roast
55
module DSL
6-
class ExecutionContext
6+
class WorkflowExecutionContext
77
def initialize(cogs, cog_stack, execution_proc)
88
@cogs = cogs
99
@cog_stack = cog_stack
1010
@execution_proc = execution_proc
11+
@bound_names = []
1112
end
1213

1314
def prepare!
1415
bind_default_cogs
1516
instance_eval(&@execution_proc)
1617
end
1718

19+
def cog_execution_context
20+
@cog_execution_context ||= CogExecutionContext.new(@cogs, @bound_names)
21+
end
22+
1823
private
1924

2025
def add_cog_instance(name, cog)
2126
@cogs.insert(name, cog)
2227
@cog_stack.push([name, cog])
2328
end
2429

30+
def output(name)
31+
@cogs[name].output
32+
end
33+
2534
#: () -> void
2635
def bind_default_cogs
2736
bind_cog(Cogs::Cmd, :cmd)
2837
end
2938

3039
def bind_cog(cog_class, name)
40+
@bound_names << name
3141
instance_eval do
3242
define_singleton_method(name, &cog_class.on_create)
3343
end

sorbet/rbi/shims/lib/roast/dsl/execution_context.rbi renamed to sorbet/rbi/shims/lib/roast/dsl/workflow_execution_context.rbi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
module Roast
55
module DSL
6-
class ExecutionContext
6+
class WorkflowExecutionContext
77
#: (?Symbol?) {() [self: Roast::DSL::Cogs::Cmd] -> String} -> void
88
def cmd(name = nil, &block); end
99
end

0 commit comments

Comments
 (0)