wwtd 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|