class Cutlass::App

Top level class for interacting with a “pack” app

Cutlass::App.new(
  path_to_rails_app,
  buildpacks: "heroku/ruby",
  builder: "heroku/buildpacks:18"
).transaction do |app|
  app.pack_build

  expect(result.stdout).to include("Successfully built image")
end

Attributes

builder[R]
buildpacks[R]
builds[R]
config[R]
exception_on_failure[R]
image_name[R]
tmpdir[R]

Public Class Methods

new( source_path_name, config: {}, warn_io: $stderr, builder: Cutlass.default_builder, image_name: Cutlass.default_image_name, buildpacks: Cutlass.default_buildpack_paths, exception_on_failure: true ) click to toggle source
# File lib/cutlass/app.rb, line 18
def initialize(
  source_path_name,
  config: {},
  warn_io: $stderr,
  builder: Cutlass.default_builder,
  image_name: Cutlass.default_image_name,
  buildpacks: Cutlass.default_buildpack_paths,
  exception_on_failure: true
)
  @tmpdir = nil
  @source_path = nil

  @builds = []
  @on_teardown = []

  @config = config
  @warn_io = warn_io
  @builder = builder
  @image_name = image_name
  @buildpacks = Array(buildpacks).map { |buildpack| buildpack == :default ? Cutlass.default_buildpack_paths : buildpack }.flatten
  @source_path_name = source_path_name
  @exception_on_failure = exception_on_failure
end

Public Instance Methods

fail?() click to toggle source
# File lib/cutlass/app.rb, line 54
def fail?
  last_build.fail?
end
in_dir() { |tmpdir| ... } click to toggle source
# File lib/cutlass/app.rb, line 128
def in_dir
  Dir.mktmpdir do |dir|
    @tmpdir = Pathname(dir)

    FileUtils.copy_entry(source_path, @tmpdir)

    Dir.chdir(@tmpdir) do
      yield @tmpdir
    end
  end
end
last_build() click to toggle source
# File lib/cutlass/app.rb, line 58
def last_build
  raise "You must `pack_build` first" if builds.empty?

  builds.last
end
on_teardown(&block) click to toggle source
# File lib/cutlass/app.rb, line 166
def on_teardown(&block)
  @on_teardown << block
end
pack_build() { |build| ... } click to toggle source
# File lib/cutlass/app.rb, line 101
def pack_build
  build = PackBuild.new(
    config: config,
    app_dir: @tmpdir,
    builder: builder,
    buildpacks: buildpacks,
    image_name: image_name,
    exception_on_failure: exception_on_failure
  )
  on_teardown { build.teardown }

  @builds << build
  build.call

  yield build if block_given?
end
run(command, exception_on_failure: true) click to toggle source
# File lib/cutlass/app.rb, line 64
    def run(command, exception_on_failure: true)
      command = docker_command(command)
      result = BashResult.run(command)

      raise(<<~EOM) if result.failed? && exception_on_failure
        Command "#{command}" failed

        stdout: #{result.stdout}
        stderr: #{result.stderr}
        status: #{result.status}
      EOM

      result
    end
run_multi(command, exception_on_failure: true) { |run(command, exception_on_failure: exception_on_failure)| ... } click to toggle source
# File lib/cutlass/app.rb, line 83
def run_multi(command, exception_on_failure: true)
  raise "No block given" unless block_given?

  thread = Thread.new do
    yield run(command, exception_on_failure: exception_on_failure)
  end

  on_teardown { thread.join }
end
start_container(expose_ports: []) { |container| ... } click to toggle source
# File lib/cutlass/app.rb, line 93
def start_container(expose_ports: [])
  raise "No block given" unless block_given?

  ContainerBoot.new(image_id: last_build.image_id, expose_ports: expose_ports).call do |container|
    yield container
  end
end
stderr() click to toggle source
# File lib/cutlass/app.rb, line 46
def stderr
  last_build.stderr
end
stdout() click to toggle source
# File lib/cutlass/app.rb, line 42
def stdout
  last_build.stdout
end
success?() click to toggle source
# File lib/cutlass/app.rb, line 50
def success?
  last_build.success?
end
teardown() click to toggle source
# File lib/cutlass/app.rb, line 140
    def teardown
      errors = []
      @on_teardown.reverse_each do |callback|
        # Attempt to run all teardown callbacks

        callback.call
      rescue => e
        errors << e

        @warn_io.puts <<~EOM

          Error in teardown #{callback.inspect}

          It will be raised after all teardown blocks have completed

          #{e.message}

          #{e.backtrace.join($/)}
        EOM
      end
    ensure
      errors.each do |e|
        raise e
      end
    end
transaction() { |self| ... } click to toggle source
# File lib/cutlass/app.rb, line 118
def transaction
  raise "No block given" unless block_given?

  in_dir do
    yield self
  ensure
    teardown
  end
end

Private Instance Methods

docker_command(command) click to toggle source
# File lib/cutlass/app.rb, line 79
        def docker_command(command)
  "docker run --entrypoint='/cnb/lifecycle/launcher' #{image_name} #{command.to_s.shellescape}"
end
source_path() click to toggle source
# File lib/cutlass/app.rb, line 170
        def source_path
  @source_path ||= Cutlass.resolve_path(@source_path_name)
end