lib/flo/runner.rb
# Copyright © 2019, Salesforce.com, Inc.
# All Rights Reserved.
# Licensed under the BSD 3-Clause license.
# For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause
require 'flo/command'
require 'flo/command_collection'
require 'flo/state'
require 'flo/config'
require 'flo/task'
require 'cleanroom'
module Flo
# This is the main class for instantiating and performing Flo commands. If
# you are wanting to interact with Flo via a ruby script, this is the class
# you want. Utilizing Flo through the command line interface will invoke this
# class after all of the argument parsing is complete.
#
# @example
# runner = Runner.new
# runner.load_config_file('path/to/config/file')
# runner.execute([:issue, :submit], id: '1234', submitter: 'John Doe')
#
# @attr_reader commands [CommandCollection] List of commands currently defined
#
class Runner
include Cleanroom
attr_reader :commands
# Creates a new runner. This object is generally useless until you load
# some configuration into it, typically using {#load_config_file}
#
def initialize(opts={})
@config = opts[:config] || Flo::Config.new
@command_class = opts[:command_class] || Flo::Command
@commands = opts[:command_collection] || Flo::CommandCollection.new
end
# Open and parse a file containing flo configuration. This file is
# evaluated within a cleanroom. See the {https://github.com/sethvargo/cleanroom cleanroom gem}
# for more information.
# @param config_file [String] path to the flo configuration file
#
def load_config_file(config_file)
evaluate_file(config_file)
end
# Open and parse any available config files, in the following order:
# * ENV['FLO_CONFIG_FILE'] # Allows the addition of custom files
# * ./.flo
# * ~/.flo
# See {#load_config_file}
#
def load_default_config_files
[ENV['FLO_CONFIG_FILE'], File.join(Dir.pwd, '.flo'), File.join(Dir.home, '.flo')].compact.each do |file|
if File.exist?(file)
self.load_config_file(file)
end
end
end
# Executes the command specified, with the arguments specified
# @param command_namespace [Array<Symbol>] An array containing the name of
# the command as a symbol, including the namespace. For example, the
# command "issue submit" would become [:issue, :submit]
# @param args=[] [Array] Options that will get passed to the command
#
def execute(command_namespace, args=[])
commands[command_namespace][:command].call(args)
end
# @api dsl
# DSL method: Returns the instance of {Config} associated with this runner. Exposes the
# {Config} instance if a block is used
#
# @yield [Config]
#
# @return [Config]
#
def config
yield(@config) if block_given?
@config
end
expose :config
# @api dsl
# DSL method: Creates and defines a {Command}, adding it to the command collection.
# Definition for the command should happen inside of the required block.
# See {Command} for methods available within the block.
# @param command_namespace [String] name of the command
# @option opts [String] :summary Summary of the command
# @option opts [String] :description Detailed description of the command
# @yield [args*] The block containing the definition for the command.
# Arguments passed into {#execute} are available within the block
#
def register_command(command_namespace, opts={}, &blk)
opts[:command] = command_class.new(providers: config.providers, &blk)
commands[command_namespace] = opts
end
expose :register_command
private
attr_reader :command_class
end
end