Module: Runbook::Run::ClassMethods

Includes:
Helpers::FormatHelper, Helpers::TmuxHelper, Hooks
Defined in:
lib/runbook/run.rb

Instance Method Summary collapse

Methods included from Helpers::TmuxHelper

#_all_panes_exist?, #_initialize_panes, #_kill_pane, #_layout_file, #_new_window, #_pager_escape_sequence, #_remove_stale_layouts, #_rename_window, #_runbook_pane, #_session_layout_files, #_session_panes, #_set_directory, #_setup_layout, #_setup_panes, #_slug, #_split, #_swap_panes, #_swap_runbook_pane, #kill_all_panes, #send_keys, #setup_layout

Methods included from Helpers::FormatHelper

#deindent

Methods included from Hooks

#_hook_index, #hooks, #hooks_for, #register_hook

Instance Method Details

#_handle_continue_result(result, object, metadata) ⇒ Object



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
# File 'lib/runbook/run.rb', line 223

def _handle_continue_result(result, object, )
  toolbox = [:toolbox]
  case result
  when :continue
    return
  when :skip
    position = [:position]
    current_step = position.split(".")[-1].to_i
    new_step = current_step + 1
    start_at = position.gsub(/\.#{current_step}$/, ".#{new_step}")
    [:start_at] = start_at
  when :jump
    result = toolbox.ask("What position would you like to jump to?")
    if past_position?([:position], result)
      [:reverse] = true
      [:reversed] = true
    end
    [:start_at] = result
  when :no_paranoid
    [:paranoid] = false
  when :exit
    toolbox.exit(0)
  end
end

#_method_name(object) ⇒ Object



209
210
211
# File 'lib/runbook/run.rb', line 209

def _method_name(object)
  object.class.to_s.underscore.gsub("/", "__")
end

#_step_choicesObject



213
214
215
216
217
218
219
220
221
# File 'lib/runbook/run.rb', line 213

def _step_choices
  [
    {key: "c", name: "Continue to execute this step", value: :continue},
    {key: "s", name: "Skip this step", value: :skip},
    {key: "j", name: "Jump to the specified position", value: :jump},
    {key: "P", name: "Disable paranoid mode", value: :no_paranoid},
    {key: "e", name: "Exit the runbook", value: :exit},
  ]
end

#execute(object, metadata) ⇒ Object



18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/runbook/run.rb', line 18

def execute(object, )
  return if should_skip?()

  method = _method_name(object)
  if respond_to?(method)
    send(method, object, )
  else
    msg = "ERROR! No execution rule for #{object.class} (#{_method_name(object)}) in #{to_s}"
    [:toolbox].error(msg)
    return
  end
end

#past_position?(current_position, position) ⇒ Boolean

Returns:

  • (Boolean)


203
204
205
206
207
# File 'lib/runbook/run.rb', line 203

def past_position?(current_position, position)
  current_pose = Gem::Version.new(current_position)
  pose = Gem::Version.new(position)
  return pose <= current_pose
end

#runbook__entities__book(object, metadata) ⇒ Object



31
32
33
# File 'lib/runbook/run.rb', line 31

def runbook__entities__book(object, )
  [:toolbox].output("Executing #{object.title}...\n\n")
end

#runbook__entities__section(object, metadata) ⇒ Object



35
36
37
# File 'lib/runbook/run.rb', line 35

def runbook__entities__section(object, )
  [:toolbox].output("Section #{[:position]}: #{object.title}\n\n")
end

#runbook__entities__step(object, metadata) ⇒ Object



39
40
41
42
43
44
45
46
47
# File 'lib/runbook/run.rb', line 39

def runbook__entities__step(object, )
  toolbox = [:toolbox]
  title = " #{object.title}".rstrip
  toolbox.output("Step #{[:position]}:#{title}\n\n")
  return if [:auto] || [:noop] ||
    ![:paranoid] || object.title.nil?
  continue_result = toolbox.expand("Continue?", _step_choices)
  _handle_continue_result(continue_result, object, )
end

#runbook__statements__ask(object, metadata) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/runbook/run.rb', line 49

def runbook__statements__ask(object, )
  target = object.parent.dsl
  existing_val = target.instance_variable_get(:"@#{object.into}")
  default = existing_val || object.default

  if [:auto]
    if default
      target.singleton_class.class_eval { attr_accessor object.into }
      target.send("#{object.into}=".to_sym, default)
      return
    end

    error_msg = "ERROR! Can't execute ask statement without default in automatic mode!"
    [:toolbox].error(error_msg)
    raise Runbook::Runner::ExecutionError, error_msg
  end

  if [:noop]
    default_msg = default ? " (default: #{default})" : ""
    [:toolbox].output("[NOOP] Ask: #{object.prompt} (store in: #{object.into})#{default_msg}")
    return
  end

  result = [:toolbox].ask(object.prompt, default: default)

  target = object.parent.dsl
  target.singleton_class.class_eval { attr_accessor object.into }
  target.send("#{object.into}=".to_sym, result)
end

#runbook__statements__confirm(object, metadata) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/runbook/run.rb', line 79

def runbook__statements__confirm(object, )
  if [:auto]
    [:toolbox].output("Skipping confirmation (auto): #{object.prompt}")
  else
    if [:noop]
      [:toolbox].output("[NOOP] Prompt: #{object.prompt}")
      return
    end

    result = [:toolbox].yes?(object.prompt)
    [:toolbox].exit(1) unless result
  end
end

#runbook__statements__description(object, metadata) ⇒ Object



93
94
95
96
# File 'lib/runbook/run.rb', line 93

def runbook__statements__description(object, )
  [:toolbox].output("Description:")
  [:toolbox].output("#{object.msg}\n")
end

#runbook__statements__layout(object, metadata) ⇒ Object



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/runbook/run.rb', line 98

def runbook__statements__layout(object, )
  if [:noop]
    [:toolbox].output(
      "[NOOP] Layout: #{object.structure.inspect}"
    )
    unless ENV["TMUX"]
      msg = "Warning: layout statement called outside a tmux pane."
      [:toolbox].warn(msg)
    end
    return
  end

  unless ENV["TMUX"]
    error_msg = "Error: layout statement called outside a tmux pane. Exiting..."
    [:toolbox].error(error_msg)
    [:toolbox].exit(1)
  end

  structure = object.structure
  title = object.parent.title
  layout_panes = setup_layout(structure, runbook_title: title)
  [:layout_panes].merge!(layout_panes)
end

#runbook__statements__note(object, metadata) ⇒ Object



122
123
124
# File 'lib/runbook/run.rb', line 122

def runbook__statements__note(object, )
  [:toolbox].output("Note: #{object.msg}")
end

#runbook__statements__notice(object, metadata) ⇒ Object



126
127
128
# File 'lib/runbook/run.rb', line 126

def runbook__statements__notice(object, )
  [:toolbox].warn("Notice: #{object.msg}")
end

#runbook__statements__ruby_command(object, metadata) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# File 'lib/runbook/run.rb', line 139

def runbook__statements__ruby_command(object, )
  if [:noop]
    [:toolbox].output("[NOOP] Run the following Ruby block:\n")
    begin
      source = deindent(object.block.source)
      [:toolbox].output("```ruby\n#{source}\n```\n")
    rescue ::MethodSource::SourceNotFoundError => e
      [:toolbox].output("Unable to retrieve source code")
    end
    return
  end

  next_index = [:index] + 1
  parent_items = object.parent.items
  remaining_items = parent_items.slice!(next_index..-1)
  object.parent.dsl.instance_exec(object, , &object.block)
  parent_items[next_index..-1].each { |item| item.dynamic! }
  parent_items.push(*remaining_items)
end

#runbook__statements__tmux_command(object, metadata) ⇒ Object



130
131
132
133
134
135
136
137
# File 'lib/runbook/run.rb', line 130

def runbook__statements__tmux_command(object, )
  if [:noop]
    [:toolbox].output("[NOOP] Run: `#{object.cmd}` in pane #{object.pane}")
    return
  end

  send_keys(object.cmd, [:layout_panes][object.pane])
end

#runbook__statements__wait(object, metadata) ⇒ Object



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/runbook/run.rb', line 159

def runbook__statements__wait(object, )
  if [:noop]
    [:toolbox].output("[NOOP] Sleep #{object.time} seconds")
    return
  end

  time = object.time
  message = "Sleeping #{time} seconds [:bar] :current/:total"
  pastel = Pastel.new
  yellow = pastel.on_yellow(" ")
  green = pastel.on_green(" ")
  progress_bar = TTY::ProgressBar.new(
    message,
    total: time,
    width: 60,
    head: ">",
    incomplete: yellow,
    complete: green,
  )
  progress_bar.start
  time.times do
    sleep(1)
    progress_bar.advance(1)
  end
end

#should_skip?(metadata) ⇒ Boolean

Returns:

  • (Boolean)


185
186
187
188
189
190
191
192
193
194
195
# File 'lib/runbook/run.rb', line 185

def should_skip?()
  if [:reversed] && [:position].empty?
    current_pose = "0"
  else
    current_pose = [:position]
  end
  return false if current_pose.empty?
  position = Gem::Version.new(current_pose)
  start_at = Gem::Version.new([:start_at])
  return position < start_at
end

#start_at_is_substep?(object, metadata) ⇒ Boolean

Returns:

  • (Boolean)


197
198
199
200
201
# File 'lib/runbook/run.rb', line 197

def start_at_is_substep?(object, )
  return false unless object.is_a?(Entity)
  return true if [:position].empty?
  [:start_at].start_with?([:position])
end