class TinyCI::Runner

Responsible for managing the running of TinyCI against a single git object.

@attr builder [TinyCI::Executor] Returns the Builder object. Used solely for testing. @attr tester [TinyCI::Executor] Returns the Tester object. Used solely for testing.

Constants

CONFIG_FILENAME

Attributes

builder[RW]
hooker[RW]
tester[RW]

Public Class Methods

new(working_dir: '.', commit:, time: nil, logger: nil, config: nil) click to toggle source

Constructor, allows injection of generic configuration params.

@param working_dir [String] The working directory to execute against. @param commit [String] SHA1 of git object to run against @param logger [Logger] Logger object @param time [Time] Override time of object creation. Used solely for testing. @param config [Hash] Override TinyCI config object, normally loaded from `.tinyci` file. Used solely for testing.

# File lib/tinyci/runner.rb, line 41
def initialize(working_dir: '.', commit:, time: nil, logger: nil, config: nil)
  @working_dir = working_dir
  @config = config
  @commit = commit
  @time = time
  @logger = logger.is_a?(MultiLogger) ? MultiLogger.new(quiet: logger.quiet) : nil
  ensure_path target_path
  setup_log
end

Public Instance Methods

run!() click to toggle source

Runs the TinyCI system against the single git object referenced in `@commit`.

@return [Boolean] `true` if the commit was built and tested successfully, `false` otherwise rubocop:disable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity

# File lib/tinyci/runner.rb, line 55
def run!
  begin
    log_info "Commit: #{@commit}"

    unless config_exists?
      log_error "No config found for #{@commit}"

      return false
    end

    log_info 'Cleaning...'
    clean

    log_info 'Exporting...'
    ensure_path export_path
    export

    begin
      config
    rescue ConfigMissingError => e
      log_error e.message
      log_error 'Removing export...'
      clean

      return false
    end
    @builder ||= instantiate_builder
    @tester  ||= instantiate_tester
    @hooker  ||= instantiate_hooker

    log_info 'Building...'
    run_hook! :before_build
    begin
      @builder.build
    rescue StandardError => e
      run_hook! :after_build_failure

      raise e if ENV['TINYCI_ENV'] == 'test'

      log_error e
      log_debug e.backtrace

      return false
    else
      run_hook! :after_build_success
    ensure
      run_hook! :after_build
    end

    log_info 'Testing...'
    run_hook! :before_test
    begin
      @tester.test
    rescue StandardError => e
      run_hook! :after_test_failure

      raise e if ENV['TINYCI_ENV'] == 'test'

      log_error e
      log_debug e.backtrace

      return false
    else
      run_hook! :after_test_success
    ensure
      run_hook! :after_test
    end

    log_info "Finished #{@commit}"
  rescue StandardError => e
    raise e if ENV['TINYCI_ENV'] == 'test'

    log_error e
    log_debug e.backtrace
    return false
  ensure
    run_hook! :after_all
  end

  true
end

Private Instance Methods

clean() click to toggle source

Delete the export path

# File lib/tinyci/runner.rb, line 206
def clean
  FileUtils.rm_rf export_path
end
config() click to toggle source

The {Config} object from the `.tinyci.yml` file in the exported directory

# File lib/tinyci/runner.rb, line 201
def config
  @config ||= Config.new(config_path)
end
config_exists?() click to toggle source
# File lib/tinyci/runner.rb, line 196
def config_exists?
  file_exists_in_git? CONFIG_FILENAME
end
config_path() click to toggle source
# File lib/tinyci/runner.rb, line 192
def config_path
  File.expand_path(CONFIG_FILENAME, export_path)
end
export() click to toggle source

Export a clean copy of the repo at the given commit, without a .git directory etc. This implementation is slightly hacky but its the cleanest way to do it in the absence of a `git export` subcommand. see stackoverflow.com/a/163769

# File lib/tinyci/runner.rb, line 214
def export
  execute_pipe git_cmd('archive', '--format=tar',
                       @commit), ['tar', '-C', export_path, '-xf', '-']
end
instantiate_builder() click to toggle source

Instantiate the Builder object according to the class named in the config

# File lib/tinyci/runner.rb, line 155
def instantiate_builder
  klass = TinyCI::Builders.const_get(@config[:builder][:class])
  konfig = @config[:builder][:config].merge(
    target: target_path,
    export: export_path,
    commit: @commit,
    logger: @logger
  )
  klass.new(konfig)
end
instantiate_hooker() click to toggle source

Instantiate the Hooker object according to the class named in the config

# File lib/tinyci/runner.rb, line 179
def instantiate_hooker
  return nil unless @config[:hooker].is_a? Hash

  klass = TinyCI::Hookers.const_get(@config[:hooker][:class])
  konfig = @config[:hooker][:config].merge(
    target: target_path,
    export: export_path,
    commit: @commit,
    logger: @logger
  )
  klass.new(konfig)
end
instantiate_tester() click to toggle source

Instantiate the Tester object according to the class named in the config

# File lib/tinyci/runner.rb, line 167
def instantiate_tester
  klass = TinyCI::Testers.const_get(@config[:tester][:class])
  konfig = @config[:tester][:config].merge(
    target: target_path,
    export: export_path,
    commit: @commit,
    logger: @logger
  )
  klass.new(konfig)
end
run_hook!(name) click to toggle source

rubocop:enable Metrics/AbcSize, Metrics/PerceivedComplexity, Metrics/MethodLength, Metrics/CyclomaticComplexity

# File lib/tinyci/runner.rb, line 140
def run_hook!(name)
  return unless @hooker

  @hooker.send("#{name}!")
end
setup_log() click to toggle source

Creates log file if it doesnt exist

# File lib/tinyci/runner.rb, line 147
def setup_log
  return unless @logger.is_a? MultiLogger

  @logger.add_output_path logfile_path
  @logger.add_output_path repo_logfile_path
end