wwtd 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. data.tar.gz.sig +0 -0
  2. data/bin/wwtd +5 -0
  3. data/lib/wwtd.rb +186 -0
  4. data/lib/wwtd/version.rb +3 -0
  5. metadata +101 -0
  6. metadata.gz.sig +0 -0
Binary file
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH << File.expand_path("../../lib", __FILE__)
3
+ require "rubygems" if RUBY_VERSION < "1.9"
4
+ require "wwtd"
5
+ exit WWTD.run(ARGV)
@@ -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
@@ -0,0 +1,3 @@
1
+ module WWTD
2
+ VERSION = "0.1.2"
3
+ end
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
+
Binary file