wwtd 0.2.1 → 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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/bin/wwtd +1 -1
- data/lib/wwtd.rb +22 -162
- data/lib/wwtd/cli.rb +73 -0
- data/lib/wwtd/colors.rb +25 -0
- data/lib/wwtd/ruby.rb +88 -0
- data/lib/wwtd/version.rb +1 -1
- metadata +5 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa67745551b56d3fb2c7fbf2e06fb3a253916877
|
4
|
+
data.tar.gz: 5e2fb3b4a30fab6c8e1c12ea35bb36eb4a64d058
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e5b6f48c94877458ff7bf8707ad0954eaf12d07a7e7a16e3309039effb34a5843afda6cbc1d7d91b4ad9666f6c04554a907b929a6857a7119e505aa458d3f718
|
7
|
+
data.tar.gz: 70871fa5a3d12a9d986461d0c82406f84d398a8d1b634a2233201b38067ff9fb83d8971bf91c15f6bac0576f8eb2467c5c3ab511d71519ea0b80efb5ffa2210e
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/bin/wwtd
CHANGED
data/lib/wwtd.rb
CHANGED
@@ -5,54 +5,50 @@ require "shellwords"
|
|
5
5
|
require "parallel"
|
6
6
|
require "tempfile"
|
7
7
|
require "tmpdir"
|
8
|
+
require "wwtd/colors"
|
9
|
+
require "wwtd/ruby"
|
10
|
+
require "wwtd/cli"
|
8
11
|
|
9
12
|
module WWTD
|
10
13
|
CONFIG = ".travis.yml"
|
11
14
|
DEFAULT_GEMFILE = "Gemfile"
|
12
15
|
COMBINATORS = ["rvm", "gemfile", "env"]
|
13
16
|
UNDERSTOOD = ["rvm", "gemfile", "matrix", "script", "bundler_args"]
|
14
|
-
INFO_MAX_CHARACTERS = 30
|
15
17
|
|
16
18
|
class << self
|
17
|
-
def
|
18
|
-
options = parse_options(argv)
|
19
|
-
|
20
|
-
# Read actual .travis.yml
|
19
|
+
def read_travis_yml
|
21
20
|
config = (File.exist?(CONFIG) ? YAML.load_file(CONFIG) : {})
|
22
21
|
config.delete("source_key") # we don't need that we already have the source
|
23
22
|
ignored = config.keys - UNDERSTOOD
|
24
|
-
|
23
|
+
[matrix(config), ignored]
|
24
|
+
end
|
25
|
+
|
26
|
+
def run(matrix, options, &block)
|
27
|
+
run_in_parallel(matrix, options) do |config, lock|
|
28
|
+
state = if Ruby.available?(config["rvm"])
|
29
|
+
yield(:start, config, matrix)
|
30
|
+
result = run_config(config, lock)
|
31
|
+
result ? :success : :failure
|
32
|
+
else
|
33
|
+
:missing
|
34
|
+
end
|
25
35
|
|
26
|
-
|
27
|
-
matrix = matrix(config)
|
28
|
-
results = run_full_matrix(matrix, options)
|
36
|
+
yield(state, config)
|
29
37
|
|
30
|
-
|
31
|
-
if matrix.size > 1
|
32
|
-
puts "\nResults:"
|
33
|
-
puts results.map(&:last)
|
38
|
+
[state, config]
|
34
39
|
end
|
35
|
-
|
36
|
-
results.all?(&:first) ? 0 : 1
|
37
40
|
end
|
38
41
|
|
39
42
|
private
|
40
43
|
|
41
|
-
def
|
44
|
+
def run_in_parallel(matrix, options)
|
42
45
|
results = nil
|
43
46
|
with_clean_dot_bundle do
|
44
47
|
Dir.mktmpdir do |lock| # does not return values in ruby 1.8
|
45
48
|
results = Parallel.map(matrix.each_with_index, :in_processes => options[:parallel].to_i) do |config, i|
|
49
|
+
# set env as parallel_tests does to reuse existing infrastructure
|
46
50
|
ENV["TEST_ENV_NUMBER"] = (i == 0 ? "" : (i + 1).to_s) if options[:parallel]
|
47
|
-
|
48
|
-
config_info = config_info(matrix, config)
|
49
|
-
puts "#{yellow("START")} #{config_info}"
|
50
|
-
|
51
|
-
result = run_config(config, lock)
|
52
|
-
info = "#{result ? green("SUCCESS") : red("FAILURE")} #{config_info}"
|
53
|
-
puts info
|
54
|
-
|
55
|
-
[result, info]
|
51
|
+
yield config, lock
|
56
52
|
end
|
57
53
|
end
|
58
54
|
end
|
@@ -72,35 +68,6 @@ module WWTD
|
|
72
68
|
end
|
73
69
|
end
|
74
70
|
|
75
|
-
def config_info(matrix, config)
|
76
|
-
config = config.select { |k,v| matrix.map { |c| c[k] }.uniq.size > 1 }.sort # find non-unique values aka interesting
|
77
|
-
maximum_value_lengths = Hash[config.map { |k,v| [k, matrix.map { |h| h[k].to_s.size }.max ] }] # find maximum value length for each key so we can align
|
78
|
-
config.map do |k, v|
|
79
|
-
value = truncate(v, INFO_MAX_CHARACTERS).ljust([INFO_MAX_CHARACTERS, maximum_value_lengths[k]].min)
|
80
|
-
"#{k}: #{value}"
|
81
|
-
end.join(" ") # truncate values that are too long
|
82
|
-
end
|
83
|
-
|
84
|
-
def tint(color, string)
|
85
|
-
if $stdout.tty?
|
86
|
-
"\e[#{color}m#{string}\e[0m"
|
87
|
-
else
|
88
|
-
string
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def red(string)
|
93
|
-
tint(31, string)
|
94
|
-
end
|
95
|
-
|
96
|
-
def green(string)
|
97
|
-
tint(32, string)
|
98
|
-
end
|
99
|
-
|
100
|
-
def yellow(string)
|
101
|
-
tint(33, string)
|
102
|
-
end
|
103
|
-
|
104
71
|
def matrix(config)
|
105
72
|
matrix = [{}]
|
106
73
|
COMBINATORS.each do |multiplier|
|
@@ -114,15 +81,6 @@ module WWTD
|
|
114
81
|
matrix.map! { |c| config.merge(c) }
|
115
82
|
end
|
116
83
|
|
117
|
-
def truncate(value, number)
|
118
|
-
value = value.to_s # accidental numbers like 'rvm: 2.0'
|
119
|
-
if value.size > number
|
120
|
-
"#{value[0...27]}..."
|
121
|
-
else
|
122
|
-
value
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
84
|
def run_config(config, lock)
|
127
85
|
with_clean_env do
|
128
86
|
Shellwords.split(config["env"] || "").each do |part|
|
@@ -135,7 +93,7 @@ module WWTD
|
|
135
93
|
end
|
136
94
|
wants_bundle = gemfile || File.exist?(DEFAULT_GEMFILE)
|
137
95
|
|
138
|
-
switch_ruby =
|
96
|
+
switch_ruby = Ruby.switch_statement(config["rvm"])
|
139
97
|
|
140
98
|
if wants_bundle
|
141
99
|
flock("#{lock}/#{config["rvm"] || "rvm"}") do
|
@@ -153,86 +111,6 @@ module WWTD
|
|
153
111
|
end
|
154
112
|
end
|
155
113
|
|
156
|
-
def switch_ruby(version)
|
157
|
-
return unless version
|
158
|
-
version = normalize_ruby_version(version)
|
159
|
-
if rvm_executable
|
160
|
-
"rvm #{version} do "
|
161
|
-
else
|
162
|
-
if ruby_root = ENV["RUBY_ROOT"] # chruby or RUBY_ROOT set
|
163
|
-
switch_path(File.dirname(ruby_root), version)
|
164
|
-
elsif rbenv_executable
|
165
|
-
rubies_root = cache_command("which rbenv").sub(%r{/(\.?rbenv)/.*}, "/\\1") + "/versions"
|
166
|
-
switch_path(rubies_root, version)
|
167
|
-
else
|
168
|
-
"false # could not find rvm, rbenv or RUBY_ROOT # "
|
169
|
-
end
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
def switch_path(rubies_root, version)
|
174
|
-
extract_jruby_rbenv_options!(version)
|
175
|
-
if ruby_root = ruby_root(rubies_root, version)
|
176
|
-
gem_home = Dir["#{ruby_root}/lib/ruby/gems/*"].first
|
177
|
-
ENV["PATH"] = "#{ruby_root}/bin:#{ENV["PATH"]}"
|
178
|
-
ENV["GEM_HOME"] = gem_home
|
179
|
-
""
|
180
|
-
else
|
181
|
-
"false # could not find #{version} in #{rubies_root} # "
|
182
|
-
end
|
183
|
-
end
|
184
|
-
|
185
|
-
def rvm_executable
|
186
|
-
cache_command("which rvm")
|
187
|
-
end
|
188
|
-
|
189
|
-
def rbenv_executable
|
190
|
-
cache_command("which rbenv")
|
191
|
-
end
|
192
|
-
|
193
|
-
def cache_command(command)
|
194
|
-
cache(command) do
|
195
|
-
if result = capture(command)
|
196
|
-
result.strip
|
197
|
-
end
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def ruby_root(root, version)
|
202
|
-
Dir.glob("#{root}/*").detect { |p| File.basename(p).start_with?(version) }
|
203
|
-
end
|
204
|
-
|
205
|
-
def cache(key)
|
206
|
-
@cache ||= {}
|
207
|
-
if @cache.key?(key)
|
208
|
-
@cache[key]
|
209
|
-
else
|
210
|
-
@cache[key] = yield
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
# set ruby-opts for jruby flavors
|
215
|
-
def extract_jruby_rbenv_options!(version)
|
216
|
-
if version.sub!("-d19", "")
|
217
|
-
ENV["JRUBY_OPTS"] = "--1.9"
|
218
|
-
elsif version.sub!("-d18", "")
|
219
|
-
ENV["JRUBY_OPTS"] = "--1.8"
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
def capture(command)
|
224
|
-
result = `#{command}`
|
225
|
-
$?.success? ? result : nil
|
226
|
-
end
|
227
|
-
|
228
|
-
# Taken from https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/script/rvm.rb
|
229
|
-
def normalize_ruby_version(rvm)
|
230
|
-
rvm.to_s.
|
231
|
-
gsub(/-(\d{2})mode$/, '-d\1').
|
232
|
-
gsub(/^rbx$/, 'rbx-weekly-d18').
|
233
|
-
gsub(/^rbx-d(\d{2})$/, 'rbx-weekly-d\1')
|
234
|
-
end
|
235
|
-
|
236
114
|
def committed?(file)
|
237
115
|
@committed_files ||= (File.exist?(".git") && `git ls-files`.split("\n")) || []
|
238
116
|
@committed_files.include?(file)
|
@@ -267,23 +145,5 @@ module WWTD
|
|
267
145
|
yield
|
268
146
|
end
|
269
147
|
end
|
270
|
-
|
271
|
-
def parse_options(argv)
|
272
|
-
options = {}
|
273
|
-
OptionParser.new do |opts|
|
274
|
-
opts.banner = <<-BANNER.gsub(/^ {10}/, "")
|
275
|
-
WWTD: Travis simulator - faster + no more waiting for build emails
|
276
|
-
|
277
|
-
Usage:
|
278
|
-
wwtd
|
279
|
-
|
280
|
-
Options:
|
281
|
-
BANNER
|
282
|
-
opts.on("-p", "--parallel [PROCESSES]", Integer, "Run in parallel") { |c| options[:parallel] = c || Parallel.processor_count }
|
283
|
-
opts.on("-h", "--help", "Show this.") { puts opts; exit }
|
284
|
-
opts.on("-v", "--version", "Show Version"){ puts WWTD::VERSION; exit}
|
285
|
-
end.parse!(argv)
|
286
|
-
options
|
287
|
-
end
|
288
148
|
end
|
289
149
|
end
|
data/lib/wwtd/cli.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module WWTD
|
2
|
+
module CLI
|
3
|
+
INFO_MAX_CHARACTERS = 30
|
4
|
+
COLOR_MAP = {:start => :yellow, :success => :green}
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def run(argv=[])
|
8
|
+
# Read travis.yml
|
9
|
+
matrix, ignored = ::WWTD.read_travis_yml
|
10
|
+
puts "Ignoring: #{ignored.sort.join(", ")}" unless ignored.empty?
|
11
|
+
|
12
|
+
# Execute tests
|
13
|
+
results = ::WWTD.run(matrix, parse_options(argv)) do |state, config|
|
14
|
+
puts info_line(state, config, matrix)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Summary
|
18
|
+
if results.size > 1
|
19
|
+
puts "\nResults:"
|
20
|
+
puts results.map { |state, config| info_line(state, config, matrix) }
|
21
|
+
end
|
22
|
+
|
23
|
+
results.all? { |state, config| state == :success } ? 0 : 1
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def info_line(state, config, matrix)
|
29
|
+
config_info = config_info(matrix, config)
|
30
|
+
color = COLOR_MAP[state] || :red
|
31
|
+
"#{Colors.send(color, state.to_s.upcase)} #{config_info}"
|
32
|
+
end
|
33
|
+
|
34
|
+
# human readable config without options that are the same in all configs
|
35
|
+
# {"a" => 1, "b" => 2} + {"a" => 2, "b" => 2} => {"a" => 1} + {"a" => 2}
|
36
|
+
def config_info(matrix, config)
|
37
|
+
config = config.select { |k,v| matrix.map { |c| c[k] }.uniq.size > 1 }.sort # find non-unique values aka interesting
|
38
|
+
maximum_value_lengths = Hash[config.map { |k,v| [k, matrix.map { |h| h[k].to_s.size }.max ] }] # find maximum value length for each key so we can align
|
39
|
+
config.map do |k, v|
|
40
|
+
value = truncate(v, INFO_MAX_CHARACTERS).ljust([INFO_MAX_CHARACTERS, maximum_value_lengths[k]].min)
|
41
|
+
"#{k}: #{value}"
|
42
|
+
end.join(" ") # truncate values that are too long
|
43
|
+
end
|
44
|
+
|
45
|
+
def truncate(value, number)
|
46
|
+
value = value.to_s # accidental numbers like 'rvm: 2.0'
|
47
|
+
if value.size > number
|
48
|
+
"#{value[0...27]}..."
|
49
|
+
else
|
50
|
+
value
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def parse_options(argv)
|
55
|
+
options = {}
|
56
|
+
OptionParser.new do |opts|
|
57
|
+
opts.banner = <<-BANNER.gsub(/^ {10}/, "")
|
58
|
+
WWTD: Travis simulator - faster + no more waiting for build emails
|
59
|
+
|
60
|
+
Usage:
|
61
|
+
wwtd
|
62
|
+
|
63
|
+
Options:
|
64
|
+
BANNER
|
65
|
+
opts.on("-p", "--parallel [PROCESSES]", Integer, "Run in parallel") { |c| options[:parallel] = c || Parallel.processor_count }
|
66
|
+
opts.on("-h", "--help", "Show this.") { puts opts; exit }
|
67
|
+
opts.on("-v", "--version", "Show Version"){ puts WWTD::VERSION; exit}
|
68
|
+
end.parse!(argv)
|
69
|
+
options
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/wwtd/colors.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module WWTD
|
2
|
+
module Colors
|
3
|
+
class << self
|
4
|
+
def tint(color, string)
|
5
|
+
if $stdout.tty?
|
6
|
+
"\e[#{color}m#{string}\e[0m"
|
7
|
+
else
|
8
|
+
string
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def red(string)
|
13
|
+
tint(31, string)
|
14
|
+
end
|
15
|
+
|
16
|
+
def green(string)
|
17
|
+
tint(32, string)
|
18
|
+
end
|
19
|
+
|
20
|
+
def yellow(string)
|
21
|
+
tint(33, string)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/wwtd/ruby.rb
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
module WWTD
|
2
|
+
module Ruby
|
3
|
+
class << self
|
4
|
+
def available?(version)
|
5
|
+
!version || switch_statement(version)
|
6
|
+
end
|
7
|
+
|
8
|
+
def switch_statement(version)
|
9
|
+
return unless version
|
10
|
+
version = normalize_ruby_version(version)
|
11
|
+
if rvm_executable
|
12
|
+
command = "rvm #{version} do "
|
13
|
+
command if cache_command("#{command} ruby -v")
|
14
|
+
else
|
15
|
+
if ruby_root = ENV["RUBY_ROOT"] # chruby or RUBY_ROOT set
|
16
|
+
switch_path(File.dirname(ruby_root), version)
|
17
|
+
elsif rbenv_executable
|
18
|
+
rubies_root = cache_command("which rbenv").sub(%r{/(\.?rbenv)/.*}, "/\\1") + "/versions"
|
19
|
+
switch_path(rubies_root, version)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def switch_path(rubies_root, version)
|
27
|
+
extract_jruby_rbenv_options!(version)
|
28
|
+
if ruby_root = ruby_root(rubies_root, version)
|
29
|
+
gem_home = Dir["#{ruby_root}/lib/ruby/gems/*"].first
|
30
|
+
ENV["PATH"] = "#{ruby_root}/bin:#{ENV["PATH"]}"
|
31
|
+
ENV["GEM_HOME"] = gem_home
|
32
|
+
""
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def rvm_executable
|
37
|
+
cache_command("which rvm")
|
38
|
+
end
|
39
|
+
|
40
|
+
def rbenv_executable
|
41
|
+
cache_command("which rbenv")
|
42
|
+
end
|
43
|
+
|
44
|
+
def cache_command(command)
|
45
|
+
cache(command) do
|
46
|
+
if result = capture(command)
|
47
|
+
result.strip
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def ruby_root(root, version)
|
53
|
+
Dir.glob("#{root}/*").detect { |p| File.basename(p).start_with?(version) }
|
54
|
+
end
|
55
|
+
|
56
|
+
def cache(key)
|
57
|
+
@cache ||= {}
|
58
|
+
if @cache.key?(key)
|
59
|
+
@cache[key]
|
60
|
+
else
|
61
|
+
@cache[key] = yield
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# set ruby-opts for jruby flavors
|
66
|
+
def extract_jruby_rbenv_options!(version)
|
67
|
+
if version.sub!("-d19", "")
|
68
|
+
ENV["JRUBY_OPTS"] = "--1.9"
|
69
|
+
elsif version.sub!("-d18", "")
|
70
|
+
ENV["JRUBY_OPTS"] = "--1.8"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def capture(command)
|
75
|
+
result = `#{command}`
|
76
|
+
$?.success? ? result : nil
|
77
|
+
end
|
78
|
+
|
79
|
+
# Taken from https://github.com/travis-ci/travis-build/blob/master/lib/travis/build/script/rvm.rb
|
80
|
+
def normalize_ruby_version(rvm)
|
81
|
+
rvm.to_s.
|
82
|
+
gsub(/-(\d{2})mode$/, '-d\1').
|
83
|
+
gsub(/^rbx$/, 'rbx-weekly-d18').
|
84
|
+
gsub(/^rbx-d(\d{2})$/, 'rbx-weekly-d\1')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/lib/wwtd/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wwtd
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
@@ -29,7 +29,7 @@ cert_chain:
|
|
29
29
|
y0kCSWmK6D+x/SbfS6r7Ke07MRqziJdB9GuE1+0cIRuFh8EQ+LN6HXCKM5pon/GU
|
30
30
|
ycwMXfl0
|
31
31
|
-----END CERTIFICATE-----
|
32
|
-
date: 2013-11-
|
32
|
+
date: 2013-11-20 00:00:00.000000000 Z
|
33
33
|
dependencies:
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
35
|
name: parallel
|
@@ -54,6 +54,9 @@ extra_rdoc_files: []
|
|
54
54
|
files:
|
55
55
|
- bin/wwtd
|
56
56
|
- lib/wwtd.rb
|
57
|
+
- lib/wwtd/cli.rb
|
58
|
+
- lib/wwtd/colors.rb
|
59
|
+
- lib/wwtd/ruby.rb
|
57
60
|
- lib/wwtd/tasks.rb
|
58
61
|
- lib/wwtd/version.rb
|
59
62
|
homepage: http://github.com/grosser/wwtd
|
metadata.gz.sig
CHANGED
Binary file
|