Expanding trivial build matrices
This commit is contained in:
parent
1416da2c99
commit
47c3454848
@ -1,5 +1,6 @@
|
|||||||
source 'https://rubygems.org'
|
source 'https://rubygems.org'
|
||||||
|
|
||||||
|
gem 'activesupport'
|
||||||
gem 'puma'
|
gem 'puma'
|
||||||
gem 'sinatra'
|
gem 'sinatra'
|
||||||
gem 'sinatra-contrib', require: 'sinatra/contrib'
|
gem 'sinatra-contrib', require: 'sinatra/contrib'
|
5
matriarch/config.ru
Normal file
5
matriarch/config.ru
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
lib = File.expand_path('../lib', __FILE__)
|
||||||
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
||||||
|
|
||||||
|
require 'matriarch'
|
||||||
|
run Matriarch::App
|
4
matriarch/lib/matriarch.rb
Normal file
4
matriarch/lib/matriarch.rb
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
module Matriarch
|
||||||
|
autoload :App, 'matriarch/app'
|
||||||
|
autoload :Config, 'matriarch/config'
|
||||||
|
end
|
19
matriarch/lib/matriarch/app.rb
Normal file
19
matriarch/lib/matriarch/app.rb
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
require 'matriarch'
|
||||||
|
require 'json'
|
||||||
|
require 'sinatra/base'
|
||||||
|
require 'sinatra/json'
|
||||||
|
|
||||||
|
module Matriarch
|
||||||
|
class App < Sinatra::Base
|
||||||
|
get '/' do
|
||||||
|
"oh hai\n"
|
||||||
|
end
|
||||||
|
|
||||||
|
post '/matrix' do
|
||||||
|
config = ::Matriarch::Config.new(JSON.parse(request.body.read))
|
||||||
|
json data: config.expand
|
||||||
|
end
|
||||||
|
|
||||||
|
run! if app_file == $PROGRAM_NAME
|
||||||
|
end
|
||||||
|
end
|
189
matriarch/lib/matriarch/config.rb
Normal file
189
matriarch/lib/matriarch/config.rb
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
require 'active_support/core_ext/array/wrap'
|
||||||
|
require 'active_support/core_ext/hash/keys'
|
||||||
|
require 'active_support/core_ext/hash/slice'
|
||||||
|
require 'active_support/core_ext/object/try'
|
||||||
|
|
||||||
|
module Matriarch
|
||||||
|
class Config
|
||||||
|
DEFAULT_LANG = 'ruby'.freeze
|
||||||
|
|
||||||
|
ENV_KEYS = [
|
||||||
|
:compiler,
|
||||||
|
:csharp,
|
||||||
|
:d,
|
||||||
|
:dart,
|
||||||
|
:elixir,
|
||||||
|
:env,
|
||||||
|
:fsharp,
|
||||||
|
:gemfile,
|
||||||
|
:ghc,
|
||||||
|
:go,
|
||||||
|
:haxe,
|
||||||
|
:jdk,
|
||||||
|
:julia,
|
||||||
|
:mono,
|
||||||
|
:node_js,
|
||||||
|
:otp_release,
|
||||||
|
:perl,
|
||||||
|
:perl6,
|
||||||
|
:php,
|
||||||
|
:python,
|
||||||
|
:ruby,
|
||||||
|
:rust,
|
||||||
|
:rvm,
|
||||||
|
:scala,
|
||||||
|
:visualbasic,
|
||||||
|
:xcode_scheme,
|
||||||
|
:xcode_sdk
|
||||||
|
].freeze
|
||||||
|
|
||||||
|
EXPANSION_KEYS_FEATURE = [:os].freeze
|
||||||
|
|
||||||
|
EXPANSION_KEYS_LANGUAGE = {
|
||||||
|
'c' => [:compiler],
|
||||||
|
'c++' => [:compiler],
|
||||||
|
'clojure' => [:lein, :jdk],
|
||||||
|
'cpp' => [:compiler],
|
||||||
|
'csharp' => [:csharp, :mono],
|
||||||
|
'd' => [:d],
|
||||||
|
'dart' => [:dart],
|
||||||
|
'elixir' => [:elixir, :otp_release],
|
||||||
|
'erlang' => [:otp_release],
|
||||||
|
'fsharp' => [:fsharp, :mono],
|
||||||
|
'go' => [:go],
|
||||||
|
'groovy' => [:jdk],
|
||||||
|
'haskell' => [:ghc],
|
||||||
|
'haxe' => [:haxe],
|
||||||
|
'java' => [:jdk],
|
||||||
|
'julia' => [:julia],
|
||||||
|
'node_js' => [:node_js],
|
||||||
|
'objective-c' => [:rvm, :gemfile, :xcode_sdk, :xcode_scheme],
|
||||||
|
'perl' => [:perl],
|
||||||
|
'perl6' => [:perl6],
|
||||||
|
'php' => [:php],
|
||||||
|
'python' => [:python],
|
||||||
|
'ruby' => [:rvm, :gemfile, :jdk, :ruby],
|
||||||
|
'rust' => [:rust],
|
||||||
|
'scala' => [:scala, :jdk],
|
||||||
|
'visualbasic' => [:visualbasic, :mono]
|
||||||
|
}.freeze
|
||||||
|
|
||||||
|
EXPANSION_KEYS_UNIVERSAL = [:env, :branch].freeze
|
||||||
|
|
||||||
|
def self.matrix_keys_for(config, options = {})
|
||||||
|
keys = matrix_keys(config, options)
|
||||||
|
keys & config.keys.map(&:to_sym)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.matrix_keys(config, options = {})
|
||||||
|
lang = Array(config.symbolize_keys[:language]).first
|
||||||
|
keys = ENV_KEYS
|
||||||
|
keys &= EXPANSION_KEYS_LANGUAGE.fetch(lang, EXPANSION_KEYS_LANGUAGE[DEFAULT_LANG])
|
||||||
|
keys << :os if options[:multi_os]
|
||||||
|
keys += [:dist, :group] if options[:dist_group_expansion]
|
||||||
|
keys | EXPANSION_KEYS_UNIVERSAL
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(config, options = {})
|
||||||
|
@config = config.symbolize_keys
|
||||||
|
@options = options
|
||||||
|
end
|
||||||
|
|
||||||
|
def expand
|
||||||
|
configs = expand_matrix
|
||||||
|
configs = include_matrix_configs(exclude_matrix_configs(configs))
|
||||||
|
configs = configs.map { |config| cleanup_config(merge_config(Hash[config])) }
|
||||||
|
configs
|
||||||
|
# configs.map { |config| Build::Config::OS.new(config, options).run }
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
attr_reader :config, :options
|
||||||
|
|
||||||
|
def allow_failure_configs
|
||||||
|
(settings[:allow_failures] || []).select do |config|
|
||||||
|
config = config.to_hash.symbolize_keys if config.respond_to?(:to_hash)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fast_finish?
|
||||||
|
settings[:fast_finish]
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def settings
|
||||||
|
@settings ||= config[:matrix] || {}
|
||||||
|
@settings = {} if @settings.is_a?(Array)
|
||||||
|
@settings
|
||||||
|
end
|
||||||
|
|
||||||
|
def expand_matrix
|
||||||
|
rows = config.slice(*expand_keys).values.select { |value| value.is_a?(Array) }
|
||||||
|
max_size = rows.max_by(&:size).try(:size) || 1
|
||||||
|
|
||||||
|
array = expand_keys.inject([]) do |result, key|
|
||||||
|
values = Array.wrap(config[key])
|
||||||
|
values += [values.last] * (max_size - values.size)
|
||||||
|
result << values.map { |value| [key, value] }
|
||||||
|
end
|
||||||
|
|
||||||
|
permutations(array).uniq
|
||||||
|
end
|
||||||
|
|
||||||
|
# recursively builds up permutations of values in the rows of a nested array
|
||||||
|
def permutations(base, result = [])
|
||||||
|
base = base.dup
|
||||||
|
base.empty? ? [result] : base.shift.map { |value| permutations(base, result + [value]) }.flatten(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
def expand_keys
|
||||||
|
@expand_keys ||= config.keys.map(&:to_sym) & self.class.matrix_keys_for(config, options)
|
||||||
|
end
|
||||||
|
|
||||||
|
def exclude_matrix_configs(configs)
|
||||||
|
configs.reject { |config| exclude_config?(config) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def exclude_config?(config)
|
||||||
|
exclude_configs = normalize_matrix_filter_configs(settings[:exclude] || [])
|
||||||
|
config = config.map { |config| [config[0].to_s, *config[1..-1]] }.sort
|
||||||
|
exclude_configs.any? do |excluded|
|
||||||
|
excluded.all? { |matrix_key| config.include? matrix_key }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def include_matrix_configs(configs)
|
||||||
|
include_configs = normalize_matrix_filter_configs(settings[:include] || [])
|
||||||
|
if configs.flatten.empty? && settings.has_key?(:include)
|
||||||
|
include_configs
|
||||||
|
else
|
||||||
|
configs + include_configs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def normalize_matrix_filter_configs(configs)
|
||||||
|
configs = configs.select { |c| c.is_a?(Hash) }
|
||||||
|
configs = configs.compact.map(&:stringify_keys)
|
||||||
|
configs.map(&:to_a).map(&:sort)
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge_config(row)
|
||||||
|
config.select { |key, value| include_key?(key) }.merge(row)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cleanup_config(config)
|
||||||
|
config.delete(:matrix)
|
||||||
|
config
|
||||||
|
end
|
||||||
|
|
||||||
|
def include_key?(key)
|
||||||
|
self.class.matrix_keys_for(config, options).include?(key.to_sym) || !known_env_key?(key.to_sym)
|
||||||
|
end
|
||||||
|
|
||||||
|
def known_env_key?(key)
|
||||||
|
(ENV_KEYS | EXPANSION_KEYS_FEATURE).include?(key)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -1,5 +0,0 @@
|
|||||||
require 'sinatra/base'
|
|
||||||
|
|
||||||
class App < Sinatra::Base
|
|
||||||
run! if app_file == $PROGRAM_NAME
|
|
||||||
end
|
|
@ -1,2 +0,0 @@
|
|||||||
require './app'
|
|
||||||
run App
|
|
Loading…
Reference in New Issue
Block a user