wwtd 0.1.2
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.
- data.tar.gz.sig +0 -0
- data/bin/wwtd +5 -0
- data/lib/wwtd.rb +186 -0
- data/lib/wwtd/version.rb +3 -0
- metadata +101 -0
- metadata.gz.sig +0 -0
data.tar.gz.sig
ADDED
Binary file
|
data/bin/wwtd
ADDED
data/lib/wwtd.rb
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
require "wwtd/version"
|
2
|
+
require "optparse"
|
3
|
+
require "yaml"
|
4
|
+
require "shellwords"
|
5
|
+
require "parallel"
|
6
|
+
require "tempfile"
|
7
|
+
|
8
|
+
module WWTD
|
9
|
+
CONFIG = ".travis.yml"
|
10
|
+
DEFAULT_GEMFILE = "Gemfile"
|
11
|
+
COMBINATORS = ["rvm", "gemfile", "env"]
|
12
|
+
UNDERSTOOD = ["rvm", "gemfile", "matrix", "script", "bundler_args"]
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def run(argv)
|
16
|
+
options = parse_options(argv)
|
17
|
+
|
18
|
+
# Read actual .travis.yml
|
19
|
+
config = (File.exist?(CONFIG) ? YAML.load_file(CONFIG) : {})
|
20
|
+
config.delete("source_key") # we don't need that we already have the source
|
21
|
+
ignored = config.keys - UNDERSTOOD
|
22
|
+
puts "Ignoring: #{ignored.sort.join(", ")}" unless ignored.empty?
|
23
|
+
|
24
|
+
# Execute tests
|
25
|
+
matrix = matrix(config)
|
26
|
+
results = nil
|
27
|
+
Tempfile.open "wwtd" do |lock|
|
28
|
+
results = Parallel.map(matrix.each_with_index, :in_processes => options[:parallel].to_i) do |config, i|
|
29
|
+
ENV["TEST_ENV_NUMBER"] = (i == 0 ? "" : (i + 1).to_s) if options[:parallel]
|
30
|
+
|
31
|
+
config_info = config_info(matrix, config)
|
32
|
+
puts "#{yellow("START")} #{config_info}"
|
33
|
+
|
34
|
+
result = run_config(config, lock)
|
35
|
+
info = "#{result ? green("SUCCESS") : red("FAILURE")} #{config_info}"
|
36
|
+
puts info
|
37
|
+
|
38
|
+
[result, info]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Summary
|
43
|
+
if matrix.size > 1
|
44
|
+
puts "\nResults:"
|
45
|
+
puts results.map(&:last)
|
46
|
+
end
|
47
|
+
|
48
|
+
results.all?(&:first) ? 0 : 1
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def config_info(matrix, config)
|
54
|
+
config = config.select { |k,v| matrix.map { |c| c[k] }.uniq.size > 1 }.sort
|
55
|
+
"#{config.map { |k,v| "#{k}: #{truncate(v, 30)}" }.join(", ")}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def tint(color, string)
|
59
|
+
if $stdout.tty?
|
60
|
+
"\e[#{color}m#{string}\e[0m"
|
61
|
+
else
|
62
|
+
string
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def red(string)
|
67
|
+
tint(31, string)
|
68
|
+
end
|
69
|
+
|
70
|
+
def green(string)
|
71
|
+
tint(32, string)
|
72
|
+
end
|
73
|
+
|
74
|
+
def yellow(string)
|
75
|
+
tint(33, string)
|
76
|
+
end
|
77
|
+
|
78
|
+
def matrix(config)
|
79
|
+
components = COMBINATORS.map do |multiplier|
|
80
|
+
next unless values = config[multiplier]
|
81
|
+
Array(values).map { |v| {multiplier => v} }
|
82
|
+
end.compact
|
83
|
+
|
84
|
+
components = components.inject([{}]) { |all, v| all.product(v).map! { |values| merge_hashes(values) } }
|
85
|
+
if config["matrix"] && config["matrix"]["exclude"]
|
86
|
+
components -= config.delete("matrix").delete("exclude")
|
87
|
+
end
|
88
|
+
components.map! { |c| config.merge(c) }
|
89
|
+
end
|
90
|
+
|
91
|
+
def truncate(value, number)
|
92
|
+
value = value.to_s # accidental numbers like 'rvm: 2.0'
|
93
|
+
if value.size > number
|
94
|
+
"#{value[0...27]}..."
|
95
|
+
else
|
96
|
+
value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def clone(object)
|
101
|
+
Marshal.load(Marshal.dump(object))
|
102
|
+
end
|
103
|
+
|
104
|
+
def merge_hashes(array)
|
105
|
+
array.inject({}) { |all, v| all.merge!(v); all }
|
106
|
+
end
|
107
|
+
|
108
|
+
def run_config(config, lock)
|
109
|
+
if gemfile = config["gemfile"]
|
110
|
+
ENV["BUNDLE_GEMFILE"] = gemfile
|
111
|
+
end
|
112
|
+
wants_bundle = gemfile || File.exist?(DEFAULT_GEMFILE)
|
113
|
+
|
114
|
+
Shellwords.split(config["env"] || "").each do |part|
|
115
|
+
name, value = part.split("=", 2)
|
116
|
+
ENV[name] = value
|
117
|
+
end
|
118
|
+
|
119
|
+
with_clean_env do
|
120
|
+
rvm = "rvm #{config["rvm"]} do " if config["rvm"]
|
121
|
+
|
122
|
+
if wants_bundle
|
123
|
+
flock(lock) do
|
124
|
+
default_bundler_args = "--deployment" if File.exist?("#{gemfile || DEFAULT_GEMFILE}.lock")
|
125
|
+
bundle_command = "#{rvm}bundle install #{config["bundler_args"] || default_bundler_args}"
|
126
|
+
return false unless sh "#{bundle_command.strip} --quiet --path #{Dir.pwd}/vendor/bundle"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
default_command = (wants_bundle ? "bundle exec rake" : "rake")
|
131
|
+
command = config["script"] || default_command
|
132
|
+
command = "#{rvm}#{command}"
|
133
|
+
|
134
|
+
sh(command)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def flock(file)
|
139
|
+
File.open(file.path) do |f|
|
140
|
+
begin
|
141
|
+
f.flock(File::LOCK_EX)
|
142
|
+
yield
|
143
|
+
ensure
|
144
|
+
f.flock(File::LOCK_UN)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# http://grosser.it/2010/12/11/sh-without-rake/
|
150
|
+
def sh(cmd)
|
151
|
+
puts cmd
|
152
|
+
IO.popen(cmd) do |pipe|
|
153
|
+
while str = pipe.gets
|
154
|
+
puts str
|
155
|
+
end
|
156
|
+
end
|
157
|
+
$?.success?
|
158
|
+
end
|
159
|
+
|
160
|
+
def with_clean_env(&block)
|
161
|
+
if defined?(Bundler)
|
162
|
+
Bundler.with_clean_env(&block)
|
163
|
+
else
|
164
|
+
yield
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
def parse_options(argv)
|
169
|
+
options = {}
|
170
|
+
OptionParser.new do |opts|
|
171
|
+
opts.banner = <<-BANNER.gsub(/^ {10}/, "")
|
172
|
+
WWTD: Travis simulator - faster + no more waiting for build emails
|
173
|
+
|
174
|
+
Usage:
|
175
|
+
wwtd
|
176
|
+
|
177
|
+
Options:
|
178
|
+
BANNER
|
179
|
+
opts.on("-p", "--parallel [PROCESSES]", Integer, "Run in parallel") { |c| options[:parallel] = c || Parallel.processor_count }
|
180
|
+
opts.on("-h", "--help", "Show this.") { puts opts; exit }
|
181
|
+
opts.on("-v", "--version", "Show Version"){ puts WWTD::VERSION; exit}
|
182
|
+
end.parse!(argv)
|
183
|
+
options
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
data/lib/wwtd/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wwtd
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 31
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Michael Grosser
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain:
|
17
|
+
- |
|
18
|
+
-----BEGIN CERTIFICATE-----
|
19
|
+
MIIDMjCCAhqgAwIBAgIBADANBgkqhkiG9w0BAQUFADA/MRAwDgYDVQQDDAdtaWNo
|
20
|
+
YWVsMRcwFQYKCZImiZPyLGQBGRYHZ3Jvc3NlcjESMBAGCgmSJomT8ixkARkWAml0
|
21
|
+
MB4XDTEzMDIwMzE4MTMxMVoXDTE0MDIwMzE4MTMxMVowPzEQMA4GA1UEAwwHbWlj
|
22
|
+
aGFlbDEXMBUGCgmSJomT8ixkARkWB2dyb3NzZXIxEjAQBgoJkiaJk/IsZAEZFgJp
|
23
|
+
dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMorXo/hgbUq97+kII9H
|
24
|
+
MsQcLdC/7wQ1ZP2OshVHPkeP0qH8MBHGg6eYisOX2ubNagF9YTCZWnhrdKrwpLOO
|
25
|
+
cPLaZbjUjljJ3cQR3B8Yn1veV5IhG86QseTBjymzJWsLpqJ1UZGpfB9tXcsFtuxO
|
26
|
+
6vHvcIHdzvc/OUkICttLbH+1qb6rsHUceqh+JrH4GrsJ5H4hAfIdyS2XMK7YRKbh
|
27
|
+
h+IBu6dFWJJByzFsYmV1PDXln3UBmgAt65cmCu4qPfThioCGDzbSJrGDGLmw/pFX
|
28
|
+
FPpVCm1zgYSb1v6Qnf3cgXa2f2wYGm17+zAVyIDpwryFru9yF/jJxE38z/DRsd9R
|
29
|
+
/88CAwEAAaM5MDcwCQYDVR0TBAIwADAdBgNVHQ4EFgQUsiNnXHtKeMYYcr4yJVmQ
|
30
|
+
WONL+IwwCwYDVR0PBAQDAgSwMA0GCSqGSIb3DQEBBQUAA4IBAQAlyN7kKo/NQCQ0
|
31
|
+
AOzZLZ3WAePvStkCFIJ53tsv5Kyo4pMAllv+BgPzzBt7qi605mFSL6zBd9uLou+W
|
32
|
+
Co3s48p1dy7CjjAfVQdmVNHF3MwXtfC2OEyvSQPi4xKR8iba8wa3xp9LVo1PuLpw
|
33
|
+
/6DsrChWw74HfsJN6qJOK684hJeT8lBYAUfiC3wD0owoPSg+XtyAAddisR+KV5Y1
|
34
|
+
NmVHuLtQcNTZy+gRht3ahJRMuC6QyLmkTsf+6MaenwAMkAgHdswGsJztOnNnBa3F
|
35
|
+
y0kCSWmK6D+x/SbfS6r7Ke07MRqziJdB9GuE1+0cIRuFh8EQ+LN6HXCKM5pon/GU
|
36
|
+
ycwMXfl0
|
37
|
+
-----END CERTIFICATE-----
|
38
|
+
|
39
|
+
date: 2013-09-01 00:00:00 Z
|
40
|
+
dependencies:
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: parallel
|
43
|
+
prerelease: false
|
44
|
+
type: :runtime
|
45
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ">="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
hash: 3
|
51
|
+
segments:
|
52
|
+
- 0
|
53
|
+
version: "0"
|
54
|
+
version_requirements: *id001
|
55
|
+
description:
|
56
|
+
email: michael@grosser.it
|
57
|
+
executables:
|
58
|
+
- wwtd
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files: []
|
62
|
+
|
63
|
+
files:
|
64
|
+
- bin/wwtd
|
65
|
+
- lib/wwtd.rb
|
66
|
+
- lib/wwtd/version.rb
|
67
|
+
homepage: http://github.com/grosser/wwtd
|
68
|
+
licenses:
|
69
|
+
- MIT
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
hash: 3
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 3
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
requirements: []
|
94
|
+
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.8.25
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: Travis simulator so you do not need to wait for the build
|
100
|
+
test_files: []
|
101
|
+
|
metadata.gz.sig
ADDED
Binary file
|