matrixeval-ruby 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6bd932a09eb30fdf342cc0596af3e6cd82496deaa0af2746bdc79a06b1c85911
4
- data.tar.gz: b13ef75ed283407d0d3e9ac50f0d0053a81a39dbcab737183e6886b9caf34a99
3
+ metadata.gz: 21cd041a53b811584d5ba4c44cc7cca0990add95f39251b566425d8e41b8d5c5
4
+ data.tar.gz: 342cb96612cee61f74683af65a150e3b86a574e835dfb8736e7a600ab86e9dc5
5
5
  SHA512:
6
- metadata.gz: a8593994584983cde95650942a8ca0479c58412ecdccaddb2ab4aa31f378544f46fead1f05d9e12f33f405b68aeb8d5fdf4017059e39f81c22a8d494d89619e6
7
- data.tar.gz: b83de57cc53b6b3a35dd86e0fd4196218a900219af7868b3870feff925db05a0c6fe6c0820cbef94903dac4c186684ac13d897a31ce75a612149d945f5cf31eb
6
+ metadata.gz: 4c058092c0c3279fc1359f6802d7dbb56cb8a7f2057a7af0b3c3967e5459c36cba7316539722c6577821c147cdaf13fabfaa06f24f4847976787c07f6fa09d47
7
+ data.tar.gz: faf39d5d47abd8e1af39ab6521c4a719646f10ce016f76c563a516926e7b8554e1ec7646eaac0d6742d58ebada94bbe828ab83fa553486d0aa485e2114315581
data/CHANGELOG.md CHANGED
@@ -1,8 +1,15 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [0.2.0] - 2022-02-10
4
+
5
+ - Change config format from 0.1 to 0.2
6
+ - CLI description
7
+ - Other errors fix
8
+
3
9
  ## [0.1.1] - 2022-02-09
4
10
 
5
11
  - Fix a execution report issue
12
+
6
13
  ## [0.1.0] - 2022-02-09
7
14
 
8
15
  - Initial release
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- matrixeval-ruby (0.1.0)
4
+ matrixeval-ruby (0.1.1)
5
5
  concurrent-ruby
6
6
  rainbow (~> 3.1)
7
7
  terminal-table
data/README.md CHANGED
@@ -19,7 +19,22 @@ Or install it yourself as:
19
19
 
20
20
  ## Usage
21
21
 
22
- TODO: Write usage instructions here
22
+ Initialize
23
+
24
+ ```bash
25
+ matrixeval init
26
+ ```
27
+
28
+ Customize `matrixeval.yml` file and run commands like:
29
+
30
+ ```bash
31
+ matrixeval --all bundle install
32
+ matrixeval --all rspec
33
+ matrixeval --ruby 3.0 rspec a_spec.rb
34
+ matrixeval --ruby 3.1 --rails 7.0 rake test
35
+ matrixeval bash
36
+ ```
37
+ Run `matrixeval --help` for more details
23
38
 
24
39
  ## Development
25
40
 
data/exe/matrixeval CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'matrixeval/ruby'
4
- puts "Hello, MatrixEval!"
4
+
5
5
  Matrixeval.start(ARGV)
data/exe/meval CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'matrixeval/ruby'
4
- puts "Hello, MatrixEval!"
4
+
5
5
  Matrixeval.start(ARGV)
@@ -24,11 +24,58 @@ module Matrixeval
24
24
 
25
25
  def parse!
26
26
  OptionParser.new do |opts|
27
- opts.banner = "Usage: meval/matrixeval --[VECTOR_KEY] [VECTOR_CHOICE] [COMMAND] [COMMAND_OPTIONS]"
27
+ opts.version = Matrixeval::Ruby::VERSION
28
+ opts.program_name = ""
29
+ opts.banner = <<~USAGE
30
+ Usage:
31
+ matrixeval(meval) [OPTIONS] COMMAND
32
+ USAGE
33
+
34
+ opts.separator ""
35
+ opts.separator "Options:"
36
+
37
+ opts.on "-a", "--all", "# Run the COMMAND against all matrix combinations"
28
38
 
29
39
  Config.vectors.each do |vector|
30
- opts.on("--#{vector.key} [VERSION]", "Set #{vector.key} version")
40
+ # short = "-#{vector.short_key}"
41
+ long = "--#{vector.key} [VERSION]"
42
+ desc = [
43
+ "# Run the COMMAND against a specific #{vector.key} version",
44
+ "# Options: #{vector.variants.map(&:key).join("/")}",
45
+ "# Default: #{vector.default_variant.key}",
46
+ "# Customizable"
47
+ ]
48
+ opts.separator ""
49
+ opts.on(long, *desc)
50
+ end
51
+
52
+ opts.separator ""
53
+ opts.separator "Commands: #{Config.commands.join("/")} (Customizable)"
54
+
55
+ opts.separator ""
56
+ opts.separator "MatrixEval Options:"
57
+
58
+ opts.on("-h", "--help", "# Show help") do
59
+ puts opts.help
60
+ exit
31
61
  end
62
+
63
+ opts.on("-v", "--version", "# Show version") do
64
+ puts opts.version
65
+ exit
66
+ end
67
+
68
+ opts.separator ""
69
+ opts.separator "Customizations:"
70
+ opts.separator " You can customize all options in matrixeval.yml"
71
+
72
+ opts.separator ""
73
+ opts.separator "Example:"
74
+ opts.separator " matrixeval --all bundle install"
75
+ opts.separator " matrixeval --ruby 3.0 rspec a_spec.rb"
76
+ opts.separator " matrixeval --ruby 3.1 --active_model 7.0 rake test"
77
+ opts.separator " matrixeval bash"
78
+
32
79
  end.parse!(context_arguments, into: options)
33
80
  end
34
81
 
@@ -2,28 +2,38 @@ require_relative "./command_line/parse_context_arguments"
2
2
 
3
3
  module Matrixeval
4
4
  module Ruby
5
+ COMMANDS = ['rake', 'rspec', 'bundle', 'bash']
6
+
5
7
  class CommandLine
6
8
 
7
- attr_reader :argv
9
+ attr_accessor :argv
8
10
 
9
11
  def initialize(argv)
10
12
  @argv = argv
11
13
  end
12
14
 
15
+ def valid?
16
+ init? ||
17
+ !context_options.empty? ||
18
+ !seperator_index.nil?
19
+ end
20
+
13
21
  def init?
14
22
  argv[0] == 'init'
15
23
  end
16
24
 
17
25
  def all?
18
- argv[0] == 'all'
26
+ context_options[:all]
19
27
  end
20
28
 
21
29
  def context_options
22
- ParseContextArguments.call(context_arguments)
30
+ @context_options ||= ParseContextArguments.call(context_arguments)
23
31
  end
24
32
 
25
33
  def context_arguments
26
- argv[0...seperator_index]
34
+ arguments = argv[0...seperator_index]
35
+ arguments << "-h" if argv.empty?
36
+ arguments
27
37
  end
28
38
 
29
39
  def rest_arguments
@@ -34,14 +44,10 @@ module Matrixeval
34
44
 
35
45
  def seperator_index
36
46
  argv.index do |argument|
37
- seperator_commands.include?(argument)
47
+ Config.commands.include?(argument)
38
48
  end
39
49
  end
40
50
 
41
- def seperator_commands
42
- ['rake', 'rspec', 'bundle', 'bash']
43
- end
44
-
45
51
  end
46
52
  end
47
53
  end
@@ -2,6 +2,9 @@ module Matrixeval
2
2
  module Ruby
3
3
  class Config
4
4
  class YAML
5
+
6
+ class MissingError < StandardError; end
7
+
5
8
  class << self
6
9
 
7
10
  def create
@@ -25,6 +28,8 @@ module Matrixeval
25
28
  end
26
29
 
27
30
  def yaml
31
+ raise MissingError unless File.exist?(path)
32
+
28
33
  ::YAML.load File.read(path)
29
34
  end
30
35
 
@@ -49,6 +49,11 @@ module Matrixeval
49
49
  YAML["parallel_workers"] || "number_of_processors"
50
50
  end
51
51
 
52
+ def commands
53
+ cmds = YAML["commands"] || []
54
+ COMMANDS + cmds
55
+ end
56
+
52
57
  end
53
58
  end
54
59
  end
@@ -0,0 +1,15 @@
1
+ module Matrixeval
2
+ module Ruby
3
+ class Container
4
+
5
+ attr_reader :image, :env
6
+
7
+ def initialize(options)
8
+ options ||= {}
9
+ @image = options["image"]
10
+ @env = options["env"] || {}
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -29,7 +29,7 @@ module Matrixeval
29
29
 
30
30
  Config.main_vector_variants.map do |variant|
31
31
  services[variant.docker_compose_service_name] = {
32
- "image" => variant.image,
32
+ "image" => variant.container.image,
33
33
  "volumes" => mounts(variant),
34
34
  "environment" => {
35
35
  "BUNDLE_PATH" => "/bundle",
@@ -37,7 +37,7 @@ module Matrixeval
37
37
  "BUNDLE_APP_CONFIG" => "/bundle",
38
38
  "BUNDLE_BIN" => "/bundle/bin",
39
39
  "PATH" => "/app/bin:/bundle/bin:$PATH"
40
- },
40
+ }.merge(variant.container.env),
41
41
  "working_dir" => "/app"
42
42
  }
43
43
  end
@@ -16,13 +16,18 @@ module Matrixeval
16
16
  end
17
17
 
18
18
  attr_reader :argv, :command
19
+ attr_accessor :threads, :matrixeval_results
19
20
 
20
21
  def initialize(argv)
21
22
  @argv = argv
22
23
  @command = CommandLine.new(argv)
24
+ @threads ||= []
25
+ @matrixeval_results ||= []
23
26
  end
24
27
 
25
28
  def start
29
+ validates
30
+
26
31
  if command.init?
27
32
  init
28
33
  elsif command.all?
@@ -30,12 +35,31 @@ module Matrixeval
30
35
  else
31
36
  run_a_specific_context
32
37
  end
38
+ rescue OptionParser::InvalidOption => e
39
+ puts <<~ERROR
40
+ #{e.message}
41
+ See 'matrixeval --help'
42
+ ERROR
43
+ exit
44
+ rescue Config::YAML::MissingError
45
+ puts "Please run 'matrixeval init' first to generate matrixeval.yml"
46
+ exit
33
47
  ensure
34
48
  turn_on_stty_opost
35
49
  end
36
50
 
37
51
  private
38
52
 
53
+ def validates
54
+ return if command.valid?
55
+
56
+ puts <<~ERROR
57
+ matrixeval: '#{argv.join(' ')}' is not a MatrixEval command.
58
+ See 'matrixeval --help'
59
+ ERROR
60
+ exit
61
+ end
62
+
39
63
  def init
40
64
  Config::YAML.create
41
65
  Gitignore.update
@@ -47,6 +71,8 @@ module Matrixeval
47
71
  GemfileLocks.create
48
72
  Gitignore.update
49
73
 
74
+ pull_all_images
75
+
50
76
  if workers_count == 1
51
77
  run_all_contexts_sequentially
52
78
  else
@@ -69,10 +95,10 @@ module Matrixeval
69
95
  end
70
96
 
71
97
  def run_all_contexts_in_parallel
72
- parallel do |contexts|
98
+ parallel(contexts) do |sub_contexts|
73
99
  Thread.current[:matrixeval_results] = []
74
100
 
75
- contexts.each do |context|
101
+ sub_contexts.each do |context|
76
102
  docker_compose = DockerCompose.new(context)
77
103
  success = docker_compose.run(command.rest_arguments)
78
104
 
@@ -98,12 +124,25 @@ module Matrixeval
98
124
  docker_compose.run(command.rest_arguments)
99
125
  end
100
126
 
127
+ def pull_all_images
128
+ parallel(Config.main_vector_variants) do |sub_variants|
129
+ sub_variants.each do |variant|
130
+ puts "Docker image check/pull #{variant.container.image}"
131
+ image_exists = system %Q{[ -n "$(docker images -q #{variant.container.image})" ]}
132
+ next if image_exists
133
+
134
+ system "docker pull #{variant.container.image}"
135
+ end
136
+ end
137
+ end
138
+
101
139
  def report
102
140
  turn_on_stty_opost
103
141
 
104
142
  table = Terminal::Table.new(title: Rainbow("MatrixEval").blue.bright + " Summary", alignment: :center) do |table|
105
143
 
106
- table.add_row(Config.vectors.map(&:key) + ['result'])
144
+ headers = Config.vectors.map(&:key) + ['result']
145
+ table.add_row headers.map { |value| { value: value, alignment: :center } }
107
146
  table.add_separator
108
147
 
109
148
  matrixeval_results.each do |context, success|
@@ -120,32 +159,30 @@ module Matrixeval
120
159
  puts table
121
160
  end
122
161
 
123
- def parallel
124
- contexts = Context.all
162
+ def parallel(collection)
163
+ threads = [] unless threads.empty?
164
+ matrixeval_results = [] unless matrixeval_results.empty?
125
165
 
126
- contexts.each_slice(contexts.count / workers_count) do |sub_contexts|
166
+ collection.each_slice(per_worker_contexts_count) do |sub_collection|
127
167
  threads << Thread.new do
128
- yield sub_contexts
168
+ yield sub_collection
129
169
  end
130
170
  end
131
171
 
132
172
  threads.each(&:join)
133
173
 
134
174
  threads.each do |thread|
135
- self.matrixeval_results += thread[:matrixeval_results]
175
+ self.matrixeval_results += (thread[:matrixeval_results] || [])
136
176
  end
137
177
  end
138
178
 
139
- def threads
140
- @threads ||= []
141
- end
142
179
 
143
- def matrixeval_results
144
- @matrixeval_results ||= []
180
+ def per_worker_contexts_count
181
+ [(contexts.count / workers_count), 1].max
145
182
  end
146
183
 
147
- def matrixeval_results=(results)
148
- @matrixeval_results = results
184
+ def contexts
185
+ @contexts ||= Context.all
149
186
  end
150
187
 
151
188
  def workers_count
@@ -1,13 +1,52 @@
1
- version: 0.1
1
+ version: 0.2
2
2
  target: ruby
3
3
  parallel_workers: number_of_processors
4
+ # commands:
5
+ # - ps
6
+ # - top
7
+ # - an_additional_command
4
8
  matrix:
5
9
  ruby:
10
+ # mounts:
11
+ # - /a/path/need/to/mount:/a/path/mount/to
6
12
  variants:
7
13
  - key: 2.7
8
- image: ruby:2.7.1
14
+ container:
15
+ image: ruby:2.7.1
9
16
  - key: 3.0
10
- image: ruby:3.0.0
11
17
  default: true
18
+ container:
19
+ image: ruby:3.0.0
12
20
  - key: 3.1
13
- image: ruby:3.1.0
21
+ container:
22
+ image: ruby:3.1.0
23
+ # - key: jruby-9.3
24
+ # container:
25
+ # image: jruby:9.3
26
+ # env:
27
+ # PATH: "/opt/jruby/bin:/app/bin:/bundle/bin:$PATH"
28
+
29
+ # rails:
30
+ # variants:
31
+ # - key: 6.1
32
+ # default: true
33
+ # env:
34
+ # RAILS_VERSION: "~> 6.1.0"
35
+ # - key: 7.0
36
+ # env:
37
+ # RAILS_VERSION: "~> 7.0.0"
38
+ # another:
39
+ # variants:
40
+ # - key: key1
41
+ # default: true
42
+ # env:
43
+ # ENV_KEY: 1
44
+ # - key: key2
45
+ # env:
46
+ # ENV_KEY: 2
47
+
48
+ exclude:
49
+ # - ruby: 3.0
50
+ # rails: 4.2
51
+ # - ruby: jruby-9.3
52
+ # rails: 7.0
@@ -1,3 +1,5 @@
1
+ require_relative "./container"
2
+
1
3
  module Matrixeval
2
4
  module Ruby
3
5
  class Variant
@@ -7,14 +9,14 @@ module Matrixeval
7
9
  end
8
10
  end
9
11
 
10
- attr_reader :key, :image, :env, :vector, :default
12
+ attr_reader :key, :env, :vector, :default, :container
11
13
 
12
14
  def initialize(config = {}, vector)
13
15
  raise Error.new("Variant#key is missing") if config["key"].nil?
14
16
 
15
17
  @vector = vector
16
18
  @key = config["key"].to_s
17
- @image = config["image"]
19
+ @container = Container.new(config["container"])
18
20
  @env = config["env"] || {}
19
21
  @default = config["default"] || false
20
22
  end
@@ -24,7 +26,7 @@ module Matrixeval
24
26
  end
25
27
 
26
28
  def bundle_volume_name
27
- "bundle_#{image.gsub(/[^A-Za-z0-9]/,'_')}"
29
+ "bundle_#{container.image.gsub(/[^A-Za-z0-9]/,'_')}"
28
30
  end
29
31
 
30
32
  def id
@@ -30,7 +30,7 @@ module Matrixeval
30
30
  def default_variant
31
31
  variant = variants.find(&:default?)
32
32
  if variant.nil?
33
- raise Error.new("Please set a default variant for matrix #{vector.key}")
33
+ raise Error.new("Please set a default variant for matrix #{key}")
34
34
  end
35
35
 
36
36
  variant
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Matrixeval
4
4
  module Ruby
5
- VERSION = "0.1.1"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: matrixeval-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hopper Gee
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-02-09 00:00:00.000000000 Z
11
+ date: 2022-02-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rainbow
@@ -78,6 +78,7 @@ files:
78
78
  - lib/matrixeval/ruby/command_line/parse_context_arguments.rb
79
79
  - lib/matrixeval/ruby/config.rb
80
80
  - lib/matrixeval/ruby/config/yaml.rb
81
+ - lib/matrixeval/ruby/container.rb
81
82
  - lib/matrixeval/ruby/context.rb
82
83
  - lib/matrixeval/ruby/context/find_by_command_options.rb
83
84
  - lib/matrixeval/ruby/docker_compose.rb