Class: Browserctl::Runner

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

Constant Summary collapse

SEARCH_PATHS =
[
  "./.browserctl/workflows",
  File.expand_path("~/.browserctl/workflows")
].freeze
SAFE_WORKFLOW_NAME =
/\A[a-zA-Z0-9_-]+\z/

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.load_params_file(path) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/browserctl/runner.rb', line 59

def self.load_params_file(path)
  raise "params file not found: #{path}" unless File.exist?(path)

  case File.extname(path).downcase
  when ".yml", ".yaml"
    require "yaml"
    YAML.safe_load_file(path, symbolize_names: true)
  when ".json"
    JSON.parse(File.read(path), symbolize_names: true)
  else
    raise "unsupported params file format: #{path} (use .yml, .yaml, or .json)"
  end
rescue Psych::SyntaxError => e
  raise "invalid YAML in #{path}: #{e.message}"
rescue JSON::ParserError => e
  raise "invalid JSON in #{path}: #{e.message}"
end

Instance Method Details

#describe_workflow(name) ⇒ Hash

Returns detailed information about a workflow.

Parameters:

  • name (String)

    workflow name

Returns:

  • (Hash)

    ‘{ name:, desc:, params:, steps: }`



52
53
54
55
# File 'lib/browserctl/runner.rb', line 52

def describe_workflow(name)
  defn = fetch_workflow(name)
  { name: defn.name, desc: defn.description, params: format_params(defn), steps: defn.steps.map(&:label) }
end

#list_workflowsArray<Hash>

Lists all registered workflows from the standard search paths.

Returns:

  • (Array<Hash>)

    array of ‘{ name:, desc: }` hashes



44
45
46
47
# File 'lib/browserctl/runner.rb', line 44

def list_workflows
  load_all_workflows
  Browserctl.registry_snapshot.map { |name, defn| { name: name, desc: defn.description } }
end

#run_workflow(name, check: false, **params) ⇒ Symbol

Runs a named workflow with the given parameters.

Parameters:

  • name (String)

    workflow name (must match /A+z/)

  • params (Hash)

    keyword arguments passed to the workflow

  • check (Boolean) (defaults to: false)

    when true, attaches a Replay::Context, renders a drift report after the run, and signals drift via exit code 2.

Returns:

  • (Symbol)

    :clean (all ok, no drift), :drift (all ok, drift seen), :fail (any step failed)

Raises:



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/browserctl/runner.rb', line 23

def run_workflow(name, check: false, **params)
  defn    = fetch_workflow(name)
  ctx     = check ? Browserctl::Replay::Context.new : nil
  begin
    results = defn.call(params, Client.new, replay_context: ctx)
  rescue StandardError
    Browserctl::Workflow::PromotionLedger.record(workflow: name.to_s, verdict: :fail) if check
    raise
  end
  print_results(results)
  v = verdict(results, ctx)
  if check
    print_drift_report(ctx)
    Browserctl::Replay::Telemetry.emit(ctx, workflow: name.to_s)
    Browserctl::Workflow::PromotionLedger.record(workflow: name.to_s, verdict: v)
  end
  v
end