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.
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