treye-semaphore_test_boosters 2.5.1
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 +7 -0
- data/.gitignore +14 -0
- data/.rspec +2 -0
- data/.rubocop.yml +105 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +226 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config.reek +16 -0
- data/exe/cucumber_booster +5 -0
- data/exe/ex_unit_booster +5 -0
- data/exe/go_test_booster +5 -0
- data/exe/minitest_booster +5 -0
- data/exe/rspec_booster +5 -0
- data/lib/test_boosters.rb +28 -0
- data/lib/test_boosters/boosters/base.rb +81 -0
- data/lib/test_boosters/boosters/cucumber.rb +37 -0
- data/lib/test_boosters/boosters/ex_unit.rb +17 -0
- data/lib/test_boosters/boosters/go_test.rb +17 -0
- data/lib/test_boosters/boosters/minitest.rb +21 -0
- data/lib/test_boosters/boosters/rspec.rb +49 -0
- data/lib/test_boosters/cli_parser.rb +49 -0
- data/lib/test_boosters/files/distributor.rb +45 -0
- data/lib/test_boosters/files/leftover_files.rb +42 -0
- data/lib/test_boosters/files/split_configuration.rb +68 -0
- data/lib/test_boosters/insights_uploader.rb +24 -0
- data/lib/test_boosters/job.rb +40 -0
- data/lib/test_boosters/logger.rb +19 -0
- data/lib/test_boosters/project_info.rb +32 -0
- data/lib/test_boosters/shell.rb +51 -0
- data/lib/test_boosters/version.rb +3 -0
- data/rspec_formatters/semaphore_rspec3_json_formatter.rb +55 -0
- data/test_boosters.gemspec +32 -0
- metadata +195 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
module TestBoosters
|
2
|
+
module InsightsUploader
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def upload(booster_type, file)
|
6
|
+
return unless File.exist?(file)
|
7
|
+
|
8
|
+
cmd = "http POST '#{insights_url}' #{booster_type}:=@#{file}"
|
9
|
+
|
10
|
+
TestBoosters::Shell.execute("#{cmd} > ~/insights_uploader.log", :silent => true)
|
11
|
+
end
|
12
|
+
|
13
|
+
def insights_url
|
14
|
+
params = {
|
15
|
+
:project_hash_id => ENV["SEMAPHORE_PROJECT_UUID"],
|
16
|
+
:build_hash_id => ENV["SEMAPHORE_EXECUTABLE_UUID"],
|
17
|
+
:job_hash_id => ENV["SEMAPHORE_JOB_UUID"]
|
18
|
+
}
|
19
|
+
|
20
|
+
"https://insights-receiver.semaphoreci.com/job_reports?#{::URI.encode_www_form(params)}"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module TestBoosters
|
2
|
+
class Job
|
3
|
+
|
4
|
+
def self.run(command, known_files, leftover_files)
|
5
|
+
new(command, known_files, leftover_files).run
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(command, known_files, leftover_files)
|
9
|
+
@command = command
|
10
|
+
@known_files = known_files
|
11
|
+
@leftover_files = leftover_files
|
12
|
+
end
|
13
|
+
|
14
|
+
def display_header
|
15
|
+
puts
|
16
|
+
TestBoosters::Shell.display_files("Known files for this job", @known_files)
|
17
|
+
TestBoosters::Shell.display_files("Leftover files for this job", @leftover_files)
|
18
|
+
|
19
|
+
puts "=" * 80
|
20
|
+
puts ""
|
21
|
+
end
|
22
|
+
|
23
|
+
def files
|
24
|
+
@all_files ||= @known_files + @leftover_files
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
display_header
|
29
|
+
|
30
|
+
if files.empty?
|
31
|
+
puts("No files to run in this job!")
|
32
|
+
|
33
|
+
return 0
|
34
|
+
end
|
35
|
+
|
36
|
+
TestBoosters::Shell.execute("#{@command} #{files.join(" ")}")
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module TestBoosters
|
2
|
+
module Logger
|
3
|
+
module_function
|
4
|
+
|
5
|
+
# TODO: why are we logging info messages into the error log?
|
6
|
+
def info(message)
|
7
|
+
error_log_path = ENV["ERROR_LOG_PATH"] || "#{ENV["HOME"]}/test_booster_error.log"
|
8
|
+
|
9
|
+
File.open(error_log_path, "a") { |file| file.write("#{message}\n") }
|
10
|
+
end
|
11
|
+
|
12
|
+
def error(message)
|
13
|
+
error_log_path = ENV["ERROR_LOG_PATH"] || "#{ENV["HOME"]}/test_booster_error.log"
|
14
|
+
|
15
|
+
File.open(error_log_path, "a") { |file| file.write("#{message}\n") }
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module TestBoosters
|
2
|
+
module ProjectInfo
|
3
|
+
module_function
|
4
|
+
|
5
|
+
def display_ruby_version
|
6
|
+
version = TestBoosters::Shell.evaluate("ruby --version").gsub("ruby ", "")
|
7
|
+
|
8
|
+
puts "Ruby Version: #{version}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def display_bundler_version
|
12
|
+
version = TestBoosters::Shell.evaluate("bundle --version").gsub("Bundler version ", "")
|
13
|
+
|
14
|
+
puts "Bundler Version: #{version}"
|
15
|
+
end
|
16
|
+
|
17
|
+
def display_rspec_version
|
18
|
+
command = "(bundle list | grep -q '* rspec') && (bundle exec rspec --version | head -1) || echo 'not found'"
|
19
|
+
version = TestBoosters::Shell.evaluate(command)
|
20
|
+
|
21
|
+
puts "RSpec Version: #{version}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def display_cucumber_version
|
25
|
+
command = "(bundle list | grep -q '* cucumber') && (bundle exec cucumber --version | head -1) || echo 'not found'"
|
26
|
+
version = TestBoosters::Shell.evaluate(command)
|
27
|
+
|
28
|
+
puts "Cucumber Version: #{version}"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module TestBoosters
|
2
|
+
module Shell
|
3
|
+
module_function
|
4
|
+
|
5
|
+
# :reek:TooManyStatements
|
6
|
+
def execute(command, options = {})
|
7
|
+
TestBoosters::Logger.info("Running command: #{command}")
|
8
|
+
|
9
|
+
puts command unless options[:silent] == true
|
10
|
+
|
11
|
+
with_clean_env do
|
12
|
+
system(command)
|
13
|
+
end
|
14
|
+
|
15
|
+
signaled = $?.signaled?
|
16
|
+
termsig = $?.termsig
|
17
|
+
exited = $?.exited?
|
18
|
+
exit_status = $?.exitstatus
|
19
|
+
|
20
|
+
TestBoosters::Logger.info("Command signaled with: #{termsig}") if signaled
|
21
|
+
TestBoosters::Logger.info("Command exited : #{exited}")
|
22
|
+
TestBoosters::Logger.info("Command finished, exit status : #{exit_status}")
|
23
|
+
|
24
|
+
exit_status
|
25
|
+
end
|
26
|
+
|
27
|
+
def evaluate(command)
|
28
|
+
with_clean_env { `#{command}` }
|
29
|
+
end
|
30
|
+
|
31
|
+
def with_clean_env
|
32
|
+
defined?(Bundler) ? Bundler.with_clean_env { yield } : yield
|
33
|
+
end
|
34
|
+
|
35
|
+
def display_title(title)
|
36
|
+
puts
|
37
|
+
puts "=== #{title} ===="
|
38
|
+
puts
|
39
|
+
end
|
40
|
+
|
41
|
+
def display_files(title, files)
|
42
|
+
puts "#{title} (#{files.count} files):"
|
43
|
+
puts
|
44
|
+
|
45
|
+
files.each { |file| puts "- #{file}" }
|
46
|
+
|
47
|
+
puts "\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
RSpec::Support.require_rspec_core "formatters/base_formatter"
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
class SemaphoreFormatter < RSpec::Core::Formatters::BaseFormatter
|
5
|
+
RSpec::Core::Formatters.register self, :stop, :close
|
6
|
+
|
7
|
+
attr_reader :output_hash
|
8
|
+
|
9
|
+
def initialize(output)
|
10
|
+
super
|
11
|
+
@output_hash = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def stop(notification)
|
15
|
+
@output_hash[:examples] = notification.examples.map { |example| format_example(example) }
|
16
|
+
end
|
17
|
+
|
18
|
+
def close(_notification)
|
19
|
+
output.write @output_hash.to_json
|
20
|
+
output.close if IO === output && output != $stdout
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def format_example(example)
|
26
|
+
result = example.execution_result
|
27
|
+
|
28
|
+
{
|
29
|
+
:description => example.description,
|
30
|
+
:full_description => example.full_description,
|
31
|
+
:status => result.status,
|
32
|
+
:file_path => file_path(example),
|
33
|
+
:run_time => result.run_time
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def file_path(example)
|
38
|
+
# For shared examples 'example.file_path' returns the path of the shared example file.
|
39
|
+
# This is not optinal for our use case because we can't estimate the duration of the
|
40
|
+
# original spec file.
|
41
|
+
#
|
42
|
+
# To resolve this, we use `example.metadata[:example_group]` that contains the correct
|
43
|
+
# file path for both shared examples and regular tests
|
44
|
+
|
45
|
+
find_example_group_root_path(example.metadata[:example_group])
|
46
|
+
end
|
47
|
+
|
48
|
+
def find_example_group_root_path(example_group)
|
49
|
+
if example_group.has_key?(:parent_example_group)
|
50
|
+
find_example_group_root_path(example_group[:parent_example_group])
|
51
|
+
else
|
52
|
+
example_group[:file_path]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "test_boosters/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "treye-semaphore_test_boosters"
|
8
|
+
spec.version = TestBoosters::VERSION
|
9
|
+
spec.authors = ["Developers at Rendered Text"]
|
10
|
+
spec.email = ["devops@renderedtext.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Semaphore job parallelization.}
|
13
|
+
spec.description = %q{Gem for auto-parallelizing builds across Semaphore jobs.}
|
14
|
+
spec.homepage = "https://github.com/treye/test-boosters"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_dependency "treye-semaphore_cucumber_booster_config", "1.4.2"
|
23
|
+
|
24
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rspec", "~> 3.5"
|
26
|
+
spec.add_development_dependency "activesupport", "~> 4.0"
|
27
|
+
|
28
|
+
spec.add_development_dependency "rubocop", "~> 0.49.0"
|
29
|
+
spec.add_development_dependency "rubocop-rspec", "~> 1.13.0"
|
30
|
+
spec.add_development_dependency "reek", "4.5.6"
|
31
|
+
spec.add_development_dependency "simplecov", "~> 0.13"
|
32
|
+
end
|
metadata
ADDED
@@ -0,0 +1,195 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: treye-semaphore_test_boosters
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 2.5.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Developers at Rendered Text
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-04-09 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: treye-semaphore_cucumber_booster_config
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.4.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.4.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.5'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.5'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '4.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 0.49.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 0.49.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop-rspec
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.13.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.13.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: reek
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 4.5.6
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 4.5.6
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: simplecov
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.13'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.13'
|
125
|
+
description: Gem for auto-parallelizing builds across Semaphore jobs.
|
126
|
+
email:
|
127
|
+
- devops@renderedtext.com
|
128
|
+
executables:
|
129
|
+
- cucumber_booster
|
130
|
+
- ex_unit_booster
|
131
|
+
- go_test_booster
|
132
|
+
- minitest_booster
|
133
|
+
- rspec_booster
|
134
|
+
extensions: []
|
135
|
+
extra_rdoc_files: []
|
136
|
+
files:
|
137
|
+
- ".gitignore"
|
138
|
+
- ".rspec"
|
139
|
+
- ".rubocop.yml"
|
140
|
+
- Gemfile
|
141
|
+
- LICENSE.txt
|
142
|
+
- README.md
|
143
|
+
- Rakefile
|
144
|
+
- bin/console
|
145
|
+
- bin/setup
|
146
|
+
- config.reek
|
147
|
+
- exe/cucumber_booster
|
148
|
+
- exe/ex_unit_booster
|
149
|
+
- exe/go_test_booster
|
150
|
+
- exe/minitest_booster
|
151
|
+
- exe/rspec_booster
|
152
|
+
- lib/test_boosters.rb
|
153
|
+
- lib/test_boosters/boosters/base.rb
|
154
|
+
- lib/test_boosters/boosters/cucumber.rb
|
155
|
+
- lib/test_boosters/boosters/ex_unit.rb
|
156
|
+
- lib/test_boosters/boosters/go_test.rb
|
157
|
+
- lib/test_boosters/boosters/minitest.rb
|
158
|
+
- lib/test_boosters/boosters/rspec.rb
|
159
|
+
- lib/test_boosters/cli_parser.rb
|
160
|
+
- lib/test_boosters/files/distributor.rb
|
161
|
+
- lib/test_boosters/files/leftover_files.rb
|
162
|
+
- lib/test_boosters/files/split_configuration.rb
|
163
|
+
- lib/test_boosters/insights_uploader.rb
|
164
|
+
- lib/test_boosters/job.rb
|
165
|
+
- lib/test_boosters/logger.rb
|
166
|
+
- lib/test_boosters/project_info.rb
|
167
|
+
- lib/test_boosters/shell.rb
|
168
|
+
- lib/test_boosters/version.rb
|
169
|
+
- rspec_formatters/semaphore_rspec3_json_formatter.rb
|
170
|
+
- test_boosters.gemspec
|
171
|
+
homepage: https://github.com/treye/test-boosters
|
172
|
+
licenses:
|
173
|
+
- MIT
|
174
|
+
metadata: {}
|
175
|
+
post_install_message:
|
176
|
+
rdoc_options: []
|
177
|
+
require_paths:
|
178
|
+
- lib
|
179
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: '0'
|
184
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
|
+
requirements:
|
186
|
+
- - ">="
|
187
|
+
- !ruby/object:Gem::Version
|
188
|
+
version: '0'
|
189
|
+
requirements: []
|
190
|
+
rubyforge_project:
|
191
|
+
rubygems_version: 2.4.5.1
|
192
|
+
signing_key:
|
193
|
+
specification_version: 4
|
194
|
+
summary: Semaphore job parallelization.
|
195
|
+
test_files: []
|