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, released_check: nil) ⇒ Executor

Returns a new instance of Executor.

Parameters:

  • workspace (Workspace)

    the gem ecosystem

  • steps (Array<Hash>)

    the plan from Cascade#update

  • runner (#run, #success?) (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

  • released_check (Proc) (defaults to: nil)

    (name, version) → published on RubyGems? Used to skip releases whose version is already published; defaults to a RubyGems API lookup with a short timeout.

Raises:

  • (ArgumentError)


49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/gemchain/executor.rb', line 49

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

Instance Method Details

#runObject



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/gemchain/executor.rb', line 62

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