travis-akerl 1.8.9
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.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +2512 -0
- data/Rakefile +64 -0
- data/assets/cacert.pem +69 -0
- data/assets/init/c.yml +4 -0
- data/assets/init/clojure.yml +1 -0
- data/assets/init/cpp.yml +4 -0
- data/assets/init/erlang.yml +3 -0
- data/assets/init/go.yml +4 -0
- data/assets/init/groovy.yml +1 -0
- data/assets/init/haskell.yml +1 -0
- data/assets/init/java.yml +4 -0
- data/assets/init/node_js.yml +5 -0
- data/assets/init/objective-c.yml +1 -0
- data/assets/init/perl.yml +4 -0
- data/assets/init/php.yml +4 -0
- data/assets/init/python.yml +5 -0
- data/assets/init/ruby.yml +6 -0
- data/assets/init/scala.yml +4 -0
- data/assets/notifications/Travis CI.app/Contents/Info.plist +52 -0
- data/assets/notifications/Travis CI.app/Contents/MacOS/Travis CI +0 -0
- data/assets/notifications/Travis CI.app/Contents/PkgInfo +1 -0
- data/assets/notifications/Travis CI.app/Contents/Resources/Travis CI.icns +0 -0
- data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/Credits.rtf +29 -0
- data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
- data/assets/notifications/Travis CI.app/Contents/_CodeSignature/CodeResources +173 -0
- data/assets/notifications/Travis CI.app/Contents/embedded.provisionprofile +0 -0
- data/assets/notifications/icon.png +0 -0
- data/assets/travis.sh +163 -0
- data/assets/travis.sh.erb +64 -0
- data/bin/travis +18 -0
- data/examples/org_overview.rb +3 -0
- data/examples/pro_auth.rb +23 -0
- data/examples/stream.rb +6 -0
- data/lib/travis/auto_login.rb +3 -0
- data/lib/travis/cli/accounts.rb +31 -0
- data/lib/travis/cli/api_command.rb +182 -0
- data/lib/travis/cli/branches.rb +25 -0
- data/lib/travis/cli/cache.rb +76 -0
- data/lib/travis/cli/cancel.rb +18 -0
- data/lib/travis/cli/command.rb +422 -0
- data/lib/travis/cli/console.rb +33 -0
- data/lib/travis/cli/disable.rb +15 -0
- data/lib/travis/cli/enable.rb +31 -0
- data/lib/travis/cli/encrypt.rb +115 -0
- data/lib/travis/cli/encrypt_file.rb +140 -0
- data/lib/travis/cli/endpoint.rb +35 -0
- data/lib/travis/cli/env.rb +66 -0
- data/lib/travis/cli/help.rb +23 -0
- data/lib/travis/cli/history.rb +49 -0
- data/lib/travis/cli/init.rb +82 -0
- data/lib/travis/cli/lint.rb +49 -0
- data/lib/travis/cli/login.rb +76 -0
- data/lib/travis/cli/logout.rb +14 -0
- data/lib/travis/cli/logs.rb +65 -0
- data/lib/travis/cli/monitor.rb +111 -0
- data/lib/travis/cli/open.rb +39 -0
- data/lib/travis/cli/parser.rb +43 -0
- data/lib/travis/cli/pubkey.rb +30 -0
- data/lib/travis/cli/raw.rb +20 -0
- data/lib/travis/cli/repo_command.rb +154 -0
- data/lib/travis/cli/report.rb +101 -0
- data/lib/travis/cli/repos.rb +53 -0
- data/lib/travis/cli/requests.rb +47 -0
- data/lib/travis/cli/restart.rb +18 -0
- data/lib/travis/cli/settings.rb +79 -0
- data/lib/travis/cli/setup/anynines.rb +21 -0
- data/lib/travis/cli/setup/appfog.rb +19 -0
- data/lib/travis/cli/setup/artifacts.rb +23 -0
- data/lib/travis/cli/setup/biicode.rb +19 -0
- data/lib/travis/cli/setup/cloud_66.rb +20 -0
- data/lib/travis/cli/setup/cloud_control.rb +21 -0
- data/lib/travis/cli/setup/cloud_files.rb +20 -0
- data/lib/travis/cli/setup/cloud_foundry.rb +23 -0
- data/lib/travis/cli/setup/code_deploy.rb +55 -0
- data/lib/travis/cli/setup/deis.rb +20 -0
- data/lib/travis/cli/setup/divshot.rb +18 -0
- data/lib/travis/cli/setup/elastic_beanstalk.rb +23 -0
- data/lib/travis/cli/setup/engine_yard.rb +24 -0
- data/lib/travis/cli/setup/gcs.rb +22 -0
- data/lib/travis/cli/setup/hackage.rb +18 -0
- data/lib/travis/cli/setup/heroku.rb +20 -0
- data/lib/travis/cli/setup/modulus.rb +18 -0
- data/lib/travis/cli/setup/ninefold.rb +20 -0
- data/lib/travis/cli/setup/nodejitsu.rb +27 -0
- data/lib/travis/cli/setup/npm.rb +20 -0
- data/lib/travis/cli/setup/open_shift.rb +20 -0
- data/lib/travis/cli/setup/opsworks.rb +22 -0
- data/lib/travis/cli/setup/pypi.rb +22 -0
- data/lib/travis/cli/setup/releases.rb +35 -0
- data/lib/travis/cli/setup/ruby_gems.rb +25 -0
- data/lib/travis/cli/setup/s3.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/cli/setup.rb +66 -0
- data/lib/travis/cli/show.rb +57 -0
- data/lib/travis/cli/sshkey.rb +118 -0
- data/lib/travis/cli/status.rb +19 -0
- data/lib/travis/cli/sync.rb +30 -0
- data/lib/travis/cli/token.rb +14 -0
- data/lib/travis/cli/version.rb +17 -0
- data/lib/travis/cli/whatsup.rb +30 -0
- data/lib/travis/cli/whoami.rb +15 -0
- data/lib/travis/cli.rb +126 -0
- data/lib/travis/client/account.rb +56 -0
- data/lib/travis/client/artifact.rb +88 -0
- data/lib/travis/client/auto_login.rb +45 -0
- data/lib/travis/client/broadcast.rb +14 -0
- data/lib/travis/client/build.rb +47 -0
- data/lib/travis/client/cache.rb +25 -0
- data/lib/travis/client/commit.rb +28 -0
- data/lib/travis/client/entity.rb +238 -0
- data/lib/travis/client/env_var.rb +102 -0
- data/lib/travis/client/error.rb +38 -0
- data/lib/travis/client/has_uuid.rb +13 -0
- data/lib/travis/client/job.rb +61 -0
- data/lib/travis/client/lint_result.rb +25 -0
- data/lib/travis/client/listener.rb +183 -0
- data/lib/travis/client/methods.rb +104 -0
- data/lib/travis/client/namespace.rb +85 -0
- data/lib/travis/client/not_loadable.rb +13 -0
- data/lib/travis/client/repository.rb +224 -0
- data/lib/travis/client/request.rb +36 -0
- data/lib/travis/client/restartable.rb +23 -0
- data/lib/travis/client/session.rb +339 -0
- data/lib/travis/client/settings.rb +25 -0
- data/lib/travis/client/singleton_setting.rb +36 -0
- data/lib/travis/client/ssh_key.rb +11 -0
- data/lib/travis/client/states.rb +98 -0
- data/lib/travis/client/user.rb +67 -0
- data/lib/travis/client/weak_entity.rb +26 -0
- data/lib/travis/client.rb +38 -0
- data/lib/travis/pro/auto_login.rb +3 -0
- data/lib/travis/pro.rb +5 -0
- data/lib/travis/tools/assets.rb +21 -0
- data/lib/travis/tools/completion.rb +54 -0
- data/lib/travis/tools/formatter.rb +50 -0
- data/lib/travis/tools/github.rb +293 -0
- data/lib/travis/tools/notification.rb +69 -0
- data/lib/travis/tools/safe_string.rb +22 -0
- data/lib/travis/tools/ssl_key.rb +48 -0
- data/lib/travis/tools/system.rb +88 -0
- data/lib/travis/version.rb +3 -0
- data/lib/travis.rb +8 -0
- data/spec/cli/api_command_spec.rb +38 -0
- data/spec/cli/cancel_spec.rb +15 -0
- data/spec/cli/encrypt_spec.rb +49 -0
- data/spec/cli/endpoint_spec.rb +39 -0
- data/spec/cli/help_spec.rb +33 -0
- data/spec/cli/history_spec.rb +38 -0
- data/spec/cli/init_spec.rb +227 -0
- data/spec/cli/login_spec.rb +13 -0
- data/spec/cli/logs_spec.rb +8 -0
- data/spec/cli/open_spec.rb +33 -0
- data/spec/cli/repo_command_spec.rb +25 -0
- data/spec/cli/restart_spec.rb +15 -0
- data/spec/cli/setup_spec.rb +5 -0
- data/spec/cli/show_spec.rb +9 -0
- data/spec/cli/status_spec.rb +28 -0
- data/spec/cli/token_spec.rb +22 -0
- data/spec/cli/version_spec.rb +18 -0
- data/spec/cli/whoami_spec.rb +34 -0
- data/spec/client/account_spec.rb +32 -0
- data/spec/client/auto_login_spec.rb +25 -0
- data/spec/client/broadcast_spec.rb +10 -0
- data/spec/client/build_spec.rb +31 -0
- data/spec/client/commit_spec.rb +22 -0
- data/spec/client/job_spec.rb +30 -0
- data/spec/client/methods_spec.rb +15 -0
- data/spec/client/namespace_spec.rb +19 -0
- data/spec/client/repository_spec.rb +39 -0
- data/spec/client/session_spec.rb +165 -0
- data/spec/client/user_spec.rb +16 -0
- data/spec/client_spec.rb +17 -0
- data/spec/pro_spec.rb +10 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/fake_api.rb +731 -0
- data/spec/support/fake_github.rb +24 -0
- data/spec/support/fake_travis_config.yml +14 -0
- data/spec/support/helpers.rb +45 -0
- data/spec/travis_spec.rb +10 -0
- data/travis.gemspec +371 -0
- metadata +534 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
require 'travis/cli'
|
|
2
|
+
require 'travis/tools/notification'
|
|
3
|
+
|
|
4
|
+
module Travis
|
|
5
|
+
module CLI
|
|
6
|
+
class Monitor < ApiCommand
|
|
7
|
+
description "live monitor for what's going on"
|
|
8
|
+
on('-m', '--my-repos', 'Only monitor my own repositories')
|
|
9
|
+
|
|
10
|
+
on('-r', '--repo SLUG', 'monitor given repository (can be used more than once)') do |c, slug|
|
|
11
|
+
c.repos << slug
|
|
12
|
+
end
|
|
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
|
+
on('-b', '--builds', 'only monitor builds, not jobs')
|
|
20
|
+
on('-p', '--push', 'monitor push events')
|
|
21
|
+
on('-P', '--pull', 'monitor pull request events')
|
|
22
|
+
|
|
23
|
+
attr_reader :repos, :notification
|
|
24
|
+
|
|
25
|
+
def initialize(*)
|
|
26
|
+
@repos = []
|
|
27
|
+
super
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def setup
|
|
31
|
+
super
|
|
32
|
+
repos.map! { |r| repo(r) }
|
|
33
|
+
repos.concat(user.repositories) if my_repos?
|
|
34
|
+
setup_notification(!firehose? || :dummy) unless notification
|
|
35
|
+
debug "Using notifications: #{notification.class.name[/[^:]+$/]}"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def setup_notification(type = nil)
|
|
39
|
+
refuse = false
|
|
40
|
+
case type
|
|
41
|
+
when false then @notification = Tools::Notification.new(:dummy)
|
|
42
|
+
when nil, true then @notification = Tools::Notification.new
|
|
43
|
+
else
|
|
44
|
+
refuse = true
|
|
45
|
+
@notification = Tools::Notification.new(type)
|
|
46
|
+
end
|
|
47
|
+
rescue ArgumentError => e
|
|
48
|
+
@notification = Tools::Notification.new(:dummy)
|
|
49
|
+
error(e.message) if refuse
|
|
50
|
+
warn(e.message)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def description
|
|
54
|
+
case repos.size
|
|
55
|
+
when 0 then session.config['host']
|
|
56
|
+
when 1 then repos.first.slug
|
|
57
|
+
else "#{repos.size} repositories"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def events
|
|
62
|
+
events = %w[build:started build:finished]
|
|
63
|
+
events << 'job:started' << 'job:finished' unless builds?
|
|
64
|
+
events
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def firehose?
|
|
68
|
+
org? and repos.empty?
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def all?
|
|
72
|
+
!pull? and !push?
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def monitor?(entity)
|
|
76
|
+
return true if all?
|
|
77
|
+
entity.pull_request? ? pull? : push?
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def display(entity, time)
|
|
81
|
+
say [
|
|
82
|
+
color(formatter.time(time), entity.color),
|
|
83
|
+
color(entity.inspect_info, [entity.color, :bold]),
|
|
84
|
+
color(entity.state, entity.color),
|
|
85
|
+
color(entity.commit.subject, entity.color)
|
|
86
|
+
].join(" ")
|
|
87
|
+
notification.notify(entity.repository.slug, [
|
|
88
|
+
entity.class.name[/[^:]+$/],
|
|
89
|
+
entity.number,
|
|
90
|
+
entity.state + ":",
|
|
91
|
+
entity.commit.subject
|
|
92
|
+
].join(" "))
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def handle_event(event)
|
|
96
|
+
entity = event.job || event.build
|
|
97
|
+
time = entity.finished_at || entity.started_at
|
|
98
|
+
display(entity, time) if monitor? entity
|
|
99
|
+
rescue Travis::Client::Error => error
|
|
100
|
+
raise error if explode?
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def run
|
|
104
|
+
listen(*repos) do |listener|
|
|
105
|
+
listener.on_connect { say description, "Monitoring #{"builds for " if builds?}%s:" }
|
|
106
|
+
listener.on(*events) { |e| handle_event(e) }
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'travis/cli'
|
|
2
|
+
require 'launchy'
|
|
3
|
+
|
|
4
|
+
module Travis
|
|
5
|
+
module CLI
|
|
6
|
+
class Open < RepoCommand
|
|
7
|
+
description "opens a build or job in the browser"
|
|
8
|
+
|
|
9
|
+
on('-g', '--github', 'Open the corresponding project, compare view or pull request on GitHub')
|
|
10
|
+
on('-p', '--print', 'Print out the URL instead of opening it in a browser')
|
|
11
|
+
|
|
12
|
+
def run(number = nil)
|
|
13
|
+
url = url_for(number)
|
|
14
|
+
if print?
|
|
15
|
+
say url, "web view: %s"
|
|
16
|
+
else
|
|
17
|
+
Launchy.open(url)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def url_for(number)
|
|
24
|
+
return repo_url unless number
|
|
25
|
+
entity = job(number) || build(number)
|
|
26
|
+
error "could not find job or build #{repository.slug}##{number}" unless entity
|
|
27
|
+
github ? entity.commit.compare_url : "#{repo_url}/#{entity.class.many}/#{entity.id}"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def repo_url
|
|
31
|
+
"https://#{host}/#{slug}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def host
|
|
35
|
+
github ? "github.com" : session.config['host']
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require 'travis/cli'
|
|
2
|
+
require 'optparse'
|
|
3
|
+
|
|
4
|
+
module Travis
|
|
5
|
+
module CLI
|
|
6
|
+
module Parser
|
|
7
|
+
def on_initialize(&block)
|
|
8
|
+
@on_initialize ||= []
|
|
9
|
+
@on_initialize << block if block
|
|
10
|
+
if superclass.respond_to? :on_initialize
|
|
11
|
+
superclass.on_initialize + @on_initialize
|
|
12
|
+
else
|
|
13
|
+
@on_initialize
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def on(*args, &block)
|
|
18
|
+
block ||= begin
|
|
19
|
+
full_arg = args.detect { |a| a.start_with? '--' }
|
|
20
|
+
name = full_arg.gsub(/^--(\[no-\])?(\S+).*$/, '\2').gsub('-', '_')
|
|
21
|
+
attr_reader(name) unless method_defined? name
|
|
22
|
+
attr_writer(name) unless method_defined? "#{name}="
|
|
23
|
+
alias_method("#{name}?", name) unless method_defined? "#{name}?"
|
|
24
|
+
proc { |instance, value| instance.public_send("#{name}=", value) }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
on_initialize do |instance|
|
|
28
|
+
instance.parser.on(*args) do |value|
|
|
29
|
+
block.call(instance, value)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def new(*)
|
|
35
|
+
attr_accessor :parser unless method_defined? :parser
|
|
36
|
+
result = super
|
|
37
|
+
result.parser = OptionParser.new
|
|
38
|
+
on_initialize.each { |b| b[result] }
|
|
39
|
+
result
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
require 'travis/cli'
|
|
3
|
+
|
|
4
|
+
module Travis
|
|
5
|
+
module CLI
|
|
6
|
+
class Pubkey < RepoCommand
|
|
7
|
+
attr_accessor :key_format
|
|
8
|
+
description "prints out a repository's public key"
|
|
9
|
+
on('-p', '--pem', 'encode in format used by pem') { |c,_| c.key_format = :pem }
|
|
10
|
+
on('-f', '--fingerprint', 'display fingerprint') { |c,_| c.key_format = :fingerprint }
|
|
11
|
+
|
|
12
|
+
def run
|
|
13
|
+
error "#{key_format} format not supported by #{api_endpoint}" unless key
|
|
14
|
+
say key, "Public key for #{color(repository.slug, :info)}:\n\n%s", :bold
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
def key
|
|
20
|
+
key = repository.public_key
|
|
21
|
+
case self.key_format ||= :ssh
|
|
22
|
+
when :fingerprint then key.fingerprint
|
|
23
|
+
when :pem then key.to_s
|
|
24
|
+
when :ssh then key.to_ssh
|
|
25
|
+
else raise "unknown format #{key_format}"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require 'travis/cli'
|
|
2
|
+
require 'pp'
|
|
3
|
+
|
|
4
|
+
module Travis
|
|
5
|
+
module CLI
|
|
6
|
+
class Raw < ApiCommand
|
|
7
|
+
description "makes an (authenticated) API call and prints out the result"
|
|
8
|
+
|
|
9
|
+
skip :authenticate
|
|
10
|
+
on('--[no-]json', 'display as json')
|
|
11
|
+
|
|
12
|
+
def run(resource)
|
|
13
|
+
reply = session.get_raw(resource)
|
|
14
|
+
json? ? say(reply.to_json) : pp(reply)
|
|
15
|
+
rescue Travis::Client::NotFound
|
|
16
|
+
error "resource not found"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
require 'travis/cli'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
|
|
4
|
+
module Travis
|
|
5
|
+
module CLI
|
|
6
|
+
class RepoCommand < ApiCommand
|
|
7
|
+
GIT_REGEX = %r{/?(.*/.+?)(\.git)?$}
|
|
8
|
+
TRAVIS = %r{^https://(staging-)?api\.travis-ci\.(org|com)}
|
|
9
|
+
on('-r', '--repo SLUG', 'repository to use (will try to detect from current git clone)') { |c, slug| c.slug = slug }
|
|
10
|
+
on('-R', '--store-repo SLUG', 'like --repo, but remembers value for current directory') do |c, slug|
|
|
11
|
+
c.slug = slug
|
|
12
|
+
c.send(:store_slug, slug)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
attr_accessor :slug
|
|
16
|
+
abstract
|
|
17
|
+
|
|
18
|
+
def setup
|
|
19
|
+
setup_enterprise
|
|
20
|
+
error "Can't figure out GitHub repo name. Ensure you're in the repo directory, or specify the repo name via the -r option (e.g. travis <command> -r <owner>/<repo>)" unless self.slug ||= find_slug
|
|
21
|
+
error "GitHub repo name is invalid, it should be on the form 'owner/repo'" unless self.slug.include?("/")
|
|
22
|
+
self.api_endpoint = detect_api_endpoint
|
|
23
|
+
super
|
|
24
|
+
repository.load # makes sure we actually have access to the repo
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def repository
|
|
28
|
+
repo(slug)
|
|
29
|
+
rescue Travis::Client::NotFound
|
|
30
|
+
error "repository not known to #{api_endpoint}: #{color(slug, :important)}"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def build(number_or_id)
|
|
36
|
+
return super if number_or_id.is_a? Integer
|
|
37
|
+
repository.build(number_or_id)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def job(number_or_id)
|
|
41
|
+
return super if number_or_id.is_a? Integer
|
|
42
|
+
repository.job(number_or_id)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def branch(name)
|
|
46
|
+
repository.branch(name)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def last_build
|
|
50
|
+
repository.last_build or error("no build yet for #{slug}")
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def detected_endpoint?
|
|
54
|
+
!explicit_api_endpoint?
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def find_slug
|
|
58
|
+
load_slug || begin
|
|
59
|
+
slug = detect_slug
|
|
60
|
+
interactive? ? store_slug(slug) : slug if slug
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def detect_slug
|
|
65
|
+
git_head = `git name-rev --name-only HEAD 2>#{IO::NULL}`.chomp
|
|
66
|
+
git_remote = `git config --get branch.#{git_head}.remote 2>#{IO::NULL}`.chomp
|
|
67
|
+
git_remote = 'origin' if git_remote.empty?
|
|
68
|
+
git_info = `git ls-remote --get-url #{git_remote} 2>#{IO::NULL}`.chomp
|
|
69
|
+
|
|
70
|
+
if parse_remote(git_info) =~ GIT_REGEX
|
|
71
|
+
detectected_slug = $1
|
|
72
|
+
if interactive?
|
|
73
|
+
if agree("Detected repository as #{color(detectected_slug, :info)}, is this correct? ") { |q| q.default = 'yes' }
|
|
74
|
+
detectected_slug
|
|
75
|
+
else
|
|
76
|
+
ask("Repository slug (owner/name): ") { |q| q.default = detectected_slug }
|
|
77
|
+
end
|
|
78
|
+
else
|
|
79
|
+
info "detected repository as #{color(detectected_slug, :bold)}"
|
|
80
|
+
detectected_slug
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def parse_remote(url)
|
|
86
|
+
if url =~ /^git@[^:]+:/
|
|
87
|
+
path = url.split(':').last
|
|
88
|
+
path = "/#{path}" unless path.start_with?('/')
|
|
89
|
+
path
|
|
90
|
+
else
|
|
91
|
+
URI.parse(url).path
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def load_slug
|
|
96
|
+
stored = `git config --get travis.slug`.chomp
|
|
97
|
+
stored unless stored.empty?
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def store_slug(value)
|
|
101
|
+
`git config travis.slug #{value}` if value
|
|
102
|
+
value
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def repo_config
|
|
106
|
+
config['repos'] ||= {}
|
|
107
|
+
config['repos'][slug] ||= {}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def detect_api_endpoint
|
|
111
|
+
if explicit_api_endpoint? or enterprise?
|
|
112
|
+
repo_config['endpoint'] = api_endpoint
|
|
113
|
+
elsif ENV['TRAVIS_ENDPOINT']
|
|
114
|
+
ENV['TRAVIS_ENDPOINT']
|
|
115
|
+
elsif config['default_endpoint'] and config['default_endpoint'] !~ TRAVIS
|
|
116
|
+
repo_config['endpoint'] ||= config['default_endpoint']
|
|
117
|
+
else
|
|
118
|
+
repo_config['endpoint'] ||= begin
|
|
119
|
+
load_gh
|
|
120
|
+
GH.head("/repos/#{slug}")
|
|
121
|
+
Travis::Client::ORG_URI
|
|
122
|
+
rescue GH::Error
|
|
123
|
+
Travis::Client::COM_URI
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def travis_config
|
|
129
|
+
@travis_config ||= begin
|
|
130
|
+
payload = YAML.load_file(travis_yaml)
|
|
131
|
+
payload.respond_to?(:to_hash) ? payload.to_hash : {}
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def travis_yaml(dir = Dir.pwd)
|
|
136
|
+
path = File.expand_path('.travis.yml', dir)
|
|
137
|
+
if File.exist? path
|
|
138
|
+
path
|
|
139
|
+
else
|
|
140
|
+
parent = File.expand_path('..', dir)
|
|
141
|
+
error "no .travis.yml found" if parent == dir
|
|
142
|
+
travis_yaml(parent)
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def save_travis_config(file = travis_yaml)
|
|
147
|
+
yaml = travis_config.to_yaml
|
|
148
|
+
yaml.gsub! /^(\s+)('on'|true):/, "\\1on:"
|
|
149
|
+
yaml.gsub! /\A---\s*\n/, ''
|
|
150
|
+
File.write(file, yaml)
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
require 'travis/cli'
|
|
2
|
+
require 'travis/tools/system'
|
|
3
|
+
|
|
4
|
+
module Travis
|
|
5
|
+
module CLI
|
|
6
|
+
class Report < ApiCommand
|
|
7
|
+
description "generates a report useful for filing issues"
|
|
8
|
+
on '-r', '--known-repos', 'include repositories in report'
|
|
9
|
+
skip :authenticate, :clear_error
|
|
10
|
+
|
|
11
|
+
def run
|
|
12
|
+
display("System", :general)
|
|
13
|
+
display("CLI", :cli_info)
|
|
14
|
+
display("Session", :session_info)
|
|
15
|
+
display("Endpoints", :endpoints)
|
|
16
|
+
display("Known Repositories", :known_repos) if known_repos?
|
|
17
|
+
display_error
|
|
18
|
+
say "For issues with the command line tool, please visit #{color("https://github.com/travis-ci/travis.rb/issues", :underline)}."
|
|
19
|
+
say "For Travis CI in general, go to #{color("https://github.com/travis-ci/travis-ci/issues", :underline)} or email #{color("support@travis-ci.com", :underline)}."
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def display_error
|
|
23
|
+
return unless error = load_file("error.log")
|
|
24
|
+
display("Last Exception", :say, color(error, :info))
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def display(title, method, *args)
|
|
28
|
+
say color(title, [:bold, :underline])
|
|
29
|
+
send(method, *args) { |*a| list(*a) }
|
|
30
|
+
puts
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def list(key, value, additional = nil)
|
|
34
|
+
value = case value
|
|
35
|
+
when Array then value.empty? ? 'none' : value.map(&:inspect).join(", ")
|
|
36
|
+
when true then "yes"
|
|
37
|
+
when false then "no"
|
|
38
|
+
when nil then "unknown"
|
|
39
|
+
else value.to_s
|
|
40
|
+
end
|
|
41
|
+
additional &&= " (#{additional})"
|
|
42
|
+
say "#{key}:".ljust(known_repos? ? 50 : 25) << " " << color(value.to_s, :bold) << additional.to_s
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def general
|
|
46
|
+
yield "Ruby", Tools::System.ruby
|
|
47
|
+
yield "Operating System", Tools::System.os
|
|
48
|
+
yield "RubyGems", Tools::System.rubygems
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def cli_info
|
|
52
|
+
yield "Version", Travis::VERSION
|
|
53
|
+
yield "Plugins", defined?(TRAVIS_PLUGINS) ? TRAVIS_PLUGINS : []
|
|
54
|
+
yield "Auto-Completion", Tools::Completion.completion_installed?
|
|
55
|
+
yield "Last Version Check", last_check['at'] ? Time.at(last_check['at']) : 'never'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def session_info
|
|
59
|
+
yield "API Endpoint", api_endpoint
|
|
60
|
+
yield "Logged In", user_info
|
|
61
|
+
yield "Verify SSL", !insecure
|
|
62
|
+
yield "Enterprise", enterprise?
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def endpoints
|
|
66
|
+
config['endpoints'].each do |endpoint, info|
|
|
67
|
+
info = [
|
|
68
|
+
info['access_token'] ? 'access token' : nil,
|
|
69
|
+
info['insecure'] ? 'insecure' : nil,
|
|
70
|
+
default_endpoint == endpoint ? 'default' : nil,
|
|
71
|
+
endpoint == api_endpoint ? 'current' : nil
|
|
72
|
+
].compact
|
|
73
|
+
yield endpoint_name(endpoint), endpoint, info.join(', ')
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def endpoint_name(url, prefix = "")
|
|
78
|
+
case url
|
|
79
|
+
when Travis::Client::ORG_URI then "#{prefix}org"
|
|
80
|
+
when Travis::Client::COM_URI then "#{prefix}com"
|
|
81
|
+
when /api-staging\.travis-ci/ then endpoint_name(url.sub("api-staging.", "api."), "staging-")
|
|
82
|
+
else
|
|
83
|
+
key, _ = config['enterprise'].detect { |k,v| v.start_with? url } if config['enterprise'].respond_to?(:detect)
|
|
84
|
+
key ? "enterprise %p" % key : "???"
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def known_repos
|
|
89
|
+
config["repos"].each do |key, info|
|
|
90
|
+
yield key, info['endpoint']
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def user_info
|
|
95
|
+
access_token ? "as %p" % user.login : "no"
|
|
96
|
+
rescue Travis::Client::Error => e
|
|
97
|
+
e.message
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
require 'travis/cli'
|
|
2
|
+
|
|
3
|
+
module Travis
|
|
4
|
+
module CLI
|
|
5
|
+
class Repos < ApiCommand
|
|
6
|
+
description "lists repositories the user has certain permissions on"
|
|
7
|
+
on('-m', '--match PATTERN', 'only list repositories matching the given pattern (shell style)')
|
|
8
|
+
on('-o', '--owner LOGIN', 'only list repos for a certain owner')
|
|
9
|
+
on('-n', '--name NAME', 'only list repos with a given name')
|
|
10
|
+
on('-a', '--active', 'only list active repositories')
|
|
11
|
+
on('-A', '--inactive', 'only list inactive repositories') { |c| c.active = false }
|
|
12
|
+
on('-d', '--admin', 'only list repos with (or without) admin access')
|
|
13
|
+
on('-D', '--no-admin', 'only list repos without admin access') { |c| c.admin = false }
|
|
14
|
+
|
|
15
|
+
def run
|
|
16
|
+
repositories.each do |repo|
|
|
17
|
+
next say(repo.slug) unless interactive?
|
|
18
|
+
state_color = repo.active? ? :green : :yellow
|
|
19
|
+
say color(repo.slug, [:bold, state_color]) + " "
|
|
20
|
+
say color("(" << attributes(repo).map { |n,v| "#{n}: #{v ? "yes" : "no"}" }.join(", ") << ")", state_color)
|
|
21
|
+
description = repo.description.lines.first.chomp unless repo.description.to_s.empty?
|
|
22
|
+
say "Description: #{description || "???"}"
|
|
23
|
+
empty_line unless repo == repositories.last
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def repositories
|
|
28
|
+
@repositories ||= begin
|
|
29
|
+
repos = session.hooks.concat(user.repositories).uniq
|
|
30
|
+
session.preload(repos).sort_by(&:slug).select do |repo|
|
|
31
|
+
next false unless match? repo.slug
|
|
32
|
+
next false unless active.nil? or repo.active? == active
|
|
33
|
+
next false unless owner.nil? or repo.owner_name == owner
|
|
34
|
+
next false unless name.nil? or repo.name == name
|
|
35
|
+
next false unless admin.nil? or repo.admin? == admin
|
|
36
|
+
true
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def attributes(repo)
|
|
42
|
+
{ "active" => repo.active?, "admin" => repo.admin?, "push" => repo.push?, "pull" => repo.pull? }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def match?(string)
|
|
46
|
+
return true if match.nil?
|
|
47
|
+
flags = File::FNM_PATHNAME | File::FNM_DOTMATCH
|
|
48
|
+
flags |= File::FNM_EXTGLOB if defined? File::FNM_EXTGLOB
|
|
49
|
+
File.fnmatch?(match, string, flags)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
require 'travis/cli'
|
|
2
|
+
|
|
3
|
+
module Travis
|
|
4
|
+
module CLI
|
|
5
|
+
class Requests < RepoCommand
|
|
6
|
+
description "lists recent requests"
|
|
7
|
+
on '-l', '--limit LIMIT', 'Maximum number requests to display'
|
|
8
|
+
|
|
9
|
+
def run
|
|
10
|
+
requests = repository.requests
|
|
11
|
+
requests = requests[0, Integer(limit)] if limit
|
|
12
|
+
requests.each do |request|
|
|
13
|
+
style ||= :success if request.accepted?
|
|
14
|
+
style ||= :error if request.rejected?
|
|
15
|
+
style ||= :info
|
|
16
|
+
|
|
17
|
+
case request.event_type
|
|
18
|
+
when 'push'
|
|
19
|
+
result = request.result || "received"
|
|
20
|
+
message = request.message
|
|
21
|
+
message ||= "validation pending" unless request.rejected? or request.accepted?
|
|
22
|
+
message ||= "unknown reason" unless request.accepted?
|
|
23
|
+
message ||= "triggered new build" unless request.rejected?
|
|
24
|
+
description = "push to #{request.branch || request.tag || "???"}"
|
|
25
|
+
when 'pull_request'
|
|
26
|
+
result = request.result || "received"
|
|
27
|
+
message = request.message
|
|
28
|
+
message ||= "HEAD commit not updated" unless request.accepted?
|
|
29
|
+
message ||= "triggered new build" unless request.rejected?
|
|
30
|
+
description = "push to #{request.branch || request.tag || "???"}"
|
|
31
|
+
description = "PR ##{request.pull_request_number}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
say [
|
|
35
|
+
color(description, [:bold, style]),
|
|
36
|
+
color(result, style),
|
|
37
|
+
color("(#{message})", style)
|
|
38
|
+
].join(" ").strip + "\n"
|
|
39
|
+
|
|
40
|
+
say " " + color(request.commit.short_sha, :bold) + " - " + request.commit.subject if request.commit
|
|
41
|
+
say " received at: #{formatter.time(request.created_at)}"
|
|
42
|
+
empty_line
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
require 'travis/cli'
|
|
2
|
+
|
|
3
|
+
module Travis
|
|
4
|
+
module CLI
|
|
5
|
+
class Restart < RepoCommand
|
|
6
|
+
description "restarts a build or job"
|
|
7
|
+
|
|
8
|
+
def run(number = last_build.number)
|
|
9
|
+
authenticate
|
|
10
|
+
entity = job(number) || build(number)
|
|
11
|
+
error "could not find job or build #{repository.slug}##{number}" unless entity
|
|
12
|
+
entity.restart
|
|
13
|
+
|
|
14
|
+
say "restarted", "#{entity.class.one} ##{entity.number} has been %s"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|