semaphore_test_boosters 0.2.0 → 0.3.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
  SHA1:
3
- metadata.gz: 850317895762d06c3ef3617213efd1dac7974784
4
- data.tar.gz: 1a03f9570cbe6fdc73c46131f380eb8a694ad172
3
+ metadata.gz: de95c3faf8fec6fe5d037d492da9433df3028fa2
4
+ data.tar.gz: adbee1c687caf014f5145248b6994001365aa61c
5
5
  SHA512:
6
- metadata.gz: 88f2e599a93f15e0e56c2d0d29cdd0b845f8cea2751c334649580d76ea1e567767b4aa920230111345247163e45a9b9f827b55dae51e0689d3bab9c16698c97e
7
- data.tar.gz: e533bb7990e3ad15e5b53fce537d0c8c855762703e4b0358a82b8693f4f6f18037b2146610a2a7ac92f363658683c1401e995cd18bf9aae21206c5deafeeac88
6
+ metadata.gz: e3f19dac14a29900d51795f3ed105d70df9f09e4b983b6b78e395bae78d3e18af953b9005a7aa649764be2ad247390dea88d57d6da46a08f8566fe1b4393cc3c
7
+ data.tar.gz: 7e70e1209987c81c4a92c5d102ad82966e8fc634985f48f81c04da28938f69ac6f0dcf5dedc8e642c14aa02eb7d7c3c4279ad721d3bbe2625a8a0e7c3d55be1d
@@ -0,0 +1,15 @@
1
+ module Semaphore
2
+ require "optparse"
3
+
4
+ def self.parse
5
+ options = {}
6
+
7
+ parser = OptionParser.new do |opts|
8
+ opts.on("--thread INDEX") { |index| options[:index] = index.to_i }
9
+ end
10
+
11
+ parser.parse!
12
+
13
+ options
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Semaphore
2
+ def self.display_files(title, files)
3
+ puts "#{title} #{files.count}\n"
4
+
5
+ files.each { |file| puts "- #{file}" }
6
+
7
+ puts "\n"
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Semaphore
2
+ def self.execute(command)
3
+ log("Running command: #{command}")
4
+ system(command)
5
+ log("Command finished, exit status : #{$?.exitstatus}")
6
+
7
+ exit($?.exitstatus)
8
+ end
9
+ end
@@ -0,0 +1,26 @@
1
+ module LeftoverSpecs
2
+ def self.select(all_leftover_specs, thread_count, thread_index)
3
+ all_leftover_specs = sort_by_size(all_leftover_specs)
4
+
5
+ return [] if all_leftover_specs.empty?
6
+
7
+ specs = all_leftover_specs
8
+ .each_slice(thread_count)
9
+ .reduce{|acc, slice| acc.map{|a| a}.zip(slice.reverse)}
10
+ .map{|f| if f.kind_of?(Array) then f.flatten else [f] end} [thread_index]
11
+
12
+ if specs.nil? then []
13
+ elsif specs.kind_of?(Array) then specs.compact
14
+ end
15
+ end
16
+
17
+ def self.sort_by_size(specs) # descending
18
+ specs
19
+ .map{|f| if File.file?(f) then f else nil end}
20
+ .compact
21
+ .map{|f| [f, File.size(f)]}
22
+ .sort_by{|a| a[1]}.map{|a| a[0]}.reverse
23
+ end
24
+
25
+
26
+ end
@@ -0,0 +1,7 @@
1
+ module Semaphore
2
+ def self.log(message)
3
+ error_log_path = ENV["ERROR_LOG_PATH"] || "#{ENV["HOME"]}/test_booster_error.log"
4
+
5
+ File.open(error_log_path, "a") { |f| f.write("#{message}\n") }
6
+ end
7
+ end
@@ -1,87 +1,73 @@
1
- #!/usr/bin/env ruby
1
+ module Semaphore
2
+ require "json"
3
+ require "test_boosters/cli_parser"
4
+ require "test_boosters/logger"
5
+ require "test_boosters/executor"
6
+ require "test_boosters/display_files"
7
+ require "test_boosters/leftover_specs"
8
+
9
+ class RspecBooster
10
+ Error = -1
11
+
12
+ def initialize(thread_index)
13
+ @thread_index = thread_index
14
+ @report_path = ENV["REPORT_PATH"] || "#{ENV["HOME"]}/rspec_report.json"
15
+ @spec_path = ENV["SPEC_PATH"] || "spec"
16
+ end
17
+
18
+ def run
19
+ specs_to_run = select
20
+
21
+ if specs_to_run == Error
22
+ if @thread_index == 0
23
+ Semaphore::execute("bundle exec rspec #{@spec_path}")
24
+ end
25
+ elsif specs_to_run.empty?
26
+ puts "No spec files in this thread!"
27
+ else
28
+ Semaphore::execute("bundle exec rspec #{specs_to_run.join(" ")}")
29
+ end
30
+ end
31
+
32
+ def select
33
+ with_fallback do
34
+ rspec_report = JSON.parse(File.read(@report_path))
35
+ thread_count = rspec_report.count
36
+ thread = rspec_report[@thread_index]
37
+
38
+ all_specs = Dir["#{@spec_path}/**/*_spec.rb"].sort
39
+ all_known_specs = rspec_report.map { |t| t["files"] }.flatten.sort
40
+
41
+ all_leftover_specs = all_specs - all_known_specs
42
+ thread_leftover_specs = LeftoverSpecs.select(all_leftover_specs, thread_count, @thread_index)
43
+ thread_specs = all_specs & thread["files"].sort
44
+ specs_to_run = thread_specs + thread_leftover_specs
45
+
46
+ Semaphore::display_files("This thread specs:", thread_specs)
47
+ Semaphore::display_files("This thread leftover specs:", thread_leftover_specs)
48
+ Semaphore::display_files("All leftover specs:", all_leftover_specs)
49
+
50
+ specs_to_run
51
+ end
52
+ end
53
+
54
+
55
+ def with_fallback
56
+ yield
57
+ rescue StandardError => e
58
+ error = %{
59
+ WARNING: An error detected while parsing the test boosters report file.
60
+ WARNING: All tests will be executed on the first thread.
61
+ }
62
+
63
+ puts error
64
+
65
+ error += %{Exception: #{e.message}}
66
+
67
+ Semaphore::log(error)
68
+
69
+ Error
70
+ end
2
71
 
3
- require "optparse"
4
- require "json"
5
-
6
- def log(message)
7
- error_log_path = ENV["ERROR_LOG_PATH"] || "#{ENV["HOME"]}/test_booster_error.log"
8
-
9
- File.open(error_log_path, "a") { |f| f.write("#{message}\n") }
10
- end
11
-
12
- def display_files(title, files)
13
- puts "#{title} #{files.count}\n"
14
-
15
- files.each { |file| puts "- #{file}" }
16
-
17
- puts "\n"
18
- end
19
-
20
- def execute(command)
21
- log("Running command: #{command}")
22
- system(command)
23
- log("Command finished, exit status : #{$?.exitstatus}")
24
-
25
- exit($?.exitstatus)
26
- end
27
-
28
- def parse_cli_options
29
- options = {}
30
-
31
- parser = OptionParser.new do |opts|
32
- opts.on("--thread INDEX") { |index| options[:index] = index.to_i }
33
- end
34
-
35
- parser.parse!
36
-
37
- options
38
- end
39
-
40
- def with_fallback
41
- yield
42
- rescue StandardError => e
43
- error = %{
44
- WARNING: An error detected while parsing the test boosters report file.
45
- WARNING: All tests will be executed on the first thread.
46
- }
47
-
48
- puts error
49
-
50
- error += %{
51
- Exception:
52
- #{e.message}
53
- }
54
-
55
- log(error)
56
-
57
- execute("bundle exec rspec") if $cli_options[:index] == 1
58
- end
59
-
60
- $cli_options = parse_cli_options
61
-
62
- report_path = ENV["REPORT_PATH"] || "#{ENV["HOME"]}/rspec_report.json"
63
- spec_path = ENV["SPEC_PATH"] || "spec"
64
-
65
- with_fallback do
66
- rspec_report = JSON.parse(File.read(report_path))
67
-
68
- thread = rspec_report[$cli_options[:index] - 1]
69
-
70
- all_specs = Dir["#{spec_path}/**/*_spec.rb"].sort
71
- all_known_specs = rspec_report.map { |t| t["files"] }.flatten.sort
72
-
73
- leftover_specs = all_specs - all_known_specs
74
- thread_specs = all_specs & thread["files"].sort
75
- specs_to_run = thread_specs + (thread["run_leftover_files"] ? leftover_specs : [])
76
-
77
- display_files("Thread specs:", thread_specs)
78
-
79
- display_files("Leftover specs:", leftover_specs) if thread["run_leftover_files"]
80
-
81
- if specs_to_run.empty?
82
- puts "No spec files in this thread!"
83
- exit
84
72
  end
85
-
86
- execute("bundle exec rspec #{specs_to_run.join(" ")}")
87
73
  end
@@ -1,3 +1,3 @@
1
1
  module TestBoosters
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/test_boosters.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  require "test_boosters/version"
2
+ require "test_boosters/rspec_booster"
2
3
 
3
4
  module TestBoosters
4
5
  # Your code goes here...
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "test_boosters/rspec_booster"
4
+
5
+ cli_options = Semaphore::parse
6
+ thread_index = cli_options[:index] - 1
7
+ rspec_booster = Semaphore::RspecBooster.new(thread_index)
8
+ rspec_booster.run
@@ -6,8 +6,8 @@ require 'test_boosters/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "semaphore_test_boosters"
8
8
  spec.version = TestBoosters::VERSION
9
- spec.authors = ["Predrag Rakic"]
10
- spec.email = ["prakic@renderedtext.com"]
9
+ spec.authors = ["MAINTAINER Rendered Text"]
10
+ spec.email = ["devops@renderedtext.com"]
11
11
 
12
12
  spec.summary = %q{Semaphore job parallelization.}
13
13
  spec.description = %q{Gem for auto-parallelizing builds across Semaphore jobs.}
@@ -0,0 +1 @@
1
+ 12345678901234567890
@@ -0,0 +1 @@
1
+ 123
@@ -0,0 +1 @@
1
+ 123456789
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semaphore_test_boosters
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
- - Predrag Rakic
7
+ - MAINTAINER Rendered Text
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-02-14 00:00:00.000000000 Z
11
+ date: 2017-02-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -54,7 +54,7 @@ dependencies:
54
54
  version: '3.0'
55
55
  description: Gem for auto-parallelizing builds across Semaphore jobs.
56
56
  email:
57
- - prakic@renderedtext.com
57
+ - devops@renderedtext.com
58
58
  executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
@@ -69,9 +69,18 @@ files:
69
69
  - bin/console
70
70
  - bin/setup
71
71
  - lib/test_boosters.rb
72
+ - lib/test_boosters/cli_parser.rb
73
+ - lib/test_boosters/display_files.rb
74
+ - lib/test_boosters/executor.rb
75
+ - lib/test_boosters/leftover_specs.rb
76
+ - lib/test_boosters/logger.rb
72
77
  - lib/test_boosters/rspec_booster.rb
73
78
  - lib/test_boosters/version.rb
79
+ - script/rspec_booster
74
80
  - test_boosters.gemspec
81
+ - test_data/a_spec.rb
82
+ - test_data/b_spec.rb
83
+ - test_data/c_spec.rb
75
84
  homepage: https://github.com/renderedtext/test-boosters
76
85
  licenses:
77
86
  - MIT