Module: Browserctl::Workflow::Promoter

Defined in:
lib/browserctl/workflow/promoter.rb

Overview

Promotes a workflow file from the project-local ‘.browserctl/workflows/` directory to the user-global `~/.browserctl/workflows/` directory, where it is invocable from any project.

Promotion is gated by ‘PromotionLedger.clean_streak`: a workflow must have at least `threshold` consecutive clean `–check` runs before it can be promoted. `–force` overrides the gate.

Defined Under Namespace

Classes: IneligibleError, NotFoundError

Constant Summary collapse

DEFAULT_SOURCE_DIR =
".browserctl/workflows"

Class Method Summary collapse

Class Method Details

.promote(workflow:, force: false, threshold: PromotionLedger::DEFAULT_THRESHOLD, as_flow: false, source_dir: DEFAULT_SOURCE_DIR, ledger_path: PromotionLedger.ledger_path, flow_dir: nil) ⇒ Hash

Returns ‘{ workflow:, source:, target:, streak:, threshold:, forced: }`.

Parameters:

  • workflow (String)
  • force (Boolean) (defaults to: false)
  • threshold (Integer) (defaults to: PromotionLedger::DEFAULT_THRESHOLD)
  • source_dir (String) (defaults to: DEFAULT_SOURCE_DIR)

    override the source directory (testing)

  • ledger_path (String) (defaults to: PromotionLedger.ledger_path)

    override the ledger path (testing)

Returns:

  • (Hash)

    ‘{ workflow:, source:, target:, streak:, threshold:, forced: }`

Raises:



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/browserctl/workflow/promoter.rb', line 56

def promote(workflow:, force: false, threshold: PromotionLedger::DEFAULT_THRESHOLD, # rubocop:disable Metrics/ParameterLists
            as_flow: false, source_dir: DEFAULT_SOURCE_DIR,
            ledger_path: PromotionLedger.ledger_path, flow_dir: nil)
  src = source_path(workflow, source_dir: source_dir)
  raise NotFoundError, "workflow file not found: #{src}" unless File.exist?(src)

  streak = PromotionLedger.clean_streak(workflow: workflow, path: ledger_path)
  unless force || streak >= threshold
    raise IneligibleError.new(workflow: workflow, streak: streak, threshold: threshold)
  end

  dst = target_path(workflow)
  FileUtils.mkdir_p(File.dirname(dst))
  FileUtils.cp(src, dst)

  result = {
    workflow: workflow,
    source: src,
    target: dst,
    streak: streak,
    threshold: threshold,
    forced: force && streak < threshold
  }

  result[:flow] = wrap_as_flow(workflow, dst, flow_dir) if as_flow
  result
end

.source_path(workflow, source_dir: DEFAULT_SOURCE_DIR) ⇒ Object



42
43
44
# File 'lib/browserctl/workflow/promoter.rb', line 42

def source_path(workflow, source_dir: DEFAULT_SOURCE_DIR)
  File.join(source_dir, "#{workflow}.rb")
end

.target_dirObject



38
39
40
# File 'lib/browserctl/workflow/promoter.rb', line 38

def target_dir
  File.join(Browserctl::BROWSERCTL_DIR, "workflows")
end

.target_path(workflow) ⇒ Object



46
47
48
# File 'lib/browserctl/workflow/promoter.rb', line 46

def target_path(workflow)
  File.join(target_dir, "#{workflow}.rb")
end

.wrap_as_flow(workflow, workflow_path, flow_dir) ⇒ Object

Loads the just-promoted workflow file, infers params from its WorkflowDefinition, and writes a flow wrapper at ‘flow_dir` (defaults to `~/.browserctl/flows/<name>.rb`).



87
88
89
90
91
92
93
# File 'lib/browserctl/workflow/promoter.rb', line 87

def wrap_as_flow(workflow, workflow_path, flow_dir)
  load workflow_path
  defn = Browserctl.lookup_workflow(workflow.to_s) or
    raise NotFoundError, "workflow '#{workflow}' did not register after load"

  FlowWrapper.write(defn, overwrite: true, dir: flow_dir)
end