travis-ruby 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +58 -0
- data/LICENSE.txt +22 -0
- data/README.markdown +18 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/bin/travis-ruby +64 -0
- data/lib/em/stdout.rb +46 -0
- data/lib/resque/heartbeat.rb +47 -0
- data/lib/travis.rb +13 -0
- data/lib/travis/buildable.rb +112 -0
- data/lib/travis/buildable/config.rb +23 -0
- data/lib/travis/builder.rb +57 -0
- data/lib/travis/builder/base.rb +43 -0
- data/lib/travis/builder/pusher.rb +47 -0
- data/lib/travis/builder/rails.rb +44 -0
- data/lib/travis/builder/stdout.rb +16 -0
- data/lib/travis/config.rb +22 -0
- data/test/helper.rb +19 -0
- data/test/test_travis.rb +7 -0
- data/travis-ruby.gemspec +97 -0
- metadata +202 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "SystemTimer", :platforms => ['ruby_18']
|
4
|
+
gem "resque"
|
5
|
+
gem "resque-meta"
|
6
|
+
|
7
|
+
gem "yajl-ruby", "~> 0.7.6"
|
8
|
+
gem "em-pusher"
|
9
|
+
gem "em-http-request"
|
10
|
+
|
11
|
+
group :development do
|
12
|
+
gem "minitest", ">= 0"
|
13
|
+
gem "yard", "~> 0.6.0"
|
14
|
+
gem "bundler", "~> 1.0.0"
|
15
|
+
gem "jeweler", "~> 1.5.2"
|
16
|
+
gem "rcov", ">= 0"
|
17
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
SystemTimer (1.2.2)
|
5
|
+
addressable (2.2.4)
|
6
|
+
em-http-request (0.2.15)
|
7
|
+
addressable (>= 2.0.0)
|
8
|
+
eventmachine (>= 0.12.9)
|
9
|
+
em-pusher (0.1.0)
|
10
|
+
em-http-request (~> 0.2.10)
|
11
|
+
ruby-hmac (~> 0.4.0)
|
12
|
+
yajl-ruby (~> 0.7.6)
|
13
|
+
eventmachine (0.12.10)
|
14
|
+
git (1.2.5)
|
15
|
+
jeweler (1.5.2)
|
16
|
+
bundler (~> 1.0.0)
|
17
|
+
git (>= 1.2.5)
|
18
|
+
rake
|
19
|
+
json (1.4.6)
|
20
|
+
minitest (2.0.2)
|
21
|
+
rack (1.2.1)
|
22
|
+
rake (0.8.7)
|
23
|
+
rcov (0.9.9)
|
24
|
+
redis (2.1.1)
|
25
|
+
redis-namespace (0.10.0)
|
26
|
+
redis (< 3.0.0)
|
27
|
+
resque (1.13.0)
|
28
|
+
json (~> 1.4.6)
|
29
|
+
redis-namespace (>= 0.10.0)
|
30
|
+
sinatra (>= 0.9.2)
|
31
|
+
vegas (~> 0.1.2)
|
32
|
+
resque-meta (1.0.3)
|
33
|
+
resque (~> 1.8)
|
34
|
+
ruby-hmac (0.4.0)
|
35
|
+
sinatra (1.1.2)
|
36
|
+
rack (~> 1.1)
|
37
|
+
tilt (~> 1.2)
|
38
|
+
tilt (1.2.2)
|
39
|
+
vegas (0.1.8)
|
40
|
+
rack (>= 1.0.0)
|
41
|
+
yajl-ruby (0.7.9)
|
42
|
+
yard (0.6.4)
|
43
|
+
|
44
|
+
PLATFORMS
|
45
|
+
ruby
|
46
|
+
|
47
|
+
DEPENDENCIES
|
48
|
+
SystemTimer
|
49
|
+
bundler (~> 1.0.0)
|
50
|
+
em-http-request
|
51
|
+
em-pusher
|
52
|
+
jeweler (~> 1.5.2)
|
53
|
+
minitest
|
54
|
+
rcov
|
55
|
+
resque
|
56
|
+
resque-meta
|
57
|
+
yajl-ruby (~> 0.7.6)
|
58
|
+
yard (~> 0.6.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
MIT LICENSE
|
2
|
+
|
3
|
+
Copyright (c) 2010 Sven Fuchs <svenfuchs@artweb-design.de>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
22
|
+
|
data/README.markdown
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# travis-ruby
|
2
|
+
|
3
|
+
Description goes here.
|
4
|
+
|
5
|
+
## Contributing to travis-ruby
|
6
|
+
|
7
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
8
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
9
|
+
* Fork the project
|
10
|
+
* Start a feature/bugfix branch
|
11
|
+
* Commit and push until you are happy with your contribution
|
12
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
13
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
14
|
+
|
15
|
+
## Copyright
|
16
|
+
|
17
|
+
Copyright (c) 2011 Sven Fuchs. See LICENSE.txt for
|
18
|
+
further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'rake'
|
11
|
+
|
12
|
+
require 'jeweler'
|
13
|
+
Jeweler::Tasks.new do |gem|
|
14
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
15
|
+
gem.name = "travis-ruby"
|
16
|
+
gem.homepage = "http://github.com/bai/travis-ruby"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{Travis builder for ruby.}
|
19
|
+
gem.description = %Q{Travis builder for ruby.}
|
20
|
+
gem.email = "graf.otodrakula@gmail.com"
|
21
|
+
gem.authors = ["beawesomeinstead"]
|
22
|
+
end
|
23
|
+
Jeweler::RubygemsDotOrgTasks.new
|
24
|
+
|
25
|
+
require 'rake/testtask'
|
26
|
+
Rake::TestTask.new(:test) do |test|
|
27
|
+
test.libs << 'lib' << 'test'
|
28
|
+
test.pattern = 'test/**/test_*.rb'
|
29
|
+
test.verbose = true
|
30
|
+
end
|
31
|
+
|
32
|
+
require 'rcov/rcovtask'
|
33
|
+
Rcov::RcovTask.new do |test|
|
34
|
+
test.libs << 'test'
|
35
|
+
test.pattern = 'test/**/test_*.rb'
|
36
|
+
test.verbose = true
|
37
|
+
end
|
38
|
+
|
39
|
+
task :default => :test
|
40
|
+
|
41
|
+
require 'yard'
|
42
|
+
YARD::Rake::YardocTask.new
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/bin/travis-ruby
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
begin
|
5
|
+
require 'travis'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'travis'
|
9
|
+
end
|
10
|
+
require 'optparse'
|
11
|
+
|
12
|
+
parser = OptionParser.new do |opts|
|
13
|
+
opts.banner = "Usage: travis-ruby [options] COMMAND"
|
14
|
+
|
15
|
+
opts.separator ""
|
16
|
+
opts.separator "Options:"
|
17
|
+
|
18
|
+
opts.on("-v", "--verbose [VERBOSE]", "Run in verbose mode") do |host|
|
19
|
+
Resque.redis = host
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on("-q", "--queue [QUEUE]", "Name of the queue") do |host|
|
23
|
+
Resque.redis = host
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on("-h", "--help", "Show this message") do
|
27
|
+
puts opts
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
|
31
|
+
opts.separator ""
|
32
|
+
opts.separator "Commands:"
|
33
|
+
opts.separator " start Starts a worker"
|
34
|
+
opts.separator " stop WORKER Kills a worker"
|
35
|
+
end
|
36
|
+
|
37
|
+
def stop(worker)
|
38
|
+
abort "** travis-ruby kill WORKER_ID" if worker.nil?
|
39
|
+
pid = worker.split(':')[1].to_i
|
40
|
+
|
41
|
+
begin
|
42
|
+
Process.kill("KILL", pid)
|
43
|
+
puts "** killed #{worker}"
|
44
|
+
rescue Errno::ESRCH
|
45
|
+
puts "** worker #{worker} not running"
|
46
|
+
end
|
47
|
+
|
48
|
+
remove worker
|
49
|
+
end
|
50
|
+
|
51
|
+
def start
|
52
|
+
Travis::Builder.init
|
53
|
+
end
|
54
|
+
|
55
|
+
parser.parse!
|
56
|
+
|
57
|
+
case ARGV[0]
|
58
|
+
when 'start'
|
59
|
+
start
|
60
|
+
when 'stop'
|
61
|
+
stop ARGV[1]
|
62
|
+
else
|
63
|
+
puts parser.help
|
64
|
+
end
|
data/lib/em/stdout.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
|
3
|
+
module EventMachine
|
4
|
+
class << self
|
5
|
+
def split_stdout
|
6
|
+
stdout = nil
|
7
|
+
EM.next_tick do
|
8
|
+
stdout, read, write = STDOUT.clone, *IO.pipe
|
9
|
+
EM.attach(read, Stdout) do |connection|
|
10
|
+
connection.stdout = stdout
|
11
|
+
yield connection if block_given?
|
12
|
+
end
|
13
|
+
STDOUT.reopen(write)
|
14
|
+
end
|
15
|
+
sleep(0.01) until stdout
|
16
|
+
stdout
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Stdout < EventMachine::Connection
|
21
|
+
class << self
|
22
|
+
def output
|
23
|
+
defined?(@@output) ? @@output : @@output = true
|
24
|
+
end
|
25
|
+
|
26
|
+
def output=(output)
|
27
|
+
@@output = output
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_accessor :stdout
|
32
|
+
|
33
|
+
def callback(&block)
|
34
|
+
@callback = block
|
35
|
+
end
|
36
|
+
|
37
|
+
def receive_data(data)
|
38
|
+
stdout.print(data) if self.class.output
|
39
|
+
@callback.call(data) if @callback
|
40
|
+
end
|
41
|
+
|
42
|
+
def unbind
|
43
|
+
STDOUT.reopen(stdout)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'resque'
|
2
|
+
|
3
|
+
module Resque
|
4
|
+
def self.prune_dead_workers
|
5
|
+
Worker.all.each do |worker|
|
6
|
+
worker.unregister_worker if worker.last_heartbeat_before?(5)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Worker
|
11
|
+
def startup_with_heartbeat
|
12
|
+
startup_without_heartbeat
|
13
|
+
Thread.new do
|
14
|
+
loop do
|
15
|
+
sleep(2)
|
16
|
+
heartbeat!
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
alias startup_without_heartbeat startup
|
21
|
+
alias startup startup_with_heartbeat
|
22
|
+
|
23
|
+
# apparently the Redis connection is not thread-safe, so we connect another instance
|
24
|
+
# see https://github.com/ezmobius/redis-rb/issues#issue/75
|
25
|
+
def heartbeat_redis
|
26
|
+
@heartbeat_redis ||= begin
|
27
|
+
redis = Redis.connect(:url => Travis.config['redis']['url'])
|
28
|
+
Redis::Namespace.new(:resque, :redis => redis)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def heartbeat!
|
33
|
+
heartbeat_redis.sadd(:workers, self)
|
34
|
+
heartbeat_redis.set("worker:#{self}:heartbeat", Time.now.to_s)
|
35
|
+
rescue Exception => e
|
36
|
+
p e
|
37
|
+
end
|
38
|
+
|
39
|
+
def last_heartbeat_before?(seconds)
|
40
|
+
Time.parse(last_heartbeat).utc < (Time.now.utc - seconds)
|
41
|
+
end
|
42
|
+
|
43
|
+
def last_heartbeat
|
44
|
+
redis.get("worker:#{self}:heartbeat") || started
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/travis.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'uri'
|
3
|
+
require 'travis/buildable/config'
|
4
|
+
|
5
|
+
module Travis
|
6
|
+
class Buildable
|
7
|
+
autoload :Config, 'travis/buildable/config'
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def base_dir
|
11
|
+
@@base_dir ||= '/tmp/travis/builds'
|
12
|
+
end
|
13
|
+
|
14
|
+
def base_dir=(base_dir)
|
15
|
+
@@base_dir = base_dir
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :url, :path, :commit
|
20
|
+
|
21
|
+
def initialize(build)
|
22
|
+
@url = build[:url] || raise(ArgumentError.new('no url given'))
|
23
|
+
@commit = build[:commit]
|
24
|
+
@script = build[:script]
|
25
|
+
@path = extract_path(url)
|
26
|
+
end
|
27
|
+
|
28
|
+
def build!
|
29
|
+
Bundler.with_clean_env do
|
30
|
+
ENV['BUNDLE_GEMFILE'] = nil
|
31
|
+
chdir do
|
32
|
+
exists? ? fetch : clone
|
33
|
+
checkout
|
34
|
+
install
|
35
|
+
run_script
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
protected
|
41
|
+
def clone
|
42
|
+
execute "cd ..; git clone #{git_url}; cd -"
|
43
|
+
end
|
44
|
+
|
45
|
+
def fetch
|
46
|
+
execute 'git clean -fdx'
|
47
|
+
execute 'git fetch'
|
48
|
+
end
|
49
|
+
|
50
|
+
def checkout
|
51
|
+
execute "git checkout -qf #{commit}" if commit
|
52
|
+
end
|
53
|
+
|
54
|
+
def install
|
55
|
+
execute 'bundle install'
|
56
|
+
end
|
57
|
+
|
58
|
+
def run_script
|
59
|
+
execute(script).tap do |status|
|
60
|
+
puts "\nDone. Build script exited with: #{status}"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def script
|
65
|
+
config[:script] || @script
|
66
|
+
end
|
67
|
+
|
68
|
+
def config
|
69
|
+
@config ||= Config.new(config_url)
|
70
|
+
end
|
71
|
+
|
72
|
+
def chdir(&block)
|
73
|
+
FileUtils.mkdir_p(build_dir)
|
74
|
+
Dir.chdir(build_dir, &block)
|
75
|
+
end
|
76
|
+
|
77
|
+
def exists?
|
78
|
+
::File.exist?("#{build_dir}/.git")
|
79
|
+
end
|
80
|
+
|
81
|
+
def build_dir
|
82
|
+
@build_dir ||= begin
|
83
|
+
base = ::File.dirname(path).gsub(/\W/, '_').sub(/^_/, '')
|
84
|
+
base.gsub!('__', '_') while base.include?('__')
|
85
|
+
"#{Buildable.base_dir}/#{base}/#{::File.basename(path)}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def config_url
|
90
|
+
@config_url ||= "#{url}/raw/#{commit}/.travis.yml"
|
91
|
+
end
|
92
|
+
|
93
|
+
def git_url
|
94
|
+
url[0..6] == 'file://' ? path : "#{url.gsub(%r(http://|https://), 'git://')}.git"
|
95
|
+
end
|
96
|
+
|
97
|
+
def extract_path(url)
|
98
|
+
if url =~ %r(https?://github.com)
|
99
|
+
URI.parse(url).path
|
100
|
+
elsif url =~ %r(file://)
|
101
|
+
File.expand_path(url.gsub('file://', ''))
|
102
|
+
else
|
103
|
+
raise "unsupported url #{url}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def execute(command)
|
108
|
+
puts "$ #{command}"
|
109
|
+
system("#{command} 2>&1") ? 0 : 1
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'net/https'
|
4
|
+
require 'yaml'
|
5
|
+
require 'active_support/core_ext/hash/keys'
|
6
|
+
|
7
|
+
module Travis
|
8
|
+
class Buildable
|
9
|
+
class Config < Hash
|
10
|
+
def initialize(source)
|
11
|
+
source = URI.parse(source)
|
12
|
+
|
13
|
+
http = Net::HTTP.new(source.host, 443)
|
14
|
+
http.use_ssl = true
|
15
|
+
|
16
|
+
response, body = http.get(source.path, nil)
|
17
|
+
replace(YAML.load(body).symbolize_keys) rescue nil if response.code == '200'
|
18
|
+
rescue URI::InvalidURIError => e
|
19
|
+
{}
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'resque/plugins/meta'
|
3
|
+
|
4
|
+
module Travis
|
5
|
+
class Builder
|
6
|
+
autoload :Base, 'travis/builder/base'
|
7
|
+
autoload :Pusher, 'travis/builder/pusher'
|
8
|
+
autoload :Rails, 'travis/builder/rails'
|
9
|
+
autoload :Stdout, 'travis/builder/stdout'
|
10
|
+
|
11
|
+
extend Resque::Plugins::Meta
|
12
|
+
include Base
|
13
|
+
|
14
|
+
@queue = :builds
|
15
|
+
|
16
|
+
class << self
|
17
|
+
def init
|
18
|
+
require 'resque/heartbeat'
|
19
|
+
|
20
|
+
include Travis::Builder::Stdout
|
21
|
+
include Travis::Builder::Rails
|
22
|
+
include Travis::Builder::Pusher
|
23
|
+
|
24
|
+
Resque.redis = ENV['REDIS_URL'] || Travis.config['redis']['url']
|
25
|
+
end
|
26
|
+
|
27
|
+
def connections
|
28
|
+
@@connections ||= []
|
29
|
+
end
|
30
|
+
|
31
|
+
def perform(meta_id, payload)
|
32
|
+
EM.run do
|
33
|
+
sleep(0.01) until EM.reactor_running?
|
34
|
+
EM.defer do
|
35
|
+
begin
|
36
|
+
new(meta_id, payload).work!
|
37
|
+
sleep(0.1) until connections.empty?
|
38
|
+
EM.stop
|
39
|
+
rescue Exception => e
|
40
|
+
$_stdout.puts e.inspect
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def connections
|
48
|
+
self.class.connections
|
49
|
+
end
|
50
|
+
|
51
|
+
def register_connection(connection)
|
52
|
+
connections << connection
|
53
|
+
connection.callback { connections.delete(connection) }
|
54
|
+
connection.errback { connections.delete(connection) }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Travis
|
2
|
+
class Builder
|
3
|
+
module Base
|
4
|
+
attr_reader :build, :meta_id
|
5
|
+
|
6
|
+
def initialize(meta_id, build)
|
7
|
+
@meta_id = meta_id
|
8
|
+
@build = build.dup
|
9
|
+
end
|
10
|
+
|
11
|
+
def work!
|
12
|
+
on_start
|
13
|
+
build['status'] = buildable.build!
|
14
|
+
# sleep(1)
|
15
|
+
on_finish
|
16
|
+
end
|
17
|
+
|
18
|
+
def buildable
|
19
|
+
@buildable ||= Travis::Buildable.new(
|
20
|
+
:script => 'rake',
|
21
|
+
:commit => build['commit'],
|
22
|
+
:url => build['repository']['url']
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def repository_id
|
27
|
+
build['repository']['id']
|
28
|
+
end
|
29
|
+
|
30
|
+
def on_start
|
31
|
+
build.merge!('log' => '', 'started_at' => Time.now)
|
32
|
+
end
|
33
|
+
|
34
|
+
def on_log(chars)
|
35
|
+
build['log'] << chars
|
36
|
+
end
|
37
|
+
|
38
|
+
def on_finish
|
39
|
+
build.merge!('finished_at' => Time.now)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'em-pusher'
|
3
|
+
|
4
|
+
module Travis
|
5
|
+
class Builder
|
6
|
+
module Pusher
|
7
|
+
def on_start
|
8
|
+
super
|
9
|
+
push 'build:started', :build => build
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_log(log)
|
13
|
+
super
|
14
|
+
push 'build:log', :build => { :id => build['id'], :repository => { :id => build['repository']['id'] } }, :log => log
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_finish
|
18
|
+
super
|
19
|
+
push 'build:finished', :build => build
|
20
|
+
end
|
21
|
+
|
22
|
+
protected
|
23
|
+
def push(event, data)
|
24
|
+
# TODO fix channels
|
25
|
+
channel = 'repositories'
|
26
|
+
# channel = :"repository_#{repository_id}"
|
27
|
+
|
28
|
+
# stdout.puts "Pusher: notifying channel #{channel} about #{event}: #{data.inspect}"
|
29
|
+
register_connection pusher(channel).trigger(event, data)
|
30
|
+
# sleep(0.1) # TODO how to synchronize websocket messages
|
31
|
+
end
|
32
|
+
|
33
|
+
def pusher(channel)
|
34
|
+
EventMachine::Pusher.new(
|
35
|
+
:app_id => ENV['pusher_app_id'] || pusher_config['app_id'],
|
36
|
+
:auth_key => ENV['pusher_key'] || pusher_config['key'],
|
37
|
+
:auth_secret => ENV['pusher_secret'] || pusher_config['secret'],
|
38
|
+
:channel => channel
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def pusher_config
|
43
|
+
@pusher_config ||= Travis.config['pusher']
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'em-http-request'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module Travis
|
5
|
+
class Builder
|
6
|
+
module Rails
|
7
|
+
def work!
|
8
|
+
@done = []
|
9
|
+
super
|
10
|
+
end
|
11
|
+
|
12
|
+
def on_start
|
13
|
+
super
|
14
|
+
post(:started_at => build['started_at'])
|
15
|
+
end
|
16
|
+
|
17
|
+
def on_log(chars)
|
18
|
+
super
|
19
|
+
post(:log => chars, :append => true)
|
20
|
+
end
|
21
|
+
|
22
|
+
def on_finish
|
23
|
+
super
|
24
|
+
post(:log => build['log'], :status => build['status'], :finished_at => build['finished_at'])
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
def post(data)
|
29
|
+
host = rails_config['url'] || 'http://127.0.0.1'
|
30
|
+
url = "#{host}/builds/#{build['id']}#{'/log' if data.delete(:append)}"
|
31
|
+
uri = URI.parse(host)
|
32
|
+
data = { :body => { :_method => :put, :build => data }, :head => { :authorization => [uri.user, uri.password] } }
|
33
|
+
# stdout.puts "-- post to #{url} : #{data.inspect}"
|
34
|
+
register_connection EventMachine::HttpRequest.new(url).post(data)
|
35
|
+
rescue Exception => e
|
36
|
+
stdout.puts e.inspect
|
37
|
+
end
|
38
|
+
|
39
|
+
def rails_config
|
40
|
+
@rails_config ||= Travis.config['rails']
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Travis
|
4
|
+
class Config < Hash
|
5
|
+
def initialize
|
6
|
+
replace(load_env || load_file || {})
|
7
|
+
end
|
8
|
+
|
9
|
+
def load_env
|
10
|
+
YAML.load(ENV['travis_config']) if ENV['travis_config']
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_file
|
14
|
+
file = File.expand_path('../../../config/travis.yml', __FILE__)
|
15
|
+
YAML.load_file(file)[environment] if File.exists?(file)
|
16
|
+
end
|
17
|
+
|
18
|
+
def environment
|
19
|
+
defined?(Rails) ? Rails.env : 'test'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'minitest/unit'
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
require 'travis-ruby'
|
15
|
+
|
16
|
+
class MiniTest::Unit::TestCase
|
17
|
+
end
|
18
|
+
|
19
|
+
MiniTest::Unit.autorun
|
data/test/test_travis.rb
ADDED
data/travis-ruby.gemspec
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{travis-ruby}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["beawesomeinstead"]
|
12
|
+
s.date = %q{2011-02-20}
|
13
|
+
s.default_executable = %q{travis-ruby}
|
14
|
+
s.description = %q{Travis builder for ruby.}
|
15
|
+
s.email = %q{graf.otodrakula@gmail.com}
|
16
|
+
s.executables = ["travis-ruby"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"LICENSE.txt",
|
19
|
+
"README.markdown"
|
20
|
+
]
|
21
|
+
s.files = [
|
22
|
+
".document",
|
23
|
+
"Gemfile",
|
24
|
+
"Gemfile.lock",
|
25
|
+
"LICENSE.txt",
|
26
|
+
"README.markdown",
|
27
|
+
"Rakefile",
|
28
|
+
"VERSION",
|
29
|
+
"bin/travis-ruby",
|
30
|
+
"lib/em/stdout.rb",
|
31
|
+
"lib/resque/heartbeat.rb",
|
32
|
+
"lib/travis.rb",
|
33
|
+
"lib/travis/buildable.rb",
|
34
|
+
"lib/travis/buildable/config.rb",
|
35
|
+
"lib/travis/builder.rb",
|
36
|
+
"lib/travis/builder/base.rb",
|
37
|
+
"lib/travis/builder/pusher.rb",
|
38
|
+
"lib/travis/builder/rails.rb",
|
39
|
+
"lib/travis/builder/stdout.rb",
|
40
|
+
"lib/travis/config.rb",
|
41
|
+
"test/helper.rb",
|
42
|
+
"test/test_travis.rb",
|
43
|
+
"travis-ruby.gemspec"
|
44
|
+
]
|
45
|
+
s.homepage = %q{http://github.com/bai/travis-ruby}
|
46
|
+
s.licenses = ["MIT"]
|
47
|
+
s.require_paths = ["lib"]
|
48
|
+
s.rubygems_version = %q{1.5.2}
|
49
|
+
s.summary = %q{Travis builder for ruby.}
|
50
|
+
s.test_files = [
|
51
|
+
"test/helper.rb",
|
52
|
+
"test/test_travis.rb"
|
53
|
+
]
|
54
|
+
|
55
|
+
if s.respond_to? :specification_version then
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_runtime_dependency(%q<SystemTimer>, [">= 0"])
|
60
|
+
s.add_runtime_dependency(%q<resque>, [">= 0"])
|
61
|
+
s.add_runtime_dependency(%q<resque-meta>, [">= 0"])
|
62
|
+
s.add_runtime_dependency(%q<yajl-ruby>, ["~> 0.7.6"])
|
63
|
+
s.add_runtime_dependency(%q<em-pusher>, [">= 0"])
|
64
|
+
s.add_runtime_dependency(%q<em-http-request>, [">= 0"])
|
65
|
+
s.add_development_dependency(%q<minitest>, [">= 0"])
|
66
|
+
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
67
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
68
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
69
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
70
|
+
else
|
71
|
+
s.add_dependency(%q<SystemTimer>, [">= 0"])
|
72
|
+
s.add_dependency(%q<resque>, [">= 0"])
|
73
|
+
s.add_dependency(%q<resque-meta>, [">= 0"])
|
74
|
+
s.add_dependency(%q<yajl-ruby>, ["~> 0.7.6"])
|
75
|
+
s.add_dependency(%q<em-pusher>, [">= 0"])
|
76
|
+
s.add_dependency(%q<em-http-request>, [">= 0"])
|
77
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
78
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
79
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
80
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
81
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
82
|
+
end
|
83
|
+
else
|
84
|
+
s.add_dependency(%q<SystemTimer>, [">= 0"])
|
85
|
+
s.add_dependency(%q<resque>, [">= 0"])
|
86
|
+
s.add_dependency(%q<resque-meta>, [">= 0"])
|
87
|
+
s.add_dependency(%q<yajl-ruby>, ["~> 0.7.6"])
|
88
|
+
s.add_dependency(%q<em-pusher>, [">= 0"])
|
89
|
+
s.add_dependency(%q<em-http-request>, [">= 0"])
|
90
|
+
s.add_dependency(%q<minitest>, [">= 0"])
|
91
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
92
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
93
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
94
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
metadata
ADDED
@@ -0,0 +1,202 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: travis-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- beawesomeinstead
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-02-20 00:00:00 +02:00
|
14
|
+
default_executable: travis-ruby
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: SystemTimer
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
type: :runtime
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: resque
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: resque-meta
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *id003
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: yajl-ruby
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.7.6
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *id004
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: em-pusher
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
type: :runtime
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *id005
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: em-http-request
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
type: :runtime
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *id006
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: minitest
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: "0"
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: *id007
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
name: yard
|
95
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ~>
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: 0.6.0
|
101
|
+
type: :development
|
102
|
+
prerelease: false
|
103
|
+
version_requirements: *id008
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: bundler
|
106
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ~>
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 1.0.0
|
112
|
+
type: :development
|
113
|
+
prerelease: false
|
114
|
+
version_requirements: *id009
|
115
|
+
- !ruby/object:Gem::Dependency
|
116
|
+
name: jeweler
|
117
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ~>
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: 1.5.2
|
123
|
+
type: :development
|
124
|
+
prerelease: false
|
125
|
+
version_requirements: *id010
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rcov
|
128
|
+
requirement: &id011 !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ">="
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: "0"
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: *id011
|
137
|
+
description: Travis builder for ruby.
|
138
|
+
email: graf.otodrakula@gmail.com
|
139
|
+
executables:
|
140
|
+
- travis-ruby
|
141
|
+
extensions: []
|
142
|
+
|
143
|
+
extra_rdoc_files:
|
144
|
+
- LICENSE.txt
|
145
|
+
- README.markdown
|
146
|
+
files:
|
147
|
+
- .document
|
148
|
+
- Gemfile
|
149
|
+
- Gemfile.lock
|
150
|
+
- LICENSE.txt
|
151
|
+
- README.markdown
|
152
|
+
- Rakefile
|
153
|
+
- VERSION
|
154
|
+
- bin/travis-ruby
|
155
|
+
- lib/em/stdout.rb
|
156
|
+
- lib/resque/heartbeat.rb
|
157
|
+
- lib/travis.rb
|
158
|
+
- lib/travis/buildable.rb
|
159
|
+
- lib/travis/buildable/config.rb
|
160
|
+
- lib/travis/builder.rb
|
161
|
+
- lib/travis/builder/base.rb
|
162
|
+
- lib/travis/builder/pusher.rb
|
163
|
+
- lib/travis/builder/rails.rb
|
164
|
+
- lib/travis/builder/stdout.rb
|
165
|
+
- lib/travis/config.rb
|
166
|
+
- test/helper.rb
|
167
|
+
- test/test_travis.rb
|
168
|
+
- travis-ruby.gemspec
|
169
|
+
has_rdoc: true
|
170
|
+
homepage: http://github.com/bai/travis-ruby
|
171
|
+
licenses:
|
172
|
+
- MIT
|
173
|
+
post_install_message:
|
174
|
+
rdoc_options: []
|
175
|
+
|
176
|
+
require_paths:
|
177
|
+
- lib
|
178
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
179
|
+
none: false
|
180
|
+
requirements:
|
181
|
+
- - ">="
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
hash: -4127898013200811984
|
184
|
+
segments:
|
185
|
+
- 0
|
186
|
+
version: "0"
|
187
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
|
+
none: false
|
189
|
+
requirements:
|
190
|
+
- - ">="
|
191
|
+
- !ruby/object:Gem::Version
|
192
|
+
version: "0"
|
193
|
+
requirements: []
|
194
|
+
|
195
|
+
rubyforge_project:
|
196
|
+
rubygems_version: 1.5.2
|
197
|
+
signing_key:
|
198
|
+
specification_version: 3
|
199
|
+
summary: Travis builder for ruby.
|
200
|
+
test_files:
|
201
|
+
- test/helper.rb
|
202
|
+
- test/test_travis.rb
|