Skip to content
This repository has been archived by the owner on Nov 19, 2018. It is now read-only.

Commit

Permalink
Merge pull request #8 from KrauseFx/feature/configuration-2.0
Browse files Browse the repository at this point in the history
[WIP] Brand new configuration for everything
  • Loading branch information
KrauseFx committed Mar 6, 2015
2 parents 7f6e13e + f660373 commit fec5497
Show file tree
Hide file tree
Showing 8 changed files with 320 additions and 4 deletions.
4 changes: 2 additions & 2 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
fastlane_core (0.2.1)
fastlane_core (0.3.0)
babosa
capybara (~> 2.4.3)
colored
Expand Down Expand Up @@ -84,7 +84,7 @@ GEM
webmock (1.19.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
websocket-driver (0.5.2)
websocket-driver (0.5.3)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)
xpath (2.0.0)
Expand Down
2 changes: 1 addition & 1 deletion fastlane_core.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
spec.email = ["fastlanecore@krausefx.com"]
spec.summary = %q{Contains all shared code/dependencies of the fastlane.tools}
spec.description = %q{Contains all shared code/dependencies of the fastlane.tools}
spec.homepage = "http://fastlane.tools"
spec.homepage = "https://fastlane.tools"
spec.license = "MIT"

spec.required_ruby_version = '>= 2.0.0'
Expand Down
1 change: 1 addition & 0 deletions lib/fastlane_core.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require 'json'
require 'fastlane_core/version'
require 'fastlane_core/helper'
require 'fastlane_core/configuration'
require 'fastlane_core/update_checker'
require 'fastlane_core/languages'
require 'fastlane_core/itunes_search_api'
Expand Down
108 changes: 108 additions & 0 deletions lib/fastlane_core/configuration.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
require 'fastlane_core/configuration/config_item'
require 'fastlane_core/configuration/commander_generator'

module FastlaneCore
class Configuration
def self.create(available_options, values)
Configuration.new(available_options, values)
end

# Setting up

def initialize(available_options, values)
@available_options = available_options
@values = values

verify_input_types
verify_value_exists
verify_no_duplicates
end

def verify_input_types
raise "available_options parameter must be an array of ConfigItems".red unless @available_options.kind_of?Array
@available_options.each do |item|
raise "available_options parameter must be an array of ConfigItems".red unless item.kind_of?ConfigItem
end
raise "values parameter must be a hash".red unless @values.kind_of?Hash
end

def verify_value_exists
# Make sure the given value keys exist
@values.each do |key, value|
option = option_for_key(key)
if option
option.verify!(value) # Call the verify block for it too
else
raise "Could not find available option '#{key}' in the list of available options #{@available_options.collect { |a| a.key }}".red
end
end
end

def verify_no_duplicates
# Make sure a key was not used multiple times
@available_options.each do |current|
count = @available_options.select { |option| option.key == current.key }.count
raise "Multiple entries for configuration key '#{current.key}' found!".red if count > 1

unless current.short_option.to_s.empty?
count = @available_options.select { |option| option.short_option == current.short_option }.count
raise "Multiple entries for short_option '#{current.short_option}' found!".red if count > 1
end
end
end

# Using the class

# Returns the value for a certain key. fastlane_core tries to fetch the value from different sources
def fetch(key)
raise "Key '#{key}' must be a symbol. Example :app_id.".red unless key.kind_of?Symbol

option = option_for_key(key)
raise "Could not find option for key :#{key}. Available keys: #{@available_options.collect { |a| a.key }}".red unless option

# `if value == nil` instead of ||= because false is also a valid value

value ||= @values[key]
# TODO: configuration files
value = ENV[key.to_s] if value == nil
value = option.default_value if value == nil
value = false if (value == nil and not option.is_string) # by default boolean flags are false

while value == nil and !option.optional
value = ask("#{option.description}: ")
# Also store this value to use it from now on
begin
set(key, value)
rescue Exception => ex
puts ex
value = nil
end
end

value
end

# Overwrites or sets a new value for a given key
def set(key, value)
raise "Key '#{key}' must be a symbol. Example :app_id.".red unless key.kind_of?Symbol
option = option_for_key(key)

unless option
raise "Could not find available option '#{key}' in the list of !available options #{@available_options.collect { |a| a.key }}".red
end

option.verify!(value)

@values[key] = value
true
end

# Returns the config_item object for a given key
def option_for_key(key)
@available_options.find { |o| o.key == key }
end

# Aliases `[key]` to `fetch(key)` because Ruby can do it.
alias_method :[], :fetch
end
end
16 changes: 16 additions & 0 deletions lib/fastlane_core/configuration/commander_generator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
require 'commander'

module FastlaneCore
class CommanderGenerator
include Commander::Methods

def generate(options)
options.each do |option|
appendix = (option.is_string ? "STRING" : "")
type = (option.is_string ? String : nil)
short_option = option.short_option || "-#{option.key.to_s[0]}"
global_option short_option, "--#{option.key} #{appendix}", type, (option.description + " (#{option.env_name})")
end
end
end
end
69 changes: 69 additions & 0 deletions lib/fastlane_core/configuration/config_item.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
module FastlaneCore
class ConfigItem
attr_accessor :key, :env_name, :description, :short_option, :default_value, :verify_block, :is_string, :optional

# Creates a new option
# @param key (Symbol) the key which is used as command paramters or key in the fastlane tools
# @param env_name (String) the name of the environment variable, which is only used if no other values were found
# @param description (String) A description shown to the user
# @param short_option (String) A string of length 1 which is used for the command parameters (e.g. -f)
# @param default_value the value which is used if there was no given values and no environment values
# @param verify_block an optional block which is called when a new value is set.
# Check value is valid. This could be type checks or if a folder/file exists
# You have to raise a specific exception if something goes wrong. Append .red after the string
# @param is_string (String) is that parameter a string?
# @param optional (Boolean) is false by default. If set to true, also string values will not be asked to the user
def initialize(key: nil, env_name: nil, description: nil, short_option: nil, default_value: nil, verify_block: nil, is_string: true, optional: false)
raise "key must be a symbol" unless key.kind_of?Symbol
raise "env_name must be a String" unless env_name.kind_of?String
if short_option
raise "short_option must be a String of length 1" unless (short_option.kind_of?String and short_option.gsub('-', '').length == 1)
end
if description
raise "Do not let descriptions end with a '.', since it's used for user inputs as well".red if (description[-1] == '.')
end

@key = key
@env_name = env_name
@description = description
@short_option = short_option
@default_value = default_value
@verify_block = verify_block
@is_string = is_string
@optional = optional
end


# This will raise an exception if the value is not valid
def verify!(value)
raise "Invalid value '#{value}' for option '#{self}'".red unless is_valid?value
true
end

# Make sure, the value is valid (based on the verify block)
# Returns false if that's not the case
def is_valid?(value)
# we also allow nil values, which do not have to be verified.
if value
if @is_string
raise "Please pass a path as String".red unless value.kind_of?String
end

if @verify_block
begin
@verify_block.call(value)
rescue Exception => ex
Helper.log.fatal "Error setting value '#{value}' for option '#{@key}'".red
raise ex
end
end
end

true
end

def to_s
[@key, @description].join(": ")
end
end
end
2 changes: 1 addition & 1 deletion lib/fastlane_core/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module FastlaneCore
VERSION = "0.2.1"
VERSION = "0.3.0"
end
122 changes: 122 additions & 0 deletions spec/configuration_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
describe FastlaneCore do
describe FastlaneCore::Configuration do
describe "Create a new Configuration Manager" do

it "raises an error if no hash is given" do
expect {
FastlaneCore::Configuration.create([], "string")
}.to raise_error "values parameter must be a hash".red
end

it "raises an error if no array is given" do
expect {
FastlaneCore::Configuration.create("string", {})
}.to raise_error "available_options parameter must be an array of ConfigItems".red
end

it "raises an error if array contains invalid elements" do
expect {
FastlaneCore::Configuration.create(["string"], {})
}.to raise_error "available_options parameter must be an array of ConfigItems".red
end


it "raises an error if the option of a given value is not available" do
expect {
FastlaneCore::Configuration.create([], {cert_name: "value"})
}.to raise_error "Could not find available option 'cert_name' in the list of available options []".red
end

it "raises an error if a description ends with a ." do
expect {
FastlaneCore::Configuration.create([FastlaneCore::ConfigItem.new(
key: :cert_name,
env_name: "asdf",
description: "Set the profile name.")], {})
}.to raise_error "Do not let descriptions end with a '.', since it's used for user inputs as well".red
end

it "raises an error if a a key was used twice" do
expect {
FastlaneCore::Configuration.create([FastlaneCore::ConfigItem.new(
key: :cert_name,
env_name: "asdf"),
FastlaneCore::ConfigItem.new(
key: :cert_name,
env_name: "asdf")], {})
}.to raise_error "Multiple entries for configuration key 'cert_name' found!".red
end

describe "Use a valid Configuration Manager" do
before do
@options = [
FastlaneCore::ConfigItem.new(key: :cert_name,
env_name: "SIGH_PROVISIONING_PROFILE_NAME",
description: "Set the profile name",
default_value: "production_default",
verify_block: nil),
FastlaneCore::ConfigItem.new(key: :output,
env_name: "SIGH_OUTPUT_PATH",
description: "Directory in which the profile should be stored",
default_value: ".",
verify_block: Proc.new do |value|
raise "Could not find output directory '#{value}'".red unless File.exists?(value)
end)
]
@values = {
cert_name: "asdf",
output: ".."
}
@config = FastlaneCore::Configuration.create(@options, @values)
end

describe "fetch" do
it "raises an error if a non symbol was given" do
expect {
@config.fetch(123)
}.to raise_error "Key '123' must be a symbol. Example :app_id.".red
end

it "raises an error if this option does not exist" do
expect {
@config[:asdfasdf]
}.to raise_error "Could not find option for key :asdfasdf. Available keys: [:cert_name, :output]".red
end

it "returns the value for the given key if given" do
expect(@config.fetch(:cert_name)).to eq(@values[:cert_name])
end

it "returns the value for the given key if given using []" do
expect(@config[:cert_name]).to eq(@values[:cert_name])
end

it "returns the default value if nothing else was given" do
@config.set(:cert_name, nil)
expect(@config[:cert_name]).to eq("production_default")
end
end

describe "verify_block" do
it "throws an error if the key doesn't exist" do
expect {
@config.set(:non_existing, "value")
}.to raise_error("Could not find available option 'non_existing' in the list of !available options [:cert_name, :output]".red)
end

it "throws an error if it's invalid" do
expect {
@config.set(:output, 132)
}.to raise_error("Please pass a path as String".red)
end

it "allows valid updates" do
new_val = "../../"
expect(@config.set(:output, new_val)).to eq(true)
expect(@config[:output]).to eq(new_val)
end
end
end
end
end
end

0 comments on commit fec5497

Please sign in to comment.