travis-akerl 1.8.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (185) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +2512 -0
  4. data/Rakefile +64 -0
  5. data/assets/cacert.pem +69 -0
  6. data/assets/init/c.yml +4 -0
  7. data/assets/init/clojure.yml +1 -0
  8. data/assets/init/cpp.yml +4 -0
  9. data/assets/init/erlang.yml +3 -0
  10. data/assets/init/go.yml +4 -0
  11. data/assets/init/groovy.yml +1 -0
  12. data/assets/init/haskell.yml +1 -0
  13. data/assets/init/java.yml +4 -0
  14. data/assets/init/node_js.yml +5 -0
  15. data/assets/init/objective-c.yml +1 -0
  16. data/assets/init/perl.yml +4 -0
  17. data/assets/init/php.yml +4 -0
  18. data/assets/init/python.yml +5 -0
  19. data/assets/init/ruby.yml +6 -0
  20. data/assets/init/scala.yml +4 -0
  21. data/assets/notifications/Travis CI.app/Contents/Info.plist +52 -0
  22. data/assets/notifications/Travis CI.app/Contents/MacOS/Travis CI +0 -0
  23. data/assets/notifications/Travis CI.app/Contents/PkgInfo +1 -0
  24. data/assets/notifications/Travis CI.app/Contents/Resources/Travis CI.icns +0 -0
  25. data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/Credits.rtf +29 -0
  26. data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
  27. data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
  28. data/assets/notifications/Travis CI.app/Contents/_CodeSignature/CodeResources +173 -0
  29. data/assets/notifications/Travis CI.app/Contents/embedded.provisionprofile +0 -0
  30. data/assets/notifications/icon.png +0 -0
  31. data/assets/travis.sh +163 -0
  32. data/assets/travis.sh.erb +64 -0
  33. data/bin/travis +18 -0
  34. data/examples/org_overview.rb +3 -0
  35. data/examples/pro_auth.rb +23 -0
  36. data/examples/stream.rb +6 -0
  37. data/lib/travis/auto_login.rb +3 -0
  38. data/lib/travis/cli/accounts.rb +31 -0
  39. data/lib/travis/cli/api_command.rb +182 -0
  40. data/lib/travis/cli/branches.rb +25 -0
  41. data/lib/travis/cli/cache.rb +76 -0
  42. data/lib/travis/cli/cancel.rb +18 -0
  43. data/lib/travis/cli/command.rb +422 -0
  44. data/lib/travis/cli/console.rb +33 -0
  45. data/lib/travis/cli/disable.rb +15 -0
  46. data/lib/travis/cli/enable.rb +31 -0
  47. data/lib/travis/cli/encrypt.rb +115 -0
  48. data/lib/travis/cli/encrypt_file.rb +140 -0
  49. data/lib/travis/cli/endpoint.rb +35 -0
  50. data/lib/travis/cli/env.rb +66 -0
  51. data/lib/travis/cli/help.rb +23 -0
  52. data/lib/travis/cli/history.rb +49 -0
  53. data/lib/travis/cli/init.rb +82 -0
  54. data/lib/travis/cli/lint.rb +49 -0
  55. data/lib/travis/cli/login.rb +76 -0
  56. data/lib/travis/cli/logout.rb +14 -0
  57. data/lib/travis/cli/logs.rb +65 -0
  58. data/lib/travis/cli/monitor.rb +111 -0
  59. data/lib/travis/cli/open.rb +39 -0
  60. data/lib/travis/cli/parser.rb +43 -0
  61. data/lib/travis/cli/pubkey.rb +30 -0
  62. data/lib/travis/cli/raw.rb +20 -0
  63. data/lib/travis/cli/repo_command.rb +154 -0
  64. data/lib/travis/cli/report.rb +101 -0
  65. data/lib/travis/cli/repos.rb +53 -0
  66. data/lib/travis/cli/requests.rb +47 -0
  67. data/lib/travis/cli/restart.rb +18 -0
  68. data/lib/travis/cli/settings.rb +79 -0
  69. data/lib/travis/cli/setup/anynines.rb +21 -0
  70. data/lib/travis/cli/setup/appfog.rb +19 -0
  71. data/lib/travis/cli/setup/artifacts.rb +23 -0
  72. data/lib/travis/cli/setup/biicode.rb +19 -0
  73. data/lib/travis/cli/setup/cloud_66.rb +20 -0
  74. data/lib/travis/cli/setup/cloud_control.rb +21 -0
  75. data/lib/travis/cli/setup/cloud_files.rb +20 -0
  76. data/lib/travis/cli/setup/cloud_foundry.rb +23 -0
  77. data/lib/travis/cli/setup/code_deploy.rb +55 -0
  78. data/lib/travis/cli/setup/deis.rb +20 -0
  79. data/lib/travis/cli/setup/divshot.rb +18 -0
  80. data/lib/travis/cli/setup/elastic_beanstalk.rb +23 -0
  81. data/lib/travis/cli/setup/engine_yard.rb +24 -0
  82. data/lib/travis/cli/setup/gcs.rb +22 -0
  83. data/lib/travis/cli/setup/hackage.rb +18 -0
  84. data/lib/travis/cli/setup/heroku.rb +20 -0
  85. data/lib/travis/cli/setup/modulus.rb +18 -0
  86. data/lib/travis/cli/setup/ninefold.rb +20 -0
  87. data/lib/travis/cli/setup/nodejitsu.rb +27 -0
  88. data/lib/travis/cli/setup/npm.rb +20 -0
  89. data/lib/travis/cli/setup/open_shift.rb +20 -0
  90. data/lib/travis/cli/setup/opsworks.rb +22 -0
  91. data/lib/travis/cli/setup/pypi.rb +22 -0
  92. data/lib/travis/cli/setup/releases.rb +35 -0
  93. data/lib/travis/cli/setup/ruby_gems.rb +25 -0
  94. data/lib/travis/cli/setup/s3.rb +25 -0
  95. data/lib/travis/cli/setup/sauce_connect.rb +21 -0
  96. data/lib/travis/cli/setup/service.rb +73 -0
  97. data/lib/travis/cli/setup.rb +66 -0
  98. data/lib/travis/cli/show.rb +57 -0
  99. data/lib/travis/cli/sshkey.rb +118 -0
  100. data/lib/travis/cli/status.rb +19 -0
  101. data/lib/travis/cli/sync.rb +30 -0
  102. data/lib/travis/cli/token.rb +14 -0
  103. data/lib/travis/cli/version.rb +17 -0
  104. data/lib/travis/cli/whatsup.rb +30 -0
  105. data/lib/travis/cli/whoami.rb +15 -0
  106. data/lib/travis/cli.rb +126 -0
  107. data/lib/travis/client/account.rb +56 -0
  108. data/lib/travis/client/artifact.rb +88 -0
  109. data/lib/travis/client/auto_login.rb +45 -0
  110. data/lib/travis/client/broadcast.rb +14 -0
  111. data/lib/travis/client/build.rb +47 -0
  112. data/lib/travis/client/cache.rb +25 -0
  113. data/lib/travis/client/commit.rb +28 -0
  114. data/lib/travis/client/entity.rb +238 -0
  115. data/lib/travis/client/env_var.rb +102 -0
  116. data/lib/travis/client/error.rb +38 -0
  117. data/lib/travis/client/has_uuid.rb +13 -0
  118. data/lib/travis/client/job.rb +61 -0
  119. data/lib/travis/client/lint_result.rb +25 -0
  120. data/lib/travis/client/listener.rb +183 -0
  121. data/lib/travis/client/methods.rb +104 -0
  122. data/lib/travis/client/namespace.rb +85 -0
  123. data/lib/travis/client/not_loadable.rb +13 -0
  124. data/lib/travis/client/repository.rb +224 -0
  125. data/lib/travis/client/request.rb +36 -0
  126. data/lib/travis/client/restartable.rb +23 -0
  127. data/lib/travis/client/session.rb +339 -0
  128. data/lib/travis/client/settings.rb +25 -0
  129. data/lib/travis/client/singleton_setting.rb +36 -0
  130. data/lib/travis/client/ssh_key.rb +11 -0
  131. data/lib/travis/client/states.rb +98 -0
  132. data/lib/travis/client/user.rb +67 -0
  133. data/lib/travis/client/weak_entity.rb +26 -0
  134. data/lib/travis/client.rb +38 -0
  135. data/lib/travis/pro/auto_login.rb +3 -0
  136. data/lib/travis/pro.rb +5 -0
  137. data/lib/travis/tools/assets.rb +21 -0
  138. data/lib/travis/tools/completion.rb +54 -0
  139. data/lib/travis/tools/formatter.rb +50 -0
  140. data/lib/travis/tools/github.rb +293 -0
  141. data/lib/travis/tools/notification.rb +69 -0
  142. data/lib/travis/tools/safe_string.rb +22 -0
  143. data/lib/travis/tools/ssl_key.rb +48 -0
  144. data/lib/travis/tools/system.rb +88 -0
  145. data/lib/travis/version.rb +3 -0
  146. data/lib/travis.rb +8 -0
  147. data/spec/cli/api_command_spec.rb +38 -0
  148. data/spec/cli/cancel_spec.rb +15 -0
  149. data/spec/cli/encrypt_spec.rb +49 -0
  150. data/spec/cli/endpoint_spec.rb +39 -0
  151. data/spec/cli/help_spec.rb +33 -0
  152. data/spec/cli/history_spec.rb +38 -0
  153. data/spec/cli/init_spec.rb +227 -0
  154. data/spec/cli/login_spec.rb +13 -0
  155. data/spec/cli/logs_spec.rb +8 -0
  156. data/spec/cli/open_spec.rb +33 -0
  157. data/spec/cli/repo_command_spec.rb +25 -0
  158. data/spec/cli/restart_spec.rb +15 -0
  159. data/spec/cli/setup_spec.rb +5 -0
  160. data/spec/cli/show_spec.rb +9 -0
  161. data/spec/cli/status_spec.rb +28 -0
  162. data/spec/cli/token_spec.rb +22 -0
  163. data/spec/cli/version_spec.rb +18 -0
  164. data/spec/cli/whoami_spec.rb +34 -0
  165. data/spec/client/account_spec.rb +32 -0
  166. data/spec/client/auto_login_spec.rb +25 -0
  167. data/spec/client/broadcast_spec.rb +10 -0
  168. data/spec/client/build_spec.rb +31 -0
  169. data/spec/client/commit_spec.rb +22 -0
  170. data/spec/client/job_spec.rb +30 -0
  171. data/spec/client/methods_spec.rb +15 -0
  172. data/spec/client/namespace_spec.rb +19 -0
  173. data/spec/client/repository_spec.rb +39 -0
  174. data/spec/client/session_spec.rb +165 -0
  175. data/spec/client/user_spec.rb +16 -0
  176. data/spec/client_spec.rb +17 -0
  177. data/spec/pro_spec.rb +10 -0
  178. data/spec/spec_helper.rb +29 -0
  179. data/spec/support/fake_api.rb +731 -0
  180. data/spec/support/fake_github.rb +24 -0
  181. data/spec/support/fake_travis_config.yml +14 -0
  182. data/spec/support/helpers.rb +45 -0
  183. data/spec/travis_spec.rb +10 -0
  184. data/travis.gemspec +371 -0
  185. metadata +534 -0
@@ -0,0 +1,25 @@
1
+ require 'travis/cli/setup'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Setup
6
+ class RubyGems < Service
7
+ description "automatic release to RubyGems"
8
+
9
+ def run
10
+ deploy 'rubygems', 'release' do |config|
11
+ authorization_file = File.expand_path('.rubygems/authorization', ENV['HOME'])
12
+ credentials_file = File.expand_path('.gem/credentials', ENV['HOME'])
13
+
14
+ config['api_key'] ||= File.read(authorization_file) if File.exist? authorization_file
15
+ config['api_key'] ||= YAML.load_file(credentials_file)[:rubygems_api_key] if File.exist? credentials_file
16
+ config['api_key'] ||= ask("RubyGems API token: ") { |q| q.echo = "*" }.to_s
17
+ config['gem'] ||= ask("Gem name: ") { |q| q.default = repository.name }.to_s
18
+
19
+ on("Release only tagged commits? ", config, 'tags' => true)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'travis/cli/setup'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Setup
6
+ class S3 < Service
7
+ description "automatic pushing to S3"
8
+
9
+ def run
10
+ deploy 's3', 'push' do |config|
11
+ config['access_key_id'] = ask("Access key ID: ").to_s
12
+ config['secret_access_key'] = ask("Secret access key: ") { |q| q.echo = "*" }.to_s
13
+ config['bucket'] = ask("Bucket: ").to_s
14
+ local_dir = ask("Local project directory to upload (Optional): ").to_s
15
+ config['local-dir'] = local_dir unless local_dir.empty?
16
+ upload_dir = ask("S3 upload directory (Optional): ").to_s
17
+ config['upload-dir'] = upload_dir unless upload_dir.empty?
18
+ config['acl'] = ask("S3 ACL Settings (private, public_read, public_read_write, authenticated_read, bucket_owner_read, bucket_owner_full_control): ").to_s { |q| q.default = 'private'}
19
+ encrypt(config, 'secret_access_key') if agree("Encrypt secret access key? ") { |q| q.default = 'yes' }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ require 'travis/cli/setup'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Setup
6
+ class SauceConnect < Service
7
+ description "Sauce Connet addon for Sauce Labs integration"
8
+ service_name "sauce_connect"
9
+
10
+ def run
11
+ travis_config['addons'] ||= {}
12
+ configure 'sauce_connect', {}, travis_config['addons'] do |config|
13
+ config['username'] = ask("Sauce Labs user: ").to_s
14
+ config['access_key'] = ask("Sauce Labs access key: ") { |q| q.echo = "*" }.to_s
15
+ encrypt(config, 'access_key') if agree("Encrypt access key? ") { |q| q.default = 'yes' }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,73 @@
1
+ require 'travis/cli/setup'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Setup
6
+ class Service
7
+ def self.normalized_name(string)
8
+ string.to_s.downcase.gsub(/[^a-z\d]/, '')
9
+ end
10
+
11
+ def self.description(description = nil)
12
+ @description ||= ""
13
+ @description = description if description
14
+ @description
15
+ end
16
+
17
+ def self.service_name(service_name = nil)
18
+ @service_name ||= normalized_name(name[/[^:]+$/])
19
+ @service_name = service_name if service_name
20
+ @service_name
21
+ end
22
+
23
+ def self.known_as?(name)
24
+ normalized_name(service_name) == normalized_name(name)
25
+ end
26
+
27
+ attr_accessor :command
28
+
29
+ def initialize(command)
30
+ @command = command
31
+ end
32
+
33
+ def method_missing(*args, &block)
34
+ @command.send(*args, &block)
35
+ end
36
+
37
+ private
38
+
39
+ def on(question, config, condition)
40
+ return unless agree(question) { |q| q.default = 'yes' }
41
+ config['on'] ||= {}
42
+ config['on'].merge! condition
43
+ end
44
+
45
+ def encrypt(config, key)
46
+ encrypted = repository.encrypt(config.fetch(key))
47
+ config[key] = { 'secure' => encrypted }
48
+ end
49
+
50
+ def configure(key, value = {}, config = travis_config)
51
+ error "#{key} section already exists in .travis.yml, run with --force to override" if config.include? key and not force?
52
+ yield(config[key] = value)
53
+ end
54
+
55
+ def branch
56
+ @branch ||= `git rev-parse --symbolic-full-name --abbrev-ref HEAD`.chomp
57
+ end
58
+
59
+ def deploy(provider, verb = "deploy")
60
+ configure('deploy', 'provider' => provider) do |config|
61
+ yield config
62
+
63
+ on("#{verb.capitalize} only from #{repository.slug}? ", config, 'repo' => repository.slug)
64
+ on("#{verb.capitalize} from #{branch} branch? ", config, 'branch' => branch) if branch != 'master' and branch != 'HEAD'
65
+
66
+ encrypt(config, 'password') if config['password'] and agree("Encrypt Password? ") { |q| q.default = 'yes' }
67
+ encrypt(config, 'api_key') if config['api_key'] and agree("Encrypt API key? ") { |q| q.default = 'yes' }
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,66 @@
1
+ require 'travis/cli'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Setup < RepoCommand
6
+ autoload :Anynines, 'travis/cli/setup/anynines'
7
+ autoload :Appfog, 'travis/cli/setup/appfog'
8
+ autoload :Artifacts, 'travis/cli/setup/artifacts'
9
+ autoload :Biicode, 'travis/cli/setup/biicode'
10
+ autoload :CloudControl, 'travis/cli/setup/cloud_control'
11
+ autoload :CloudFoundry, 'travis/cli/setup/cloud_foundry'
12
+ autoload :CodeDeploy, 'travis/cli/setup/code_deploy'
13
+ autoload :EngineYard, 'travis/cli/setup/engine_yard'
14
+ autoload :Heroku, 'travis/cli/setup/heroku'
15
+ autoload :Nodejitsu, 'travis/cli/setup/nodejitsu'
16
+ autoload :NPM, 'travis/cli/setup/npm'
17
+ autoload :OpenShift, 'travis/cli/setup/open_shift'
18
+ autoload :PyPI, 'travis/cli/setup/pypi'
19
+ autoload :RubyGems, 'travis/cli/setup/ruby_gems'
20
+ autoload :Ninefold, 'travis/cli/setup/ninefold'
21
+ autoload :S3, 'travis/cli/setup/s3'
22
+ autoload :CloudFiles, 'travis/cli/setup/cloud_files'
23
+ autoload :Divshot, 'travis/cli/setup/divshot'
24
+ autoload :Hackage, 'travis/cli/setup/hackage'
25
+ autoload :OpsWorks, 'travis/cli/setup/opsworks'
26
+ autoload :SauceConnect, 'travis/cli/setup/sauce_connect'
27
+ autoload :Modulus, 'travis/cli/setup/modulus'
28
+ autoload :Releases, 'travis/cli/setup/releases'
29
+ autoload :GCS, 'travis/cli/setup/gcs'
30
+ autoload :Cloud_66, 'travis/cli/setup/cloud_66'
31
+ autoload :ElasticBeanstalk, 'travis/cli/setup/elastic_beanstalk'
32
+ autoload :Deis, 'travis/cli/setup/deis'
33
+ autoload :Service, 'travis/cli/setup/service'
34
+
35
+ description "sets up an addon or deploy target"
36
+ on('-f', '--force', 'override config section if it already exists')
37
+
38
+ def self.service(name)
39
+ normal_name = Service.normalized_name(name)
40
+ const_name = constants(false).detect { |c| Service.normalized_name(c) == normal_name }
41
+ constant = const_get(const_name) if const_name
42
+ constant if constant and constant < Service and constant.known_as? name
43
+ end
44
+
45
+ def self.services
46
+ constants(false).sort.map { |c| const_get(c) }.select { |c| c < Service }
47
+ end
48
+
49
+ def help
50
+ services = self.class.services.map { |s| "\t" << color(s.service_name.ljust(20), :command) << color(s.description, :info) }.join("\n")
51
+ super("\nAvailable services:\n\n#{services}\n\n")
52
+ end
53
+
54
+ def run(service, file = travis_yaml)
55
+ service(service).run
56
+ save_travis_config(file)
57
+ end
58
+
59
+ def service(name)
60
+ factory = self.class.service(name)
61
+ error("unknown service #{name}") unless factory
62
+ factory.new(self)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,57 @@
1
+ require 'travis/cli'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Show < RepoCommand
6
+ description "displays a build or job"
7
+
8
+ def run(number = last_build.number)
9
+ number = repository.branch(number).number if number !~ /^\d+(\.\d+)?$/ and repository.branch(number)
10
+ entity = job(number) || build(number)
11
+
12
+ error "could not find job or build #{repository.slug}##{number}" unless entity
13
+
14
+ say template(__FILE__) % [
15
+ entity.class.one.capitalize,
16
+ entity.number,
17
+ entity.commit.subject,
18
+ entity.state,
19
+ entity.color,
20
+ entity.pull_request? ? "pull request" : "push",
21
+ entity.branch_info,
22
+ entity.commit.compare_url,
23
+ formatter.duration(entity.duration),
24
+ formatter.time(entity.started_at),
25
+ formatter.time(entity.finished_at)
26
+ ]
27
+
28
+ if entity.respond_to? :jobs
29
+ empty_line
30
+ entity.jobs.each do |job|
31
+ say [
32
+ color("##{job.number} #{job.state}:".ljust(16), [job.color, :bold]),
33
+ formatter.duration(job.duration).ljust(14),
34
+ formatter.job_config(job.config),
35
+ (color("(failure allowed)", :info) if job.allow_failures?)
36
+ ].compact.join(" ").rstrip
37
+ end
38
+ else
39
+ config = formatter.job_config(entity.config)
40
+ say color("Allow Failure: ", :info) + entity.allow_failures?.inspect
41
+ say color("Config: ", :info) + config unless config.empty?
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ __END__
49
+
50
+ <[[ color("%s #%s: ", :bold) ]]> <[[ color(%p, :bold) ]]>
51
+ <[[ color("State: ", :info) ]]><[[ color(%p, :%s) ]]>
52
+ <[[ color("Type: ", :info) ]]>%s
53
+ <[[ color("Branch: ", :info) ]]>%s
54
+ <[[ color("Compare URL: ", :info) ]]>%s
55
+ <[[ color("Duration: ", :info) ]]>%s
56
+ <[[ color("Started: ", :info) ]]>%s
57
+ <[[ color("Finished: ", :info) ]]>%s
@@ -0,0 +1,118 @@
1
+ require 'travis/cli'
2
+ require 'travis/tools/ssl_key'
3
+ require 'travis/tools/github'
4
+
5
+ module Travis
6
+ module CLI
7
+ class Sshkey < RepoCommand
8
+ description "checks, updates or deletes an SSH key"
9
+ on '-D', '--delete', 'remove SSH key'
10
+ on '-d', '--description DESCRIPTION', 'set description'
11
+ on '-u', '--upload FILE', 'upload key from given file'
12
+ on '-s', '--stdin', 'upload key read from stdin'
13
+ on '-c', '--check', 'set exit code depending on key existing'
14
+ on '-g', '--generate', 'generate SSH key and set up for given GitHub user'
15
+ on '-p', '--passphrase PASSPHRASE', 'pass phrase to decrypt with when using --upload'
16
+
17
+ def_delegators :repository, :ssh_key
18
+
19
+ def run
20
+ error "SSH keys are not available on #{color(session.config['host'], :bold)}" if org?
21
+ delete_key if delete?
22
+ update_key File.read(upload), upload if upload?
23
+ update_key $stdin.read, 'stdin' if stdin?
24
+ generate_key if generate?
25
+ display_key
26
+ end
27
+
28
+ def display_key
29
+ say "Current SSH key: #{color(ssh_key.description, :info)}"
30
+ say "Finger print: #{color(ssh_key.fingerprint, :info)}"
31
+ rescue Travis::Client::NotFound
32
+ say "No custom SSH key installed."
33
+ exit 1 if check?
34
+ end
35
+
36
+ def update_key(value, file)
37
+ error "#{file} does not look like a private key" unless value.lines.first =~ /PRIVATE KEY/
38
+ value = remove_passphrase(value)
39
+ self.description ||= ask("Key description: ") { |q| q.default = "Custom Key" } if interactive?
40
+ say "Updating ssh key for #{color slug, :info} with key from #{color file, :info}"
41
+ empty_line
42
+ ssh_key.update(:value => value, :description => description || file)
43
+ end
44
+
45
+ def delete_key
46
+ return if interactive? and not danger_zone? "Remove SSH key for #{color slug, :info}?"
47
+ say "Removing ssh key for #{color slug, :info}"
48
+ ssh_key.delete
49
+ rescue Travis::Client::NotFound
50
+ warn "no key found to remove"
51
+ end
52
+
53
+ def generate_key
54
+ github.with_basic_auth do |gh|
55
+ login = gh['user']['login']
56
+ check_access(gh)
57
+ empty_line
58
+
59
+ say "Generating RSA key."
60
+ private_key = Tools::SSLKey.generate_rsa
61
+ self.description ||= "key for fetching dependencies for #{slug} via #{login}"
62
+
63
+ say "Uploading public key to GitHub."
64
+ gh.post("/user/keys", :title => "#{description} (Travis CI)", :key => Tools::SSLKey.rsa_ssh(private_key.public_key))
65
+
66
+ say "Uploading private key to Travis CI."
67
+ ssh_key.update(:value => private_key.to_s, :description => description)
68
+
69
+ empty_line
70
+ say "You can store the private key to reuse it for other repositories (travis sshkey --upload FILE)."
71
+ if agree("Store private key? ") { |q| q.default = "no" }
72
+ path = ask("Path: ") { |q| q.default = "id_travis_rsa" }
73
+ File.write(path, private_key.to_s)
74
+ end
75
+ end
76
+ end
77
+
78
+ def remove_passphrase(value)
79
+ return value unless Tools::SSLKey.has_passphrase? value
80
+ return Tools::SSLKey.remove_passphrase(value, passphrase) || error("wrong pass phrase") if passphrase
81
+ error "Key is encrypted, but missing --passphrase option" unless interactive?
82
+ say "The private key is protected by a pass phrase."
83
+ result = Tools::SSLKey.remove_passphrase(value, ask("Enter pass phrase: ") { |q| q.echo = "*" }) until result
84
+ empty_line
85
+ result
86
+ end
87
+
88
+ def check_access(gh)
89
+ gh["repos/#{slug}"]
90
+ rescue GH::Error
91
+ error "GitHub account has no read access to #{color slug, :bold}"
92
+ end
93
+
94
+ def github
95
+ @github ||= begin
96
+ load_gh
97
+ Tools::Github.new(session.config['github']) do |g|
98
+ g.note = "token for fetching dependencies for #{slug} (Travis CI)"
99
+ g.explode = explode?
100
+ g.ask_login = proc { ask("Username: ") }
101
+ g.ask_password = proc { |user| ask("Password for #{user}: ") { |q| q.echo = "*" } }
102
+ g.ask_otp = proc { |user| ask("Two-factor authentication code for #{user}: ") }
103
+ g.login_header = proc { login_header }
104
+ g.debug = proc { |log| debug(log) }
105
+ g.after_tokens = proc { g.explode = true and error("no suitable github token found") }
106
+ end
107
+ end
108
+ end
109
+
110
+ def login_header
111
+ say "We need the #{color("GitHub login", :important)} for the account you want to add the key to."
112
+ say "This information will #{color("not be sent to Travis CI", :important)}, only to #{color(github_endpoint.host, :info)}."
113
+ say "The password will not be displayed."
114
+ empty_line
115
+ end
116
+ end
117
+ end
118
+ end
@@ -0,0 +1,19 @@
1
+ require 'travis/cli'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Status < RepoCommand
6
+ description "checks status of the latest build"
7
+
8
+ on '-x', '--[no-]exit-code', 'sets the exit code to 1 if the build failed'
9
+ on '-q', '--[no-]quiet', 'does not print anything'
10
+ on '-p', '--[no-]fail-pending', 'sets the status code to 1 if the build is pending'
11
+
12
+ def run
13
+ say color(last_build.state, last_build.color), "build ##{last_build.number} %s" unless quiet?
14
+ exit 1 if exit_code? and last_build.unsuccessful?
15
+ exit 1 if fail_pending? and last_build.pending?
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,30 @@
1
+ require 'travis/cli'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Sync < ApiCommand
6
+ description "triggers a new sync with GitHub"
7
+
8
+ on '-c', '--check', 'only check the sync status'
9
+ on '-b', '--background', 'will trigger sync but not block until sync is done'
10
+ on '-f', '--force', 'will force sync, even if one is already running'
11
+
12
+ def run
13
+ authenticate
14
+
15
+ if check?
16
+ say "#{"not " unless user.syncing?}syncing", "#{user.login} is currently %s"
17
+ elsif user.syncing? and not force?
18
+ error "user is already syncing"
19
+ elsif background?
20
+ say "starting synchronization"
21
+ sync(false)
22
+ else
23
+ say "synchronizing: "
24
+ sync
25
+ say color(" done", :success)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,14 @@
1
+ require 'travis/cli'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Token < ApiCommand
6
+ description "outputs the secret API token"
7
+
8
+ def run
9
+ authenticate
10
+ say access_token, "Your access token is %s"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ require 'travis/cli'
2
+ require 'travis/version'
3
+
4
+ module Travis
5
+ module CLI
6
+ class Version < Command
7
+ description "outputs the client version"
8
+
9
+ def run
10
+ say Travis::VERSION
11
+ end
12
+
13
+ def check_version
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,30 @@
1
+ require 'travis/cli'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Whatsup < ApiCommand
6
+ description "lists most recent builds"
7
+ on('-m', '--my-repos', 'Only display my own repositories')
8
+
9
+ def run
10
+ say "nothing to show" if recent.empty?
11
+
12
+ recent.each do |repo|
13
+ say [
14
+ color(repo.slug, [:bold, repo.color]),
15
+ color("#{repo.last_build.state}: ##{repo.last_build.number}", repo.color)
16
+ ].join(" ")
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def recent
23
+ @recent ||= begin
24
+ recent = my_repos ? repos : repos(:member => user.login)
25
+ recent.select { |repo| repo.last_build }
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ require 'travis/cli'
2
+
3
+ module Travis
4
+ module CLI
5
+ class Whoami < ApiCommand
6
+ description "outputs the current user"
7
+
8
+ def run
9
+ authenticate
10
+ name = " (#{user.name})" unless user.name.to_s.empty?
11
+ say user.login, "You are %s" << name.to_s
12
+ end
13
+ end
14
+ end
15
+ end
data/lib/travis/cli.rb ADDED
@@ -0,0 +1,126 @@
1
+ begin
2
+ require 'travis/client'
3
+ rescue LoadError => e
4
+ if e.message == 'no such file to load -- json'
5
+ $stderr.puts "You should either run `gem install json` or upgrade your Ruby version!"
6
+ exit 1
7
+ else
8
+ raise e
9
+ end
10
+ end
11
+
12
+ require 'stringio'
13
+
14
+ module Travis
15
+ module CLI
16
+ autoload :Token, 'travis/cli/token'
17
+ autoload :ApiCommand, 'travis/cli/api_command'
18
+ autoload :Accounts, 'travis/cli/accounts'
19
+ autoload :Branches, 'travis/cli/branches'
20
+ autoload :Cache, 'travis/cli/cache'
21
+ autoload :Cancel, 'travis/cli/cancel'
22
+ autoload :Command, 'travis/cli/command'
23
+ autoload :Console, 'travis/cli/console'
24
+ autoload :Disable, 'travis/cli/disable'
25
+ autoload :Enable, 'travis/cli/enable'
26
+ autoload :Encrypt, 'travis/cli/encrypt'
27
+ autoload :EncryptFile, 'travis/cli/encrypt_file'
28
+ autoload :Endpoint, 'travis/cli/endpoint'
29
+ autoload :Env, 'travis/cli/env'
30
+ autoload :Help, 'travis/cli/help'
31
+ autoload :History, 'travis/cli/history'
32
+ autoload :Init, 'travis/cli/init'
33
+ autoload :Lint, 'travis/cli/lint'
34
+ autoload :Login, 'travis/cli/login'
35
+ autoload :Logout, 'travis/cli/logout'
36
+ autoload :Logs, 'travis/cli/logs'
37
+ autoload :Monitor, 'travis/cli/monitor'
38
+ autoload :Open, 'travis/cli/open'
39
+ autoload :Parser, 'travis/cli/parser'
40
+ autoload :Pubkey, 'travis/cli/pubkey'
41
+ autoload :Raw, 'travis/cli/raw'
42
+ autoload :RepoCommand, 'travis/cli/repo_command'
43
+ autoload :Report, 'travis/cli/report'
44
+ autoload :Repos, 'travis/cli/repos'
45
+ autoload :Restart, 'travis/cli/restart'
46
+ autoload :Requests, 'travis/cli/requests'
47
+ autoload :Settings, 'travis/cli/settings'
48
+ autoload :Setup, 'travis/cli/setup'
49
+ autoload :Show, 'travis/cli/show'
50
+ autoload :Sshkey, 'travis/cli/sshkey'
51
+ autoload :Status, 'travis/cli/status'
52
+ autoload :Sync, 'travis/cli/sync'
53
+ autoload :Version, 'travis/cli/version'
54
+ autoload :Whatsup, 'travis/cli/whatsup'
55
+ autoload :Whoami, 'travis/cli/whoami'
56
+
57
+ extend self
58
+
59
+ def run(*args)
60
+ args, opts = preparse(args)
61
+ name = args.shift unless args.empty?
62
+ command = command(name).new(opts)
63
+ command.parse(args)
64
+ command.execute
65
+ end
66
+
67
+ def command(name)
68
+ const_name = command_name(name)
69
+ constant = CLI.const_get(const_name) if const_name =~ /^[A-Z][A-Za-z]+$/ and const_defined? const_name
70
+ if command? constant
71
+ constant
72
+ else
73
+ $stderr.puts "unknown command #{name}"
74
+ exit 1
75
+ end
76
+ end
77
+
78
+ def commands
79
+ CLI.constants.map { |n| try_const_get(n) }.select { |c| command? c }
80
+ end
81
+
82
+ def silent
83
+ stderr, $stderr = $stderr, dummy_io
84
+ stdout, $stdout = $stdout, dummy_io
85
+ yield
86
+ ensure
87
+ $stderr = stderr if stderr
88
+ $stdout = stdout if stdout
89
+ end
90
+
91
+ private
92
+
93
+ def try_const_get(name)
94
+ CLI.const_get(name)
95
+ rescue Exception
96
+ end
97
+
98
+ def dummy_io
99
+ return StringIO.new unless defined? IO::NULL and IO::NULL
100
+ File.open(IO::NULL, 'w')
101
+ end
102
+
103
+ def command?(constant)
104
+ constant.is_a? Class and constant < Command and not constant.abstract?
105
+ end
106
+
107
+ def command_name(name)
108
+ case name
109
+ when nil, '-h', '-?' then 'Help'
110
+ when '-v' then 'Version'
111
+ when /^--/ then command_name(name[2..-1])
112
+ else name.split('-').map(&:capitalize).join
113
+ end
114
+ end
115
+
116
+ # can't use flatten as it will flatten hashes
117
+ def preparse(unparsed, args = [], opts = {})
118
+ case unparsed
119
+ when Hash then opts.merge! unparsed
120
+ when Array then unparsed.each { |e| preparse(e, args, opts) }
121
+ else args << unparsed.to_s
122
+ end
123
+ [args, opts]
124
+ end
125
+ end
126
+ end