matrixeval-ruby 0.1.1 → 0.2.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 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