semaphore_test_boosters 0.2.0 → 0.3.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/lib/test_boosters/cli_parser.rb +15 -0
- data/lib/test_boosters/display_files.rb +9 -0
- data/lib/test_boosters/executor.rb +9 -0
- data/lib/test_boosters/leftover_specs.rb +26 -0
- data/lib/test_boosters/logger.rb +7 -0
- data/lib/test_boosters/rspec_booster.rb +70 -84
- data/lib/test_boosters/version.rb +1 -1
- data/lib/test_boosters.rb +1 -0
- data/script/rspec_booster +8 -0
- data/test_boosters.gemspec +2 -2
- data/test_data/a_spec.rb +1 -0
- data/test_data/b_spec.rb +1 -0
- data/test_data/c_spec.rb +1 -0
- metadata +13 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: de95c3faf8fec6fe5d037d492da9433df3028fa2
|
4
|
+
data.tar.gz: adbee1c687caf014f5145248b6994001365aa61c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3f19dac14a29900d51795f3ed105d70df9f09e4b983b6b78e395bae78d3e18af953b9005a7aa649764be2ad247390dea88d57d6da46a08f8566fe1b4393cc3c
|
7
|
+
data.tar.gz: 7e70e1209987c81c4a92c5d102ad82966e8fc634985f48f81c04da28938f69ac6f0dcf5dedc8e642c14aa02eb7d7c3c4279ad721d3bbe2625a8a0e7c3d55be1d
|
@@ -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
|
@@ -1,87 +1,73 @@
|
|
1
|
-
|
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
|
data/lib/test_boosters.rb
CHANGED
data/test_boosters.gemspec
CHANGED
@@ -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 = ["
|
10
|
-
spec.email = ["
|
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.}
|
data/test_data/a_spec.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
12345678901234567890
|
data/test_data/b_spec.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
123
|
data/test_data/c_spec.rb
ADDED
@@ -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.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- MAINTAINER Rendered Text
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-02-
|
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
|
-
-
|
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
|