Class: Pangea::Magma::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/pangea/magma/runner.rb

Overview

Shared command-line plumbing for every Ruby↔magma invocation. Replaces hand-rolled Open3.capture3 + Tempfile + JSON.parse blocks that were duplicated across Chain#reconcile_all, Migration#apply!, Pangea::Magma.flow,migrate,split,merge.

Three call shapes:

Runner.invoke('capabilities')              # → parsed JSON Hash
Runner.invoke('flow', stdin: nil, json_arg: flow_hash)
  # writes flow_hash to a tempfile, passes its path as argv,
  # cleans up. Returns parsed JSON.
Runner.invoke('split', argv_extras: %w[--from x --from-state y ])
  # passes extras verbatim. Returns parsed JSON.

Errors raised:

Pangea::Magma::Runner::SubprocessError — non-zero exit with
  full stdout/stderr captured for the operator.

Why this exists: each ad-hoc capture3 block forgot one thing —tempfile cleanup, JSON parse on failure, stdout vs stderr — and debugging was harder for it. One typed surface here means downstream wrappers cannot regress those concerns.

Defined Under Namespace

Classes: SubprocessError

Class Method Summary collapse

Class Method Details

.invoke(subcommand, argv_extras: [], json_arg: nil, allow_exit: [], parse: :json) ⇒ Object

Invoke the magma binary with a subcommand + optional extras and/or JSON-file argument. Returns the parsed JSON Hash on stdout (always — ‘magma` subcommands emit JSON on stdout for success, JSON or text on stderr for failure).

Options:

:argv_extras — Array<String> of additional CLI args
:json_arg    — Hash; rendered to a tempfile, path appended
               to argv. The file is unlinked on return.
:allow_exit  — Array<Integer> of acceptable exit codes
               besides 0; output is still parsed. Used by
               `magma fixture verify-dir` which exits 1
               when fixtures fail but still emits JSON.
:parse       — Symbol: :json (default) or :raw (return out).


73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/pangea/magma/runner.rb', line 73

def invoke(subcommand, argv_extras: [], json_arg: nil, allow_exit: [], parse: :json)
  argv = [Pangea::Magma.binary, subcommand, *argv_extras]
  tmp = nil
  if json_arg
    tmp = Tempfile.new(["magma-#{subcommand}", '.json'])
    tmp.write(JSON.pretty_generate(json_arg))
    tmp.close
    argv << tmp.path
  end
  out, err, status = Open3.capture3(*argv)
  allowed = [0, *allow_exit]
  unless allowed.include?(status.exitstatus)
    raise SubprocessError.new(
      command:   argv,
      exit_code: status.exitstatus,
      stdout:    out,
      stderr:    err,
    )
  end
  parse == :raw ? out : JSON.parse(out)
ensure
  tmp&.unlink
end