travis 1.5.3 → 1.5.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +27 -2
- data/Rakefile +4 -69
- data/completion/travis.sh +126 -1375
- data/completion/travis.sh.erb +60 -0
- data/lib/travis/cli.rb +0 -3
- data/lib/travis/cli/accounts.rb +4 -2
- data/lib/travis/cli/api_command.rb +19 -1
- data/lib/travis/cli/command.rb +4 -4
- data/lib/travis/cli/endpoint.rb +13 -1
- data/lib/travis/cli/init.rb +26 -2
- data/lib/travis/cli/login.rb +24 -12
- data/lib/travis/cli/monitor.rb +25 -2
- data/lib/travis/cli/repo_command.rb +4 -4
- data/lib/travis/cli/setup.rb +27 -122
- data/lib/travis/cli/setup/cloud_control.rb +21 -0
- data/lib/travis/cli/setup/cloud_foundry.rb +23 -0
- data/lib/travis/cli/setup/engine_yard.rb +24 -0
- data/lib/travis/cli/setup/heroku.rb +20 -0
- data/lib/travis/cli/setup/nodejitsu.rb +27 -0
- data/lib/travis/cli/setup/open_shift.rb +20 -0
- data/lib/travis/cli/setup/ruby_gems.rb +25 -0
- data/lib/travis/cli/setup/sauce_connect.rb +21 -0
- data/lib/travis/cli/setup/service.rb +73 -0
- data/lib/travis/client/repository.rb +1 -1
- data/lib/travis/client/session.rb +27 -5
- data/lib/travis/tools/notification.rb +69 -0
- data/lib/travis/tools/system.rb +38 -0
- data/lib/travis/version.rb +1 -1
- data/spec/cli/endpoint_spec.rb +5 -0
- data/spec/cli/init_spec.rb +21 -19
- data/spec/client/repository_spec.rb +1 -0
- data/spec/client/session_spec.rb +16 -0
- data/spec/support/fake_api.rb +2 -1
- data/travis.gemspec +28 -14
- metadata +46 -19
@@ -0,0 +1,60 @@
|
|
1
|
+
# implements tab completion for complete (bash), compsys (new zsh) and compctl (old zsh)
|
2
|
+
# this file is generated by `rake completion`
|
3
|
+
|
4
|
+
_travis_complete() {
|
5
|
+
case $1 in
|
6
|
+
1) _travis_commands;;
|
7
|
+
2)
|
8
|
+
case "$2" in
|
9
|
+
# commands with smart completions (in addition to command line flags)
|
10
|
+
help) _travis_commands;;
|
11
|
+
setup) _travis_setup;;
|
12
|
+
init) _travis_init;;
|
13
|
+
*) _travis_option;;
|
14
|
+
esac;;
|
15
|
+
*) _travis_option;;
|
16
|
+
esac
|
17
|
+
}
|
18
|
+
|
19
|
+
if type compdef 1>/dev/null 2>/dev/null; then
|
20
|
+
compdef _travis travis
|
21
|
+
_travis() { _travis_complete $((${#words} - 1)) "${words[2]}"; }
|
22
|
+
_travis_commands() { list=(<%= commands.map { |c| "%s:%p" % [c.command_name, c.description] }.join(" ") %>) _describe -t common-commands 'common commands' list; }
|
23
|
+
_travis_setup() { list=(<%= Travis::CLI::Setup.services.map { |s| "%s:%p" % [s.service_name, s.description] }.join(" ") %>) _describe -t common-commands 'common commands' list; }
|
24
|
+
_travis_init() { list=(<%= Travis::CLI::Init.languages.map { |l| "#{l}:'initialize #{l} project'" }.join(" ") %>) _describe -t common-commands 'common commands' list; }
|
25
|
+
_travis_option() {
|
26
|
+
case "${words[2]}" in
|
27
|
+
<% commands.each do |c| %>
|
28
|
+
<%= "#{c.command_name})".ljust(10) %> <%= c.new.parser.compsys(" ", c.command_name).gsub(/\s+\\\s+/, ' ')[/_arguments.*/] %>;;
|
29
|
+
<% end %>
|
30
|
+
esac
|
31
|
+
}
|
32
|
+
elif type compctl 1>/dev/null 2>/dev/null; then
|
33
|
+
compctl -K _travis travis
|
34
|
+
_travis() { read -cA words && _travis_complete $((${#words} - 1)) "${words[2]}"; }
|
35
|
+
_travis_commands() { reply=(<%= commands.map(&:command_name).map(&:inspect).join(" ") %>); }
|
36
|
+
_travis_setup() { reply=(<%= Travis::CLI::Setup.services.map(&:service_name).map(&:inspect).join(" ") %>); }
|
37
|
+
_travis_init() { reply=(<%= Travis::CLI::Init.languages.map(&:inspect).join(" ") %>); }
|
38
|
+
_travis_option() {
|
39
|
+
case "${words[2]}" in
|
40
|
+
<% commands.each do |c| %>
|
41
|
+
<%= "#{c.command_name})".ljust(10) %> reply=(<%= c.new.parser.candidate("-").flat_map { |o| [o.sub('[no-]', ''), o.sub('[no-]', 'no-')] }.uniq.map(&:inspect).join(" ") %>);;
|
42
|
+
<% end %>
|
43
|
+
esac
|
44
|
+
}
|
45
|
+
elif type complete 1>/dev/null 2>/dev/null; then
|
46
|
+
complete -F _travis travis
|
47
|
+
_travis() { _travis_complete "$COMP_CWORD" "${COMP_WORDS[1]}"; }
|
48
|
+
_travis_commands() { COMPREPLY=( $(compgen -W "<%= commands.map(&:command_name).join(" ") %>" -- "${COMP_WORDS[COMP_CWORD]}") ); }
|
49
|
+
_travis_setup() { COMPREPLY=( $(compgen -W "<%= Travis::CLI::Setup.services.map(&:service_name).join(" ") %>" -- "${COMP_WORDS[COMP_CWORD]}") ); }
|
50
|
+
_travis_init() { COMPREPLY=( $(compgen -W "<%= Travis::CLI::Init.languages.join(" ") %>" -- "${COMP_WORDS[COMP_CWORD]}") ); }
|
51
|
+
_travis_option() {
|
52
|
+
local options
|
53
|
+
case "${COMP_WORDS[1]}" in
|
54
|
+
<% commands.each do |c| %>
|
55
|
+
<%= "#{c.command_name})".ljust(10) %> options="<%= c.new.parser.candidate("-").flat_map { |o| [o.sub('[no-]', ''), o.sub('[no-]', 'no-')] }.uniq.join(" ") %>";;
|
56
|
+
<% end %>
|
57
|
+
esac
|
58
|
+
COMPREPLY=( $(compgen -W "$options" -- "${COMP_WORDS[COMP_CWORD]}") )
|
59
|
+
}
|
60
|
+
fi
|
data/lib/travis/cli.rb
CHANGED
data/lib/travis/cli/accounts.rb
CHANGED
@@ -11,12 +11,14 @@ module Travis
|
|
11
11
|
color = account.subscribed? ? :green : :info
|
12
12
|
say [
|
13
13
|
color(account.login, [color, :bold]),
|
14
|
-
color("(#{account.name}):", color),
|
14
|
+
color("(#{account.name || account.login.capitalize}):", color),
|
15
15
|
account.subscribed? ? "subscribed," : "not subscribed,",
|
16
16
|
account.repos_count == 1 ? "1 repository" : "#{account.repos_count} repositories"
|
17
17
|
].join(" ")
|
18
18
|
end
|
19
|
-
|
19
|
+
unless accounts.all?(&:subscribed?) or session.config['host'].nil?
|
20
|
+
say session.config['host'], "To set up a subscription, please visit %s."
|
21
|
+
end
|
20
22
|
end
|
21
23
|
end
|
22
24
|
end
|
@@ -31,7 +31,7 @@ module Travis
|
|
31
31
|
end
|
32
32
|
|
33
33
|
def initialize(*)
|
34
|
-
@session = Travis::Client.new
|
34
|
+
@session = Travis::Client.new(:agent_info => "command #{command_name}")
|
35
35
|
super
|
36
36
|
end
|
37
37
|
|
@@ -80,6 +80,24 @@ module Travis
|
|
80
80
|
|
81
81
|
private
|
82
82
|
|
83
|
+
def load_gh
|
84
|
+
return if defined? GH
|
85
|
+
require 'gh'
|
86
|
+
|
87
|
+
gh_config = session.config['github']
|
88
|
+
gh_config &&= gh_config.inject({}) { |h,(k,v)| h.update(k.to_sym => v) }
|
89
|
+
gh_config ||= {}
|
90
|
+
gh_config[:ssl] = Travis::Client::Session::SSL_OPTIONS
|
91
|
+
gh_config[:ssl] = { :verify => false } if gh_config[:api_url] and gh_config[:api_url] != "https://api.github.com"
|
92
|
+
|
93
|
+
GH.set(gh_config)
|
94
|
+
end
|
95
|
+
|
96
|
+
def github_endpoint
|
97
|
+
load_gh
|
98
|
+
GH.with({}).api_host
|
99
|
+
end
|
100
|
+
|
83
101
|
def listen(*args)
|
84
102
|
super(*args) do |listener|
|
85
103
|
on_signal { listener.disconnect }
|
data/lib/travis/cli/command.rb
CHANGED
@@ -171,9 +171,9 @@ module Travis
|
|
171
171
|
"Usage: " << color(usage, :command)
|
172
172
|
end
|
173
173
|
|
174
|
-
def help
|
174
|
+
def help(info = "")
|
175
175
|
parser.banner = usage
|
176
|
-
self.class.description.sub(/./) { |c| c.upcase } + ".\n" + parser.to_s
|
176
|
+
self.class.description.sub(/./) { |c| c.upcase } + ".\n" + info + parser.to_s
|
177
177
|
end
|
178
178
|
|
179
179
|
def say(data, format = nil, style = nil)
|
@@ -220,8 +220,8 @@ module Travis
|
|
220
220
|
end
|
221
221
|
|
222
222
|
def color(line, style)
|
223
|
-
return line unless interactive?
|
224
|
-
terminal.color(line, Array(style).map(&:to_sym))
|
223
|
+
return line.to_s unless interactive?
|
224
|
+
terminal.color(line || '???', Array(style).map(&:to_sym))
|
225
225
|
end
|
226
226
|
|
227
227
|
def interactive?(io = output)
|
data/lib/travis/cli/endpoint.rb
CHANGED
@@ -8,8 +8,16 @@ module Travis
|
|
8
8
|
skip :authenticate
|
9
9
|
on '--drop-default', 'delete stored default endpoint'
|
10
10
|
on '--set-default', 'store endpoint as global default'
|
11
|
+
on '--github', 'display github endpoint'
|
11
12
|
|
12
|
-
def
|
13
|
+
def run_github
|
14
|
+
error "--github cannot be combined with --drop-default" if drop_default?
|
15
|
+
error "--github cannot be combined with --set-default" if set_default?
|
16
|
+
load_gh
|
17
|
+
say github_endpoint.to_s, "GitHub endpoint: %s"
|
18
|
+
end
|
19
|
+
|
20
|
+
def run_travis
|
13
21
|
if drop_default? and was = config['default_endpoint']
|
14
22
|
config.delete('default_endpoint')
|
15
23
|
say was, "default API endpoint dropped (was %s)"
|
@@ -18,6 +26,10 @@ module Travis
|
|
18
26
|
say api_endpoint, "API endpoint: %s#{" (stored as default)" if set_default?}"
|
19
27
|
end
|
20
28
|
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
github? ? run_github : run_travis
|
32
|
+
end
|
21
33
|
end
|
22
34
|
end
|
23
35
|
end
|
data/lib/travis/cli/init.rb
CHANGED
@@ -3,6 +3,15 @@ require 'travis/cli'
|
|
3
3
|
module Travis
|
4
4
|
module CLI
|
5
5
|
class Init < Enable
|
6
|
+
LANGUAGE_MAPPING = {
|
7
|
+
"node" => "node_js",
|
8
|
+
"node.js" => "node_js",
|
9
|
+
"javascript" => "node_js",
|
10
|
+
"coffeescript" => "node_js",
|
11
|
+
"c++" => "cpp",
|
12
|
+
"obj-c" => "objective-c"
|
13
|
+
}
|
14
|
+
|
6
15
|
description "generates a .travis.yml and enables the project"
|
7
16
|
|
8
17
|
on('-f', '--force', 'override .travis.yml if it already exists')
|
@@ -24,6 +33,15 @@ module Travis
|
|
24
33
|
|
25
34
|
attr_writer :travis_config
|
26
35
|
|
36
|
+
def self.languages
|
37
|
+
pattern = File.expand_path("../init/*.yml", __FILE__)
|
38
|
+
Dir[pattern].map { |f| File.basename(f, '.yml') }.sort
|
39
|
+
end
|
40
|
+
|
41
|
+
def help
|
42
|
+
super("Available languages: #{self.class.languages.join(", ")}\n\n")
|
43
|
+
end
|
44
|
+
|
27
45
|
def run(language = nil, file = '.travis.yml')
|
28
46
|
error "#{file} already exists, use --force to override" if File.exist?(file) and not force? and not print_conf?
|
29
47
|
language ||= ask('Main programming language used: ') { |q| q.default = detect_language }
|
@@ -45,14 +63,20 @@ module Travis
|
|
45
63
|
|
46
64
|
private
|
47
65
|
|
66
|
+
def template_name(language)
|
67
|
+
File.expand_path("../init/#{language}.yml", __FILE__)
|
68
|
+
end
|
69
|
+
|
48
70
|
def template(language)
|
49
|
-
|
71
|
+
language = language.to_s.downcase
|
72
|
+
language = LANGUAGE_MAPPING[language] || language
|
73
|
+
file = template_name(language)
|
50
74
|
error "unknown language #{language}" unless File.exist? file
|
51
75
|
YAML.load_file(file)
|
52
76
|
end
|
53
77
|
|
54
78
|
def detect_language
|
55
|
-
|
79
|
+
repository.github_language || "Ruby"
|
56
80
|
end
|
57
81
|
end
|
58
82
|
end
|
data/lib/travis/cli/login.rb
CHANGED
@@ -6,17 +6,14 @@ module Travis
|
|
6
6
|
module CLI
|
7
7
|
class Login < ApiCommand
|
8
8
|
description "authenticates against the API and stores the token"
|
9
|
+
on '--github-token TOKEN', 'identify by GitHub token'
|
10
|
+
on '--auto', 'try to figure out who you are automatically (might send another apps token to Travis, token will not be stored)'
|
9
11
|
|
10
12
|
skip :authenticate
|
11
|
-
attr_accessor :github_login, :github_password, :github_token, :callback
|
12
|
-
|
13
|
-
on('--github-token TOKEN', 'identify by GitHub token')
|
14
|
-
|
15
|
-
on('--auto', 'try to figure out who you are automatically (might send another apps token to Travis, token will not be stored)') do |c|
|
16
|
-
c.github_token ||= Travis::Tools::TokenFinder.find(:explode => c.explode?)
|
17
|
-
end
|
13
|
+
attr_accessor :github_login, :github_password, :github_token, :github_otp, :callback
|
18
14
|
|
19
15
|
def run
|
16
|
+
self.github_token ||= Travis::Tools::TokenFinder.find(:explode => explode?, :github => github_endpoint.host) if auto?
|
20
17
|
generate_github_token unless github_token
|
21
18
|
endpoint_config['access_token'] = github_auth(github_token)
|
22
19
|
success("Successfully logged in!")
|
@@ -27,16 +24,25 @@ module Travis
|
|
27
24
|
private
|
28
25
|
|
29
26
|
def generate_github_token
|
27
|
+
load_gh
|
30
28
|
ask_info
|
31
29
|
|
32
|
-
|
30
|
+
options = { :username => github_login, :password => github_password }
|
31
|
+
options[:headers] = { "X-GitHub-OTP" => github_otp } if github_otp
|
32
|
+
gh = GH.with(options)
|
33
|
+
|
33
34
|
reply = gh.post('/authorizations', :scopes => github_scopes, :note => "temporary token to identify on #{api_endpoint}")
|
34
35
|
|
35
36
|
self.github_token = reply['token']
|
36
37
|
self.callback = proc { gh.delete reply['_links']['self']['href'] }
|
37
|
-
rescue GH::Error =>
|
38
|
-
|
39
|
-
|
38
|
+
rescue GH::Error => error
|
39
|
+
if error.info[:response_status] == 401
|
40
|
+
ask_2fa
|
41
|
+
generate_github_token
|
42
|
+
else
|
43
|
+
raise error if explode?
|
44
|
+
error(JSON.parse(error.info[:response_body])["message"])
|
45
|
+
end
|
40
46
|
end
|
41
47
|
|
42
48
|
def github_scopes
|
@@ -44,8 +50,9 @@ module Travis
|
|
44
50
|
end
|
45
51
|
|
46
52
|
def ask_info
|
53
|
+
return if !github_login.nil?
|
47
54
|
say "We need your #{color("GitHub login", :important)} to identify you."
|
48
|
-
say "This information will #{color("not be sent to Travis CI", :important)}, only to
|
55
|
+
say "This information will #{color("not be sent to Travis CI", :important)}, only to #{color(github_endpoint.host, :info)}."
|
49
56
|
say "The password will not be displayed."
|
50
57
|
empty_line
|
51
58
|
say "Try running with #{color("--github-token", :info)} or #{color("--auto", :info)} if you don't want to enter your password anyways."
|
@@ -54,6 +61,11 @@ module Travis
|
|
54
61
|
self.github_password = ask("Password: ") { |q| q.echo = "*" }
|
55
62
|
empty_line
|
56
63
|
end
|
64
|
+
|
65
|
+
def ask_2fa
|
66
|
+
self.github_otp = ask "Two-factor authentication code: "
|
67
|
+
empty_line
|
68
|
+
end
|
57
69
|
end
|
58
70
|
end
|
59
71
|
end
|
data/lib/travis/cli/monitor.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
1
|
require 'travis/cli'
|
2
|
+
require 'travis/tools/notification'
|
2
3
|
|
3
4
|
module Travis
|
4
5
|
module CLI
|
5
6
|
class Monitor < ApiCommand
|
6
7
|
description "live monitor for what's going on"
|
7
|
-
|
8
8
|
on('-m', '--my-repos', 'Only monitor my own repositories')
|
9
|
+
|
9
10
|
on('-r', '--repo SLUG', 'monitor given repository (can be used more than once)') do |c, slug|
|
10
11
|
c.repos << slug
|
11
12
|
end
|
12
13
|
|
13
|
-
|
14
|
+
types = Tools::Notification::DEFAULT.map(&:to_s).join(", ")
|
15
|
+
on('-n', '--[no-]notify [TYPE]', "send out desktop notifications (optional type: #{types})") do |c, type|
|
16
|
+
c.setup_notification(type)
|
17
|
+
end
|
18
|
+
|
19
|
+
attr_reader :repos, :notification
|
14
20
|
|
15
21
|
def initialize(*)
|
16
22
|
@repos = []
|
@@ -21,6 +27,22 @@ module Travis
|
|
21
27
|
super
|
22
28
|
repos.map! { |r| repo(r) }
|
23
29
|
repos.concat(user.repositories) if my_repos?
|
30
|
+
setup_notification(repos.any? || :dummy) unless notification
|
31
|
+
end
|
32
|
+
|
33
|
+
def setup_notification(type = nil)
|
34
|
+
refuse = false
|
35
|
+
case type
|
36
|
+
when false then @notification = Tools::Notification.new(:dummy)
|
37
|
+
when nil, true then @notification = Tools::Notification.new
|
38
|
+
else
|
39
|
+
refuse = true
|
40
|
+
@notification = Tools::Notification.new(type)
|
41
|
+
end
|
42
|
+
rescue ArgumentError => e
|
43
|
+
@notification = Tools::Notification.new(:dummy)
|
44
|
+
error(e.message) if refuse
|
45
|
+
warn(e.message)
|
24
46
|
end
|
25
47
|
|
26
48
|
def description
|
@@ -42,6 +64,7 @@ module Travis
|
|
42
64
|
color(entity.inspect_info, [entity.color, :bold]),
|
43
65
|
color(entity.state, entity.color)
|
44
66
|
].join(" ")
|
67
|
+
notification.notify("Travis CI", "#{entity.inspect_info} #{entity.state}")
|
45
68
|
end
|
46
69
|
end
|
47
70
|
end
|
@@ -44,11 +44,10 @@ module Travis
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def find_slug
|
47
|
-
git_head
|
48
|
-
git_remote = `git config --get branch.#{git_head}.remote 2
|
49
|
-
# Default to 'origin' if no tracking is set
|
47
|
+
git_head = `git name-rev --name-only HEAD 2>#{IO::NULL}`.chomp
|
48
|
+
git_remote = `git config --get branch.#{git_head}.remote 2>#{IO::NULL}`.chomp
|
50
49
|
git_remote = 'origin' if git_remote.empty?
|
51
|
-
git_info
|
50
|
+
git_info = `git config --get remote.#{git_remote}.url 2>#{IO::NULL}`.chomp
|
52
51
|
$1 if git_info =~ GIT_REGEX
|
53
52
|
end
|
54
53
|
|
@@ -64,6 +63,7 @@ module Travis
|
|
64
63
|
ENV['TRAVIS_ENDPOINT']
|
65
64
|
else
|
66
65
|
repo_config['endpoint'] ||= begin
|
66
|
+
load_gh
|
67
67
|
GH.head("/repos/#{slug}")
|
68
68
|
Travis::Client::ORG_URI
|
69
69
|
rescue GH::Error
|
data/lib/travis/cli/setup.rb
CHANGED
@@ -1,142 +1,47 @@
|
|
1
1
|
require 'travis/cli'
|
2
|
-
require 'json'
|
3
|
-
require 'yaml'
|
4
2
|
|
5
3
|
module Travis
|
6
4
|
module CLI
|
7
5
|
class Setup < RepoCommand
|
6
|
+
autoload :CloudControl, 'travis/cli/setup/cloud_control'
|
7
|
+
autoload :CloudFoundry, 'travis/cli/setup/cloud_foundry'
|
8
|
+
autoload :EngineYard, 'travis/cli/setup/engine_yard'
|
9
|
+
autoload :Heroku, 'travis/cli/setup/heroku'
|
10
|
+
autoload :Nodejitsu, 'travis/cli/setup/nodejitsu'
|
11
|
+
autoload :OpenShift, 'travis/cli/setup/open_shift'
|
12
|
+
autoload :RubyGems, 'travis/cli/setup/ruby_gems'
|
13
|
+
autoload :SauceConnect, 'travis/cli/setup/sauce_connect'
|
14
|
+
autoload :Service, 'travis/cli/setup/service'
|
15
|
+
|
8
16
|
description "sets up an addon or deploy target"
|
9
17
|
on('-f', '--force', 'override config section if it already exists')
|
10
18
|
|
11
|
-
def
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
def setup_heroku
|
17
|
-
configure 'deploy', 'provider' => 'heroku' do |config|
|
18
|
-
config['api_key'] = `heroku auth:token 2>/dev/null`.strip
|
19
|
-
config['api_key'] = ask("Heroku API token: ") { |q| q.echo = "*" }.to_s if config['api_key'].empty?
|
20
|
-
config['app'] = `heroku apps:info 2>/dev/null`.scan(/^=== (.+)$/).flatten.first
|
21
|
-
config['app'] = ask("Heroku application name: ") { |q| q.default = repository.name }.to_s if config['app'].nil?
|
22
|
-
config['on'] = { 'repo' => repository.slug } if agree("Deploy only from #{repository.slug}? ") { |q| q.default = 'yes' }
|
23
|
-
encrypt(config, 'api_key') if agree("Encrypt API key? ") { |q| q.default = 'yes' }
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def setup_engineyard
|
28
|
-
configure 'deploy', 'provider' => 'engineyard' do |config|
|
29
|
-
eyrc = File.expand_path(".eyrc", Dir.home)
|
30
|
-
config['api_key'] = YAML.load_file(eyrc)["api_token"] if File.exists?(eyrc)
|
31
|
-
config['api_key'] = ask("API token: ") { |q| q.echo = "*" }.to_s unless config['api_key']
|
32
|
-
env = ask("Environment (optional): ").to_s
|
33
|
-
config['environment'] = env unless env.empty?
|
34
|
-
migrate = agree("Run migrations on deploy? ") { |q| q.default = 'yes' }
|
35
|
-
config['migrate'] = ask("Migration command: ") { |q| q.default = "rake db:migrate" } if migrate
|
36
|
-
config['on'] = { 'repo' => repository.slug } if agree("Deploy only from #{repository.slug}? ") { |q| q.default = 'yes' }
|
37
|
-
encrypt(config, 'api_key') if agree("Encrypt API key? ") { |q| q.default = 'yes' }
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def setup_openshift
|
42
|
-
configure 'deploy', 'provider' => 'openshift' do |config|
|
43
|
-
config['user'] = ask("OpenShift user: ").to_s
|
44
|
-
config['password'] = ask("OpenShift password: ") { |q| q.echo = "*" }.to_s
|
45
|
-
config['app'] = ask("OpenShift application name: ") { |q| q.default = repository.name }.to_s
|
46
|
-
config['domain'] = ask("OpenShift domain: ").to_s
|
47
|
-
config['on'] = { 'repo' => repository.slug } if agree("Deploy only from #{repository.slug}? ") { |q| q.default = 'yes' }
|
48
|
-
encrypt(config, 'password') if agree("Encrypt password? ") { |q| q.default = 'yes' }
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def setup_rubygems
|
53
|
-
configure 'deploy', 'provider' => 'rubygems' do |config|
|
54
|
-
authorization_file = File.expand_path('.rubygems/authorization', ENV['HOME'])
|
55
|
-
credentials_file = File.expand_path('.gem/credentials', ENV['HOME'])
|
56
|
-
|
57
|
-
config['api_key'] ||= File.read(authorization_file) if File.exist? authorization_file
|
58
|
-
config['api_key'] ||= YAML.load_file(credentials_file)[:rubygems_api_key] if File.exist? credentials_file
|
59
|
-
config['api_key'] ||= ask("RubyGems API token: ") { |q| q.echo = "*" }.to_s
|
60
|
-
config['gem'] ||= ask("Gem name: ") { |q| q.default = repository.name }.to_s
|
61
|
-
|
62
|
-
on("Release only from #{repository.slug}? ", config, 'repo' => repository.slug)
|
63
|
-
on("Release only tagged commits? ", config, 'tags' => true)
|
64
|
-
encrypt(config, 'api_key') if agree("Encrypt API key? ") { |q| q.default = 'yes' }
|
65
|
-
end
|
19
|
+
def self.service(name)
|
20
|
+
normal_name = Service.normalized_name(name)
|
21
|
+
const_name = constants(false).detect { |c| Service.normalized_name(c) == normal_name }
|
22
|
+
constant = const_get(const_name) if const_name
|
23
|
+
constant if constant and constant < Service and constant.known_as? name
|
66
24
|
end
|
67
25
|
|
68
|
-
def
|
69
|
-
|
70
|
-
jitsu_file = File.expand_path('.jitsuconf', ENV['HOME'])
|
71
|
-
|
72
|
-
if File.exist? jitsu_file
|
73
|
-
jitsu_conf = JSON.parse(File.read(jitsu_file))
|
74
|
-
config['user'] = jitsu_conf['username']
|
75
|
-
config['api_key'] = jitsu_conf['apiToken']
|
76
|
-
end
|
77
|
-
|
78
|
-
config['user'] ||= ask("Nodejitsu user: ").to_s
|
79
|
-
config['api_key'] ||= ask("Nodejitsu API token: ") { |q| q.echo = "*" }.to_s
|
80
|
-
config['on'] = { 'repo' => repository.slug } if agree("Deploy only from #{repository.slug}? ") { |q| q.default = 'yes' }
|
81
|
-
encrypt(config, 'api_key') if agree("Encrypt API key? ") { |q| q.default = 'yes' }
|
82
|
-
end
|
26
|
+
def self.services
|
27
|
+
constants(false).sort.map { |c| const_get(c) }.select { |c| c < Service }
|
83
28
|
end
|
84
29
|
|
85
|
-
def
|
86
|
-
|
87
|
-
|
88
|
-
config['username'] = ask("Sauce Labs user: ").to_s
|
89
|
-
config['access_key'] = ask("Sauce Labs access key: ") { |q| q.echo = "*" }.to_s
|
90
|
-
encrypt(config, 'access_key') if agree("Encrypt access key? ") { |q| q.default = 'yes' }
|
91
|
-
end
|
30
|
+
def help
|
31
|
+
services = self.class.services.map { |s| "\t" << color(s.service_name.ljust(20), :command) << color(s.description, :info) }.join("\n")
|
32
|
+
super("\nAvailable services:\n\n#{services}\n\n")
|
92
33
|
end
|
93
34
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
def setup_cloudcontrol
|
98
|
-
configure 'deploy', 'provider' => 'cloudcontrol' do |config|
|
99
|
-
config['email'] = ask("cloudControl email: ").to_s
|
100
|
-
config['password'] = ask("cloudControl password: ") { |q| q.echo = "*" }.to_s
|
101
|
-
app = ask("cloudControl application: ") { |q| q.default = repository.name }.to_s
|
102
|
-
dep = ask("cloudControl deployment: ") { |q| q.default = "default" }.to_s
|
103
|
-
config['deployment'] = "#{app}/#{dep}"
|
104
|
-
config['on'] = { 'repo' => repository.slug } if agree("Deploy only from #{repository.slug}? ") { |q| q.default = 'yes' }
|
105
|
-
encrypt(config, 'password') if agree("Encrypt password? ") { |q| q.default = 'yes' }
|
106
|
-
end
|
35
|
+
def run(service, file = travis_yaml)
|
36
|
+
service(service).run
|
37
|
+
save_travis_config(file)
|
107
38
|
end
|
108
39
|
|
109
|
-
def
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
config['password'] = ask("Cloud Foundry password: ") { |q| q.echo = "*" }.to_s
|
114
|
-
config['organization'] = ask("Cloud Foundry organization: ").to_s
|
115
|
-
config['space'] = ask("Cloud Foundry space: ").to_s
|
116
|
-
config['on'] = { 'repo' => repository.slug } if agree("Deploy only from #{repository.slug}? ") { |q| q.default = 'yes' }
|
117
|
-
encrypt(config, 'password') if agree("Encrypt password? ") { |q| q.default = 'yes' }
|
118
|
-
end
|
40
|
+
def service(name)
|
41
|
+
factory = self.class.service(name)
|
42
|
+
error("unknown service #{name}") unless factory
|
43
|
+
factory.new(self)
|
119
44
|
end
|
120
|
-
|
121
|
-
private
|
122
|
-
|
123
|
-
def on(question, config, condition)
|
124
|
-
return unless agree(question) { |q| q.default = 'yes' }
|
125
|
-
config['on'] ||= {}
|
126
|
-
config['on'].merge! condition
|
127
|
-
end
|
128
|
-
|
129
|
-
def encrypt(config, key)
|
130
|
-
encrypted = repository.encrypt(config.fetch(key))
|
131
|
-
config[key] = { 'secure' => encrypted }
|
132
|
-
end
|
133
|
-
|
134
|
-
def configure(key, value = {}, config = travis_config)
|
135
|
-
error "#{key} section already exists in .travis.yml, run with --force to override" if config.include? key and not force?
|
136
|
-
result = yield(config[key] = value)
|
137
|
-
save_travis_config
|
138
|
-
result
|
139
|
-
end
|
140
45
|
end
|
141
46
|
end
|
142
47
|
end
|