Class: Gemchain::Executor

Inherits:
Object
  • Object
show all
Defined in:
lib/gemchain/executor.rb

Overview

Executes a cascade plan: bumps versions, rewrites gemspec constraints, runs test suites, and releases gems to RubyGems — stopping at the first failure. All shell interaction goes through the runner so the whole pipeline is testable without touching bundler, git, or RubyGems.

Defined Under Namespace

Classes: Result, Runner

Constant Summary collapse

BUMP_LEVELS =
%i[patch minor major].freeze

Instance Method Summary collapse

Constructor Details

#initialize(workspace:, steps:, runner: nil, confirm: nil, yes: false, bump: :patch, output: $stdout) ⇒ Executor

Returns a new instance of Executor.

Parameters:

  • workspace (Workspace)

    the gem ecosystem

  • steps (Array<Hash>)

    the plan from Cascade#update

  • runner (#run) (defaults to: nil)

    command runner (defaults to the real one)

  • confirm (Proc) (defaults to: nil)

    per-release confirmation, called with a message; defaults to a [y/N] prompt on stdin

  • yes (Boolean) (defaults to: false)

    skip confirmations entirely

  • bump (Symbol) (defaults to: :patch)

    dependent version bump level (:patch, :minor, :major)

  • output (#puts) (defaults to: $stdout)

    progress output stream

Raises:

  • (ArgumentError)


38
39
40
41
42
43
44
45
46
47
48
# File 'lib/gemchain/executor.rb', line 38

def initialize(workspace:, steps:, runner: nil, confirm: nil, yes: false,
               bump: :patch, output: $stdout)
  @workspace = workspace
  @steps = steps
  @runner = runner || Runner.new
  @confirm = confirm
  @yes = yes
  @bump = bump.to_sym
  @output = output
  raise ArgumentError, "bump must be one of #{BUMP_LEVELS.inspect}" unless BUMP_LEVELS.include?(@bump)
end

Instance Method Details

#runObject



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
78
79
# File 'lib/gemchain/executor.rb', line 50

def run
  released = []
  skipped = []

  @steps.each do |step|
    begin
      case step[:action]
      when :bump
        progress(step) { bump_version(gem_dir(step[:gem]), step[:version]) }
      when :update_dependency
        progress(step) { update_dependency(gem_dir(step[:gem]), step[:dependency], step[:constraint]) }
      when :test
        progress(step) { run_tests(gem_dir(step[:gem]), step[:dependency]) }
      when :release
        if release_confirmed?(step)
          progress(step) { release(step) }
          released << step[:gem]
        else
          @output.puts "  ⏭ Skipped release of #{step[:gem]} (declined)"
          skipped << step[:gem]
        end
      end
    rescue ExecutionError => e
      return Result.new(success: false, released: released, skipped: skipped,
                        failed: {step[:gem] => e.message})
    end
  end

  Result.new(success: true, released: released, skipped: skipped, failed: nil)
end