matrixeval-ruby 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/README.md +19 -4
- data/lib/matrixeval/ruby/target.rb +87 -0
- data/lib/matrixeval/ruby/templates/matrixeval.yml +17 -2
- data/lib/matrixeval/ruby/version.rb +1 -3
- data/lib/matrixeval/ruby.rb +5 -21
- metadata +8 -57
- data/exe/matrixeval +0 -5
- data/exe/meval +0 -5
- data/lib/matrixeval/ruby/command_line/parse_context_arguments.rb +0 -85
- data/lib/matrixeval/ruby/command_line.rb +0 -57
- data/lib/matrixeval/ruby/config/yaml.rb +0 -40
- data/lib/matrixeval/ruby/config.rb +0 -98
- data/lib/matrixeval/ruby/container.rb +0 -15
- data/lib/matrixeval/ruby/context/build_docker_compose_extend.rb +0 -43
- data/lib/matrixeval/ruby/context/find_by_command_options.rb +0 -67
- data/lib/matrixeval/ruby/context.rb +0 -86
- data/lib/matrixeval/ruby/docker_compose/extend.rb +0 -21
- data/lib/matrixeval/ruby/docker_compose/extend_raw.rb +0 -19
- data/lib/matrixeval/ruby/docker_compose/file.rb +0 -135
- data/lib/matrixeval/ruby/docker_compose.rb +0 -68
- data/lib/matrixeval/ruby/extra_mount_files.rb +0 -23
- data/lib/matrixeval/ruby/gemfile_locks.rb +0 -23
- data/lib/matrixeval/ruby/gitignore.rb +0 -54
- data/lib/matrixeval/ruby/runner.rb +0 -205
- data/lib/matrixeval/ruby/variant.rb +0 -59
- data/lib/matrixeval/ruby/vector.rb +0 -39
@@ -1,67 +0,0 @@
|
|
1
|
-
module Matrixeval
|
2
|
-
module Ruby
|
3
|
-
class Context
|
4
|
-
class FindByCommandOptions
|
5
|
-
class << self
|
6
|
-
def call(options)
|
7
|
-
new(options).call
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
attr_reader :options
|
12
|
-
|
13
|
-
def initialize(options)
|
14
|
-
@options = options
|
15
|
-
end
|
16
|
-
|
17
|
-
def call
|
18
|
-
context = Context.all.find do |context|
|
19
|
-
context.main_variant == main_variant &&
|
20
|
-
context.rest_variants == rest_variants
|
21
|
-
end
|
22
|
-
|
23
|
-
raise Error.new("Can't find a corresponding matrix") if context.nil?
|
24
|
-
|
25
|
-
context
|
26
|
-
end
|
27
|
-
|
28
|
-
private
|
29
|
-
|
30
|
-
def main_variant
|
31
|
-
dig_variant Config.main_vector
|
32
|
-
end
|
33
|
-
|
34
|
-
def rest_variants
|
35
|
-
Config.rest_vectors.map do |vector|
|
36
|
-
dig_variant vector
|
37
|
-
end.sort do |v1, v2|
|
38
|
-
v1.id <=> v2.id
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def dig_variant(vector)
|
43
|
-
if option_key?(vector.key)
|
44
|
-
find_variant(vector)
|
45
|
-
else
|
46
|
-
vector.default_variant
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
def find_variant(vector)
|
51
|
-
vector.variants.find do |variant|
|
52
|
-
option(vector.key) == variant.key
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
def option(key)
|
57
|
-
options[key.to_sym] || options[key.to_s]
|
58
|
-
end
|
59
|
-
|
60
|
-
def option_key?(key)
|
61
|
-
options.key?(key.to_sym) || options.key?(key.to_s)
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
require_relative "./context/find_by_command_options"
|
2
|
-
require_relative "./context/build_docker_compose_extend"
|
3
|
-
|
4
|
-
module Matrixeval
|
5
|
-
module Ruby
|
6
|
-
class Context
|
7
|
-
|
8
|
-
class << self
|
9
|
-
|
10
|
-
def find_by_command_options!(options)
|
11
|
-
FindByCommandOptions.call(options)
|
12
|
-
end
|
13
|
-
|
14
|
-
def all
|
15
|
-
Config.variant_combinations.map do |variants|
|
16
|
-
Context.new(
|
17
|
-
main_variant: variants.find { |v| v.vector.main? },
|
18
|
-
rest_variants: variants.reject { |v| v.vector.main? }
|
19
|
-
)
|
20
|
-
end.select do |context|
|
21
|
-
Config.exclusions.none? do |exclusion|
|
22
|
-
context.match_exclusion?(exclusion)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
attr_reader :main_variant, :rest_variants
|
30
|
-
|
31
|
-
def initialize(main_variant:, rest_variants:)
|
32
|
-
@main_variant = main_variant
|
33
|
-
@rest_variants = (rest_variants || []).sort do |v1, v2|
|
34
|
-
v1.id <=> v2.id
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def name
|
39
|
-
variants.map(&:name).join(", ")
|
40
|
-
end
|
41
|
-
|
42
|
-
def id
|
43
|
-
[[main_variant.id] + rest_variants.map(&:id)].join("_")
|
44
|
-
end
|
45
|
-
|
46
|
-
def env
|
47
|
-
rest_variants.map(&:env).reduce({}, &:merge)
|
48
|
-
.merge(main_variant.env)
|
49
|
-
end
|
50
|
-
|
51
|
-
def docker_compose_service_name
|
52
|
-
main_variant.id
|
53
|
-
end
|
54
|
-
|
55
|
-
def gemfile_lock_path
|
56
|
-
Matrixeval.working_dir.join(".matrixeval/gemfile_locks/#{id}")
|
57
|
-
end
|
58
|
-
|
59
|
-
def docker_compose_file_path
|
60
|
-
Matrixeval.working_dir.join(".matrixeval/docker-compose/#{id}.yml")
|
61
|
-
end
|
62
|
-
|
63
|
-
def variants
|
64
|
-
[main_variant] + rest_variants
|
65
|
-
end
|
66
|
-
|
67
|
-
def match_exclusion?(exclusion)
|
68
|
-
return false if exclusion.empty?
|
69
|
-
|
70
|
-
variants.all? do |variant|
|
71
|
-
vector_key = variant.vector.key
|
72
|
-
if exclusion.key?(vector_key)
|
73
|
-
exclusion[vector_key].to_s == variant.key
|
74
|
-
else
|
75
|
-
true
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def docker_compose_extend
|
81
|
-
BuildDockerComposeExtend.call(self)
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
module Matrixeval
|
2
|
-
module Ruby
|
3
|
-
class DockerCompose
|
4
|
-
class Extend
|
5
|
-
|
6
|
-
def initialize(config)
|
7
|
-
@config = config || {}
|
8
|
-
end
|
9
|
-
|
10
|
-
def volumes
|
11
|
-
@config["volumes"] || {}
|
12
|
-
end
|
13
|
-
|
14
|
-
def services
|
15
|
-
@config["services"] || {}
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
@@ -1,135 +0,0 @@
|
|
1
|
-
require "erb"
|
2
|
-
|
3
|
-
module Matrixeval
|
4
|
-
module Ruby
|
5
|
-
class DockerCompose
|
6
|
-
class File
|
7
|
-
class << self
|
8
|
-
|
9
|
-
def create_all
|
10
|
-
FileUtils.mkdir_p folder
|
11
|
-
|
12
|
-
Context.all.each do |context|
|
13
|
-
new(context).create
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def folder
|
20
|
-
Matrixeval.working_dir.join(".matrixeval/docker-compose")
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
attr_reader :context
|
25
|
-
|
26
|
-
def initialize(context)
|
27
|
-
@context = context
|
28
|
-
end
|
29
|
-
|
30
|
-
def create
|
31
|
-
::File.open(docker_compose_file_path, 'w+') do |file|
|
32
|
-
file.puts build_content
|
33
|
-
end
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def docker_compose_file_path
|
39
|
-
context.docker_compose_file_path
|
40
|
-
end
|
41
|
-
|
42
|
-
def build_content
|
43
|
-
{
|
44
|
-
"version" => "3",
|
45
|
-
"services" => services_json,
|
46
|
-
"volumes" => volumes_json
|
47
|
-
}.to_yaml.sub(/---\n/, "")
|
48
|
-
end
|
49
|
-
|
50
|
-
def services_json
|
51
|
-
services = {}
|
52
|
-
|
53
|
-
services[main_variant.docker_compose_service_name] = {
|
54
|
-
"image" => main_variant.container.image,
|
55
|
-
"volumes" => mounts(main_variant),
|
56
|
-
"environment" => {
|
57
|
-
"BUNDLE_PATH" => "/bundle",
|
58
|
-
"GEM_HOME" => "/bundle",
|
59
|
-
"BUNDLE_APP_CONFIG" => "/bundle",
|
60
|
-
"BUNDLE_BIN" => "/bundle/bin",
|
61
|
-
"PATH" => "/app/bin:/bundle/bin:$PATH"
|
62
|
-
}.merge(extra_env),
|
63
|
-
"working_dir" => "/app"
|
64
|
-
}.merge(depends_on)
|
65
|
-
|
66
|
-
services.merge(docker_compose_extend.services)
|
67
|
-
end
|
68
|
-
|
69
|
-
def volumes_json
|
70
|
-
{
|
71
|
-
bundle_volume => {
|
72
|
-
"name" => bundle_volume
|
73
|
-
}
|
74
|
-
}.merge(docker_compose_extend.volumes)
|
75
|
-
end
|
76
|
-
|
77
|
-
def depends_on
|
78
|
-
if docker_compose_extend.services.keys.empty?
|
79
|
-
{}
|
80
|
-
else
|
81
|
-
{ "depends_on" => docker_compose_extend.services.keys }
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def extra_env
|
86
|
-
Config.env.merge(context.env)
|
87
|
-
.merge(main_variant.container.env)
|
88
|
-
end
|
89
|
-
|
90
|
-
def main_variant
|
91
|
-
context.main_variant
|
92
|
-
end
|
93
|
-
|
94
|
-
def bundle_volume
|
95
|
-
main_variant.bundle_volume_name
|
96
|
-
end
|
97
|
-
|
98
|
-
def mounts(variant)
|
99
|
-
[
|
100
|
-
"../..:/app:cached",
|
101
|
-
"#{variant.bundle_volume_name}:/bundle",
|
102
|
-
"../gemfile_locks/#{context.id}:/app/Gemfile.lock"
|
103
|
-
] + extra_mounts
|
104
|
-
end
|
105
|
-
|
106
|
-
def extra_mounts
|
107
|
-
mounts = Config.mounts + context.variants.map(&:mounts).flatten
|
108
|
-
mounts.map do |mount|
|
109
|
-
local_path, in_docker_path = mount.split(':')
|
110
|
-
next mount if Pathname.new(local_path).absolute?
|
111
|
-
|
112
|
-
local_path = Matrixeval.working_dir.join(local_path)
|
113
|
-
docker_compose_folder_path = Matrixeval.working_dir.join(".matrixeval/docker-compose")
|
114
|
-
local_path = local_path.relative_path_from docker_compose_folder_path
|
115
|
-
|
116
|
-
"#{local_path}:#{in_docker_path}"
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def docker_compose_extend
|
121
|
-
@docker_compose_extend ||= context.docker_compose_extend
|
122
|
-
end
|
123
|
-
|
124
|
-
def working_dir_name
|
125
|
-
Matrixeval.working_dir.basename
|
126
|
-
end
|
127
|
-
|
128
|
-
def project_name
|
129
|
-
Config.project_name.gsub(/[^A-Za-z0-9-]/,'_').downcase
|
130
|
-
end
|
131
|
-
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
@@ -1,68 +0,0 @@
|
|
1
|
-
|
2
|
-
require_relative "./docker_compose/file"
|
3
|
-
|
4
|
-
module Matrixeval
|
5
|
-
module Ruby
|
6
|
-
class DockerCompose
|
7
|
-
|
8
|
-
attr_reader :context
|
9
|
-
|
10
|
-
def initialize(context)
|
11
|
-
@context = context
|
12
|
-
end
|
13
|
-
|
14
|
-
def run(arguments)
|
15
|
-
forward_arguments = arguments.map do |arg|
|
16
|
-
arg.match(/\s/) ? "\"#{arg}\"" : arg
|
17
|
-
end.join(" ")
|
18
|
-
|
19
|
-
no_tty = %w[bash sh zsh dash].include?(arguments[0]) ? '' : '--no-TTY'
|
20
|
-
|
21
|
-
system(
|
22
|
-
<<~DOCKER_COMPOSE_COMMAND
|
23
|
-
#{docker_compose} \
|
24
|
-
run --rm \
|
25
|
-
#{no_tty} \
|
26
|
-
#{context.docker_compose_service_name} \
|
27
|
-
#{forward_arguments}
|
28
|
-
DOCKER_COMPOSE_COMMAND
|
29
|
-
)
|
30
|
-
ensure
|
31
|
-
stop_containers
|
32
|
-
clean_containers_and_anonymous_volumes
|
33
|
-
turn_on_stty_opost
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def stop_containers
|
39
|
-
system("#{docker_compose} stop >> /dev/null 2>&1")
|
40
|
-
end
|
41
|
-
|
42
|
-
def clean_containers_and_anonymous_volumes
|
43
|
-
system("#{docker_compose} rm -v -f >> /dev/null 2>&1")
|
44
|
-
end
|
45
|
-
|
46
|
-
def docker_compose
|
47
|
-
<<~DOCKER_COMPOSE_COMMAND.strip
|
48
|
-
docker --log-level error compose \
|
49
|
-
-f #{yaml_file} \
|
50
|
-
-p matrixeval-#{project_name}-#{context.id}
|
51
|
-
DOCKER_COMPOSE_COMMAND
|
52
|
-
end
|
53
|
-
|
54
|
-
def yaml_file
|
55
|
-
".matrixeval/docker-compose/#{context.id}.yml"
|
56
|
-
end
|
57
|
-
|
58
|
-
def turn_on_stty_opost
|
59
|
-
system("stty opost")
|
60
|
-
end
|
61
|
-
|
62
|
-
def project_name
|
63
|
-
Config.project_name.gsub(/[^A-Za-z0-9-]/,'_').downcase
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Matrixeval
|
2
|
-
module Ruby
|
3
|
-
class ExtraMountFiles
|
4
|
-
class << self
|
5
|
-
|
6
|
-
def create
|
7
|
-
Config.all_mounts.each do |mount|
|
8
|
-
local_path, _ = mount.split(':')
|
9
|
-
next mount if Pathname.new(local_path).absolute?
|
10
|
-
|
11
|
-
local_path = Matrixeval.working_dir.join(local_path)
|
12
|
-
next if local_path.extname.empty?
|
13
|
-
next if local_path.ascend.none? { |path| path == Matrixeval.working_dir }
|
14
|
-
|
15
|
-
FileUtils.mkdir_p local_path.dirname
|
16
|
-
FileUtils.touch local_path
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,23 +0,0 @@
|
|
1
|
-
module Matrixeval
|
2
|
-
module Ruby
|
3
|
-
class GemfileLocks
|
4
|
-
class << self
|
5
|
-
|
6
|
-
def create
|
7
|
-
FileUtils.mkdir_p gemfile_lock_folder
|
8
|
-
|
9
|
-
Context.all.each do |context|
|
10
|
-
FileUtils.touch context.gemfile_lock_path
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
private
|
15
|
-
|
16
|
-
def gemfile_lock_folder
|
17
|
-
Matrixeval.working_dir.join(".matrixeval/gemfile_locks")
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
module Matrixeval
|
2
|
-
module Ruby
|
3
|
-
class Gitignore
|
4
|
-
class << self
|
5
|
-
|
6
|
-
def update
|
7
|
-
add_docker_compose
|
8
|
-
add_gemfile_locks
|
9
|
-
end
|
10
|
-
|
11
|
-
private
|
12
|
-
|
13
|
-
def add_docker_compose
|
14
|
-
return if docker_compose_included?
|
15
|
-
|
16
|
-
File.open(gitignore_path, 'a+') do |file|
|
17
|
-
file.puts docker_compose
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def add_gemfile_locks
|
22
|
-
return if gemfile_locks_included?
|
23
|
-
|
24
|
-
File.open(gitignore_path, 'a+') do |file|
|
25
|
-
file.puts gemfile_locks
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def docker_compose_included?
|
30
|
-
File.exist?(gitignore_path) &&
|
31
|
-
File.read(gitignore_path).include?(docker_compose)
|
32
|
-
end
|
33
|
-
|
34
|
-
def gemfile_locks_included?
|
35
|
-
File.exist?(gitignore_path) &&
|
36
|
-
File.read(gitignore_path).include?(gemfile_locks)
|
37
|
-
end
|
38
|
-
|
39
|
-
def docker_compose
|
40
|
-
".matrixeval/docker-compose"
|
41
|
-
end
|
42
|
-
|
43
|
-
def gemfile_locks
|
44
|
-
".matrixeval/gemfile_locks"
|
45
|
-
end
|
46
|
-
|
47
|
-
def gitignore_path
|
48
|
-
Matrixeval.working_dir.join(".gitignore")
|
49
|
-
end
|
50
|
-
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,205 +0,0 @@
|
|
1
|
-
require 'optparse'
|
2
|
-
require 'pathname'
|
3
|
-
require 'fileutils'
|
4
|
-
require 'matrixeval/ruby/config'
|
5
|
-
require 'matrixeval/ruby/command_line'
|
6
|
-
require "concurrent/utility/processor_counter"
|
7
|
-
require 'terminal-table'
|
8
|
-
|
9
|
-
module Matrixeval
|
10
|
-
module Ruby
|
11
|
-
class Runner
|
12
|
-
class << self
|
13
|
-
def start(argv)
|
14
|
-
new(argv).start
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
attr_reader :argv, :command
|
19
|
-
|
20
|
-
def initialize(argv)
|
21
|
-
@argv = argv
|
22
|
-
@command = CommandLine.new(argv)
|
23
|
-
@threads ||= []
|
24
|
-
@matrixeval_results ||= []
|
25
|
-
end
|
26
|
-
|
27
|
-
def start
|
28
|
-
validates
|
29
|
-
|
30
|
-
if command.init?
|
31
|
-
init
|
32
|
-
elsif command.all?
|
33
|
-
run_all_contexts
|
34
|
-
else
|
35
|
-
run_a_specific_context
|
36
|
-
end
|
37
|
-
rescue OptionParser::InvalidOption => e
|
38
|
-
puts <<~ERROR
|
39
|
-
#{e.message}
|
40
|
-
See 'matrixeval --help'
|
41
|
-
ERROR
|
42
|
-
exit
|
43
|
-
rescue Config::YAML::MissingError
|
44
|
-
puts "Please run 'matrixeval init' first to generate matrixeval.yml"
|
45
|
-
exit
|
46
|
-
ensure
|
47
|
-
turn_on_stty_opost
|
48
|
-
end
|
49
|
-
|
50
|
-
private
|
51
|
-
|
52
|
-
def validates
|
53
|
-
return if command.valid?
|
54
|
-
|
55
|
-
puts <<~ERROR
|
56
|
-
matrixeval: '#{argv.join(' ')}' is not a MatrixEval command.
|
57
|
-
See 'matrixeval --help'
|
58
|
-
ERROR
|
59
|
-
exit
|
60
|
-
end
|
61
|
-
|
62
|
-
def init
|
63
|
-
Config::YAML.create
|
64
|
-
Gitignore.update
|
65
|
-
end
|
66
|
-
|
67
|
-
def run_all_contexts
|
68
|
-
Config::YAML.create
|
69
|
-
DockerCompose::File.create_all
|
70
|
-
GemfileLocks.create
|
71
|
-
Gitignore.update
|
72
|
-
ExtraMountFiles.create
|
73
|
-
|
74
|
-
pull_all_images
|
75
|
-
|
76
|
-
if workers_count == 1
|
77
|
-
run_all_contexts_sequentially
|
78
|
-
else
|
79
|
-
run_all_contexts_in_parallel
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def run_all_contexts_sequentially
|
84
|
-
Context.all.each do |context|
|
85
|
-
puts Rainbow("[ MatrixEval ] ").blue.bright + Rainbow(" #{context.name} ").white.bright.bg(:blue)
|
86
|
-
puts Rainbow("[ MatrixEval ] Run \"#{command.rest_arguments.join(" ")}\"").blue.bright
|
87
|
-
|
88
|
-
docker_compose = DockerCompose.new(context)
|
89
|
-
success = docker_compose.run(command.rest_arguments)
|
90
|
-
|
91
|
-
@matrixeval_results << [context, !!success]
|
92
|
-
end
|
93
|
-
|
94
|
-
report
|
95
|
-
end
|
96
|
-
|
97
|
-
def run_all_contexts_in_parallel
|
98
|
-
parallel(contexts) do |sub_contexts|
|
99
|
-
Thread.current[:matrixeval_results] = []
|
100
|
-
|
101
|
-
sub_contexts.each do |context|
|
102
|
-
docker_compose = DockerCompose.new(context)
|
103
|
-
success = docker_compose.run(command.rest_arguments)
|
104
|
-
|
105
|
-
Thread.current[:matrixeval_results] << [context, !!success]
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
report
|
110
|
-
end
|
111
|
-
|
112
|
-
def run_a_specific_context
|
113
|
-
Config::YAML.create
|
114
|
-
DockerCompose::File.create_all
|
115
|
-
GemfileLocks.create
|
116
|
-
Gitignore.update
|
117
|
-
ExtraMountFiles.create
|
118
|
-
|
119
|
-
context = Context.find_by_command_options!(command.context_options)
|
120
|
-
|
121
|
-
puts Rainbow("[ MatrixEval ] ").blue.bright + Rainbow(" #{context.name} ").white.bright.bg(:blue)
|
122
|
-
puts Rainbow("[ MatrixEval ] Run \"#{command.rest_arguments.join(" ")}\"").blue.bright
|
123
|
-
|
124
|
-
docker_compose = DockerCompose.new(context)
|
125
|
-
docker_compose.run(command.rest_arguments)
|
126
|
-
end
|
127
|
-
|
128
|
-
def pull_all_images
|
129
|
-
parallel(Config.main_vector_variants) do |sub_variants|
|
130
|
-
sub_variants.each do |variant|
|
131
|
-
puts "Docker image check/pull #{variant.container.image}"
|
132
|
-
image_exists = system %Q{[ -n "$(docker images -q #{variant.container.image})" ]}
|
133
|
-
next if image_exists
|
134
|
-
|
135
|
-
system "docker pull #{variant.container.image}"
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def report
|
141
|
-
turn_on_stty_opost
|
142
|
-
|
143
|
-
table = Terminal::Table.new(title: Rainbow("MatrixEval").blue.bright + " Summary", alignment: :center) do |table|
|
144
|
-
|
145
|
-
headers = Config.vectors.map(&:key) + ['result']
|
146
|
-
table.add_row headers.map { |value| { value: value, alignment: :center } }
|
147
|
-
table.add_separator
|
148
|
-
|
149
|
-
@matrixeval_results.each do |context, success|
|
150
|
-
success_cell = [success ? Rainbow('Success').green : Rainbow('Failed').red]
|
151
|
-
row = (context.variants.map(&:key) + success_cell).map do |value|
|
152
|
-
{ value: value, alignment: :center }
|
153
|
-
end
|
154
|
-
|
155
|
-
table.add_row row
|
156
|
-
end
|
157
|
-
|
158
|
-
end
|
159
|
-
|
160
|
-
puts table
|
161
|
-
end
|
162
|
-
|
163
|
-
def parallel(collection)
|
164
|
-
@threads = [] unless @threads.empty?
|
165
|
-
@matrixeval_results = [] unless @matrixeval_results.empty?
|
166
|
-
|
167
|
-
collection.each_slice(per_worker_contexts_count) do |sub_collection|
|
168
|
-
@threads << Thread.new do
|
169
|
-
yield sub_collection
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
@threads.each(&:join)
|
174
|
-
|
175
|
-
@threads.each do |thread|
|
176
|
-
@matrixeval_results += (thread[:matrixeval_results] || [])
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
|
181
|
-
def per_worker_contexts_count
|
182
|
-
[(contexts.count / workers_count), 1].max
|
183
|
-
end
|
184
|
-
|
185
|
-
def contexts
|
186
|
-
@contexts ||= Context.all
|
187
|
-
end
|
188
|
-
|
189
|
-
def workers_count
|
190
|
-
count = if Config.parallel_workers == "number_of_processors"
|
191
|
-
Concurrent.physical_processor_count
|
192
|
-
else
|
193
|
-
Integer(Config.parallel_workers)
|
194
|
-
end
|
195
|
-
|
196
|
-
[count, 1].max
|
197
|
-
end
|
198
|
-
|
199
|
-
def turn_on_stty_opost
|
200
|
-
system("stty opost")
|
201
|
-
end
|
202
|
-
|
203
|
-
end
|
204
|
-
end
|
205
|
-
end
|