module Hoe::Travis
def define_travis_tasks
def define_travis_tasks desc "Runs your tests for travis" task :travis => %w[test check_manifest] namespace :travis do desc "Run by travis-ci after running the default checks" task :after => %w[ travis:fake_config ] desc "Run by travis-ci before running the default checks" task :before => %w[ install_plugins travis:install_deps ] desc "Lint your .travis.yml" task :check do abort unless travis_yml_check '.travis.yml' end desc "Disables the travis-ci hook" task :disable do travis_disable end desc "Brings .travis.yml up in your EDITOR then checks it on save" task :edit do Tempfile.open 'travis.yml' do |io| io.write File.read '.travis.yml' io.rewind ok = travis_yml_edit io.path travis_yml_write io.path if ok end end desc "Enables the travis-ci hook" task :enable do travis_enable end desc "Triggers the travis-ci hook" task :force do travis_force end task :fake_config do travis_fake_config end desc "Generates a new .travis.yml and allows you to customize it with your EDITOR" task :generate do Tempfile.open 'travis.yml' do |io| io.write travis_yml_generate io.rewind ok = travis_yml_edit io.path travis_yml_write io.path if ok end end task :install_deps do (extra_deps + extra_dev_deps).each do |dep| begin gem(*dep) rescue Gem::LoadError name, req, = dep install_gem name, req, false end end end end end
def initialize_travis # :nodoc:
def initialize_travis # :nodoc: @github_api = URI 'https://api.github.com' end
def travis_after_script
def travis_after_script with_config { |config, _| config['travis']['after_script'] or Hoe::DEFAULT_CONFIG['travis']['after_script'] } end
def travis_before_script
def travis_before_script with_config { |config, _| config['travis']['before_script'] or Hoe::DEFAULT_CONFIG['travis']['before_script'] } end
def travis_disable
def travis_disable _, repo, = travis_github_check if hook = travis_have_hook?(repo) then travis_edit_hook repo, hook, false if hook['active'] end end
def travis_edit_hook repo, hook, enable = true
def travis_edit_hook repo, hook, enable = true patch = unless Net::HTTP.const_defined? :Patch then # Ruby 1.8 Class.new Net::HTTPRequest do |c| c.const_set :METHOD, 'PATCH' c.const_set :REQUEST_HAS_BODY, true c.const_set :RESPONSE_HAS_BODY, true end else Net::HTTP::Patch end id = hook['id'] body = { 'name' => hook['name'], 'active' => enable, 'config' => hook['config'] } travis_github_request "/repos/#{repo}/hooks/#{id}", body, patch end
def travis_enable
def travis_enable user, repo, token = travis_github_check if hook = travis_have_hook?(repo) then travis_edit_hook repo, hook unless hook['active'] else travis_make_hook repo, user, token end end
def travis_fake_config
def travis_fake_config fake_hoerc = File.expand_path '~/.hoerc' return if File.exist? fake_hoerc config = { 'exclude' => /\.(git|travis)/ } open fake_hoerc, 'w' do |io| YAML.dump config, io end end
def travis_force
def travis_force user, repo, token = travis_github_check unless hook = travis_have_hook?(repo) hook = travis_make_hook repo, user, token end travis_github_request "/repos/#{repo}/hooks/#{hook['id']}/test", {} end
def travis_github_check
def travis_github_check user = `git config github.user`.chomp abort <<-ABORT unless user t your github user and token in ~/.gitconfig e: ri Hoe::Travis and http://help.github.com/set-your-user-name-email-and-github-token/ ABORT `git config remote.origin.url` =~ /^git@github\.com:(.*).git$/ repo = $1 abort <<-ABORT unless repo able to determine your github repository. pected \"git@github.com:[repo].git\" as your remote origin ABORT token = with_config do |config, _| config['travis']['token'] end abort 'Please set your travis token via `rake config_hoe` - ' \ 'See: ri Hoe::Travis' if token =~ /FIX/ return user, repo, token end
def travis_github_request(path, body = nil,
def travis_github_request(path, body = nil, method = body ? Net::HTTP::Post : Net::HTTP::Get) begin require 'json' rescue LoadError => e raise unless e.message.end_with? 'json' abort 'Please gem install json like modern ruby versions have' end uri = @github_api + path http = Net::HTTP.new uri.host, uri.port http.use_ssl = uri.scheme.downcase == 'https' http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.cert_store = OpenSSL::X509::Store.new http.cert_store.set_default_paths req = method.new uri.request_uri if body then req.content_type = 'application/json' req.body = JSON.dump body end user = `git config github.user`.chomp pass = `git config github.password`.chomp req.basic_auth user, pass res = http.request req body = JSON.parse res.body if res.class.body_permitted? unless Net::HTTPSuccess === res then message = ": #{res['message']}" if body raise "github API error #{res.code}#{message}" end body end
def travis_have_hook? repo
def travis_have_hook? repo body = travis_github_request "/repos/#{repo}/hooks" body.find { |hook| hook['name'] == 'travis' } end
def travis_make_hook repo, user, token
def travis_make_hook repo, user, token body = { "name" => "travis", "active" => true, "config" => { "domain" => "", "token" => token, "user" => user, } } travis_github_request "/repos/#{repo}/hooks", body end
def travis_notifications
def travis_notifications email = @email.compact email.delete '' default_notifications = { 'email' => email } notifications = with_config do |config, _| config['travis']['notifications'] or Hoe::DEFAULT_CONFIG['travis']['notifications'] end || {} default_notifications.merge notifications end
def travis_script
def travis_script with_config { |config, _| config['travis']['script'] or Hoe::DEFAULT_CONFIG['travis']['script'] } end
def travis_versions
def travis_versions if have_gem? 'ZenTest' and File.exist?(File.expand_path('~/.multiruby')) then `multiruby -v` =~ /^Passed: (.*)/ $1.split(', ').map do |ruby_release| ruby_release.sub(/-.*/, '') end else with_config do |config, _| config['travis']['versions'] or Hoe::DEFAULT_CONFIG['travis']['versions'] end end.sort end
def travis_yml_check path
def travis_yml_check path require 'net/http' post_body = { 'content' => File.read(path), } req = Net::HTTP::Post.new '/lint' req.set_form post_body, 'multipart/form-data' cert_store = OpenSSL::X509::Store.new cert_store.set_default_paths http = Net::HTTP.new 'api.travis-ci.org', 443 http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.cert_store = cert_store res = http.request req unless Net::HTTPOK === res then warn "Unable to lint #{path}: #{res.body}" return false end require 'json' response = JSON.parse res.body lint = response.fetch 'lint' warnings = lint.fetch 'warnings' return true if warnings.empty? warnings.each do |warning| keys = warning.fetch 'key' message = warning.fetch 'message' if keys.empty? then warn message else warn "For #{keys.join ', '}: #{message}" end end return false rescue Net::HTTPError => e warn "Unable to lint #{path}: #{e.message}" return false end
def travis_yml_edit path
def travis_yml_edit path loop do editor = ENV['EDITOR'] || 'vi' system "#{editor} #{path}" break true if travis_yml_check path abort unless $stdout.tty? print "\nRetry edit? [Yn]\n> " $stdout.flush break false if $stdin.gets =~ /\An/i end end
def travis_yml_generate
def travis_yml_generate travis_yml = { 'after_script' => travis_after_script, 'before_script' => travis_before_script, 'language' => 'ruby', 'notifications' => travis_notifications, 'rvm' => travis_versions, 'script' => travis_script, } travis_yml.each do |key, value| travis_yml.delete key unless value end YAML.dump travis_yml end
def travis_yml_write source_file
def travis_yml_write source_file open source_file do |source_io| open '.travis.yml', 'w' do |dest_io| dest_io.write source_io.read end end end