├── .gitignore
├── .mailmap
├── .rubocop.yml
├── .snapcraft.yaml
├── .travis.yml
├── Gemfile
├── LICENSE
├── README.md
├── Rakefile
├── assets
├── cacert.pem
├── init
│ ├── bash.yml
│ ├── c.yml
│ ├── clojure.yml
│ ├── cpp.yml
│ ├── elixir.yml
│ ├── erlang.yml
│ ├── go.yml
│ ├── groovy.yml
│ ├── haskell.yml
│ ├── java.yml
│ ├── node_js.yml
│ ├── objective-c.yml
│ ├── perl.yml
│ ├── php.yml
│ ├── python.yml
│ ├── ruby.yml
│ └── scala.yml
├── notifications
│ ├── Travis CI.app
│ │ └── Contents
│ │ │ ├── Info.plist
│ │ │ ├── MacOS
│ │ │ └── Travis CI
│ │ │ ├── PkgInfo
│ │ │ ├── Resources
│ │ │ ├── Travis CI.icns
│ │ │ └── en.lproj
│ │ │ │ ├── Credits.rtf
│ │ │ │ ├── InfoPlist.strings
│ │ │ │ └── MainMenu.nib
│ │ │ ├── _CodeSignature
│ │ │ └── CodeResources
│ │ │ └── embedded.provisionprofile
│ └── icon.png
├── travis.sh
└── travis.sh.erb
├── bin
└── travis
├── examples
├── org_overview.rb
├── pro_auth.rb
└── stream.rb
├── lib
├── travis.rb
└── travis
│ ├── auto_login.rb
│ ├── cli.rb
│ ├── cli
│ ├── accounts.rb
│ ├── api_command.rb
│ ├── branches.rb
│ ├── cache.rb
│ ├── cancel.rb
│ ├── command.rb
│ ├── console.rb
│ ├── disable.rb
│ ├── enable.rb
│ ├── encrypt.rb
│ ├── encrypt_file.rb
│ ├── endpoint.rb
│ ├── env.rb
│ ├── help.rb
│ ├── history.rb
│ ├── init.rb
│ ├── lint.rb
│ ├── login.rb
│ ├── logout.rb
│ ├── logs.rb
│ ├── monitor.rb
│ ├── open.rb
│ ├── parser.rb
│ ├── pubkey.rb
│ ├── raw.rb
│ ├── regenerate_token.rb
│ ├── remove_token.rb
│ ├── repo_command.rb
│ ├── report.rb
│ ├── repos.rb
│ ├── requests.rb
│ ├── restart.rb
│ ├── settings.rb
│ ├── setup.rb
│ ├── setup
│ │ ├── anynines.rb
│ │ ├── appfog.rb
│ │ ├── artifacts.rb
│ │ ├── biicode.rb
│ │ ├── cloud_66.rb
│ │ ├── cloud_control.rb
│ │ ├── cloud_files.rb
│ │ ├── cloud_foundry.rb
│ │ ├── code_deploy.rb
│ │ ├── deis.rb
│ │ ├── divshot.rb
│ │ ├── elastic_beanstalk.rb
│ │ ├── engine_yard.rb
│ │ ├── gcs.rb
│ │ ├── hackage.rb
│ │ ├── heroku.rb
│ │ ├── modulus.rb
│ │ ├── ninefold.rb
│ │ ├── nodejitsu.rb
│ │ ├── npm.rb
│ │ ├── open_shift.rb
│ │ ├── opsworks.rb
│ │ ├── pypi.rb
│ │ ├── releases.rb
│ │ ├── ruby_gems.rb
│ │ ├── s3.rb
│ │ ├── sauce_connect.rb
│ │ └── service.rb
│ ├── show.rb
│ ├── sshkey.rb
│ ├── status.rb
│ ├── sync.rb
│ ├── token.rb
│ ├── version.rb
│ ├── whatsup.rb
│ └── whoami.rb
│ ├── client.rb
│ ├── client
│ ├── account.rb
│ ├── artifact.rb
│ ├── auto_login.rb
│ ├── broadcast.rb
│ ├── build.rb
│ ├── cache.rb
│ ├── commit.rb
│ ├── entity.rb
│ ├── env_var.rb
│ ├── error.rb
│ ├── has_uuid.rb
│ ├── job.rb
│ ├── lint_result.rb
│ ├── listener.rb
│ ├── methods.rb
│ ├── namespace.rb
│ ├── not_loadable.rb
│ ├── repository.rb
│ ├── request.rb
│ ├── restartable.rb
│ ├── session.rb
│ ├── settings.rb
│ ├── singleton_setting.rb
│ ├── ssh_key.rb
│ ├── states.rb
│ ├── user.rb
│ └── weak_entity.rb
│ ├── pro.rb
│ ├── pro
│ └── auto_login.rb
│ ├── tools
│ ├── assets.rb
│ ├── completion.rb
│ ├── formatter.rb
│ ├── github.rb
│ ├── notification.rb
│ ├── safe_string.rb
│ ├── ssl_key.rb
│ └── system.rb
│ └── version.rb
├── spec
├── cli
│ ├── api_command_spec.rb
│ ├── cancel_spec.rb
│ ├── encrypt_file_spec.rb
│ ├── encrypt_spec.rb
│ ├── endpoint_spec.rb
│ ├── help_spec.rb
│ ├── history_spec.rb
│ ├── init_spec.rb
│ ├── logs_spec.rb
│ ├── open_spec.rb
│ ├── repo_command_spec.rb
│ ├── restart_spec.rb
│ ├── setup
│ │ └── service_spec.rb
│ ├── setup_spec.rb
│ ├── show_spec.rb
│ ├── status_spec.rb
│ ├── token_spec.rb
│ ├── version_spec.rb
│ └── whoami_spec.rb
├── client
│ ├── account_spec.rb
│ ├── auto_login_spec.rb
│ ├── broadcast_spec.rb
│ ├── build_spec.rb
│ ├── commit_spec.rb
│ ├── job_spec.rb
│ ├── methods_spec.rb
│ ├── namespace_spec.rb
│ ├── repository_spec.rb
│ ├── session_spec.rb
│ └── user_spec.rb
├── client_spec.rb
├── pro_spec.rb
├── spec_helper.rb
├── support
│ ├── fake_api.rb
│ ├── fake_github.rb
│ ├── fake_travis_config.yml
│ └── helpers.rb
└── travis_spec.rb
└── travis.gemspec
/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | Gemfile.lock
3 | spec/tmp
4 | doc
5 | .ruby*
6 | pkg
7 |
--------------------------------------------------------------------------------
/.mailmap:
--------------------------------------------------------------------------------
1 | <konstantin.mailinglists@googlemail.com> <konstantin.haase@gmail.com>
2 | joshua-anderson <j@zatigo.com>
3 | Peter Souter <p.morsou@gmail.com>
4 |
--------------------------------------------------------------------------------
/.rubocop.yml:
--------------------------------------------------------------------------------
1 | require: rubocop-performance
2 | require: rubocop-rspec
3 |
4 | Documentation:
5 | Enabled: false
6 | Metrics/ClassLength:
7 | Enabled: false
8 | Style/ClassAndModuleChildren:
9 | Enabled: false
10 | Metrics/LineLength:
11 | Enabled: false
12 | Metrics/MethodLength:
13 | Max: 40
14 | Style/AsciiComments:
15 | Enabled: false
16 | Metrics/AbcSize:
17 | Enabled: false
18 | Style/GuardClause:
19 | Enabled: false
20 | Style/FormatStringToken:
21 | Enabled: false
22 | Lint/AssignmentInCondition:
23 | Enabled: false
24 | Style/IfUnlessModifier:
25 | Enabled: false
26 | Naming/MemoizedInstanceVariableName:
27 | EnforcedStyleForLeadingUnderscores: required
28 | Style/MultilineBlockChain:
29 | Enabled: false
30 | Lint/ConstantDefinitionInBlock:
31 | Enabled: false
32 | Naming/VariableNumber:
33 | Enabled: false
34 | Metrics/BlockLength:
35 | Enabled: false
36 | Lint/ImplicitStringConcatenation:
37 | Enabled: false
38 | Metrics/MethodLength:
39 | Enabled: false
40 | Style/StructInheritance:
41 | Enabled: false
42 | Lint/RescueException:
43 | Enabled: false
44 | Lint/SuppressedException:
45 | Enabled: false
46 | Naming/MemoizedInstanceVariableName:
47 | Enabled: false
48 | Style/SymbolProc:
49 | Enabled: false
50 | RSpec/MultipleMemoizedHelpers:
51 | Enabled: false
--------------------------------------------------------------------------------
/.snapcraft.yaml:
--------------------------------------------------------------------------------
1 | name: travis
2 | version: '1.8.13'
3 | summary: Travis CI client
4 | description: CLI and Ruby client library for Travis CI
5 |
6 | grade: stable
7 |
8 | confinement: strict
9 |
10 | apps:
11 | travis:
12 | command: travis
13 | plugs: [network, home, removable-media]
14 |
15 | parts:
16 | travis:
17 | plugin: ruby
18 | source: https://github.com/travis-ci/travis.rb/archive/v1.8.13.tar.gz
19 | override-build: |
20 | snapcraftctl build
21 | gem build travis.gemspec
22 | gem install travis-*.gem --env-shebang
23 | prime: ['-lib/ruby/gems/*/gems/ffi-*/ext/ffi_c/libffi-*/include/ffitarget.h']
24 | stage-packages: [git]
25 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | jobs:
3 | include:
4 | - rvm: "3.2"
5 | cache: bundler
6 | dist: bionic
7 | before_script:
8 | - gem install faraday -v 1.0.1
9 | - os: osx
10 | # Broken ruby 3.2 workaround
11 | osx_image: xcode11.4.1
12 | before_install:
13 | - rvm get stable && rvm reload && rvm install 3.2.5 --verify-downloads 1 --disable-install-doc -C --without-tcl,--without-tk,--without-gmp && rvm use 3.2.5 --default
14 | - stage: deploy
15 | if: repo = travis-ci/travis.rb and branch = master and type = push
16 | dist: bionic
17 | rvm: "3.2"
18 | deploy:
19 | provider: rubygems
20 | api_key:
21 | secure: KcBpkFaes74KGMm8X/rRA8e13+t3PmkefsAvOAR+iF4g1GyuLSPkP92Fb9vFfsXBph+qmFh5rNa2lIRf/3RXW6COxY7CMMaARxUfJOKE0rmIwF0qfKI+RZDh6abg92iYngunMZVN8WVft6Lv9ZTOYCWxr1Zs1Ll/Rl4PfvHNd1g=
22 | gem: travis
23 | edge: true
24 |
25 | script:
26 | - bundle exec rake
27 | - gem build travis.gemspec
28 | - gem install travis-*.gem
29 |
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | source 'https://rubygems.org'
4 | gemspec
5 |
6 | gem 'travis-gh'
7 | gem 'rake'
8 | gem 'activesupport', '~> 7.0.6'
9 |
10 | group :development, :test do
11 | gem 'rubocop'
12 | gem 'rubocop-performance'
13 | gem 'rubocop-rspec'
14 | gem 'simplecov-console'
15 | end
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT LICENSE
2 |
3 | Copyright (c) 2014 Travis CI GmbH <support@travis-ci.com>
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/Rakefile:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | $LOAD_PATH.unshift File.expand_path('lib', __dir__)
4 | windows = RUBY_PLATFORM =~ /mswin|mingw/
5 |
6 | require 'bundler/gem_tasks'
7 |
8 | desc 'run specs'
9 | task(:spec) { ruby "-S rspec spec#{' -c' unless windows}" }
10 |
11 | desc 'generate gemspec, update readme'
12 | task update: :completion do
13 | require 'travis/version'
14 | content = File.read('travis.gemspec')
15 |
16 | # fetch data
17 | fields = {
18 | authors: sort_by_commits_alpha(`git shortlog -sn`.b, /[^\d\s].*/).uniq,
19 | email: sort_by_commits_alpha(`git shortlog -sne`.b, /[^<]+@[^>]+/).uniq,
20 | files: `git ls-files`.b.split("\n").reject { |f| f =~ /^(\.|Gemfile)/ }
21 | }
22 |
23 | # :(
24 | fields[:email].delete('konstantin.haase@gmail.com')
25 |
26 | # insert data
27 | fields.each do |field, values|
28 | updated = " s.#{field} = ["
29 | updated << values.map { |v| "\n %p" % v }.join(',')
30 | updated << "\n ]"
31 | content.sub!(/ s\.#{field} = \[\n( .*\n)* \]/, updated)
32 | end
33 |
34 | # set version
35 | content.sub!(/(s\.version.*=\s+).*/, "\\1\"#{Travis::VERSION}\"")
36 |
37 | # escape unicode
38 | content.gsub!(/./) { |c| c.bytesize > 1 ? "\\u{#{c.codepoints.first.to_s(16)}}" : c }
39 |
40 | File.open('travis.gemspec', 'w') { |f| f << content }
41 |
42 | readme = File.read('README.md').b
43 | readme.gsub!(/^(\s+\$ travis version\n\s+).*$/, "\\1#{Travis::VERSION}")
44 | readme.gsub!(/(gem install travis -v )\S+/, "\\1#{Travis::VERSION}")
45 | readme.gsub!(/^\*\*#{Regexp.escape(Travis::VERSION)}\*\* \(not yet released?\)\n/i,
46 | "**#{Travis::VERSION}** (#{Time.now.strftime('%B %-d, %Y')})\n")
47 |
48 | Travis::CLI.commands.each do |c|
49 | readme.sub!(/^( \* \[`#{c.command_name}`\]\(##{c.command_name}\)).*$/, "\\1 - #{c.description}")
50 | end
51 |
52 | File.write('README.md', readme)
53 | end
54 |
55 | task :completion do
56 | require 'travis/tools/completion'
57 | Travis::Tools::Completion.compile
58 | end
59 |
60 | task 'travis.gemspec' => :update
61 | task 'README.md' => :update
62 |
63 | task gemspec: :update
64 | task default: :spec
65 | task default: :gemspec unless windows || (RUBY_VERSION < '2.0')
66 | task test: :spec
67 |
68 | def sort_by_commits_alpha(shortlog_output, patt)
69 | shortlog_output.split("\n").sort do |a, b|
70 | a_comm, a_name = a.strip.split(/\t/)
71 | b_comm, b_name = b.strip.split(/\t/)
72 |
73 | if a_comm.to_i != b_comm.to_i
74 | a_comm.to_i <=> b_comm.to_i
75 | else
76 | b_name <=> a_name # we will reserve this sort afterwards, so we need the opposite order here
77 | end
78 | end.join("\n").scan(patt).reverse
79 | end
80 |
--------------------------------------------------------------------------------
/assets/cacert.pem:
--------------------------------------------------------------------------------
1 | AddTrust External Root
2 | ======================
3 | -----BEGIN CERTIFICATE-----
4 | MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
5 | QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
6 | VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
7 | NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
8 | cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
9 | Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
10 | +iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
11 | Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
12 | aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
13 | 2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
14 | 7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
15 | BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
16 | VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
17 | VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
18 | IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
19 | j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
20 | 6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
21 | e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
22 | G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
23 | -----END CERTIFICATE-----
24 |
25 | COMODO Certification Authority
26 | ==============================
27 | -----BEGIN CERTIFICATE-----
28 | MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
29 | BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
30 | A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
31 | dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
32 | MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
33 | T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
34 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
35 | +7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
36 | xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
37 | 4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
38 | 1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
39 | rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
40 | BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
41 | b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
42 | AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
43 | OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
44 | RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
45 | IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
46 | +8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
47 | -----END CERTIFICATE-----
48 |
49 | DigiCert High Assurance EV Root CA
50 | ==================================
51 | -----BEGIN CERTIFICATE-----
52 | MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
53 | EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
54 | KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
55 | MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
56 | MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
57 | Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
58 | Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
59 | OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
60 | MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
61 | NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
62 | h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
63 | Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
64 | JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
65 | V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
66 | myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
67 | mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
68 | vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
69 | -----END CERTIFICATE-----
--------------------------------------------------------------------------------
/assets/init/bash.yml:
--------------------------------------------------------------------------------
1 | language: bash
2 |
--------------------------------------------------------------------------------
/assets/init/c.yml:
--------------------------------------------------------------------------------
1 | language: c
2 | compiler:
3 | - clang
4 | - gcc
--------------------------------------------------------------------------------
/assets/init/clojure.yml:
--------------------------------------------------------------------------------
1 | language: clojure
--------------------------------------------------------------------------------
/assets/init/cpp.yml:
--------------------------------------------------------------------------------
1 | language: cpp
2 | compiler:
3 | - clang
4 | - gcc
--------------------------------------------------------------------------------
/assets/init/elixir.yml:
--------------------------------------------------------------------------------
1 | language: elixir
2 | elixir:
3 | - '1.10.2'
4 | - '1.9.4'
5 | otp_release:
6 | - '22.3'
7 | - '21.3'
8 | - '20.3'
9 |
--------------------------------------------------------------------------------
/assets/init/erlang.yml:
--------------------------------------------------------------------------------
1 | language: erlang
2 | otp_release:
3 | - R16B
4 |
--------------------------------------------------------------------------------
/assets/init/go.yml:
--------------------------------------------------------------------------------
1 | language: go
2 | go:
3 | - "1.0"
4 | - "1.3"
5 |
--------------------------------------------------------------------------------
/assets/init/groovy.yml:
--------------------------------------------------------------------------------
1 | language: groovy
2 |
--------------------------------------------------------------------------------
/assets/init/haskell.yml:
--------------------------------------------------------------------------------
1 | language: haskell
2 |
--------------------------------------------------------------------------------
/assets/init/java.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk:
3 | - oraclejdk7
4 | - openjdk6
--------------------------------------------------------------------------------
/assets/init/node_js.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "stable"
4 | - "6"
5 | - "4"
6 |
--------------------------------------------------------------------------------
/assets/init/objective-c.yml:
--------------------------------------------------------------------------------
1 | language: objective-c
2 |
--------------------------------------------------------------------------------
/assets/init/perl.yml:
--------------------------------------------------------------------------------
1 | language: perl
2 | perl:
3 | - "5.16"
4 | - "5.14"
--------------------------------------------------------------------------------
/assets/init/php.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | php:
3 | - "5.5"
4 | - "5.4"
--------------------------------------------------------------------------------
/assets/init/python.yml:
--------------------------------------------------------------------------------
1 | language: python
2 | python:
3 | - "2.7"
4 | - "3.3"
5 | - "pypy"
6 |
--------------------------------------------------------------------------------
/assets/init/ruby.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.0.0
4 | - 1.9.3
5 | - jruby-19mode
6 | - rbx-2
7 |
--------------------------------------------------------------------------------
/assets/init/scala.yml:
--------------------------------------------------------------------------------
1 | language: scala
2 | scala:
3 | - "2.10.1"
4 | - "2.9.3"
--------------------------------------------------------------------------------
/assets/notifications/Travis CI.app/Contents/Info.plist:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | <key>BuildMachineOSBuild</key>
6 | <string>13A603</string>
7 | <key>CFBundleDevelopmentRegion</key>
8 | <string>en</string>
9 | <key>CFBundleExecutable</key>
10 | <string>Travis CI</string>
11 | <key>CFBundleIconFile</key>
12 | <string>Travis CI</string>
13 | <key>CFBundleIdentifier</key>
14 | <string>org.travis-ci.Travis-CI</string>
15 | <key>CFBundleInfoDictionaryVersion</key>
16 | <string>6.0</string>
17 | <key>CFBundleName</key>
18 | <string>Travis CI</string>
19 | <key>CFBundlePackageType</key>
20 | <string>APPL</string>
21 | <key>CFBundleShortVersionString</key>
22 | <string>1.6.0</string>
23 | <key>CFBundleSignature</key>
24 | <string>????</string>
25 | <key>CFBundleVersion</key>
26 | <string>9</string>
27 | <key>DTCompiler</key>
28 | <string>com.apple.compilers.llvm.clang.1_0</string>
29 | <key>DTPlatformBuild</key>
30 | <string>5A2053</string>
31 | <key>DTPlatformVersion</key>
32 | <string>GM</string>
33 | <key>DTSDKBuild</key>
34 | <string>13A595</string>
35 | <key>DTSDKName</key>
36 | <string>macosx10.9</string>
37 | <key>DTXcode</key>
38 | <string>0501</string>
39 | <key>DTXcodeBuild</key>
40 | <string>5A2053</string>
41 | <key>LSMinimumSystemVersion</key>
42 | <string>10.8</string>
43 | <key>LSUIElement</key>
44 | <true/>
45 | <key>NSHumanReadableCopyright</key>
46 | <string>Copyright © 2012 Eloy Durán. All rights reserved.</string>
47 | <key>NSMainNibFile</key>
48 | <string>MainMenu</string>
49 | <key>NSPrincipalClass</key>
50 | <string>NSApplication</string>
51 | </dict>
52 | </plist>
53 |
--------------------------------------------------------------------------------
/assets/notifications/Travis CI.app/Contents/MacOS/Travis CI:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/travis-ci/travis.rb/d298045e3e01b45d7c9cc60214cdddd326a445dc/assets/notifications/Travis CI.app/Contents/MacOS/Travis CI
--------------------------------------------------------------------------------
/assets/notifications/Travis CI.app/Contents/PkgInfo:
--------------------------------------------------------------------------------
1 | APPL????
--------------------------------------------------------------------------------
/assets/notifications/Travis CI.app/Contents/Resources/Travis CI.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/travis-ci/travis.rb/d298045e3e01b45d7c9cc60214cdddd326a445dc/assets/notifications/Travis CI.app/Contents/Resources/Travis CI.icns
--------------------------------------------------------------------------------
/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/Credits.rtf:
--------------------------------------------------------------------------------
1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
2 | {\colortbl;\red255\green255\blue255;}
3 | \paperw9840\paperh8400
4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
5 |
6 | \f0\b\fs24 \cf0 Engineering:
7 | \b0 \
8 | Some people\
9 | \
10 |
11 | \b Human Interface Design:
12 | \b0 \
13 | Some other people\
14 | \
15 |
16 | \b Testing:
17 | \b0 \
18 | Hopefully not nobody\
19 | \
20 |
21 | \b Documentation:
22 | \b0 \
23 | Whoever\
24 | \
25 |
26 | \b With special thanks to:
27 | \b0 \
28 | Mom\
29 | }
30 |
--------------------------------------------------------------------------------
/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/travis-ci/travis.rb/d298045e3e01b45d7c9cc60214cdddd326a445dc/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/InfoPlist.strings
--------------------------------------------------------------------------------
/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/MainMenu.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/travis-ci/travis.rb/d298045e3e01b45d7c9cc60214cdddd326a445dc/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/MainMenu.nib
--------------------------------------------------------------------------------
/assets/notifications/Travis CI.app/Contents/_CodeSignature/CodeResources:
--------------------------------------------------------------------------------
1 | <?xml version="1.0" encoding="UTF-8"?>
2 | <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3 | <plist version="1.0">
4 | <dict>
5 | <key>files</key>
6 | <dict>
7 | <key>Resources/Travis CI.icns</key>
8 | <data>
9 | lyhCVg6fw9a5ugUz0vPsuUP76Ao=
10 | </data>
11 | <key>Resources/en.lproj/Credits.rtf</key>
12 | <dict>
13 | <key>hash</key>
14 | <data>
15 | YKJIFIsxneJuNkJNJQIcJIjiPOg=
16 | </data>
17 | <key>optional</key>
18 | <true/>
19 | </dict>
20 | <key>Resources/en.lproj/InfoPlist.strings</key>
21 | <dict>
22 | <key>hash</key>
23 | <data>
24 | MiLKDDnrUKr4EmuvhS5VQwxHGK8=
25 | </data>
26 | <key>optional</key>
27 | <true/>
28 | </dict>
29 | <key>Resources/en.lproj/MainMenu.nib</key>
30 | <dict>
31 | <key>hash</key>
32 | <data>
33 | fhQhxk1J1ydtmmhPXFRlyOzhQ58=
34 | </data>
35 | <key>optional</key>
36 | <true/>
37 | </dict>
38 | </dict>
39 | <key>files2</key>
40 | <dict>
41 | <key>Resources/Travis CI.icns</key>
42 | <data>
43 | lyhCVg6fw9a5ugUz0vPsuUP76Ao=
44 | </data>
45 | <key>Resources/en.lproj/Credits.rtf</key>
46 | <dict>
47 | <key>hash</key>
48 | <data>
49 | YKJIFIsxneJuNkJNJQIcJIjiPOg=
50 | </data>
51 | <key>optional</key>
52 | <true/>
53 | </dict>
54 | <key>Resources/en.lproj/InfoPlist.strings</key>
55 | <dict>
56 | <key>hash</key>
57 | <data>
58 | MiLKDDnrUKr4EmuvhS5VQwxHGK8=
59 | </data>
60 | <key>optional</key>
61 | <true/>
62 | </dict>
63 | <key>Resources/en.lproj/MainMenu.nib</key>
64 | <dict>
65 | <key>hash</key>
66 | <data>
67 | fhQhxk1J1ydtmmhPXFRlyOzhQ58=
68 | </data>
69 | <key>optional</key>
70 | <true/>
71 | </dict>
72 | <key>embedded.provisionprofile</key>
73 | <data>
74 | pgK1X4SQVn778OSK8DwaZme2X+E=
75 | </data>
76 | </dict>
77 | <key>rules</key>
78 | <dict>
79 | <key>^Resources/</key>
80 | <true/>
81 | <key>^Resources/.*\.lproj/</key>
82 | <dict>
83 | <key>optional</key>
84 | <true/>
85 | <key>weight</key>
86 | <real>1000</real>
87 | </dict>
88 | <key>^Resources/.*\.lproj/locversion.plistlt;/key>
89 | <dict>
90 | <key>omit</key>
91 | <true/>
92 | <key>weight</key>
93 | <real>1100</real>
94 | </dict>
95 | <key>^version.plistlt;/key>
96 | <true/>
97 | </dict>
98 | <key>rules2</key>
99 | <dict>
100 | <key>.*\.dSYM($|/)</key>
101 | <dict>
102 | <key>weight</key>
103 | <real>11</real>
104 | </dict>
105 | <key>^(.*/)?\.DS_Storelt;/key>
106 | <dict>
107 | <key>omit</key>
108 | <true/>
109 | <key>weight</key>
110 | <real>2000</real>
111 | </dict>
112 | <key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
113 | <dict>
114 | <key>nested</key>
115 | <true/>
116 | <key>weight</key>
117 | <real>10</real>
118 | </dict>
119 | <key>^.*</key>
120 | <true/>
121 | <key>^Info\.plistlt;/key>
122 | <dict>
123 | <key>omit</key>
124 | <true/>
125 | <key>weight</key>
126 | <real>20</real>
127 | </dict>
128 | <key>^PkgInfolt;/key>
129 | <dict>
130 | <key>omit</key>
131 | <true/>
132 | <key>weight</key>
133 | <real>20</real>
134 | </dict>
135 | <key>^Resources/</key>
136 | <dict>
137 | <key>weight</key>
138 | <real>20</real>
139 | </dict>
140 | <key>^Resources/.*\.lproj/</key>
141 | <dict>
142 | <key>optional</key>
143 | <true/>
144 | <key>weight</key>
145 | <real>1000</real>
146 | </dict>
147 | <key>^Resources/.*\.lproj/locversion.plistlt;/key>
148 | <dict>
149 | <key>omit</key>
150 | <true/>
151 | <key>weight</key>
152 | <real>1100</real>
153 | </dict>
154 | <key>^[^/]+lt;/key>
155 | <dict>
156 | <key>nested</key>
157 | <true/>
158 | <key>weight</key>
159 | <real>10</real>
160 | </dict>
161 | <key>^embedded\.provisionprofilelt;/key>
162 | <dict>
163 | <key>weight</key>
164 | <real>20</real>
165 | </dict>
166 | <key>^version\.plistlt;/key>
167 | <dict>
168 | <key>weight</key>
169 | <real>20</real>
170 | </dict>
171 | </dict>
172 | </dict>
173 | </plist>
174 |
--------------------------------------------------------------------------------
/assets/notifications/Travis CI.app/Contents/embedded.provisionprofile:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/travis-ci/travis.rb/d298045e3e01b45d7c9cc60214cdddd326a445dc/assets/notifications/Travis CI.app/Contents/embedded.provisionprofile
--------------------------------------------------------------------------------
/assets/notifications/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/travis-ci/travis.rb/d298045e3e01b45d7c9cc60214cdddd326a445dc/assets/notifications/icon.png
--------------------------------------------------------------------------------
/assets/travis.sh.erb:
--------------------------------------------------------------------------------
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 | settings) _travis_settings;;
13 | init) _travis_init;;
14 | *) _travis_option;;
15 | esac;;
16 | *) _travis_option;;
17 | esac
18 | }
19 |
20 | if type compdef 1>/dev/null 2>/dev/null; then
21 | compdef _travis travis
22 | _travis() { _travis_complete $((${#words} - 1)) "${words[2]}"; }
23 | _travis_commands() { list=(<%= commands.map { |c| "%s:%p" % [c.command_name, c.description] }.join(" ") %>) _describe -t common-commands 'common commands' list; }
24 | _travis_setup() { list=(<%= Travis::CLI::Setup.services.map { |s| "%s:%p" % [s.service_name, s.description] }.join(" ") %>) _describe -t common-commands 'common commands' list; }
25 | _travis_settings() { list=(<%= Travis::CLI::Settings::DESCRIPTIONS.map { |k,v| "%s:%p" % [k, v] }.join(" ") %>) _describe -t common-commands 'common commands' list; }
26 | _travis_init() { list=(<%= Travis::CLI::Init.languages.map { |l| "#{l}:'initialize #{l} project'" }.join(" ") %>) _describe -t common-commands 'common commands' list; }
27 | _travis_option() {
28 | case "${words[2]}" in
29 | <% commands.each do |c| %>
30 | <%= "#{c.command_name})".ljust(10) %> <%= c.new.parser.compsys(" ", c.command_name).gsub(/\s+\\\s+/, ' ')[/_arguments.*/] %>;;
31 | <% end %>
32 | esac
33 | }
34 | elif type compctl 1>/dev/null 2>/dev/null; then
35 | compctl -K _travis travis
36 | _travis() { read -cA words && _travis_complete $((${#words} - 1)) "${words[2]}"; }
37 | _travis_commands() { reply=(<%= commands.map(&:command_name).map(&:inspect).join(" ") %>); }
38 | _travis_setup() { reply=(<%= Travis::CLI::Setup.services.map(&:service_name).map(&:inspect).join(" ") %>); }
39 | _travis_settings() { reply=(<%= Travis::CLI::Settings::DESCRIPTIONS.keys.join(" ") %>); }
40 | _travis_init() { reply=(<%= Travis::CLI::Init.languages.map(&:inspect).join(" ") %>); }
41 | _travis_option() {
42 | case "${words[2]}" in
43 | <% commands.each do |c| %>
44 | <%= "#{c.command_name})".ljust(10) %> reply=(<%= c.new.parser.candidate("-").flat_map { |o| [o.sub('[no-]', ''), o.sub('[no-]', 'no-')] }.uniq.map(&:inspect).join(" ") %>);;
45 | <% end %>
46 | esac
47 | }
48 | elif type complete 1>/dev/null 2>/dev/null; then
49 | complete -F _travis travis
50 | _travis() { _travis_complete "$COMP_CWORD" "${COMP_WORDS[1]}"; }
51 | _travis_commands() { COMPREPLY=( $(compgen -W "<%= commands.map(&:command_name).join(" ") %>" -- "${COMP_WORDS[COMP_CWORD]}") ); }
52 | _travis_setup() { COMPREPLY=( $(compgen -W "<%= Travis::CLI::Setup.services.map(&:service_name).join(" ") %>" -- "${COMP_WORDS[COMP_CWORD]}") ); }
53 | _travis_settings() { COMPREPLY=( $(compgen -W "<%= Travis::CLI::Settings::DESCRIPTIONS.keys.join(" ") %>" -- "${COMP_WORDS[COMP_CWORD]}") ); }
54 | _travis_init() { COMPREPLY=( $(compgen -W "<%= Travis::CLI::Init.languages.map(&:inspect).join(" ") %>" -- "${COMP_WORDS[COMP_CWORD]}") ); }
55 | _travis_option() {
56 | local options
57 | case "${COMP_WORDS[1]}" in
58 | <% commands.each do |c| %>
59 | <%= "#{c.command_name})".ljust(10) %> options="<%= c.new.parser.candidate("-").flat_map { |o| [o.sub('[no-]', ''), o.sub('[no-]', 'no-')] }.uniq.join(" ") %>";;
60 | <% end %>
61 | esac
62 | COMPREPLY=( $(compgen -W "$options" -- "${COMP_WORDS[COMP_CWORD]}") )
63 | }
64 | fi
65 |
--------------------------------------------------------------------------------
/bin/travis:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 | # frozen_string_literal: true
3 |
4 | # :(
5 | Encoding.default_external = Encoding::UTF_8 if defined? Encoding
6 |
7 | # load travis library
8 | require 'bundler/setup' if File.exist? File.expand_path('../Gemfile', __dir__)
9 | require 'travis/cli'
10 |
11 | # load plugins
12 | TRAVIS_PLUGINS = []
13 | config_path = ENV.fetch('TRAVIS_CONFIG_PATH') { File.expand_path('.travis', Dir.home) }
14 | Dir.glob(File.expand_path('*/init.rb', config_path)) do |file|
15 | TRAVIS_PLUGINS << file.sub("#{config_path}/", '').sub(%r{/init\.rb$}, '')
16 | load(file)
17 | end
18 | TRAVIS_PLUGINS.freeze
19 |
20 | # and off we go then
21 | Travis::CLI.run(ARGV)
22 |
--------------------------------------------------------------------------------
/examples/org_overview.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis'
4 | repos = Travis::Repository.find_all(owner_name: 'travis-ci')
5 | repos.each { |repo| puts "#{repo.slug} #{repo.last_build_state}" }
6 |
--------------------------------------------------------------------------------
/examples/pro_auth.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/pro'
4 | require 'travis/tools/github'
5 | require 'highline/import' # so we can hide the password
6 |
7 | github_token = ask('GitHub token: ')
8 |
9 | # Set up GitHub tool for doing the login handshake.
10 | github = Travis::Tools::Github.new(drop_token: true) do |g|
11 | g.github_token = github_token
12 | end
13 |
14 | # Create temporary GitHub token and use it to authenticate against Travis CI.
15 | github.with_token do |token|
16 | Travis::Pro.github_auth(token)
17 | end
18 |
19 | # Look up the current user.
20 | user = Travis::Pro::User.current
21 | puts "Hello #{user.login}!"
22 |
23 | # Display repositories the user is a member of.
24 | repos = Travis::Pro::Repository.find_all(member: user.login)
25 | repos.each { |repo| puts "#{repo.slug} #{repo.last_build_state}" }
26 |
--------------------------------------------------------------------------------
/examples/stream.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis'
4 |
5 | Travis.listen do |listener|
6 | listener.on('job:started') { |e| puts "job started for #{e.repository.slug}" }
7 | listener.on('job:finished') { |e| puts "job finished for #{e.repository.slug}" }
8 | end
9 |
--------------------------------------------------------------------------------
/lib/travis.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Travis
4 | autoload :Client, 'travis/client'
5 | autoload :CLI, 'travis/cli'
6 | autoload :Pro, 'travis/pro'
7 | autoload :Version, 'travis/version'
8 |
9 | include Client::Namespace.new
10 | end
11 |
--------------------------------------------------------------------------------
/lib/travis/auto_login.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis'
4 | require 'travis/client/auto_login'
5 | Travis::Client::AutoLogin.new(Travis).authenticate
6 |
--------------------------------------------------------------------------------
/lib/travis/cli.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | begin
4 | require 'travis/client'
5 | rescue LoadError => e
6 | raise e unless e.message == 'no such file to load -- json'
7 |
8 | warn 'You should either run `gem install json` or upgrade your Ruby version!'
9 | exit 1
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 :RegenerateToken, 'travis/cli/regenerate_token'
43 | autoload :RemoveToken, 'travis/cli/remove_token'
44 | autoload :RepoCommand, 'travis/cli/repo_command'
45 | autoload :Report, 'travis/cli/report'
46 | autoload :Repos, 'travis/cli/repos'
47 | autoload :Restart, 'travis/cli/restart'
48 | autoload :Requests, 'travis/cli/requests'
49 | autoload :Settings, 'travis/cli/settings'
50 | autoload :Setup, 'travis/cli/setup'
51 | autoload :Show, 'travis/cli/show'
52 | autoload :Sshkey, 'travis/cli/sshkey'
53 | autoload :Status, 'travis/cli/status'
54 | autoload :Sync, 'travis/cli/sync'
55 | autoload :Version, 'travis/cli/version'
56 | autoload :Whatsup, 'travis/cli/whatsup'
57 | autoload :Whoami, 'travis/cli/whoami'
58 |
59 | extend self
60 |
61 | def run(*args)
62 | args, opts = preparse(args)
63 | name = args.shift unless args.empty?
64 | command = command(name).new(opts)
65 | command.parse(args)
66 | command.execute
67 | end
68 |
69 | def command(name)
70 | const_name = command_name(name)
71 | constant = CLI.const_get(const_name) if const_name =~ (/^[A-Z][A-Za-z]+$/) && const_defined?(const_name)
72 | if command? constant
73 | constant
74 | else
75 | warn "unknown command #{name}"
76 | exit 1
77 | end
78 | end
79 |
80 | def commands
81 | CLI.constants.map { |n| try_const_get(n) }.select { |c| command? c }
82 | end
83 |
84 | def silent
85 | stderr = $stderr
86 | $stderr = dummy_io
87 | stdout = $stdout
88 | $stdout = dummy_io
89 | yield
90 | ensure
91 | $stderr = stderr if stderr
92 | $stdout = stdout if stdout
93 | end
94 |
95 | private
96 |
97 | def try_const_get(name)
98 | CLI.const_get(name)
99 | rescue Exception
100 | end
101 |
102 | def dummy_io
103 | return StringIO.new unless defined? IO::NULL && IO::NULL
104 |
105 | File.open(IO::NULL, 'w')
106 | end
107 |
108 | def command?(constant)
109 | constant.is_a? Class and constant < Command and !constant.abstract?
110 | end
111 |
112 | def command_name(name)
113 | case name
114 | when nil, '-h', '-?' then 'Help'
115 | when '-v' then 'Version'
116 | when /^--/ then command_name(name[2..])
117 | else name.split('-').map(&:capitalize).join
118 | end
119 | end
120 |
121 | # can't use flatten as it will flatten hashes
122 | def preparse(unparsed, args = [], opts = {})
123 | case unparsed
124 | when Hash then opts.merge! unparsed
125 | when Array then unparsed.each { |e| preparse(e, args, opts) }
126 | else args << unparsed.to_s
127 | end
128 | [args, opts]
129 | end
130 | end
131 | end
132 |
--------------------------------------------------------------------------------
/lib/travis/cli/accounts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Accounts < ApiCommand
8 | description 'displays accounts and their subscription status'
9 |
10 | def run
11 | authenticate
12 | accounts.each do |account|
13 | color = account.on_trial? ? :info : :green
14 | say [
15 | color(account.login, [color, :bold]),
16 | color("(#{account.name || account.login.capitalize}):", color),
17 | "#{description(account)},",
18 | account.repos_count == 1 ? '1 repository' : "#{account.repos_count} repositories"
19 | ].join(' ')
20 | end
21 | return if accounts.none?(&:on_trial?) || session.config['host'].nil?
22 |
23 | say session.config['host'], 'To set up a subscription, please visit %s.'
24 | end
25 |
26 | def description(account)
27 | return 'subscribed' if account.subscribed?
28 | return 'educational account' if account.educational?
29 |
30 | 'not subscribed'
31 | end
32 | end
33 | end
34 | end
35 |
--------------------------------------------------------------------------------
/lib/travis/cli/branches.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Branches < RepoCommand
8 | description 'displays the most recent build for each branch'
9 |
10 | def run
11 | repository.last_on_branch.each do |build|
12 | say [
13 | color("#{build.branch_info}:".ljust(longest + 2), %i[info bold]),
14 | color("##{build.number.to_s.ljust(4)} #{build.state}".ljust(16), build.color),
15 | build.commit.subject
16 | ].join(' ').strip + "\n"
17 | end
18 | end
19 |
20 | private
21 |
22 | def longest
23 | repository.branches.keys.map { |b| b.size }.max
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/lib/travis/cli/cache.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Cache < RepoCommand
8 | description 'lists or deletes repository caches'
9 | on '-d', '--delete', 'delete listed caches'
10 | on '-b', '--branch BRANCH', 'only list/delete caches on given branch'
11 | on '-m', '--match STRING', 'only list/delete caches where slug matches given string'
12 | on '-f', '--force', 'do not ask user to confirm deleting the caches'
13 |
14 | def run
15 | error "not allowed to access caches for #{color(repository.slug, :bold)}" unless repository.push?
16 | branches = caches.group_by(&:branch)
17 | check_caches
18 |
19 | warn "Deleted the following caches:\n" if delete?
20 | branches.each { |name, list| display_branch(name, list) }
21 | size = caches.inject(0) { |s, c| s + c.size }
22 | say 'Overall size of above caches: ' << formatter.file_size(size)
23 | end
24 |
25 | private
26 |
27 | def check_caches
28 | return if caches.any?
29 |
30 | say 'no caches found'
31 | exit
32 | end
33 |
34 | def display_branch(name, list)
35 | say color(name ? "On branch #{name}:" : 'Global:', :important)
36 | list.each { |c| display_cache(c) }
37 | puts
38 | end
39 |
40 | def display_cache(cache)
41 | say [
42 | color(cache.slug.ljust(space), :bold),
43 | 'last modified: ' << formatter.time(cache.last_modified),
44 | 'size: ' << formatter.file_size(cache.size)
45 | ].join(' ') << "\n"
46 | end
47 |
48 | def params
49 | params = {}
50 | params[:branch] = branch if branch?
51 | params[:match] = match if match?
52 | params
53 | end
54 |
55 | def caches
56 | @caches ||= drop? ? repository.delete_caches(params) : repository.caches(params)
57 | end
58 |
59 | def space
60 | @space ||= caches.map(&:slug).map(&:size).max
61 | end
62 |
63 | def drop?
64 | return false unless delete?
65 | return true if force?
66 |
67 | error 'not deleting caches without --force' unless interactive?
68 | error 'aborted' unless danger_zone? "Do you really want to delete #{description}?"
69 | true
70 | end
71 |
72 | def description
73 | description = color('all caches', :important)
74 | description << " on branch #{color(branch, :important)}" if branch?
75 | description << " that match #{color(match, :important)}" if match?
76 | description
77 | end
78 | end
79 | end
80 | end
81 |
--------------------------------------------------------------------------------
/lib/travis/cli/cancel.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Cancel < RepoCommand
8 | description 'cancels a job or build'
9 |
10 | def run(number = last_build.number)
11 | authenticate
12 | entity = job(number) || build(number)
13 | error "could not find job or build #{repository.slug}##{number}" unless entity
14 | entity.cancel
15 |
16 | say 'canceled', "#{entity.class.one} ##{entity.number} has been %s"
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/lib/travis/cli/console.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Console < ApiCommand
8 | description 'interactive shell; requires `pry`'
9 | on '-x', '--eval LINE', 'run line of ruby' do |c, line|
10 | c.instance_eval(line)
11 | exit
12 | end
13 |
14 | def run
15 | ensure_pry
16 |
17 | Object.send(:include, Client::Namespace.new(session))
18 | hooks = defined?(Pry::Hooks) ? Pry::Hooks.new : {}
19 | opts = { quiet: true, output: $stdout, hooks: }
20 | opts.merge!({ prompt: }) if prompt
21 | binding.pry(opts)
22 | end
23 |
24 | private
25 |
26 | def ensure_pry
27 | require 'pry'
28 | rescue LoadError
29 | msg = [
30 | 'You need to install pry to use Travis CLI console. Try',
31 | nil,
32 | '$ (sudo) gem install pry'
33 | ].join("\n")
34 | error msg
35 | end
36 |
37 | def prompt
38 | if Pry.const_defined? :SIMPLE_PROMPT
39 | Pry::SIMPLE_PROMPT
40 | elsif defined?(Pry::Prompt)
41 | Pry::Prompt[:simple]
42 | end
43 | end
44 | end
45 | end
46 | end
47 |
--------------------------------------------------------------------------------
/lib/travis/cli/disable.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Disable < RepoCommand
8 | description 'disables a project'
9 |
10 | def run
11 | authenticate
12 | repository.disable
13 | say 'disabled', color("#{slug}: %s :(", :error)
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/travis/cli/enable.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Enable < RepoCommand
8 | description 'enables a project'
9 | on('-s', '--skip-sync', "don't trigger a sync if the repo is unknown")
10 |
11 | def run
12 | authenticate
13 | error "not allowed to update service hook for #{color(repository.slug, :bold)}" unless repository.admin?
14 | repository.enable
15 | say 'enabled', color("#{slug}: %s :)", :success)
16 | end
17 |
18 | private
19 |
20 | def repository
21 | repo(slug)
22 | rescue Travis::Client::NotFound
23 | unless skip_sync?
24 | say 'repository not known to Travis CI (or no access?)'
25 | say 'triggering sync: '
26 | sync
27 | say ' done'
28 | end
29 | super
30 | end
31 | end
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/lib/travis/cli/encrypt.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Encrypt < RepoCommand
8 | description 'encrypts values for the .travis.yml'
9 | attr_accessor :config_key
10 |
11 | on('-a', '--add [KEY]', 'adds it to .travis.yml under KEY (default: env.global)') do |c, value|
12 | c.config_key = value || 'env.global'
13 | end
14 |
15 | on('-s', '--[no-]split', 'treat each line as a separate input')
16 | on('-p', '--append', "don't override existing values, instead treat as list")
17 | on('-x', '--override', 'override existing value')
18 |
19 | def run(*args)
20 | confirm = force_interactive.nil? || force_interactive
21 | error 'cannot combine --override and --append' if append? && override?
22 | error '--append without --add makes no sense' if append? && !add?
23 | error '--override without --add makes no sense' if override? && !add?
24 | self.override |= !config_key.start_with?('env.') if add? && !append?
25 |
26 | if args.first =~ %r{\w+/\w+} && !args.first.include?('=')
27 | warn 'WARNING: The name of the repository is now passed to the command with the -r option:'
28 | warn " #{command("encrypt [...] -r #{args.first}")}"
29 | warn ' If you tried to pass the name of the repository as the first argument, you'
30 | warn " probably won't get the results you wanted.\n"
31 | end
32 |
33 | data = args.join(' ')
34 |
35 | if data.empty?
36 | say color('Reading from stdin, press Ctrl+D when done', :info) if $stdin.tty?
37 | data = $stdin.read
38 | end
39 |
40 | data = split? ? data.split("\n") : [data.strip]
41 | warn_env_assignments(data)
42 | encrypted = data.map { |data| repository.encrypt(data) }
43 |
44 | if config_key
45 | set_config(encrypted.map { |e| { 'secure' => e } })
46 | confirm_and_save_travis_config confirm
47 | else
48 | list = encrypted.map { |data| format(data.inspect, ' secure: %s') }
49 | say(list.join("\n"), template(__FILE__), :none)
50 | end
51 | rescue OpenSSL::PKey::RSAError => e
52 | error "#{e.message.sub(' for key size', '')} - consider using " <<
53 | color('travis encrypt-file', %i[red bold]) <<
54 | color(' or ', :red) <<
55 | color('travis env set', %i[red bold])
56 | end
57 |
58 | private
59 |
60 | def add?
61 | !!config_key
62 | end
63 |
64 | def set_config(result)
65 | parent_config[last_key] = merge_config(result)
66 | end
67 |
68 | def merge_config(result)
69 | case subconfig = (parent_config[last_key] unless override?)
70 | when nil then result.size == 1 ? result.first : result
71 | when Array then subconfig + result
72 | else result.unshift(subconfig)
73 | end
74 | end
75 |
76 | def subconfig; end
77 |
78 | def key_chain
79 | @key_chain ||= config_key.split('.')
80 | end
81 |
82 | def last_key
83 | key_chain.last
84 | end
85 |
86 | def parent_config
87 | @parent_config ||= traverse_config(travis_config, *key_chain[0..-2])
88 | end
89 |
90 | def traverse_config(hash, key = nil, *rest)
91 | return hash unless key
92 |
93 | hash[key] = case value = hash[key]
94 | when nil then {}
95 | when Hash then value
96 | else { 'matrix' => Array(value) }
97 | end
98 |
99 | traverse_config(hash[key], *rest)
100 | end
101 |
102 | def warn_env_assignments(data)
103 | return unless /env/.match(config_key) && data.find { |d| /=/.match(d).nil? }
104 |
105 | warn "Environment variables in #{config_key} should be formatted as FOO=bar"
106 | end
107 | end
108 | end
109 | end
110 |
111 | __END__
112 | Please add the following to your <[[ color('.travis.yml', :info) ]]> file:
113 |
114 | %s
115 |
116 | Pro Tip: You can add it automatically by running with <[[ color('--add', :info) ]]>.
117 |
--------------------------------------------------------------------------------
/lib/travis/cli/endpoint.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Endpoint < ApiCommand
8 | description 'displays or changes the API endpoint'
9 |
10 | skip :authenticate
11 | on '--drop-default', 'delete stored default endpoint'
12 | on '--set-default', 'store endpoint as global default'
13 | on '--github', 'display github endpoint'
14 |
15 | def run_github
16 | error '--github cannot be combined with --drop-default' if drop_default?
17 | error '--github cannot be combined with --set-default' if set_default?
18 | load_gh
19 | say github_endpoint.to_s, 'GitHub endpoint: %s'
20 | end
21 |
22 | def run_travis
23 | if drop_default? && (was = config['default_endpoint'])
24 | config.delete('default_endpoint')
25 | say was, 'default API endpoint dropped (was %s)'
26 | else
27 | config['default_endpoint'] = api_endpoint if set_default?
28 | say api_endpoint, "API endpoint: %s#{' (stored as default)' if set_default?}"
29 | end
30 | end
31 |
32 | def run
33 | github? ? run_github : run_travis
34 | end
35 | end
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/travis/cli/env.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'shellwords'
5 |
6 | module Travis
7 | module CLI
8 | class Env < RepoCommand
9 | on('-P', '--[no-]public', 'make new values public')
10 | on('-p', '--[no-]private', 'make new values private') { |c, v| c.public = !v }
11 | on('-u', '--[no-]unescape', 'do not escape values')
12 | on('-f', '--force', 'do not ask for confirmation when clearing out all variables')
13 |
14 | description 'show or modify build environment variables'
15 | subcommands :list, :set, :unset, :copy, :clear
16 |
17 | def setup
18 | super
19 | authenticate
20 | error "not allowed to access environment variables for #{color(repository.slug, :bold)}" unless repository.push?
21 | end
22 |
23 | def set(name, value)
24 | options ||= { public: } unless public.nil?
25 | say color('[+] ', %i[green bold]) + "setting environment variable #{color "$#{name}", :info}"
26 | value = Shellwords.escape(value) unless unescape?
27 | env_vars.upsert(name, value, options || {})
28 | end
29 |
30 | def copy(*names)
31 | names.each do |name|
32 | if ENV.include? name
33 | set(name, ENV[name])
34 | else
35 | warn "missing in current environment: #{color "$#{name}", :bold}"
36 | end
37 | end
38 | end
39 |
40 | def unset(*names)
41 | remove_vars { |var| names.include? var.name }
42 | end
43 |
44 | def clear
45 | exit if env_vars.empty?
46 | exit 1 if interactive? && !force? && !danger_zone?("Clear out all env variables for #{color(
47 | repository.slug, :bold
48 | )}?")
49 | remove_vars
50 | end
51 |
52 | def remove_vars
53 | env_vars.each do |var|
54 | next if block_given? && !yield(var)
55 |
56 | say color('[x] ', %i[red bold]) + "removing environment variable #{color "$#{var.name}", :info}"
57 | var.delete
58 | end
59 | end
60 |
61 | def list
62 | say color("# environment variables for #{color repository.slug, :bold}", :info)
63 | env_vars.each { |v| say "#{v.name}=" << color(v.value || '[secure]', :bold) }
64 | end
65 |
66 | def env_vars
67 | repository.env_vars
68 | end
69 | end
70 | end
71 | end
72 |
--------------------------------------------------------------------------------
/lib/travis/cli/help.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Help < Command
8 | description 'helps you out when in dire need of information'
9 |
10 | CommandGroup = Struct.new(:cmds, :header)
11 |
12 | def run(command = nil)
13 | if command
14 | say CLI.command(command).new.help
15 | else
16 | api_cmds = CommandGroup.new(api_commands, 'API commands')
17 | repo_cmds = CommandGroup.new(repo_commands, 'Repo commands')
18 | other_cmds = CommandGroup.new(other_commands, 'non-API commands')
19 |
20 | say "Usage: travis COMMAND ...\n\nAvailable commands:\n\n"
21 | [other_cmds, api_cmds, repo_cmds].each do |cmd_grp|
22 | say " #{cmd_grp.header}"
23 | cmd_grp.cmds.each do |cmd|
24 | say " #{color(cmd.command_name, :command).ljust(25)} #{color(cmd.description, :info)}"
25 | end
26 | end
27 | say "\nrun `#{$PROGRAM_NAME} help COMMAND` for more info"
28 | end
29 | end
30 |
31 | def cmd_group_header(title)
32 | say " #{color(title, :green)}"
33 | end
34 |
35 | def api_commands
36 | CLI.commands.select do |cmd|
37 | cmd.ancestors.include?(CLI::ApiCommand) &&
38 | !cmd.ancestors.include?(CLI::RepoCommand)
39 | end.sort_by { |c| c.command_name }
40 | end
41 |
42 | def repo_commands
43 | CLI.commands.select do |cmd|
44 | cmd.ancestors.include? CLI::RepoCommand
45 | end.sort_by { |c| c.command_name }
46 | end
47 |
48 | def other_commands
49 | CLI.commands.reject do |cmd|
50 | cmd.ancestors.include? CLI::ApiCommand
51 | end.sort_by { |c| c.command_name }
52 | end
53 | end
54 | end
55 | end
56 |
--------------------------------------------------------------------------------
/lib/travis/cli/history.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class History < RepoCommand
8 | description "displays a project's build history"
9 |
10 | on('-a', '--after BUILD', 'Only show history after a given build number')
11 | on('-p', '--pull-request NUMBER', 'Only show history for the given Pull Request')
12 | on('-b', '--branch BRANCH', 'Only show history for the given branch')
13 | on('-l', '--limit LIMIT', 'Maximum number of history items')
14 | on('-d', '--date', 'Include date in output')
15 | on('-c', '--committer', 'Include committer in output')
16 | on('--[no-]all', 'Display all history items')
17 |
18 | def run
19 | countdown = Integer(limit || 10) unless all?
20 | params = { after_number: after } if after
21 | repository.each_build(params) do |build|
22 | next unless display? build
23 |
24 | display(build)
25 |
26 | if countdown
27 | countdown -= 1
28 | break if countdown < 1
29 | end
30 | end
31 | end
32 |
33 | private
34 |
35 | def display?(build)
36 | return build.pr_number == pull_request.to_i if pull_request
37 | return build.branch_info == branch if branch
38 |
39 | true
40 | end
41 |
42 | def display(build)
43 | say [
44 | date? && color(formatter.time(build.finished_at || build.started_at), build.color),
45 | color("##{build.number} #{build.state}:".ljust(16), [build.color, :bold]),
46 | color(build.branch_info.to_s, :info),
47 | committer? && build.commit.author_name.ljust(25),
48 | build.commit.subject
49 | ].compact.join(' ').strip + "\n"
50 | end
51 | end
52 | end
53 | end
54 |
--------------------------------------------------------------------------------
/lib/travis/cli/init.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Init < Enable
8 | LANGUAGE_MAPPING = {
9 | 'node' => 'node_js',
10 | 'node.js' => 'node_js',
11 | 'javascript' => 'node_js',
12 | 'coffeescript' => 'node_js',
13 | 'c++' => 'cpp',
14 | 'obj-c' => 'objective-c'
15 | }.freeze
16 |
17 | description 'generates a .travis.yml and enables the project'
18 |
19 | on('-f', '--force', 'override .travis.yml if it already exists')
20 | on('-k', '--skip-enable', 'do not enable project, only add .travis.yml')
21 | on('-p', '--print-conf', 'print generated config instead of writing to file')
22 |
23 | options = %w[
24 | script before_script after_script after_success install before_install
25 | compiler otp_release go jdk node_js perl php python rvm scala
26 | env gemfile
27 | ]
28 |
29 | options.each do |option|
30 | on "--#{option.gsub('_', '-')} VALUE",
31 | "sets #{option} option in .travis.yml (can be used more than once)" do |c, value|
32 | c.custom_config[option] &&= Array(c.custom_config[option]) << value
33 | c.custom_config[option] ||= value
34 | end
35 | end
36 |
37 | attr_writer :travis_config
38 |
39 | def self.languages
40 | Dir[File.expand_path('init/*.yml', Travis::Tools::Assets::BASE)]
41 | .map { |f| File.basename(f, '.yml') }.sort
42 | end
43 |
44 | def help
45 | super("Available languages: #{self.class.languages.join(', ')}\n\n")
46 | end
47 |
48 | def run(language = nil, file = '.travis.yml')
49 | error "#{file} already exists, use --force to override" if File.exist?(file) && !force? && !print_conf?
50 | language ||= ask('Main programming language used: ') { |q| q.default = detect_language }
51 | self.travis_config = template(language).merge(custom_config)
52 |
53 | if print_conf?
54 | puts travis_config.to_yaml
55 | else
56 | save_travis_config(file)
57 | say("#{file} file created!")
58 | end
59 |
60 | super() unless skip_enable?
61 | end
62 |
63 | def custom_config
64 | @custom_config ||= {}
65 | end
66 |
67 | private
68 |
69 | def template_name(language)
70 | asset_path("init/#{language}.yml")
71 | end
72 |
73 | def template(language)
74 | language = language.to_s.downcase
75 | language = LANGUAGE_MAPPING[language] || language
76 | file = template_name(language)
77 | error "unknown language #{language}" unless File.exist? file
78 | YAML.load_file(file)
79 | end
80 |
81 | def detect_language
82 | repository.github_language || 'Ruby'
83 | end
84 | end
85 | end
86 | end
87 |
--------------------------------------------------------------------------------
/lib/travis/cli/lint.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'yaml'
5 |
6 | module Travis
7 | module CLI
8 | class Lint < ApiCommand
9 | description 'display warnings for a .travis.yml'
10 | on '-q', '--[no-]quiet', 'does not print anything'
11 | on '-x', '--[no-]exit-code', 'sets the exit code to 1 if there are warning'
12 |
13 | def run(file = nil)
14 | file ||= '.travis.yml' if $stdin.tty? || $stdin.eof?
15 |
16 | if file && (file != '-')
17 | debug "reading #{file}"
18 | error "file does not exist: #{color(file, :bold)}" unless File.exist? file
19 | error "cannot read #{color(file, :bold)}" unless File.readable? file
20 | content = File.read(file)
21 | else
22 | debug 'reading stdin'
23 | file = 'STDIN'
24 | content = $stdin.read
25 | end
26 |
27 | begin
28 | YAML.load(content)
29 | rescue Psych::SyntaxError => e
30 | error "#{file} is not valid YAML: #{e.message}"
31 | end
32 |
33 | lint = session.lint(content)
34 |
35 | unless quiet?
36 | if lint.ok?
37 | say 'valid', color("Hooray, #{file} looks %s :)", :success)
38 | else
39 | say "Warnings for #{color(file, :info)}:"
40 | lint.warnings.each do |warning|
41 | say "#{color('[x]', %i[red bold])} "
42 | if warning.key.any?
43 | say [
44 | color('in ', :info),
45 | color(warning.key.join('.'), %i[info bold underline]),
46 | color(' section:', :info), ' '
47 | ].join
48 | end
49 | say warning.message.gsub(/"(.*?)"/) { color(::Regexp.last_match(1), %i[info important]) }
50 | end
51 | end
52 | end
53 |
54 | exit 1 if lint.warnings? && exit_code?
55 | end
56 | end
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/lib/travis/cli/login.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'travis/tools/github'
5 | require 'json'
6 |
7 | module Travis
8 | module CLI
9 | class Login < ApiCommand
10 | skip :authenticate
11 |
12 | description 'authenticates against the API and stores the token'
13 | on('-g', '--github-token TOKEN', 'identify by GitHub token')
14 | on('-T', '--auto-token',
15 | 'try to figure out who you are automatically (might send another apps token to Travis, token will not be stored)')
16 | on('--list-github-token', 'instead of actually logging in, list found GitHub tokens')
17 | on('--skip-token-check', 'don\'t verify the token with github')
18 |
19 | attr_accessor :user_login
20 |
21 | def list_token
22 | github.after_tokens = proc {}
23 | github.each_token do |token|
24 | say token
25 | end
26 | end
27 |
28 | def login
29 | session.access_token = nil
30 | github.with_token do |token|
31 | endpoint_config['access_token'] = github_auth(token)
32 | if user_login && (user.login != user_login)
33 | error(format('user mismatch: logged in as %p instead of %p', user.login,
34 | user_login))
35 | end
36 | unless user.correct_scopes?
37 | error(
38 | "#{user.login} has not granted Travis CI the required permissions. " \
39 | "Please try re-syncing your user data at https://#{session.config['host']}/account/preferences " \
40 | "and try logging in via #{session.config['host']}"
41 | )
42 | end
43 | success("Successfully logged in as #{user.login}!")
44 | end
45 |
46 | return if session.access_token
47 |
48 | raise Travis::Client::GitHubLoginFailed, 'all GitHub tokens given were invalid'
49 | end
50 |
51 | def run
52 | list_github_token ? list_token : login
53 | end
54 |
55 | def github
56 | @github ||= begin
57 | load_gh
58 | Tools::Github.new(session.config['github']) do |g|
59 | g.note = "temporary token to identify with the travis command line client against #{api_endpoint}"
60 | g.explode = explode?
61 | g.github_token = github_token
62 | g.auto_token = auto_token
63 | g.check_token = !skip_token_check?
64 | g.drop_token = !list_github_token
65 | g.login_header = proc { login_header }
66 | g.debug = proc { |log| debug(log) }
67 | g.after_tokens = proc { g.explode = true and error('no suitable github token found') }
68 | end
69 | end
70 | end
71 |
72 | def login_header
73 | say 'GitHub deprecated its Authorizations API exchanging a password for a token.'
74 | say 'Please visit https://github.blog/2020-07-30-token-authentication-requirements-for-api-and-git-operations for more information.'
75 | say "Try running with #{color('--github-token', :info)} or #{color('--auto-token', :info)} ."
76 | end
77 | end
78 | end
79 | end
80 |
--------------------------------------------------------------------------------
/lib/travis/cli/logout.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Logout < ApiCommand
8 | description 'deletes the stored API token'
9 |
10 | def run
11 | session.logout
12 | endpoint_config.delete('access_token')
13 | success('Successfully logged out!')
14 | end
15 | end
16 | end
17 | end
18 |
--------------------------------------------------------------------------------
/lib/travis/cli/logs.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'travis/tools/safe_string'
5 | require 'travis/tools/system'
6 |
7 | module Travis
8 | module CLI
9 | class Logs < RepoCommand
10 | attr_accessor :delete, :reason
11 |
12 | description 'streams test logs'
13 | on('-d', '--delete [REASON]', 'remove logs') do |c, reason|
14 | c.delete = true
15 | c.reason = reason
16 | end
17 | on('-f', '--force', 'do not ask user to confirm deleting the logs')
18 | on('--[no-]stream', 'only print current logs, do not stream')
19 |
20 | def setup
21 | super
22 | check_websocket
23 | end
24 |
25 | include Tools::SafeString
26 | def run(number = last_build.number)
27 | self.stream = true if stream.nil?
28 | job ||= job(number) || error("no such job ##{number}")
29 | delete ? delete_log(job) : display_log(job)
30 | end
31 |
32 | def delete_log(job)
33 | unless force?
34 | error 'not deleting logs without --force' unless interactive?
35 | error 'aborted' unless danger_zone? "Do you really want to delete the build log for #{color(job.inspect_info,
36 | :underline)}?"
37 | end
38 |
39 | warn "deleting log for #{color(job.inspect_info, %i[bold info])}"
40 | job.delete_log(reason || {})
41 | end
42 |
43 | def display_log(job)
44 | info "displaying logs for #{color(job.inspect_info, %i[bold info])}"
45 | return print_log(job.log.body) unless stream?
46 |
47 | job.log.body { |part| print_log(part) }
48 | ensure
49 | print "\e[0m" if interactive?
50 | end
51 |
52 | def print_log(part)
53 | print interactive? ? encoded(part) : clean(part)
54 | end
55 |
56 | private
57 |
58 | def job(number)
59 | number = last_build.number + number if number.start_with? '.'
60 | job = super(number) || build(number) || branch(number)
61 | job = job.jobs.first if job.respond_to? :jobs
62 | job
63 | end
64 |
65 | def check_websocket
66 | require 'websocket-native' if stream?
67 | rescue LoadError => e
68 | raise e if e.respond_to?(:path) && (e.path != 'websocket-native')
69 |
70 | info 'speed up log streaming by installing the websocket-native gem'
71 | end
72 | end
73 | end
74 | end
75 |
--------------------------------------------------------------------------------
/lib/travis/cli/monitor.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'travis/tools/notification'
5 |
6 | module Travis
7 | module CLI
8 | class Monitor < ApiCommand
9 | description "live monitor for what's going on"
10 | on('-m', '--my-repos', 'Only monitor my own repositories')
11 |
12 | on('-r', '--repo SLUG', 'monitor given repository (can be used more than once)') do |c, slug|
13 | c.repos << slug
14 | c.send(:error, 'SLUG should be of the form OWNER/REPO') unless slug.split('/').compact.size == 2
15 | end
16 |
17 | types = Tools::Notification::DEFAULT.map(&:to_s).join(', ')
18 | on('-n', '--[no-]notify [TYPE]', "send out desktop notifications (optional type: #{types})") do |c, type|
19 | c.setup_notification(type)
20 | end
21 |
22 | on('-b', '--builds', 'only monitor builds, not jobs')
23 | on('-p', '--push', 'monitor push events')
24 | on('-P', '--pull', 'monitor pull request events')
25 |
26 | attr_reader :repos, :notification
27 |
28 | def initialize(*)
29 | @repos = []
30 | super
31 | end
32 |
33 | def setup
34 | super
35 | repos.map! { |r| repo(r) }
36 | repos.concat(user.repositories) if my_repos?
37 | setup_notification(true) unless notification
38 | debug "Using notifications: #{notification.class.name[/[^:]+$/]}"
39 | end
40 |
41 | def setup_notification(type = nil)
42 | refuse = false
43 | case type
44 | when false then @notification = Tools::Notification.new(:dummy)
45 | when nil, true then @notification = Tools::Notification.new
46 | else
47 | refuse = true
48 | @notification = Tools::Notification.new(type)
49 | end
50 | rescue ArgumentError => e
51 | @notification = Tools::Notification.new(:dummy)
52 | error(e.message) if refuse
53 | warn(e.message)
54 | end
55 |
56 | def description
57 | case repos.size
58 | when 0 then session.config['host']
59 | when 1 then repos.first.slug
60 | else "#{repos.size} repositories"
61 | end
62 | end
63 |
64 | def events
65 | events = %w[build:started build:finished]
66 | events << 'job:started' << 'job:finished' unless builds?
67 | events
68 | end
69 |
70 | def all?
71 | !pull? and !push?
72 | end
73 |
74 | def monitor?(entity)
75 | return true if all?
76 |
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 => e
100 | raise e 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
112 |
--------------------------------------------------------------------------------
/lib/travis/cli/open.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'launchy'
5 |
6 | module Travis
7 | module CLI
8 | class Open < RepoCommand
9 | description 'opens a build or job in the browser'
10 |
11 | on('-g', '--github', 'Open the corresponding project, compare view or pull request on GitHub')
12 | on('-p', '--print', 'Print out the URL instead of opening it in a browser')
13 |
14 | def run(number = nil)
15 | url = url_for(number)
16 | if print?
17 | say url, 'web view: %s'
18 | else
19 | Launchy.open(url)
20 | end
21 | end
22 |
23 | private
24 |
25 | def url_for(number)
26 | return repo_url unless number
27 |
28 | entity = job(number) || build(number)
29 | error "could not find job or build #{repository.slug}##{number}" unless entity
30 | github ? entity.commit.compare_url : "#{repo_url}/#{entity.class.many}/#{entity.id}"
31 | end
32 |
33 | def repo_url
34 | "https://#{host}/#{slug}"
35 | end
36 |
37 | def host
38 | github ? 'github.com' : session.config['host']
39 | end
40 | end
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/lib/travis/cli/parser.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'optparse'
5 |
6 | module Travis
7 | module CLI
8 | module Parser
9 | def on_initialize(&block)
10 | @on_initialize ||= []
11 | @on_initialize << block if block
12 | if superclass.respond_to? :on_initialize
13 | superclass.on_initialize + @on_initialize
14 | else
15 | @on_initialize
16 | end
17 | end
18 |
19 | def on(*args, &block)
20 | block ||= begin
21 | full_arg = args.detect { |a| a.start_with? '--' }
22 | name = full_arg.gsub(/^--(\[no-\])?(\S+).*$/, '\2').gsub('-', '_')
23 | attr_reader(name) unless method_defined? name
24 | attr_writer(name) unless method_defined? "#{name}="
25 | alias_method("#{name}?", name) unless method_defined? "#{name}?"
26 | proc { |instance, value| instance.public_send("#{name}=", value) }
27 | end
28 |
29 | on_initialize do |instance|
30 | instance.parser.on(*args) do |value|
31 | block.call(instance, value)
32 | end
33 | end
34 | end
35 |
36 | def new(*)
37 | attr_accessor :parser unless method_defined? :parser
38 | result = super
39 | result.parser = OptionParser.new
40 | on_initialize.each { |b| b[result] }
41 | result
42 | end
43 | end
44 | end
45 | end
46 |
--------------------------------------------------------------------------------
/lib/travis/cli/pubkey.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Pubkey < RepoCommand
8 | attr_accessor :key_format
9 |
10 | description "prints out a repository's public key"
11 | on('-p', '--pem', 'encode in format used by pem') { |c, _| c.key_format = :pem }
12 | on('-f', '--fingerprint', 'display fingerprint') { |c, _| c.key_format = :fingerprint }
13 |
14 | def run
15 | error "#{key_format} format not supported by #{api_endpoint}" unless key
16 | say key, "Public key for #{color(repository.slug, :info)}:\n\n%s", :bold
17 | end
18 |
19 | private
20 |
21 | def key
22 | key = repository.public_key
23 | case self.key_format ||= :ssh
24 | when :fingerprint then key.fingerprint
25 | when :pem then key.to_s
26 | when :ssh then key.to_ssh
27 | else raise "unknown format #{key_format}"
28 | end
29 | end
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/lib/travis/cli/raw.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Raw < ApiCommand
8 | description 'makes an (authenticated) API call and prints out the result'
9 |
10 | skip :authenticate
11 | on('--[no-]json', 'display as json')
12 |
13 | def run(resource)
14 | reply = session.get_raw(resource)
15 | json? ? say(reply.to_json) : pp(reply)
16 | rescue Travis::Client::NotFound
17 | error 'resource not found'
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/lib/travis/cli/regenerate_token.rb:
--------------------------------------------------------------------------------
1 | require 'travis/cli'
2 |
3 | module Travis
4 | module CLI
5 | class RegenerateToken < ApiCommand
6 | description "regenerates the stored API token"
7 |
8 | def run
9 | token = session.regenerate_token['token']
10 | endpoint_config['access_token'] = token
11 | success("Successfully regenerated the token!")
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/travis/cli/remove_token.rb:
--------------------------------------------------------------------------------
1 | require 'travis/cli'
2 |
3 | module Travis
4 | module CLI
5 | class RemoveToken < ApiCommand
6 | description "deletes the stored API token"
7 |
8 | def run
9 | session.remove_token
10 | endpoint_config['access_token'] = nil
11 | success("Successfully removed the access token!")
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/travis/cli/report.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'travis/tools/system'
5 |
6 | module Travis
7 | module CLI
8 | class Report < ApiCommand
9 | description 'generates a report useful for filing issues'
10 | on '-r', '--known-repos', 'include repositories in report'
11 | skip :authenticate, :clear_error
12 |
13 | def run
14 | display('System', :general)
15 | display('CLI', :cli_info)
16 | display('Session', :session_info)
17 | display('Endpoints', :endpoints)
18 | display('Known Repositories', :known_repos) if known_repos?
19 | display_error
20 | say "For issues with the command line tool, please visit #{color(
21 | 'https://github.com/travis-ci/travis.rb/issues', :underline
22 | )}."
23 | say "For Travis CI in general, go to #{color('https://github.com/travis-ci/travis-ci/issues',
24 | :underline)} or email #{color('support@travis-ci.com',
25 | :underline)}."
26 | end
27 |
28 | def display_error
29 | return unless (error = load_file('error.log'))
30 |
31 | display('Last Exception', :say, color(error, :info))
32 | end
33 |
34 | def display(title, method, *args)
35 | say color(title, %i[bold underline])
36 | send(method, *args) { |*a| list(*a) }
37 | puts
38 | end
39 |
40 | def list(key, value, additional = nil)
41 | value = case value
42 | when Array then value.empty? ? 'none' : value.map(&:inspect).join(', ')
43 | when true then 'yes'
44 | when false then 'no'
45 | when nil then 'unknown'
46 | else value.to_s
47 | end
48 | additional &&= " (#{additional})"
49 | say "#{key}:".ljust(known_repos? ? 50 : 25) << ' ' << color(value.to_s, :bold) << additional.to_s
50 | end
51 |
52 | def general
53 | yield 'Ruby', Tools::System.ruby
54 | yield 'Operating System', Tools::System.os
55 | yield 'RubyGems', Tools::System.rubygems
56 | end
57 |
58 | def cli_info
59 | yield 'Version', Travis::VERSION
60 | yield 'Plugins', defined?(TRAVIS_PLUGINS) ? TRAVIS_PLUGINS : []
61 | yield 'Auto-Completion', Tools::Completion.completion_installed?
62 | yield 'Last Version Check', last_check['at'] ? Time.at(last_check['at']) : 'never'
63 | end
64 |
65 | def session_info
66 | yield 'API Endpoint', api_endpoint
67 | yield 'Logged In', user_info
68 | yield 'Verify SSL', !insecure
69 | yield 'Enterprise', enterprise?
70 | end
71 |
72 | def endpoints
73 | config['endpoints'].each do |endpoint, info|
74 | info = [
75 | info['access_token'] ? 'access token' : nil,
76 | info['insecure'] ? 'insecure' : nil,
77 | default_endpoint == endpoint ? 'default' : nil,
78 | endpoint == api_endpoint ? 'current' : nil
79 | ].compact
80 | yield endpoint_name(endpoint), endpoint, info.join(', ')
81 | end
82 | end
83 |
84 | def endpoint_name(url, prefix = '')
85 | case url
86 | when Travis::Client::COM_URI then "#{prefix}com"
87 | when /api-staging\.travis-ci/ then endpoint_name(url.sub('api-staging.', 'api.'), 'staging-')
88 | else
89 | key, = config['enterprise'].detect { |_k, v| v.start_with? url } if config['enterprise'].respond_to?(:detect)
90 | key ? 'enterprise %p' % key : '???'
91 | end
92 | end
93 |
94 | def known_repos
95 | config['repos'].each do |key, info|
96 | yield key, info['endpoint']
97 | end
98 | end
99 |
100 | def user_info
101 | access_token ? 'as %p' % user.login : 'no'
102 | rescue Travis::Client::Error => e
103 | e.message
104 | end
105 | end
106 | end
107 | end
108 |
--------------------------------------------------------------------------------
/lib/travis/cli/repos.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Repos < ApiCommand
8 | description 'lists repositories the user has certain permissions on'
9 | on('-m', '--match PATTERN', 'only list repositories matching the given pattern (shell style)')
10 | on('-o', '--owner LOGIN', 'only list repos for a certain owner')
11 | on('-n', '--name NAME', 'only list repos with a given name')
12 | on('-a', '--active', 'only list active repositories')
13 | on('-A', '--inactive', 'only list inactive repositories') { |c| c.active = false }
14 | on('-d', '--admin', 'only list repos with (or without) admin access')
15 | on('-D', '--no-admin', 'only list repos without admin access') { |c| c.admin = false }
16 |
17 | def run
18 | repositories.each do |repo|
19 | next say(repo.slug) unless interactive?
20 |
21 | state_color = repo.active? ? :green : :yellow
22 | say "#{color(repo.slug, [:bold, state_color])} "
23 | say color('(' << attributes(repo).map { |n, v| "#{n}: #{v ? 'yes' : 'no'}" }.join(', ') << ')', state_color)
24 | description = repo.description.lines.first.chomp unless repo.description.to_s.empty?
25 | say "Description: #{description || '???'}"
26 | empty_line unless repo == repositories.last
27 | end
28 | end
29 |
30 | def repositories
31 | @repositories ||= begin
32 | repos = session.hooks.concat(user.repositories).uniq
33 | session.preload(repos).sort_by(&:slug).select do |repo|
34 | next false unless match? repo.slug
35 | next false unless active.nil? || (repo.active? == active)
36 | next false unless owner.nil? || (repo.owner_name == owner)
37 | next false unless name.nil? || (repo.name == name)
38 | next false unless admin.nil? || (repo.admin? == admin)
39 |
40 | true
41 | end
42 | end
43 | end
44 |
45 | def attributes(repo)
46 | { 'active' => repo.active?, 'admin' => repo.admin?, 'push' => repo.push?, 'pull' => repo.pull? }
47 | end
48 |
49 | def match?(string)
50 | return true if match.nil?
51 |
52 | flags = File::FNM_PATHNAME | File::FNM_DOTMATCH
53 | flags |= File::FNM_EXTGLOB if defined? File::FNM_EXTGLOB
54 | File.fnmatch?(match, string, flags)
55 | end
56 | end
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/lib/travis/cli/requests.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Requests < RepoCommand
8 | description 'lists recent requests'
9 | on '-l', '--limit LIMIT', 'Maximum number requests to display'
10 |
11 | def run
12 | requests = repository.requests
13 | requests = requests[0, Integer(limit)] if limit
14 | requests.each do |request|
15 | style ||= :success if request.accepted?
16 | style ||= :error if request.rejected?
17 | style ||= :info
18 |
19 | case request.event_type
20 | when 'push'
21 | result = request.result || 'received'
22 | message = request.message
23 | message ||= 'validation pending' unless request.rejected? || request.accepted?
24 | message ||= 'unknown reason' unless request.accepted?
25 | message ||= 'triggered new build' unless request.rejected?
26 | description = "push to #{request.branch || request.tag || '???'}"
27 | when 'pull_request'
28 | result = request.result || 'received'
29 | message = request.message
30 | message ||= 'HEAD commit not updated' unless request.accepted?
31 | message ||= 'triggered new build' unless request.rejected?
32 | description = "PR ##{request.pull_request_number}"
33 | end
34 |
35 | say [
36 | color(description, [:bold, style]),
37 | color(result, style),
38 | color("(#{message})", style)
39 | ].join(' ').strip + "\n"
40 |
41 | say " #{color(request.commit.short_sha, :bold)} - #{request.commit.subject}" if request.commit
42 | say " received at: #{formatter.time(request.created_at)}"
43 | empty_line
44 | end
45 | end
46 | end
47 | end
48 | end
49 |
--------------------------------------------------------------------------------
/lib/travis/cli/restart.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Restart < RepoCommand
8 | description 'restarts a build or job'
9 |
10 | def run(number = last_build.number)
11 | authenticate
12 | entity = job(number) || build(number)
13 | error "could not find job or build #{repository.slug}##{number}" unless entity
14 | entity.restart
15 |
16 | say 'restarted', "#{entity.class.one} ##{entity.number} has been %s"
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/lib/travis/cli/settings.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Settings < RepoCommand
8 | attr_accessor :setting
9 |
10 | description 'access repository settings'
11 | on('--keys', 'always use setting key instead of description')
12 | on('-t', '--enable', 'enable boolean setting(s)') { |c| c.setting = true }
13 | on('-f', '--disable', 'disable boolean setting(s)') { |c| c.setting = false }
14 | on('-s', '--set VALUE', 'set to given value') { |c, v| c.setting = v }
15 | on('-c', '--configure', 'change settings interactively')
16 |
17 | DESCRIPTIONS = {
18 | builds_only_with_travis_yml: 'Only run builds with a .travis.yml',
19 | build_pushes: 'Build pushes',
20 | build_pull_requests: 'Build pull requests',
21 | maximum_number_of_builds: 'Maximum number of concurrent builds',
22 | auto_cancel_pushes: 'Cancel older push builds that are not yet running',
23 | auto_cancel_pull_requests: 'Cancel older pull request builds that are not yet running'
24 | }.freeze
25 |
26 | def run(*keys)
27 | exit 1 if interactive? && keys.empty? && !setting.nil? && !all_settings? && !configure?
28 | authenticate
29 | say repository.slug, 'Settings for %s:'
30 | repository.settings.to_h.each do |key, value|
31 | next unless keys.empty? || keys.include?(key)
32 |
33 | if configure?
34 | repository.settings[key] = if boolean? key
35 | agree("#{describe(key, "enable #{key}")}? ") do |q|
36 | default = setting.nil? ? value : setting
37 | q.default = default ? 'yes' : 'no'
38 | end
39 | else
40 | ask("#{describe(key, "Value for #{key}")}: ", Integer) do |q|
41 | default = setting.to_i if setting && setting.respond_to?(:to_i)
42 | default ||= value
43 | default ||= 0
44 | q.default = default
45 | end
46 | end
47 | else
48 | value = repository.settings[key] = setting unless setting.nil?
49 | descr = color(describe(key, color(key, :info)) do |s|
50 | "#{key.ljust(30)} #{color(s, %i[reset bold])}"
51 | end, :info)
52 | say format_value(value) << ' ' << descr
53 | end
54 | end
55 | repository.settings.save if configure? || !setting.nil?
56 | end
57 |
58 | def boolean?(key)
59 | key.to_sym != :maximum_number_of_builds
60 | end
61 |
62 | def format_value(value)
63 | case value
64 | when false, nil then color('[-]', %i[bold red])
65 | when true then color('[+]', %i[bold green])
66 | else color(value.to_s.rjust(3), %i[bold blue])
67 | end
68 | end
69 |
70 | def all_settings?
71 | agree("Really #{setting ? 'enable' : 'disable'} all settings? ") do |q|
72 | q.default = 'no'
73 | end
74 | end
75 |
76 | def describe(key, description = key)
77 | return description if keys?
78 |
79 | desc = DESCRIPTIONS[key.to_sym]
80 | desc &&= yield(desc) if block_given?
81 | desc || description
82 | end
83 | end
84 | end
85 | end
86 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Setup < RepoCommand
8 | autoload :Anynines, 'travis/cli/setup/anynines'
9 | autoload :Appfog, 'travis/cli/setup/appfog'
10 | autoload :Artifacts, 'travis/cli/setup/artifacts'
11 | autoload :Biicode, 'travis/cli/setup/biicode'
12 | autoload :CloudControl, 'travis/cli/setup/cloud_control'
13 | autoload :CloudFoundry, 'travis/cli/setup/cloud_foundry'
14 | autoload :CodeDeploy, 'travis/cli/setup/code_deploy'
15 | autoload :EngineYard, 'travis/cli/setup/engine_yard'
16 | autoload :Heroku, 'travis/cli/setup/heroku'
17 | autoload :Nodejitsu, 'travis/cli/setup/nodejitsu'
18 | autoload :NPM, 'travis/cli/setup/npm'
19 | autoload :OpenShift, 'travis/cli/setup/open_shift'
20 | autoload :PyPI, 'travis/cli/setup/pypi'
21 | autoload :RubyGems, 'travis/cli/setup/ruby_gems'
22 | autoload :Ninefold, 'travis/cli/setup/ninefold'
23 | autoload :S3, 'travis/cli/setup/s3'
24 | autoload :CloudFiles, 'travis/cli/setup/cloud_files'
25 | autoload :Divshot, 'travis/cli/setup/divshot'
26 | autoload :Hackage, 'travis/cli/setup/hackage'
27 | autoload :OpsWorks, 'travis/cli/setup/opsworks'
28 | autoload :SauceConnect, 'travis/cli/setup/sauce_connect'
29 | autoload :Modulus, 'travis/cli/setup/modulus'
30 | autoload :Releases, 'travis/cli/setup/releases'
31 | autoload :GCS, 'travis/cli/setup/gcs'
32 | autoload :Cloud_66, 'travis/cli/setup/cloud_66'
33 | autoload :ElasticBeanstalk, 'travis/cli/setup/elastic_beanstalk'
34 | autoload :Deis, 'travis/cli/setup/deis'
35 | autoload :Service, 'travis/cli/setup/service'
36 |
37 | description 'sets up an addon or deploy target'
38 | on('-f', '--force', 'override config section if it already exists')
39 |
40 | def self.service(name)
41 | normal_name = Service.normalized_name(name)
42 | const_name = constants(false).detect { |c| Service.normalized_name(c) == normal_name }
43 | constant = const_get(const_name) if const_name
44 | constant if constant && (constant < Service) && constant.known_as?(name)
45 | end
46 |
47 | def self.services
48 | constants(false).sort.map { |c| const_get(c) }.select { |c| c < Service }
49 | end
50 |
51 | def help
52 | services = self.class.services.map do |s|
53 | "\t" << color(s.service_name.ljust(20), :command) << color(s.description, :info)
54 | end.join("\n")
55 | super("\nAvailable services:\n\n#{services}\n\n")
56 | end
57 |
58 | def run(service, file = travis_yaml)
59 | service(service).run
60 | save_travis_config(file)
61 | end
62 |
63 | def service(name)
64 | factory = self.class.service(name)
65 | error("unknown service #{name}") unless factory
66 | factory.new(self)
67 | end
68 | end
69 | end
70 | end
71 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/anynines.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Anynines < Service
9 | description 'automatic deployment to anynines'
10 |
11 | def run
12 | deploy 'anynines' do |config|
13 | config['username'] ||= ask('anynines username: ').to_s
14 | config['password'] ||= ask('anynines password: ') { |q| q.echo = '*' }.to_s
15 | config['organization'] ||= ask('anynines organization: ').to_s
16 | config['space'] ||= ask('anynines space: ').to_s
17 | end
18 | end
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/appfog.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Appfog < Service
9 | description 'automatic deployment to Appfog'
10 |
11 | def run
12 | deploy 'appfog' do |config|
13 | config['email'] = ask('Email address: ').to_s
14 | config['password'] = ask('Password: ') { |q| q.echo = '*' }.to_s
15 | config['app'] = ask('App name: ') { |q| q.default = repository.name }.to_s
16 | end
17 | end
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/artifacts.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Artifacts < Service
9 | description 'automatic artifact shipping to S3'
10 | service_name 'artifacts'
11 |
12 | def run
13 | travis_config['addons'] ||= {}
14 | configure 'artifacts', {}, travis_config['addons'] do |config|
15 | config['key'] = ask('Access key ID: ').to_s
16 | config['secret'] = ask('Secret access key: ') { |q| q.echo = '*' }.to_s
17 | config['bucket'] = ask('Bucket: ').to_s
18 | encrypt(config, 'key') if agree('Encrypt access key ID? ') { |q| q.default = 'yes' }
19 | encrypt(config, 'secret') if agree('Encrypt secret access key? ') { |q| q.default = 'yes' }
20 | end
21 | end
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/biicode.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Biicode < Service
9 | description 'automatic publish to biicode'
10 |
11 | def run
12 | deploy 'biicode', 'release' do |config|
13 | config['user'] ||= ask('biicode username: ') { |q| q }.to_s
14 | config['password'] ||= ask('biicode password: ') { |q| q.echo = '*' }.to_s
15 | on('publish only tagged commits? ', config, 'tags' => true)
16 | end
17 | end
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/cloud_66.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Cloud_66 < Service
9 | description 'Automatic deployment to Cloud 66'
10 | service_name 'cloud66'
11 |
12 | def run
13 | deploy 'cloud66', 'release' do |config|
14 | config['redeployment_hook'] ||= ask('Cloud 66 Redeployment Hook Url: ') { |q| q.echo = '*' }.to_s
15 |
16 | encrypt(config, 'redeployment_hook') if agree('Encrypt Redeployment Hook?') { |q| q.default = 'yes' }
17 | end
18 | end
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/cloud_control.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class CloudControl < Service
9 | description 'automatic deployment to cloudControl'
10 |
11 | def run
12 | deploy 'cloudcontrol' do |config|
13 | config['email'] = ask('cloudControl email: ').to_s
14 | config['password'] = ask('cloudControl password: ') { |q| q.echo = '*' }.to_s
15 | app = ask('cloudControl application: ') { |q| q.default = repository.name }.to_s
16 | dep = ask('cloudControl deployment: ') { |q| q.default = 'default' }.to_s
17 | config['deployment'] = "#{app}/#{dep}"
18 | end
19 | end
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/cloud_files.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class CloudFiles < Service
9 | description 'automatic pushing to Rackspace Cloud Files'
10 |
11 | def run
12 | deploy 'cloudfiles' do |config|
13 | config['username'] = ask('Rackspace Username: ').to_s
14 | config['api_key'] = ask('Rackspace Api Key: ') { |q| q.echo = '*' }.to_s
15 | config['region'] = ask('Cloud Files Region: ').to_s
16 | config['container'] = ask('Container: ').to_s
17 | end
18 | end
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/cloud_foundry.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class CloudFoundry < Service
9 | description 'automatic deployment to Cloud Foundry'
10 |
11 | def run
12 | deploy 'cloudfoundry' do |config|
13 | target_file = File.expand_path('.cf/config.json', Dir.home)
14 | config['api'] ||= JSON.parse(File.read(target_file))['Target'] if File.exist? target_file
15 | config['api'] ||= ask('Cloud Foundry api: ').to_s
16 | config['username'] ||= ask('Cloud Foundry username: ').to_s
17 | config['password'] ||= ask('Cloud Foundry password: ') { |q| q.echo = '*' }.to_s
18 | config['organization'] ||= ask('Cloud Foundry organization: ').to_s
19 | config['space'] ||= ask('Cloud Foundry space: ').to_s
20 | end
21 | end
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/code_deploy.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 | require 'shellwords'
5 |
6 | module Travis
7 | module CLI
8 | class Setup
9 | class CodeDeploy < Service
10 | description 'triggering a new deployment on Amazon CodeDeploy'
11 | AWS_CONFIG = File.expand_path('.aws/config', ENV['HOME'])
12 |
13 | def run
14 | if File.readable? AWS_CONFIG
15 | content = File.read(AWS_CONFIG)
16 | access_key = content[/aws_access_key_id = (\S+)\n/, 1]
17 | secret_access_key = content[/aws_secret_access_key = (\S+)\n/, 1]
18 | end
19 |
20 | deploy 'codedeploy' do |config|
21 | config['access_key_id'] = ask('Access key ID: ') { |q| q.default = access_key if access_key }.to_s
22 | secret_access_key = nil unless access_key == config['access_key_id']
23 | config['secret_access_key'] = secret_access_key || ask('Secret access key: ') { |q| q.echo = '*' }.to_s
24 | config['bucket'] = ask('S3 Bucket: ').to_s
25 | config['key'] = ask('S3 Key: ').to_s
26 | config['bundle_type'] = ask('Bundle Type: ') do |q|
27 | q.default = config['key'][/\.(zip|tar|tgz)$/, 1]
28 | end.to_s
29 | config['application'] = ask('Application Name: ') { |q| q.default = repository.name }.to_s
30 | config['deployment_group'] = ask('Deployment Group Name: ').to_s
31 | encrypt(config, 'secret_access_key') if agree('Encrypt secret access key? ') { |q| q.default = 'yes' }
32 | end
33 |
34 | return unless agree('Also push bundle to S3? ')
35 |
36 | cd = travis_config['deploy']
37 | s3 = {
38 | 'provider' => 's3',
39 | 'access_key_id' => cd['access_key_id'],
40 | 'secret_access_key' => cd['secret_access_key'],
41 | 'local_dir' => 'dpl_cd_upload',
42 | 'skip_cleanup' => true,
43 | 'on' => cd['on'],
44 | 'bucket' => cd['bucket']
45 | }
46 |
47 | s3['upload_dir'] = File.dirname(cd['key']) if cd['key'].include? '/'
48 | travis_config['deploy'] = [s3, cd]
49 | upload_file_name = File.basename(cd['key'])
50 | source_file = ask('Source File: ') { |q| q.default = upload_file_name }
51 | travis_config['before_deploy'] = [
52 | 'mkdir -p dpl_cd_upload',
53 | "mv #{Shellwords.escape(source_file)} dpl_cd_upload/#{Shellwords.escape(upload_file_name)}"
54 | ]
55 | end
56 | end
57 | end
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/deis.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Deis < Service
9 | description 'automatic deployment to a deis app'
10 |
11 | def run
12 | deploy 'deis' do |config|
13 | config['controller'] ||= ask('Deis Controller: ').to_s
14 | config['app'] ||= ask('Deis App: ').to_s
15 | config['username'] ||= ask('Deis Username: ').to_s
16 | config['password'] ||= ask('Deis Password: ') { |q| q.echo = '*' }.to_s
17 | end
18 | end
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/divshot.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Divshot < Service
9 | description 'deployment to Divshot.io'
10 |
11 | def run
12 | deploy 'divshot' do |config|
13 | config['api_key'] = ask('Divshot Api Key: ') { |q| q.echo = '*' }.to_s
14 | config['environment'] = ask('Divshot Environment: ').to_s
15 | end
16 | end
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/elastic_beanstalk.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class ElasticBeanstalk < Service
9 | description 'deployment to AWS Elastic Beanstalk'
10 |
11 | def run
12 | deploy 'elasticbeanstalk' do |config|
13 | config['access_key_id'] = ask('Access key ID: ').to_s
14 | config['secret_access_key'] = ask('Secret access key: ') { |q| q.echo = '*' }.to_s
15 | config['region'] = ask('Elastic Beanstalk region: ') { |q| q.default = 'us-east-1' }.to_s
16 | config['app'] = ask('Elastic Beanstalk application name: ').to_s
17 | config['env'] = ask('Elastic Beanstalk environment to update: ').to_s
18 | config['bucket_name'] = ask('Bucket name to upload app to: ').to_s
19 |
20 | encrypt(config, 'secret_access_key') if agree('Encrypt secret access key? ') { |q| q.default = 'yes' }
21 | end
22 | end
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/engine_yard.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 | require 'yaml'
5 |
6 | module Travis
7 | module CLI
8 | class Setup
9 | class EngineYard < Service
10 | description 'automatic deployment to Engine Yard'
11 |
12 | def run
13 | deploy 'engineyard' do |config|
14 | eyrc = File.expand_path('.eyrc', Dir.home)
15 | config['api_key'] = YAML.load_file(eyrc)['api_token'] if File.exist?(eyrc)
16 | config['api_key'] = ask('API token: ') { |q| q.echo = '*' }.to_s unless config['api_key']
17 | env = ask('Environment (optional): ').to_s
18 | config['environment'] = env unless env.empty?
19 | migrate = agree('Run migrations on deploy? ') { |q| q.default = 'yes' }
20 | config['migrate'] = ask('Migration command: ') { |q| q.default = 'rake db:migrate' } if migrate
21 | end
22 | end
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/gcs.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class GCS < Service
9 | description 'automatic pushing to Google Cloud Storage'
10 |
11 | def run
12 | deploy 'gcs' do |config|
13 | config['access_key_id'] = ask('Access key ID: ').to_s
14 | config['secret_access_key'] = ask('Secret access key: ') { |q| q.echo = '*' }.to_s
15 | config['bucket'] = ask('Bucket: ').to_s
16 | local_dir = ask('Local project directory to upload (Optional): ').to_s
17 | config['local-dir'] = local_dir unless local_dir.empty?
18 | encrypt(config, 'secret_access_key') if agree('Encrypt secret access key? ') { |q| q.default = 'yes' }
19 | end
20 | end
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/hackage.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Hackage < Service
9 | description 'automatic deployment of hackage packages'
10 |
11 | def run
12 | deploy 'hackage' do |config|
13 | config['username'] ||= ask('Hackage Username: ').to_s
14 | config['password'] ||= ask('Hackage Password: ') { |q| q.echo = '*' }.to_s
15 | end
16 | end
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/heroku.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Heroku < Service
9 | description 'automatic deployment to Heroku'
10 |
11 | def run
12 | deploy 'heroku' do |config|
13 | config['api_key'] = `heroku auth:token 2>/dev/null`.strip
14 | config['api_key'] = ask('Heroku API token: ') { |q| q.echo = '*' }.to_s if config['api_key'].empty?
15 | config['app'] = `heroku apps:info 2>/dev/null`.scan(/^=== (.+)$/).flatten.first
16 | if config['app'].nil?
17 | config['app'] = ask('Heroku application name: ') do |q|
18 | q.default = repository.name
19 | end.to_s
20 | end
21 | end
22 | end
23 | end
24 | end
25 | end
26 | end
27 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/modulus.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Modulus < Service
9 | description 'deployment to Modulus'
10 |
11 | def run
12 | deploy 'modulus' do |config|
13 | config['api_key'] = ask('Modulus Api Key: ') { |q| q.echo = '*' }.to_s
14 | config['project_name'] = ask('Modulus Project Name: ').to_s
15 | end
16 | end
17 | end
18 | end
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/ninefold.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Ninefold < Service
9 | description 'Automatic deployment to Ninefold'
10 |
11 | def run
12 | deploy 'ninefold', 'release' do |config|
13 | config['app_id'] ||= ask('Ninefold App ID: ').to_s
14 | config['auth_token'] ||= ask('Ninefold Auth Token: ') { |q| q.echo = '*' }.to_s
15 |
16 | encrypt(config, 'auth_token') if agree('Encrypt Auth Token? ') { |q| q.default = 'yes' }
17 | end
18 | end
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/nodejitsu.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 | require 'json'
5 |
6 | module Travis
7 | module CLI
8 | class Setup
9 | class Nodejitsu < Service
10 | description 'automatic deployment to Nodejitsu'
11 |
12 | def run
13 | deploy 'nodejitsu' do |config|
14 | jitsu_file = File.expand_path('.jitsuconf', ENV['HOME'])
15 |
16 | if File.exist? jitsu_file
17 | jitsu_conf = JSON.parse(File.read(jitsu_file))
18 | config['user'] = jitsu_conf['username']
19 | config['api_key'] = jitsu_conf['apiToken']
20 | end
21 |
22 | config['user'] ||= ask('Nodejitsu user: ').to_s
23 | config['api_key'] ||= ask('Nodejitsu API token: ') { |q| q.echo = '*' }.to_s
24 | end
25 | end
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/npm.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class NPM < Service
9 | description 'automatic release to npm'
10 |
11 | def run
12 | deploy 'npm', 'release' do |config|
13 | config['email'] ||= ask('npm email address: ') { |q| q }.to_s
14 | config['api_key'] ||= ask('npm api key: ') { |q| q.echo = '*' }.to_s
15 |
16 | on('release only tagged commits? ', config, 'tags' => true)
17 | end
18 | end
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/open_shift.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class OpenShift < Service
9 | description 'automatic deployment to OpenShfit'
10 |
11 | def run
12 | deploy 'openshift' do |config|
13 | config['user'] = ask('OpenShift user: ').to_s
14 | config['password'] = ask('OpenShift password: ') { |q| q.echo = '*' }.to_s
15 | config['app'] = ask('OpenShift application name: ') { |q| q.default = repository.name }.to_s
16 | config['domain'] = ask('OpenShift domain: ').to_s
17 | end
18 | end
19 | end
20 | end
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/opsworks.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class OpsWorks < Service
9 | description 'deployment to OpsWorks'
10 |
11 | def run
12 | deploy 'opsworks' do |config|
13 | config['access_key_id'] = ask('Access key ID: ').to_s
14 | config['secret_access_key'] = ask('Secret access key: ') { |q| q.echo = '*' }.to_s
15 | config['app-id'] = ask('App ID: ').to_s
16 | config['migrate'] = true if agree('Migrate the Database? ') { |q| q.default = 'no' }
17 |
18 | encrypt(config, 'secret_access_key') if agree('Encrypt secret access key? ') { |q| q.default = 'yes' }
19 | end
20 | end
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/pypi.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class PyPI < Service
9 | description 'automatic deployment to PyPI'
10 |
11 | def run
12 | deploy 'pypi', 'release' do |config|
13 | config['user'] ||= ask('Username: ').to_s
14 | config['password'] ||= ask('Password: ') { |q| q.echo = '*' }.to_s
15 |
16 | on('release only tagged commits? ', config, 'tags' => true)
17 | # the default of pypi `setup.py build` is the `sdist`
18 | on('deploy as wheel file too? ', config, 'distributions' => 'sdist bdist_wheel')
19 | end
20 | end
21 | end
22 | end
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/releases.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 | require 'travis/tools/github'
5 |
6 | module Travis
7 | module CLI
8 | class Setup
9 | class Releases < Service
10 | description 'Upload Assets to GitHub Releases'
11 |
12 | def run
13 | deploy 'releases' do |config|
14 | github.with_token { |t| config['api_key'] = t }
15 | raise Travis::Client::GitHubLoginFailed, 'all GitHub tokens given were invalid' if config['api_key'].nil?
16 |
17 | config['file'] = ask('File to Upload: ').to_s
18 | end
19 | end
20 |
21 | def github
22 | @github ||= begin
23 | load_gh
24 | Tools::Github.new(session.config['github']) do |g|
25 | g.drop_token = false
26 | g.github_token = github_token
27 | g.debug = proc { |log| debug(log) }
28 | g.after_tokens = proc { g.explode = true and error('no suitable github token found') }
29 | g.scopes = ['repo']
30 | g.note = "automatic releases for #{repository.slug}"
31 | end
32 | end
33 | end
34 | end
35 | end
36 | end
37 | end
38 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/ruby_gems.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class RubyGems < Service
9 | description 'automatic release to RubyGems'
10 |
11 | def run
12 | deploy 'rubygems', 'release' do |config|
13 | authorization_file = File.expand_path('.rubygems/authorization', ENV['HOME'])
14 | credentials_file = File.expand_path('.gem/credentials', ENV['HOME'])
15 |
16 | config['api_key'] ||= File.read(authorization_file) if File.exist? authorization_file
17 | config['api_key'] ||= YAML.load_file(credentials_file)[:rubygems_api_key] if File.exist? credentials_file
18 | config['api_key'] ||= ask('RubyGems API token: ') { |q| q.echo = '*' }.to_s
19 | config['gem'] ||= ask('Gem name: ') { |q| q.default = repository.name }.to_s
20 |
21 | on('Release only tagged commits? ', config, 'tags' => true)
22 | end
23 | end
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/s3.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class S3 < Service
9 | description 'automatic pushing to S3'
10 |
11 | def run
12 | deploy 's3', 'push' do |config|
13 | config['access_key_id'] = ask('Access key ID: ').to_s
14 | config['secret_access_key'] = ask('Secret access key: ') { |q| q.echo = '*' }.to_s
15 | config['bucket'] = ask('Bucket: ').to_s
16 | local_dir = ask('Local project directory to upload (Optional): ').to_s
17 | config['local-dir'] = local_dir unless local_dir.empty?
18 | upload_dir = ask('S3 upload directory (Optional): ').to_s
19 | config['upload-dir'] = upload_dir unless upload_dir.empty?
20 | config['acl'] = ask('S3 ACL Settings (private, public_read, public_read_write, authenticated_read, bucket_owner_read, bucket_owner_full_control): ').to_s do |q|
21 | q.default = 'private'
22 | end
23 | encrypt(config, 'secret_access_key') if agree('Encrypt secret access key? ') { |q| q.default = 'yes' }
24 | end
25 | end
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/sauce_connect.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class SauceConnect < Service
9 | description 'Sauce Connet addon for Sauce Labs integration'
10 | service_name 'sauce_connect'
11 |
12 | def run
13 | travis_config['addons'] ||= {}
14 | configure 'sauce_connect', {}, travis_config['addons'] do |config|
15 | config['username'] = ask('Sauce Labs user: ').to_s
16 | config['access_key'] = ask('Sauce Labs access key: ') { |q| q.echo = '*' }.to_s
17 | encrypt(config, 'access_key') if agree('Encrypt access key? ') { |q| q.default = 'yes' }
18 | end
19 | end
20 | end
21 | end
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/lib/travis/cli/setup/service.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli/setup'
4 |
5 | module Travis
6 | module CLI
7 | class Setup
8 | class Service
9 | def self.normalized_name(string)
10 | string.to_s.downcase.gsub(/[^a-z\d]/, '')
11 | end
12 |
13 | def self.description(description = nil)
14 | @description ||= ''
15 | @description = description if description
16 | @description
17 | end
18 |
19 | def self.service_name(service_name = nil)
20 | @service_name ||= normalized_name(name[/[^:]+$/])
21 | @service_name = service_name if service_name
22 | @service_name
23 | end
24 |
25 | def self.known_as?(name)
26 | normalized_name(service_name) == normalized_name(name)
27 | end
28 |
29 | attr_accessor :command
30 |
31 | def initialize(command)
32 | @command = command
33 | end
34 |
35 | def method_missing(*args, &block)
36 | @command.send(*args, &block)
37 | end
38 |
39 | private
40 |
41 | def on(question, config, condition)
42 | return unless agree(question) { |q| q.default = 'yes' }
43 |
44 | config['on'] ||= {}
45 | config['on'].merge! condition
46 | end
47 |
48 | def encrypt(config, key)
49 | encrypted = repository.encrypt(config.fetch(key))
50 | config[key] = { 'secure' => encrypted }
51 | end
52 |
53 | def configure(key, value = {}, config = travis_config)
54 | if config.include?(key) && !force?
55 | error "#{key} section already exists in .travis.yml, run with --force to override"
56 | end
57 | yield(config[key] = value)
58 | end
59 |
60 | def branch
61 | @branch ||= `git rev-parse --symbolic-full-name --abbrev-ref HEAD`.chomp
62 | end
63 |
64 | def deploy(provider, verb = 'deploy')
65 | configure('deploy', 'provider' => provider) do |config|
66 | yield config
67 |
68 | on("#{verb.capitalize} only from #{repository.slug}? ", config, 'repo' => repository.slug)
69 | if (branch != 'master') && (branch != 'HEAD')
70 | on("#{verb.capitalize} from #{branch} branch? ", config,
71 | 'branch' => branch)
72 | end
73 |
74 | config['skip_cleanup'] = 'true' unless config.key?('skip_cleanup') || (config.fetch('edge',
75 | 'false') != 'false')
76 |
77 | encrypt(config, 'password') if config['password'] && agree('Encrypt Password? ') do |q|
78 | q.default = 'yes'
79 | end
80 | encrypt(config, 'api_key') if config['api_key'] && agree('Encrypt API key? ') { |q| q.default = 'yes' }
81 | end
82 | end
83 | end
84 | end
85 | end
86 | end
87 |
--------------------------------------------------------------------------------
/lib/travis/cli/show.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Show < RepoCommand
8 | description 'displays a build or job'
9 |
10 | def run(number = last_build.number)
11 | number = repository.branch(number).number if number !~ /^\d+(\.\d+)?$/ && repository.branch(number)
12 | entity = job(number) || build(number)
13 |
14 | error "could not find job or build #{repository.slug}##{number}" unless entity
15 |
16 | say template(__FILE__) % [
17 | entity.class.one.capitalize,
18 | entity.number,
19 | entity.commit.subject,
20 | entity.state,
21 | entity.color,
22 | entity.pull_request? ? 'pull request' : 'push',
23 | entity.branch_info,
24 | entity.commit.short_sha,
25 | entity.commit.compare_url,
26 | formatter.duration(entity.duration),
27 | formatter.time(entity.started_at),
28 | formatter.time(entity.finished_at)
29 | ]
30 |
31 | if entity.respond_to? :jobs
32 | empty_line
33 | entity.jobs.each do |job|
34 | say [
35 | color("##{job.number} #{job.state}:".ljust(16), [job.color, :bold]),
36 | formatter.duration(job.duration).ljust(14),
37 | formatter.job_config(job.config),
38 | (color('(failure allowed)', :info) if job.allow_failures?)
39 | ].compact.join(' ').rstrip
40 | end
41 | else
42 | config = formatter.job_config(entity.config)
43 | say color('Allow Failure: ', :info) + entity.allow_failures?.inspect
44 | say color('Config: ', :info) + config unless config.empty?
45 | end
46 | end
47 | end
48 | end
49 | end
50 |
51 | __END__
52 |
53 | <[[ color("%s #%s: ", :bold) ]]> <[[ color(%p, :bold) ]]>
54 | <[[ color("State: ", :info) ]]><[[ color(%p, :%s) ]]>
55 | <[[ color("Type: ", :info) ]]>%s
56 | <[[ color("Branch: ", :info) ]]>%s
57 | <[[ color("Commit: ", :info) ]]>%s
58 | <[[ color("Compare URL: ", :info) ]]>%s
59 | <[[ color("Duration: ", :info) ]]>%s
60 | <[[ color("Started: ", :info) ]]>%s
61 | <[[ color("Finished: ", :info) ]]>%s
--------------------------------------------------------------------------------
/lib/travis/cli/sshkey.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'travis/tools/ssl_key'
5 | require 'travis/tools/github'
6 |
7 | module Travis
8 | module CLI
9 | class Sshkey < RepoCommand
10 | description 'checks, updates or deletes an SSH key'
11 | on '-D', '--delete', 'remove SSH key'
12 | on '-d', '--description DESCRIPTION', 'set description'
13 | on '-u', '--upload FILE', 'upload key from given file'
14 | on '-s', '--stdin', 'upload key read from stdin'
15 | on '-c', '--check', 'set exit code depending on key existing'
16 | on '-g', '--generate', 'generate SSH key and set up for given GitHub user'
17 | on '-p', '--passphrase PASSPHRASE', 'pass phrase to decrypt with when using --upload'
18 | on '-g', '--github-token TOKEN', 'identify by GitHub token'
19 |
20 | def_delegators :repository, :ssh_key
21 |
22 | def run
23 | delete_key if delete?
24 | update_key File.read(upload), upload if upload?
25 | update_key $stdin.read, 'stdin' if stdin?
26 | generate_key if generate?
27 | display_key
28 | end
29 |
30 | def display_key
31 | say "Current SSH key: #{color(ssh_key.description, :info)}"
32 | say "Finger print: #{color(ssh_key.fingerprint, :info)}"
33 | rescue Travis::Client::NotFound
34 | say 'No custom SSH key installed.'
35 | exit 1 if check?
36 | end
37 |
38 | def update_key(value, file)
39 | error "#{file} does not look like a private key" unless value.lines.first =~ /PRIVATE KEY/
40 | value = remove_passphrase(value)
41 | self.description ||= ask('Key description: ') { |q| q.default = 'Custom Key' } if interactive?
42 | say "Updating ssh key for #{color slug, :info} with key from #{color file, :info}"
43 | empty_line
44 | ssh_key.update(value:, description: description || file)
45 | end
46 |
47 | def delete_key
48 | return if interactive? && !danger_zone?("Remove SSH key for #{color slug, :info}?")
49 |
50 | say "Removing ssh key for #{color slug, :info}"
51 | ssh_key.delete
52 | rescue Travis::Client::NotFound
53 | warn 'no key found to remove'
54 | end
55 |
56 | def generate_key
57 | access_token = nil
58 | github.with_token do |token|
59 | access_token = github_auth(token)
60 | end
61 | raise Travis::Client::GitHubLoginFailed, 'all GitHub tokens given were invalid' unless access_token
62 |
63 | gh = GH.with(token: github_token)
64 | login = gh['user']['login']
65 | check_access(gh)
66 | empty_line
67 |
68 | say 'Generating RSA key.'
69 | private_key = Tools::SSLKey.generate_rsa
70 | self.description ||= "key for fetching dependencies for #{slug} via #{login}"
71 |
72 | say 'Uploading public key to GitHub.'
73 | gh.post('/user/keys', title: "#{description} (Travis CI)",
74 | key: Tools::SSLKey.rsa_ssh(private_key.public_key))
75 |
76 | say 'Uploading private key to Travis CI.'
77 | ssh_key.update(value: private_key.to_s, description:)
78 |
79 | empty_line
80 | say 'You can store the private key to reuse it for other repositories (travis sshkey --upload FILE).'
81 | return unless agree('Store private key? ') { |q| q.default = 'no' }
82 |
83 | path = ask('Path: ') { |q| q.default = 'id_travis_rsa' }
84 | File.write(path, private_key.to_s)
85 | end
86 |
87 | def remove_passphrase(value)
88 | return value unless Tools::SSLKey.has_passphrase? value
89 | return Tools::SSLKey.remove_passphrase(value, passphrase) || error('wrong pass phrase') if passphrase
90 |
91 | error 'Key is encrypted, but missing --passphrase option' unless interactive?
92 | say 'The private key is protected by a pass phrase.'
93 | result = Tools::SSLKey.remove_passphrase(value, ask('Enter pass phrase: ') { |q| q.echo = '*' }) until result
94 | empty_line
95 | result
96 | end
97 |
98 | def check_access(gh)
99 | gh["repos/#{slug}"]
100 | rescue GH::Error
101 | error "GitHub account has no read access to #{color slug, :bold}"
102 | end
103 |
104 | def github
105 | @github ||= begin
106 | load_gh
107 | Tools::Github.new(session.config['github']) do |g|
108 | g.note = "token for fetching dependencies for #{slug} (Travis CI)"
109 | g.explode = explode?
110 | g.github_token = github_token
111 | g.login_header = proc { login_header }
112 | g.debug = proc { |log| debug(log) }
113 | g.after_tokens = proc { g.explode = true and error('no suitable github token found') }
114 | end
115 | end
116 | end
117 |
118 | def login_header
119 | say 'GitHub deprecated its Authorizations API exchanging a password for a token.'
120 | say 'Please visit https://github.blog/2020-07-30-token-authentication-requirements-for-api-and-git-operations for more information.'
121 | say "Try running with #{color('--github-token', :info)} or #{color('--auto-token', :info)} ."
122 | end
123 | end
124 | end
125 | end
126 |
--------------------------------------------------------------------------------
/lib/travis/cli/status.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Status < RepoCommand
8 | description 'checks status of the latest build'
9 |
10 | on '-x', '--[no-]exit-code', 'sets the exit code to 1 if the build failed'
11 | on '-q', '--[no-]quiet', 'does not print anything'
12 | on '-p', '--[no-]fail-pending', 'sets the status code to 1 if the build is pending'
13 |
14 | def run
15 | say color(last_build.state, last_build.color), "build ##{last_build.number} %s" unless quiet?
16 | exit 1 if exit_code? && last_build.unsuccessful?
17 | exit 1 if fail_pending? && last_build.pending?
18 | end
19 | end
20 | end
21 | end
22 |
--------------------------------------------------------------------------------
/lib/travis/cli/sync.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Sync < ApiCommand
8 | description 'triggers a new sync with GitHub'
9 |
10 | on '-c', '--check', 'only check the sync status'
11 | on '-b', '--background', 'will trigger sync but not block until sync is done'
12 | on '-f', '--force', 'will force sync, even if one is already running'
13 |
14 | def run
15 | authenticate
16 |
17 | if check?
18 | say "#{'not ' unless user.syncing?}syncing", "#{user.login} is currently %s"
19 | elsif user.syncing? && !force?
20 | error 'user is already syncing'
21 | elsif background?
22 | say 'starting synchronization'
23 | sync(false)
24 | else
25 | say 'synchronizing: '
26 | sync
27 | say color(' done', :success)
28 | end
29 | end
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/lib/travis/cli/token.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Token < ApiCommand
8 | description 'outputs the secret API token'
9 |
10 | def run
11 | authenticate
12 | say access_token, 'Your access token is %s'
13 | end
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/travis/cli/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 | require 'travis/version'
5 |
6 | module Travis
7 | module CLI
8 | class Version < Command
9 | description 'outputs the client version'
10 |
11 | def run
12 | say Travis::VERSION
13 | end
14 |
15 | def check_version; end
16 | end
17 | end
18 | end
19 |
--------------------------------------------------------------------------------
/lib/travis/cli/whatsup.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/cli'
4 |
5 | module Travis
6 | module CLI
7 | class Whatsup < ApiCommand
8 | description 'lists most recent builds'
9 | on('-m', '--my-repos', 'Only display my own repositories')
10 |
11 | def run
12 | say 'nothing to show' if recent.empty?
13 |
14 | recent.each do |repo|
15 | say [
16 | color(repo.slug, [:bold, repo.color]),
17 | color("#{repo.last_build.state}: ##{repo.last_build.number}", repo.color)
18 | ].join(' ')
19 | end
20 | end
21 |
22 | private
23 |
24 | def recent
25 | @recent ||= begin
26 | recent = my_repos ? repos : repos(member: user.login)
27 | recent.select { |repo| repo.last_build }
28 | end
29 | end
30 | end
31 | end
32 | end
33 |
--------------------------------------------------------------------------------
/lib/travis/cli/whoami.rb:
--------------------------------------------------------------------------------
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
16 |
--------------------------------------------------------------------------------
/lib/travis/client.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client/error'
4 | require 'travis/client/states'
5 | require 'travis/client/restartable'
6 | require 'travis/client/not_loadable'
7 | require 'travis/client/has_uuid'
8 | require 'travis/client/methods'
9 | require 'travis/client/session'
10 | require 'travis/client/entity'
11 | require 'travis/client/user'
12 | require 'travis/client/repository'
13 | require 'travis/client/env_var'
14 | require 'travis/client/build'
15 | require 'travis/client/artifact'
16 | require 'travis/client/cache'
17 | require 'travis/client/commit'
18 | require 'travis/client/job'
19 | require 'travis/client/namespace'
20 | require 'travis/client/account'
21 | require 'travis/client/broadcast'
22 | require 'travis/client/settings'
23 | require 'travis/client/singleton_setting'
24 | require 'travis/client/ssh_key'
25 | require 'travis/client/request'
26 | require 'travis/client/listener'
27 | require 'travis/client/lint_result'
28 |
29 | module Travis
30 | module Client
31 |
32 | COM_URI = 'https://api.travis-ci.com/'
33 |
34 | def self.new(options = {})
35 | options[:uri] ||= COM_URI if options.is_a?(Hash) && !(options['uri'])
36 | Session.new(options)
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/lib/travis/client/account.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | class Account < Entity
8 | attributes :name, :login, :type, :repos_count, :subscribed, :education
9 |
10 | one :account
11 | many :accounts
12 |
13 | inspect_info :login
14 | id_field :login
15 |
16 | def self.cast_id(id)
17 | String(id)
18 | end
19 |
20 | def self.id?(object)
21 | object.is_a? String
22 | end
23 |
24 | def subscribed
25 | load_attribute('subscribed') { true } if member?
26 | end
27 |
28 | def education
29 | load_attribute('education') { false } if member?
30 | end
31 |
32 | def on_trial?
33 | !subscribed? and !education?
34 | end
35 |
36 | def repos_count
37 | load_attribute('repos_count') { repositories.count }
38 | end
39 |
40 | def repositories
41 | attributes['repositories'] ||= session.repos(owner_name: login)
42 | end
43 |
44 | def member?
45 | session.accounts.include? self
46 | end
47 |
48 | alias educational? education?
49 |
50 | private
51 |
52 | def load_attribute(name, &block)
53 | session.accounts if missing? name
54 | block ? attributes.fetch(name.to_s, &block) : attributes[name.to_s]
55 | end
56 | end
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/lib/travis/client/artifact.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 | require 'travis/tools/safe_string'
5 |
6 | module Travis
7 | module Client
8 | class Artifact < Entity
9 | CHUNKED = 'application/json; chunked=true; version=2, application/json; version=2'
10 | TEXT = "#{CHUNKED}, text/plain".freeze
11 |
12 | # @!parse attr_reader :job_id, :type, :body
13 | attributes :job_id, :type, :body
14 |
15 | # @!parse attr_reader :job
16 | has :job
17 |
18 | def delete_body(reason = {})
19 | reason = { reason: } unless reason.is_a? Hash
20 | session.patch_raw("jobs/#{job_id}/log", reason)
21 | reload
22 | rescue Travis::Client::Error => e
23 | raise unless e.message == '409'
24 |
25 | self
26 | end
27 |
28 | def encoded_body
29 | Tools::SafeString.encoded(body)
30 | end
31 |
32 | def colorized_body
33 | attributes['colorized_body'] ||= Tools::SafeString.colorized(body)
34 | end
35 |
36 | def clean_body
37 | attributes['clean_body'] ||= Tools::SafeString.clean(body)
38 | end
39 |
40 | def current_body
41 | attributes['current_body'] ||= begin
42 | body = load_attribute('body')
43 | if body.to_s.empty?
44 | log = session.get_raw("jobs/#{job_id}/log", nil, 'Accept' => TEXT)
45 | body = log.is_a?(String) ? log : log['log']['body']
46 | end
47 | body
48 | end
49 | end
50 |
51 | def body(stream = block_given?)
52 | return current_body unless block_given? || stream
53 | return yield(current_body) unless stream && job.pending?
54 |
55 | number = 0
56 |
57 | session.listen(self) do |listener|
58 | listener.on 'job:log' do |event|
59 | next unless event.payload['number'] > number
60 |
61 | number = event.payload['number']
62 | yield event.payload['_log']
63 | listener.disconnect if event.payload['final']
64 | end
65 |
66 | listener.on 'job:finished' do |_event|
67 | listener.disconnect
68 | end
69 |
70 | listener.on_connect do
71 | data = session.get_raw("/logs/#{id}", nil, 'Accept' => CHUNKED)['log']
72 | if data['parts']
73 | data['parts'].each { |p| yield p['content'] }
74 | number = data['parts'].last['number'] if data['parts'].any?
75 | else
76 | yield data['body']
77 | listener.disconnect
78 | end
79 | end
80 | end
81 | end
82 |
83 | def pusher_entity
84 | job
85 | end
86 |
87 | one :log
88 | many :logs
89 | aka :artifact
90 | end
91 | end
92 | end
93 |
--------------------------------------------------------------------------------
/lib/travis/client/auto_login.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 | require 'travis/tools/github'
5 | require 'yaml'
6 |
7 | module Travis
8 | module Client
9 | class AutoLogin
10 | NoTokenError = Class.new(RuntimeError)
11 | attr_reader :session
12 |
13 | def initialize(session, options = {})
14 | @session = session.session
15 | config_path = ENV.fetch('TRAVIS_CONFIG_PATH') { File.expand_path('.travis', Dir.home) }
16 | @config_file = options.fetch(:config_file) { File.expand_path('config.yml', config_path) }
17 | @auto_token = options.fetch(:auto_token, true)
18 | @raise = options.fetch(:raise, true)
19 | end
20 |
21 | def authenticate
22 | return if (session.access_token = cli_token)
23 |
24 | github.with_token { |t| session.github_auth(t) }
25 | end
26 |
27 | def github
28 | @github ||= Tools::Github.new(session.config['github']) do |g|
29 | g.explode = true
30 | g.auto_token = @auto_token
31 | g.after_tokens = proc { raise NoTokenError, 'no suitable github token found' } if @raise
32 | end
33 | end
34 |
35 | def cli_token
36 | result = cli_config
37 | result &&= result['endpoints']
38 | result &&= result[session.uri]
39 | result && result['access_token']
40 | end
41 |
42 | def cli_config
43 | @cli_config ||= YAML.load_file(@config_file) if File.exist? @config_file
44 | end
45 | end
46 | end
47 | end
48 |
--------------------------------------------------------------------------------
/lib/travis/client/broadcast.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | class Broadcast < Entity
8 | attributes :recipient_id, :recipient_type, :kind, :message, :expired, :created_at, :updated_at
9 |
10 | one :broadcast
11 | many :broadcasts
12 |
13 | inspect_info :message
14 | end
15 | end
16 | end
17 |
--------------------------------------------------------------------------------
/lib/travis/client/build.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | class Build < Entity
8 | include Restartable
9 | include States
10 | preloadable
11 |
12 | # @!parse attr_reader :repository_id, :commit_id, :number, :pull_request, :pull_request_number, :pull_request_title, :config, :state, :started_at, :finished_at, :duration, :job_ids
13 | attributes :repository_id, :commit_id, :number, :pull_request, :pull_request_number, :pull_request_title,
14 | :config, :state, :started_at, :finished_at, :duration, :job_ids
15 | time :started_at, :finished_at
16 |
17 | alias pull_request? pull_request
18 | alias pr_number pull_request_number
19 |
20 | # @!parse attr_reader :repository, :commit, :jobs
21 | has :repository, :commit, :jobs
22 |
23 | one :build
24 | many :builds
25 | aka :branch, :branches
26 |
27 | def delete_logs(reason = {})
28 | jobs.each do |job|
29 | job.delete_log(reason)
30 | end
31 | end
32 |
33 | def push?
34 | !pull_request?
35 | end
36 |
37 | def branch_info
38 | info = commit.branch
39 | pull_request? ? info + " (PR ##{pr_number})" : info
40 | end
41 |
42 | def pusher_channels
43 | repository.pusher_channels
44 | end
45 |
46 | def inspect_info
47 | "#{repository.slug}##{number}"
48 | end
49 | end
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/lib/travis/client/cache.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client/weak_entity'
4 |
5 | module Travis
6 | module Client
7 | class Cache < WeakEntity
8 | # @!parse attr_reader :repository_id, :size, :slug, :branch, :last_modified
9 | attributes :repository_id, :size, :slug, :branch, :last_modified
10 | time :last_modified
11 |
12 | # @!parse attr_reader :repository
13 | has :repository
14 |
15 | one :cache
16 | many :caches
17 |
18 | def delete
19 | repository.delete_caches(branch:, match: slug)
20 | end
21 |
22 | def inspect_info
23 | [repository.slug, branch, slug].compact.join(' ')
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/lib/travis/client/commit.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | class Commit < Entity
8 | include NotLoadable
9 |
10 | # @!parse attr_reader :sha, :branch, :message, :committed_at, :author_name, :author_email, :committer_name, :committer_email, :compare_url
11 | attributes :sha, :branch, :message, :committed_at, :author_name, :author_email, :committer_name,
12 | :committer_email, :compare_url
13 | time :committed_at
14 |
15 | one :commit
16 | many :commits
17 |
18 | def subject
19 | message.to_s.lines.first.to_s.strip
20 | end
21 |
22 | def short_sha
23 | sha.to_s[0..6]
24 | end
25 |
26 | def inspect_info
27 | "#{short_sha} #{subject.inspect}"
28 | end
29 | end
30 | end
31 | end
32 |
--------------------------------------------------------------------------------
/lib/travis/client/env_var.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 | require 'delegate'
5 |
6 | module Travis
7 | module Client
8 | class EnvVar < Entity
9 | class List < DelegateClass(Array)
10 | attr_reader :repository
11 |
12 | def initialize(repository, &block)
13 | @repository = repository
14 | @generator = block || ::Proc.new { session.get(EnvVar.path(repository))['env_vars'] }
15 | super(nil)
16 | end
17 |
18 | def list=(list)
19 | __setobj__ list.dup.freeze
20 | end
21 |
22 | def __getobj__
23 | super || (self.list = @generator.call)
24 | end
25 |
26 | def reload
27 | __setobj__ nil
28 | self
29 | end
30 |
31 | def session
32 | repository.session
33 | end
34 |
35 | def repository_id
36 | repository.id
37 | end
38 |
39 | def add(name, value, options = {})
40 | body = JSON.dump(env_var: options.merge(name:, value:))
41 | result = session.post(EnvVar.path(self), body)
42 | self.list += [result['env_var']]
43 | end
44 |
45 | def upsert(name, value, options = {})
46 | entries = select { |e| e.name == name }
47 | if entries.any?
48 | entries.first.update(options.merge(value:))
49 | entries[1..].each { |e| e.delete }
50 | else
51 | add(name, value, options)
52 | end
53 | reload
54 | end
55 |
56 | def [](key)
57 | return super if key.is_a? Integer
58 |
59 | detect { |e| e.name == key.to_s }
60 | end
61 |
62 | def []=(key, value)
63 | return super if key.is_a? Integer
64 |
65 | upsert(key.to_s, value)
66 | end
67 |
68 | alias list __getobj__
69 | end
70 |
71 | def self.path(object)
72 | repository_id = object.is_a?(Repository) ? object.id : object.repository_id
73 | raise 'repository unknown' unless repository_id
74 |
75 | "/settings/env_vars/#{object.id if object.is_a? EnvVar}?repository_id=#{repository_id}"
76 | end
77 |
78 | include NotLoadable
79 | extend HasUuid
80 | one :env_var
81 | many :env_vars
82 |
83 | # @!parse attr_reader :name, :public, :repository_id
84 | attributes :name, :value, :public, :repository_id
85 |
86 | # @!parse attr_reader :repository
87 | has :repository
88 |
89 | def update(options)
90 | options = { value: options } unless options.is_a? Hash
91 | result = session.patch(EnvVar.path(self), JSON.dump(env_var: options))
92 | attributes.replace(result['env_var'].attributes)
93 | self
94 | end
95 |
96 | def delete
97 | session.delete_raw EnvVar.path(self)
98 | repository.env_vars.reload
99 | true
100 | end
101 |
102 | def inspect_info
103 | "#{name}=#{value ? value.inspect : '[secure]'}"
104 | end
105 | end
106 | end
107 | end
108 |
--------------------------------------------------------------------------------
/lib/travis/client/error.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | class Error < StandardError
8 | end
9 |
10 | class SSLError < Error
11 | end
12 |
13 | class NotFound < Error
14 | end
15 |
16 | class NotLoggedIn < Error
17 | end
18 |
19 | class InvalidTokenError < Error
20 | end
21 |
22 | class GitHubLoginFailed < Error
23 | end
24 |
25 | class RepositoryMigrated < Error
26 | end
27 |
28 | class AssetNotFound < Error
29 | def initialize(file, *args)
30 | if (md = file.match(%r{init/(?<lang>[^.]+)\.yml$}))
31 | super "unknown language #{md[:lang]}", *args
32 | else
33 | super file, *args
34 | end
35 | end
36 | end
37 |
38 | class ValidationFailed < Error
39 | attr_reader :errors
40 |
41 | def initialize(message = nil, *args)
42 | message = parse_message(message) if message
43 | super(message, *args)
44 | end
45 |
46 | def parse_message(message)
47 | response = JSON.parse(message)
48 | message = response['message'].to_s
49 | if (@errors = response['errors']) && @errors.any?
50 | readable = @errors.map { |e| "#{e['field']}: #{e['code'].gsub('_', ' ')}" }
51 | message += " (#{readable.join(', ')})"
52 | end
53 | message
54 | rescue JSON::ParserError
55 | message
56 | end
57 | end
58 | end
59 | end
60 |
--------------------------------------------------------------------------------
/lib/travis/client/has_uuid.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Travis
4 | module Client
5 | module HasUuid
6 | def id?(object)
7 | object =~ /\A(?:\w+-){4}\w+\Z/ if object.is_a? String
8 | end
9 |
10 | def cast_id(object)
11 | object.to_str
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/travis/client/job.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | class Job < Entity
8 | include Restartable
9 | include States
10 | preloadable
11 |
12 | # @!parse attr_reader :repository_id, :build_id, :commit_id, :log_id, :number, :config, :state, :started_at, :finished_at, :queue, :allow_failure, :tags
13 | attributes :repository_id, :build_id, :commit_id, :log_id, :number, :config, :state, :started_at, :finished_at,
14 | :queue, :allow_failure, :tags
15 | time :started_at, :finished_at
16 |
17 | alias allow_failure? allow_failure
18 |
19 | # @!parse attr_reader :commit, :repository, :build
20 | has :commit, :repository, :build, :log
21 |
22 | one :job
23 | many :jobs
24 |
25 | def pull_request?
26 | build.pull_request?
27 | end
28 |
29 | def push?
30 | build.push?
31 | end
32 |
33 | def branch_info
34 | build.branch_info
35 | end
36 |
37 | def allow_failures?
38 | return false unless config.include?('matrix') && config['matrix'].include?('allow_failures')
39 |
40 | config['matrix']['allow_failures'].any? do |allow|
41 | allow.all? { |key, value| config[key] == value }
42 | end
43 | end
44 |
45 | def duration
46 | attributes['duration'] ||= begin
47 | start = started_at || Time.now
48 | finish = finished_at || Time.now
49 | (finish - start).to_i
50 | end
51 | end
52 |
53 | def delete_log(reason = {})
54 | log.delete_body(reason)
55 | end
56 |
57 | def pusher_channels
58 | build.pusher_channels + ["job-#{id}"]
59 | end
60 |
61 | def inspect_info
62 | "#{repository.slug}##{number}"
63 | end
64 | end
65 | end
66 | end
67 |
--------------------------------------------------------------------------------
/lib/travis/client/lint_result.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Travis
4 | module Client
5 | class LintResult
6 | Warning = Struct.new(:key, :message)
7 | attr_accessor :warnings
8 |
9 | def initialize(payload)
10 | @warnings = []
11 | payload = payload['lint'] if payload['lint']
12 |
13 | Array(payload['warnings']).each do |warning|
14 | @warnings << Warning.new(warning['key'], warning['message'])
15 | end
16 | end
17 |
18 | def warnings?
19 | warnings.any?
20 | end
21 |
22 | def ok?
23 | !warnings?
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/lib/travis/client/methods.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 | require 'yaml'
5 |
6 | module Travis
7 | module Client
8 | module Methods
9 | def access_token
10 | session.access_token
11 | end
12 |
13 | def access_token=(token)
14 | session.access_token = token
15 | end
16 |
17 | def api_endpoint
18 | session.uri
19 | end
20 |
21 | def github_auth(github_token)
22 | reply = session.post_raw('/auth/github', github_token:)
23 | unless reply.respond_to?(:key?) && reply.key?('access_token')
24 | raise InvalidTokenError,
25 | 'token is invalid, or does not have sufficient scope; see https://docs.travis-ci.com/user/github-oauth-scopes/ for more information on scope'
26 | end
27 |
28 | session.access_token = reply['access_token']
29 | end
30 |
31 | def explicit_api_endpoint?
32 | @explicit_api_endpoint ||= false
33 | end
34 |
35 | def api_endpoint=(uri)
36 | @explicit_api_endpoint = true
37 | session.uri = uri
38 | end
39 |
40 | def repos(params = {})
41 | session.find_many(Repository, params)
42 | end
43 |
44 | def repo(id_or_slug)
45 | session.find_one(Repository, id_or_slug)
46 | end
47 |
48 | def build(id)
49 | session.find_one(Build, id)
50 | end
51 |
52 | def job(id)
53 | session.find_one(Job, id)
54 | end
55 |
56 | def artifact(id)
57 | session.find_one(Artifact, id)
58 | end
59 |
60 | alias log artifact
61 |
62 | def user
63 | session.find_one(User)
64 | rescue NotFound
65 | raise NotLoggedIn, 'currently not logged in'
66 | end
67 |
68 | def account(name)
69 | session.find_one(Account, name)
70 | end
71 |
72 | def accounts
73 | session.find_many(Account, all: true)
74 | end
75 |
76 | def broadcasts
77 | session.find_many(Broadcast)
78 | end
79 |
80 | def restart(entity)
81 | # btw, internally we call this reset, not restart, as it resets the state machine
82 | # but we thought that would be too confusing
83 | raise Error, "cannot restart a #{entity.class.one}" unless entity.restartable?
84 |
85 | session.post_raw("/#{entity.class.many}/#{entity.id}/restart")
86 | entity.reload
87 | end
88 |
89 | def cancel(entity)
90 | raise Error, "cannot cancel a #{entity.class.one}" unless entity.cancelable?
91 |
92 | session.post_raw("/#{entity.class.many}/#{entity.id}/cancel")
93 | entity.reload
94 | end
95 |
96 | def logout
97 | session.get_raw('/logout')
98 | end
99 |
100 | def regenerate_token
101 | session.headers['Travis-Api-Version'] = '3'
102 | token = session.patch_raw('/access_token')
103 | session.headers.delete('Travis-Api-Version')
104 |
105 | token
106 | end
107 |
108 | def remove_token
109 | session.headers['Travis-Api-Version'] = '3'
110 | resp = session.delete_raw('/access_token')
111 | session.headers.delete('Travis-Api-Version')
112 |
113 | resp
114 | end
115 |
116 | def listen(*entities, &block)
117 | listener = Listener.new(session)
118 | listener.subscribe(*entities, &block)
119 | listener.listen
120 | end
121 |
122 | def lint(body)
123 | body = body.to_yaml unless body.is_a? String
124 | result = session.post_raw('/lint', 'content' => body)
125 | LintResult.new(result)
126 | end
127 |
128 | def hooks
129 | session.get('hooks')['hooks']
130 | end
131 | end
132 | end
133 | end
134 |
--------------------------------------------------------------------------------
/lib/travis/client/namespace.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | class Namespace < Module
8 | class Curry < Module
9 | attr_accessor :namespace, :type
10 |
11 | def initialize(namespace, type)
12 | @namespace = namespace
13 | @type = type
14 | end
15 |
16 | def find_one(id = nil)
17 | result = session.find_one(type, id)
18 | result.curry = self
19 | result
20 | end
21 |
22 | def current
23 | result = session.find_one_or_many(type)
24 | Array(result).each { |e| e.curry = self }
25 | result
26 | end
27 |
28 | def find_many(params = {})
29 | session.find_many(type, params).each do |entity|
30 | entity.curry = self
31 | end
32 | end
33 |
34 | alias find find_one
35 | alias find_all find_many
36 |
37 | def clear_cache
38 | session.clear_cache
39 | end
40 |
41 | def clear_cache!
42 | session.clear_cache!
43 | end
44 |
45 | private
46 |
47 | def session
48 | namespace.session
49 | end
50 | end
51 |
52 | include Methods
53 | attr_accessor :session
54 |
55 | def initialize(session = nil)
56 | session = Travis::Client.new(session || {}) unless session.is_a? Session
57 | @session = session
58 |
59 | Entity.subclasses.each do |subclass|
60 | name = subclass.name[/[^:]+$/]
61 | const_set(name, Curry.new(self, subclass))
62 | end
63 | end
64 |
65 | def included(klass)
66 | fix_names(klass)
67 | delegate_session(klass)
68 | end
69 |
70 | private
71 |
72 | def fix_names(klass)
73 | constants.each do |name|
74 | const = klass.const_get(name)
75 | klass.const_set(name, const) if const == const_get(name)
76 | end
77 | end
78 |
79 | def delegate_session(klass)
80 | return if [Object, Kernel].include?(klass)
81 |
82 | klass.extend(Methods)
83 | namespace = self
84 | klass.define_singleton_method(:session) { namespace.session }
85 | klass.define_singleton_method(:session=) { |value| namespace.session = value }
86 | end
87 | end
88 | end
89 | end
90 |
--------------------------------------------------------------------------------
/lib/travis/client/not_loadable.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Travis
4 | module Client
5 | module NotLoadable
6 | def missing?(_attribute)
7 | false
8 | end
9 |
10 | def complete?
11 | true
12 | end
13 | end
14 | end
15 | end
16 |
--------------------------------------------------------------------------------
/lib/travis/client/request.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client/weak_entity'
4 |
5 | module Travis
6 | module Client
7 | class Request < WeakEntity
8 | # @!parse attr_reader :commit_id, :repository_id, :created_at, :owner_id, :owner_type, :event_type, :base_commit, :head_commit, :result, :message, :pull_request, :pull_request_number, :pull_request_title, :branch, :tag
9 | attributes :commit_id, :repository_id, :created_at, :owner_id, :owner_type, :event_type, :base_commit,
10 | :head_commit, :result, :message, :pull_request, :pull_request_number, :pull_request_title, :branch, :tag
11 | time :created_at
12 |
13 | # @!parse attr_reader :repository
14 | has :repository, :commit
15 |
16 | one :request
17 | many :requests
18 |
19 | def owner
20 | repository.owner
21 | end
22 |
23 | def accepted?
24 | result == 'accepted'
25 | end
26 |
27 | def rejected?
28 | result == 'rejected'
29 | end
30 |
31 | def inspect_info
32 | [
33 | repository && repository.slug,
34 | event_type, branch || pull_request_number, result
35 | ].compact.join(' ')
36 | end
37 | end
38 | end
39 | end
40 |
--------------------------------------------------------------------------------
/lib/travis/client/restartable.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | module Restartable
8 | def restartable?
9 | true
10 | end
11 |
12 | def restart
13 | session.restart(self)
14 | end
15 |
16 | def cancelable?
17 | true
18 | end
19 |
20 | def cancel
21 | session.cancel(self)
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/lib/travis/client/settings.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client/weak_entity'
4 | require 'json'
5 |
6 | module Travis
7 | module Client
8 | class Settings < WeakEntity
9 | attr_accessor :repository
10 |
11 | # @!parse attr_reader :builds_only_with_travis_yml, :build_pushes, :build_pull_requests, :maximum_number_of_builds, :auto_cancel_pushes, :auto_cancel_pull_requests
12 | attributes :builds_only_with_travis_yml, :build_pushes, :build_pull_requests, :maximum_number_of_builds,
13 | :auto_cancel_pushes, :auto_cancel_pull_requests
14 | one :settings
15 | many :settings
16 |
17 | def save
18 | raise 'repository unknown' unless repository
19 |
20 | result = session.patch("/repos/#{repository.id}/settings", JSON.dump('settings' => attributes))
21 | attributes.replace(result['settings'].attributes)
22 | self
23 | end
24 |
25 | def inspect_info
26 | repository ? repository.slug : repository
27 | end
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/lib/travis/client/singleton_setting.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'json'
4 |
5 | module Travis
6 | module Client
7 | class SingletonSetting < Entity
8 | def self.base_path
9 | "settings/#{one}"
10 | end
11 |
12 | has :repository
13 |
14 | def repository_id
15 | id
16 | end
17 |
18 | def path
19 | "#{self.class.base_path}/#{id}"
20 | end
21 |
22 | def update(values = {})
23 | values = { 'value' => values } unless values.is_a? Hash
24 | values.each { |key, value| attributes[key.to_s] = value.to_s }
25 | session.patch_raw(path, JSON.dump(self.class.one => attributes))
26 | reload
27 | end
28 |
29 | def delete
30 | session.delete_raw(path)
31 | reload
32 | true
33 | end
34 |
35 | alias save update
36 | end
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/lib/travis/client/ssh_key.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'json'
4 |
5 | module Travis
6 | module Client
7 | class SshKey < SingletonSetting
8 | attributes :description, :fingerprint
9 | one :ssh_key
10 | many :ssh_keys
11 | end
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/lib/travis/client/states.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | module States
8 | STATES = %w[created queued received started passed failed errored canceled ready].freeze
9 |
10 | def ready?
11 | state == 'ready'
12 | end
13 |
14 | def pending?
15 | check_state
16 | %w[created started queued received].include? state
17 | end
18 |
19 | def started?
20 | check_state
21 | state != 'created' and state != 'received' and state != 'queued'
22 | end
23 |
24 | def received?
25 | check_state
26 | state != 'created' and state != 'queued'
27 | end
28 |
29 | def queued?
30 | check_state
31 | state != 'created'
32 | end
33 |
34 | def finished?
35 | !pending?
36 | end
37 |
38 | def passed?
39 | check_state
40 | state == 'passed'
41 | end
42 |
43 | def errored?
44 | check_state
45 | state == 'errored'
46 | end
47 |
48 | def failed?
49 | check_state
50 | state == 'failed'
51 | end
52 |
53 | def canceled?
54 | check_state
55 | state == 'canceled'
56 | end
57 |
58 | def unsuccessful?
59 | errored? or failed? or canceled?
60 | end
61 |
62 | def created?
63 | check_state
64 | !!state
65 | end
66 |
67 | def color
68 | case state
69 | when 'created', 'queued', 'received', 'started' then 'yellow'
70 | when 'passed', 'ready' then 'green'
71 | when 'errored', 'canceled', 'failed' then 'red'
72 | end
73 | end
74 |
75 | def yellow?
76 | color == 'yellow'
77 | end
78 |
79 | def green?
80 | color == 'green'
81 | end
82 |
83 | def red?
84 | color == 'red'
85 | end
86 |
87 | def running?
88 | state == 'started'
89 | end
90 |
91 | alias successful? passed?
92 |
93 | private
94 |
95 | def check_state
96 | raise Error, format('unknown state %p for %p', state, self) unless STATES.include? state
97 | end
98 | end
99 | end
100 | end
101 |
--------------------------------------------------------------------------------
/lib/travis/client/user.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | class User < Entity
8 | # @!parse attr_reader :login, :name, :email, :gravatar_id, :locale, :is_syncing, :synced_at, :correct_scopes
9 | attributes :login, :name, :email, :gravatar_id, :locale, :is_syncing, :synced_at, :correct_scopes, :channels
10 | inspect_info :login
11 |
12 | one :user
13 | many :users
14 |
15 | def synced_at=(time)
16 | set_attribute(:synced_at, time(time))
17 | end
18 |
19 | def sync
20 | session.post_raw('/users/sync')
21 | reload
22 | end
23 |
24 | def channels
25 | load_attribute(:is_syncing) # dummy to trigger load, as channels might not be included
26 | attributes['channels'] ||= ['common']
27 | end
28 |
29 | def permissions
30 | attributes['permissions'] ||= begin
31 | repos = session.get('/users/permissions')
32 | repos.each_value { |r| r.compact! }
33 | repos
34 | end
35 | end
36 |
37 | def repositories
38 | permissions['permissions']
39 | end
40 |
41 | def push_access
42 | permissions['push']
43 | end
44 |
45 | def pull_access
46 | permissions['pull']
47 | end
48 |
49 | def admin_access
50 | permissions['admin']
51 | end
52 |
53 | def push_access?(repo)
54 | push_access.include? repo
55 | end
56 |
57 | def pull_access?(repo)
58 | pull_access.include? repo
59 | end
60 |
61 | def admin_access?(repo)
62 | admin_access.include? repo
63 | end
64 |
65 | alias syncing? is_syncing
66 | alias correct_scopes? correct_scopes
67 | end
68 | end
69 | end
70 |
--------------------------------------------------------------------------------
/lib/travis/client/weak_entity.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | module Client
7 | class WeakEntity < Entity
8 | include NotLoadable
9 |
10 | def self.weak?
11 | true
12 | end
13 |
14 | def self.id_field
15 | raise 'weak entities do not have id fields'
16 | end
17 |
18 | def self.id?(object)
19 | object.nil?
20 | end
21 |
22 | def self.cast_id(object)
23 | return object if id? object
24 |
25 | raise 'weak entities do not have id fields'
26 | end
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/lib/travis/pro.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client'
4 |
5 | module Travis
6 | Pro = Client::Namespace.new
7 | end
8 |
--------------------------------------------------------------------------------
/lib/travis/pro/auto_login.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/pro'
4 | require 'travis/client/auto_login'
5 | Travis::Client::AutoLogin.new(Travis::Pro).authenticate
6 |
--------------------------------------------------------------------------------
/lib/travis/tools/assets.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'pathname'
4 | module Travis
5 | module Tools
6 | module Assets
7 | BASE = File.expand_path('../../../assets', __dir__)
8 |
9 | module_function
10 |
11 | def asset_path(file)
12 | Pathname.glob(File.expand_path(file, BASE)).tap do |x|
13 | raise Travis::Client::AssetNotFound, file if x.empty?
14 | end.first.to_s
15 | end
16 |
17 | def asset(file)
18 | File.read(asset_path(file))
19 | end
20 |
21 | class << self
22 | alias [] asset_path
23 | alias read asset
24 | end
25 | end
26 | end
27 | end
28 |
--------------------------------------------------------------------------------
/lib/travis/tools/completion.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: false
2 |
3 | require 'travis/tools/assets'
4 | require 'travis/cli'
5 | require 'fileutils'
6 | require 'erb'
7 |
8 | module Travis
9 | module Tools
10 | module Completion
11 | RCS = ['.zshrc', '.bashrc'].map { |f| File.expand_path(f, ENV['HOME']) }
12 | include FileUtils
13 |
14 | module_function
15 |
16 | def config_path
17 | ENV.fetch('TRAVIS_CONFIG_PATH') { File.expand_path('.travis', ENV['HOME']) }
18 | end
19 |
20 | def cmp_file
21 | File.expand_path('travis.sh', config_path)
22 | end
23 |
24 | def install_completion
25 | update_completion
26 | source = 'source ' << cmp_file
27 |
28 | RCS.each do |file|
29 | next unless File.exist?(file) && File.writable?(file)
30 | next if File.read(file).include? source
31 |
32 | File.open(file, 'a') { |f| f.puts('', '# added by travis gem', "[ ! -s #{cmp_file} ] || #{source}") }
33 | end
34 | end
35 |
36 | def update_completion
37 | FileUtils.mkdir_p(config_path)
38 | FileUtils.cp(Assets['travis.sh'], cmp_file)
39 | end
40 |
41 | def completion_installed?
42 | source = 'source ' << config_path
43 | RCS.each do |file|
44 | next unless File.exist?(file) && File.writable?(file)
45 | return false unless File.read(file).include? source
46 | end
47 | true
48 | end
49 |
50 | def compile
51 | commands = Travis::CLI.commands.sort_by { |c| c.command_name }
52 | template = Assets.read('travis.sh.erb')
53 | source = ERB.new(template).result(binding).gsub(/^ +\n/, '')
54 | File.write(Assets['travis.sh'], source)
55 | end
56 | end
57 | end
58 | end
59 |
--------------------------------------------------------------------------------
/lib/travis/tools/formatter.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'time'
4 |
5 | module Travis
6 | module Tools
7 | class Formatter
8 | DAY = 24 * 60 * 60
9 | TIME_FORMAT = '%Y-%m-%d %H:%M:%S'
10 | CONFIG_KEYS = %w[rvm gemfile env jdk otp_release php node_js perl python scala
11 | compiler os].freeze
12 |
13 | def duration(seconds, suffix = nil)
14 | return 'none' if seconds.nil?
15 |
16 | seconds = (Time.now - seconds).to_i if seconds.is_a? Time
17 | output = []
18 | minutes, seconds = seconds.divmod(60)
19 | hours, minutes = minutes.divmod(60)
20 | output << "#{hours} hrs" if hours.positive?
21 | output << "#{minutes} min" if minutes.positive?
22 | output << "#{seconds} sec" if seconds.positive? || output.empty?
23 | output << suffix if suffix
24 | output.join(' ')
25 | end
26 |
27 | def file_size(input, human: true)
28 | return "#{input} B" unless human
29 |
30 | format = 'B'
31 | iec = %w[KiB MiB GiB TiB PiB EiB ZiB YiB]
32 | while human && (input > 512) && iec.any?
33 | input /= 1024.0
34 | format = iec.shift
35 | end
36 | input = input.round(2) if input.is_a? Float
37 | "#{input} #{format}"
38 | end
39 |
40 | def time(time)
41 | return 'not yet' if time.nil? # or time > Time.now
42 |
43 | # return duration(time, "ago") if Time.now - time < DAY
44 | time.localtime.strftime(TIME_FORMAT)
45 | end
46 |
47 | def job_config(config)
48 | output = []
49 | config.each_pair do |key, value|
50 | output << "#{key}: #{value}" if CONFIG_KEYS.include? key
51 | end
52 | output.join(', ')
53 | end
54 | end
55 | end
56 | end
57 |
--------------------------------------------------------------------------------
/lib/travis/tools/notification.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis'
4 | require 'travis/tools/system'
5 | require 'travis/tools/assets'
6 | require 'cgi'
7 |
8 | module Travis
9 | module Tools
10 | module Notification
11 | module_function
12 |
13 | DEFAULT = %i[osx growl libnotify].freeze
14 | ICON = Assets['notifications/icon.png']
15 |
16 | def new(*list)
17 | list.concat(DEFAULT) if list.empty?
18 | notification = list.map { |n| get(n) }.detect { |n| n.available? }
19 | raise ArgumentError, "no notification system found (looked for #{list.join(', ')})" unless notification
20 |
21 | notification
22 | end
23 |
24 | def get(name)
25 | const = constants.detect { |c| c.to_s[/[^:]+$/].downcase == name.to_s }
26 | raise ArgumentError, 'unknown notifications type %p' % name unless const
27 |
28 | const_get(const).new
29 | end
30 |
31 | class Dummy
32 | def notify(title, body); end
33 |
34 | def available?
35 | true
36 | end
37 | end
38 |
39 | class OSX
40 | BIN_PATH = Assets['notifications/Travis CI.app/Contents/MacOS/Travis CI']
41 |
42 | def notify(title, body)
43 | system BIN_PATH, '-message', body.to_s, '-title', title.to_s, '-sender', 'org.travis-ci.Travis-CI'
44 | end
45 |
46 | def available?
47 | System.mac? and System.recent_version?(System.os_version.to_s,
48 | '10.8') and System.running? 'NotificationCenter'
49 | end
50 | end
51 |
52 | class Growl
53 | def notify(title, body)
54 | system 'growlnotify', '-n', 'Travis', '--image', ICON, '-m', body, title
55 | end
56 |
57 | def available?
58 | System.has? 'growlnotify' and System.running? 'Growl'
59 | end
60 | end
61 |
62 | class LibNotify
63 | def notify(title, body)
64 | system 'notify-send', '--expire-time=10000', '-h', 'int:transient:1', '-i', ICON, title, CGI.escapeHTML(body)
65 | end
66 |
67 | def available?
68 | System.has? 'notify-send'
69 | end
70 | end
71 | end
72 | end
73 | end
74 |
--------------------------------------------------------------------------------
/lib/travis/tools/safe_string.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Travis
4 | module Tools
5 | module SafeString
6 | module_function
7 |
8 | def encoded(string)
9 | return string unless string.respond_to? :encode
10 |
11 | string.encode 'utf-8'
12 | rescue Encoding::UndefinedConversionError
13 | string.force_encoding 'utf-8'
14 | end
15 |
16 | def colorized(string)
17 | encoded(string).gsub(/[^[:print:]\e\n]/, '')
18 | end
19 |
20 | def clean(string)
21 | colorized(string).gsub(/\e[^m]+m/, '')
22 | end
23 | end
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/lib/travis/tools/ssl_key.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'openssl'
4 | require 'base64'
5 |
6 | module Travis
7 | module Tools
8 | module SSLKey
9 | module_function
10 |
11 | def generate_rsa(size = 2048)
12 | OpenSSL::PKey::RSA.generate(size)
13 | end
14 |
15 | def public_rsa_key(string)
16 | @to_rsa ||= OpenSSL::PKey::RSA.new(string)
17 | rescue OpenSSL::PKey::RSAError
18 | public_key = string.gsub('RSA PUBLIC KEY', 'PUBLIC KEY')
19 | @to_rsa = OpenSSL::PKey::RSA.new(public_key)
20 | end
21 |
22 | def has_passphrase?(key)
23 | OpenSSL::PKey::RSA.new(key, key[0..1023])
24 | false
25 | rescue OpenSSL::OpenSSLError
26 | true
27 | end
28 |
29 | def remove_passphrase(key, passphrase)
30 | OpenSSL::PKey::RSA.new(key, passphrase).to_s
31 | rescue OpenSSL::PKey::RSAError
32 | false
33 | end
34 |
35 | def rsa_ssh(key)
36 | ['ssh-rsa ', "\0\0\0\assh-rsa#{sized_bytes(key.e)}#{sized_bytes(key.n)}"].pack('a*m').gsub("\n", '')
37 | end
38 |
39 | def sized_bytes(value)
40 | bytes = to_byte_array(value.to_i)
41 | [bytes.size, *bytes].pack('NC*')
42 | end
43 |
44 | def to_byte_array(num, *significant)
45 | return significant if num.between?(-1, 0) && (significant[0][7] == num[7])
46 |
47 | to_byte_array(*num.divmod(256)) + significant
48 | end
49 | end
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/lib/travis/tools/system.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Travis
4 | module Tools
5 | module System
6 | module_function
7 |
8 | def recent_version?(version, minimum)
9 | version = version.split('.').map { |s| s.to_i }
10 | minimum = minimum.split('.').map { |s| s.to_i }
11 | (version <=> minimum) >= 0
12 | end
13 |
14 | def windows?
15 | File::ALT_SEPARATOR == '\\'
16 | end
17 |
18 | def mac?
19 | RUBY_PLATFORM =~ /darwin/i
20 | end
21 |
22 | def linux?
23 | RUBY_PLATFORM =~ /linux/i
24 | end
25 |
26 | def unix?
27 | !windows?
28 | end
29 |
30 | def os
31 | os_name ? "#{os_name} #{os_version}".strip : os_type
32 | end
33 |
34 | def full_os
35 | os_name == os_type ? os : "#{os} like #{os_type}"
36 | end
37 |
38 | def os_version
39 | @os_version ||= has?(:sw_vers) && `sw_vers -productVersion`.chomp
40 | @os_version ||= has?(:lsb_release) && `lsb_release -r -s`.chomp
41 | end
42 |
43 | def os_name
44 | @os_name ||= has?(:sw_vers) && `sw_vers -productName`.chomp
45 | @os_name ||= has?(:lsb_release) && `lsb_release -i -s`.chomp
46 | end
47 |
48 | def os_type
49 | @os_type ||= windows? ? 'Windows' : `uname`.chomp
50 | end
51 |
52 | def ruby_engine
53 | defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
54 | end
55 |
56 | def ruby_version
57 | format('%s-p%s', RUBY_VERSION, RUBY_PATCHLEVEL)
58 | end
59 |
60 | def ruby
61 | case ruby_engine
62 | when 'ruby' then "Ruby #{ruby_version}"
63 | when 'jruby' then "JRuby #{JRUBY_VERSION} like Ruby #{ruby_version}"
64 | when 'rbx' then "Rubinius #{Rubinius.version[/\d\S+/]} like Ruby #{ruby_version}"
65 | else "#{ruby_engine} like Ruby #{ruby_version}"
66 | end
67 | end
68 |
69 | def rubygems
70 | return 'no RubyGems' unless defined? Gem
71 |
72 | "RubyGems #{Gem::VERSION}"
73 | end
74 |
75 | def description(*args)
76 | [full_os, ruby, rubygems, *args.flatten].compact.uniq.join('; ')
77 | end
78 |
79 | def has?(command)
80 | return false unless unix?
81 |
82 | @has ||= {}
83 | @has.fetch(command) { @has[command] = system "command -v #{command} 2>/dev/null >/dev/null" }
84 | end
85 |
86 | def running?(app)
87 | return false unless unix?
88 |
89 | system "/usr/bin/pgrep -u $(whoami) #{app} >/dev/null"
90 | end
91 | end
92 | end
93 | end
94 |
--------------------------------------------------------------------------------
/lib/travis/version.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | module Travis
4 | VERSION = '1.14.0'
5 | end
6 |
--------------------------------------------------------------------------------
/spec/cli/api_command_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::ApiCommand do
6 | describe 'enterprise' do
7 | travis_config_path = ENV['TRAVIS_CONFIG_PATH']
8 | subject(:api_command) { described_class.new }
9 |
10 | before do
11 | ENV['TRAVIS_CONFIG_PATH'] = File.expand_path '../support', File.dirname(__FILE__)
12 | config = api_command.send(:load_file, 'fake_travis_config.yml')
13 | api_command.config = YAML.load(config)
14 |
15 | api_command.api_endpoint = 'https://travis-ci-enterprise/api'
16 | api_command.enterprise_name = 'default'
17 | end
18 |
19 | after do
20 | ENV['TRAVIS_CONFIG_PATH'] = travis_config_path
21 | end
22 |
23 | describe '#setup_enterprise' do
24 | before do
25 | api_command.send(:setup_enterprise)
26 | end
27 |
28 | it 'keeps verifying peers' do
29 | api_command.insecure.should be_falsey
30 | end
31 |
32 | it 'uses default CAs' do
33 | api_command.session.ssl.should_not include(:ca_file)
34 | end
35 |
36 | it 'flags endpoint' do
37 | api_command.endpoint_config.should include('enterprise' => true)
38 | end
39 | end
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/spec/cli/cancel_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Cancel do
6 | example 'travis cancel' do
7 | run_cli('cancel', '-t', 'token').should be_success
8 | end
9 |
10 | example 'travis cancel 6180.1' do
11 | run_cli('cancel', '6180.1', '-t', 'token').should be_success
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/cli/encrypt_file_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'fileutils'
5 | require 'digest'
6 |
7 | describe Travis::CLI::EncryptFile do
8 | CMD_TARGET = 'README.md'
9 |
10 | before do
11 |
12 | ENV['TRAVIS_TOKEN'] = 'token'
13 | Digest.stub(:hexencode).and_return 'randomhex' # to avoid relying on Dir.pwd value for hex
14 | end
15 |
16 | after do
17 | FileUtils.rm_f "#{CMD_TARGET}.enc"
18 | end
19 |
20 | example "travis encrypt-file #{CMD_TARGET}" do
21 | run_cli('encrypt-file', CMD_TARGET).should be_success
22 | File.exist?("#{CMD_TARGET}.enc").should be true
23 | end
24 |
25 | example "travis encrypt-file #{CMD_TARGET} -a" do
26 | run_cli('encrypt-file', CMD_TARGET, '-a') { |i| i.puts 'n' }.should be_success
27 | stdout.should match(/Overwrite the config file/)
28 | File.exist?("#{CMD_TARGET}.enc").should be true
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/spec/cli/encrypt_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Encrypt do
6 |
7 | before { ENV['TRAVIS_TOKEN'] = 'token' }
8 |
9 | example 'travis encrypt foo' do
10 | run_cli('encrypt', 'foo').should be_success
11 | stdout.should match(/^".{60,}"\n$/)
12 | end
13 |
14 | example 'travis encrypt foo -r rails/rails' do
15 | run_cli('encrypt', 'foo', '-r', 'rails/rails').should be_success
16 | stdout.should match(/^".{60,}"\n$/)
17 | end
18 |
19 | example 'travis encrypt foo -i' do
20 | run_cli('encrypt', 'foo', '-i', '--skip-completion-check', '-r', 'travis-ci/travis.rb').should be_success
21 | stdout.should start_with("Please add the following to your .travis.yml file:\n\n secure: ")
22 | end
23 |
24 | example 'cat foo | travis encrypt' do
25 | run_cli('encrypt') { |i| i.puts('foo') }
26 | stdout.should match(/\A".{60,}"\n\Z/)
27 | end
28 |
29 | example 'cat foo\\nbar | travis encrypt -s' do
30 | run_cli('encrypt', '-s') { |i| i.puts("foo\nbar") }
31 | stdout.should match(/\A(".{60,}"\n){2}\Z/)
32 | end
33 |
34 | example 'cat foo\\nbar | travis encrypt' do
35 | run_cli('encrypt') { |i| i.puts("foo\nbar") }
36 | stdout.should match(/\A".{60,}"\n\Z/)
37 | end
38 |
39 | example 'travis encrypt rails/rails foo' do
40 | run_cli('encrypt', 'rails/rails', 'foo').should be_success
41 | stderr.should match(/WARNING/)
42 | end
43 |
44 | example 'travis encrypt foo=foo/bar' do
45 | run_cli('encrypt', 'foo=foo/bar').should be_success
46 | stderr.should_not match(/WARNING/)
47 | end
48 |
49 | example 'travis encrypt FOO bar -a' do
50 | described_class.any_instance.stub(:save_travis_config)
51 | run_cli('encrypt', 'FOO', 'bar', '-a') { |i| i.puts 'foo' }.should be_success
52 | stderr.should match(/Environment variables in env\.global should be formatted as FOO=bar/)
53 | end
54 |
55 | example 'travis encrypt FOO bar -a foo' do
56 | described_class.any_instance.stub(:save_travis_config)
57 | run_cli('encrypt', 'FOO', 'bar', '-a', 'foo') { |i| i.puts 'foo' }.should be_success
58 | stdout.should match(/Overwrite the config file/)
59 | end
60 |
61 | example 'travis encrypt FOO bar -a --no-interactive' do
62 | described_class.any_instance.stub(:save_travis_config)
63 | run_cli('encrypt', 'FOO', 'bar', '-a', '--no-interactive').should be_success
64 | stderr.should match(/Environment variables in env\.global should be formatted as FOO=bar/)
65 | end
66 |
67 | example 'travis encrypt FOO=bar -a foo --no-interactive' do
68 | described_class.any_instance.stub(:save_travis_config)
69 | run_cli('encrypt', 'FOO=bar', '-a', 'foo', '--no-interactive').should be_success
70 | stdout.should be_empty
71 | end
72 | end
73 |
--------------------------------------------------------------------------------
/spec/cli/endpoint_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Endpoint do
6 | example 'travis endpoint' do
7 | run_cli('endpoint').should be_success
8 | stdout.should be == "https://api.travis-ci.com/\n"
9 | end
10 |
11 | example 'travis endpoint --pro' do
12 | run_cli('endpoint', '--pro').should be_success
13 | stdout.should be == "https://api.travis-ci.com/\n"
14 | end
15 |
16 | example 'travis endpoint --com' do
17 | run_cli('endpoint', '--com').should be_success
18 | stdout.should be == "https://api.travis-ci.com/\n"
19 | end
20 |
21 | example 'travis endpoint -e http://localhost:3000/' do
22 | run_cli('endpoint', '-e', 'http://localhost:3000/').should be_success
23 | stdout.should be == "http://localhost:3000/\n"
24 | end
25 |
26 | example 'TRAVIS_ENDPOINT=http://localhost:3000/ travis endpoint' do
27 | ENV['TRAVIS_ENDPOINT'] = 'http://localhost:3000/'
28 | run_cli('endpoint').should be_success
29 | stdout.should be == "http://localhost:3000/\n"
30 | end
31 |
32 | example 'travis endpoint --github' do
33 | run_cli('endpoint', '--github').should be_success
34 | stdout.should be == "https://api.github.com\n"
35 | end
36 |
37 | example 'travis endpoint -i' do
38 | run_cli('endpoint', '-i').should be_success
39 | stdout.should be == "API endpoint: https://api.travis-ci.com/\n"
40 | end
41 | end
42 |
--------------------------------------------------------------------------------
/spec/cli/help_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Help do
6 | example 'travis help' do
7 | run_cli('help').should be_success
8 | stdout.should include('Usage: travis COMMAND')
9 | end
10 |
11 | example 'travis --help' do
12 | run_cli('--help').should be_success
13 | stdout.should include('Usage: travis COMMAND')
14 | end
15 |
16 | example 'travis -h' do
17 | run_cli('-h').should be_success
18 | stdout.should include('Usage: travis COMMAND')
19 | end
20 |
21 | example 'travis -?' do
22 | run_cli('-?').should be_success
23 | stdout.should include('Usage: travis COMMAND')
24 | end
25 |
26 | example 'travis help endpoint' do
27 | run_cli('help', 'endpoint').should be_success
28 | stdout.should include('Usage: travis endpoint [OPTIONS]')
29 | end
30 |
31 | example 'travis endpoint --help' do
32 | run_cli('endpoint', '--help').should be_success
33 | stdout.should include('Usage: travis endpoint [OPTIONS]')
34 | end
35 | end
36 |
--------------------------------------------------------------------------------
/spec/cli/history_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::History do
6 |
7 | before { ENV['TRAVIS_TOKEN'] = 'token' }
8 |
9 | example 'travis history' do
10 | run_cli('history').should be_success
11 | stdout.should be == "#6180 failed: master Associaton -> Association\n"
12 | end
13 |
14 | example 'travis history -d' do
15 | run_cli('history', '-d').should be_success
16 | stdout.should be =~ /2013-01-13 \d+:55:17 #6180 failed: master Associaton -> Association/
17 | end
18 |
19 | example 'travis history -a 6180' do
20 | run_cli('history', '-a', '6180').should be_success
21 | stdout.should be == ''
22 | end
23 |
24 | example 'travis history -b master' do
25 | run_cli('history', '-b', 'master').should be_success
26 | stdout.should be == "#6180 failed: master Associaton -> Association\n"
27 | end
28 |
29 | example 'travis history -b not-master' do
30 | run_cli('history', '-b', 'not-master').should be_success
31 | stdout.should be_empty
32 | end
33 |
34 | example 'travis history -p 5' do
35 | run_cli('history', '-p', '5').should be_success
36 | stdout.should be_empty
37 | end
38 |
39 | example 'travis history -c' do
40 | run_cli('history', '-c').should be_success
41 | stdout.should be == "#6180 failed: master Steve Klabnik Associaton -> Association\n"
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/spec/cli/logs_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Logs do
6 | before { ENV['TRAVIS_TOKEN'] = 'token' }
7 |
8 | example 'logs 6180.1' do
9 | run_cli('logs', '6180.1', '-E').should be_success
10 | stdout.should be == "$ export GEM=railties\n"
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/cli/open_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Open do
6 |
7 | before { ENV['TRAVIS_TOKEN'] = 'token' }
8 |
9 | example 'travis open -p' do
10 | run_cli('open', '-p').should be_success
11 | stdout.should match(%r{https://travis-ci.com/[\w\W]*/travis\.rb})
12 | end
13 |
14 | example 'travis open 6180 -p' do
15 | run_cli('open', '6180', '-p').should be_success
16 | stdout.should match(%r{https://travis-ci.com/[\w\W]*/travis\.rb/builds/4125095})
17 | end
18 |
19 | example 'travis open 6180.1 -p' do
20 | run_cli('open', '6180.1', '-p').should be_success
21 | stdout.should match(%r{https://travis-ci.com/[\w\W]*/travis\.rb/jobs/4125096})
22 | end
23 |
24 | example 'travis open -pg' do
25 | run_cli('open', '-pg').should be_success
26 | stdout.should match(%r{https://github.com/[\w\W]*/travis\.rb})
27 | end
28 |
29 | example 'travis open 6180 -pg' do
30 | run_cli('open', '6180', '-pg').should be_success
31 | stdout.should be == "https://github.com/rails/rails/compare/6581d798e830...a0265b98f16c\n"
32 | end
33 |
34 | example 'travis open 6180.1 -pg' do
35 | run_cli('open', '6180.1', '-pg').should be_success
36 | stdout.should be == "https://github.com/rails/rails/compare/6581d798e830...a0265b98f16c\n"
37 | end
38 | end
39 |
--------------------------------------------------------------------------------
/spec/cli/repo_command_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'uri'
5 |
6 | describe Travis::CLI::RepoCommand do
7 | describe '#parse_remote' do
8 | subject(:repo_command) { described_class.new }
9 |
10 | it 'handles git@github.com URIs' do
11 | path = repo_command.send(:parse_remote, 'git@github.com:travis-ci/travis.rb.git')
12 | path.should be == '/travis-ci/travis.rb.git'
13 | end
14 |
15 | it 'handles GitHub Enterprise URIS' do
16 | path = repo_command.send(:parse_remote, 'git@example.com:travis-ci/travis.rb.git')
17 | path.should be == '/travis-ci/travis.rb.git'
18 | end
19 |
20 | it 'handles HTTPS URIs' do
21 | path = repo_command.send(:parse_remote, 'https://github.com/travis-ci/travis.rb.git')
22 | path.should be == '/travis-ci/travis.rb.git'
23 | end
24 |
25 | it 'raises URI::InvalidURIError for invalid URIs' do
26 | expect { repo_command.send(:parse_remote, 'foo@example.com:baz/bar.git') }.to raise_error(URI::InvalidURIError)
27 | end
28 | end
29 | end
30 |
--------------------------------------------------------------------------------
/spec/cli/restart_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Restart do
6 | example 'travis restart' do
7 | run_cli('restart', '-t', 'token').should be_success
8 | end
9 |
10 | example 'travis restart 6180.1' do
11 | run_cli('restart', '6180.1', '-t', 'token').should be_success
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/cli/setup/service_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Setup::Service do
6 | subject :service do
7 | repository = double('repository', { slug: 'test_slug' })
8 | setup = double('Setup', repository:)
9 | described_class.new(setup)
10 | end
11 |
12 | describe '#deploy' do
13 | subject :deploy_config do
14 | { 'provider' => 'dummy' }
15 | end
16 |
17 | before do
18 | allow(service).to receive(:configure).and_yield(deploy_config)
19 | allow(service).to receive(:on).and_return(nil)
20 | end
21 |
22 | context 'with no existing deploy section' do
23 | it 'creates section contents without optional items' do
24 | service.send(:deploy, 'dummy') { |_| }
25 | expect(deploy_config).to include(
26 | 'provider' => 'dummy',
27 | 'skip_cleanup' => 'true'
28 | )
29 | end
30 | end
31 |
32 | context 'with existing deploy section' do
33 | it 'doesn\'t overwrite existing skip_cleanup' do
34 | deploy_config['skip_cleanup'] = 'false'
35 | service.send(:deploy, 'dummy') { |_| }
36 | expect(deploy_config).to include('skip_cleanup' => 'false')
37 | end
38 |
39 | it 'doesn\'t set skip_cleanup for v2' do
40 | deploy_config['edge'] = 'true'
41 | service.send(:deploy, 'dummy') { |_| }
42 | expect(deploy_config).not_to include('skip_cleanup')
43 | end
44 |
45 | it 'sets skip_cleanup for explicit v1' do
46 | deploy_config['edge'] = 'false'
47 | service.send(:deploy, 'dummy') { |_| }
48 | expect(deploy_config).to include('skip_cleanup' => 'true')
49 | end
50 | end
51 | end
52 | end
53 |
--------------------------------------------------------------------------------
/spec/cli/setup_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
--------------------------------------------------------------------------------
/spec/cli/show_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Show do
6 | before { ENV['TRAVIS_TOKEN'] = 'token' }
7 |
8 | example 'show 6180.1' do
9 | run_cli('show', '6180.1', '-E').should be_success
10 | stdout.should include('Config: ')
11 | stdout.should include('env: GEM=railties')
12 | end
13 | end
14 |
--------------------------------------------------------------------------------
/spec/cli/status_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Status do
6 |
7 | before { ENV['TRAVIS_TOKEN'] = 'token' }
8 |
9 | example 'travis status' do
10 | run_cli('status').should be_success
11 | stdout.should be == "failed\n"
12 | end
13 |
14 | example 'travis status -x' do
15 | run_cli('status', '-x').should_not be_success
16 | stdout.should be == "failed\n"
17 | end
18 |
19 | example 'travis status -q' do
20 | run_cli('status', '-q').should be_success
21 | stdout.should be_empty
22 | end
23 |
24 | example 'travis status -pqx' do
25 | run_cli('endpoint', '-pqx').should_not be_success
26 | stdout.should be_empty
27 | end
28 |
29 | example 'travis status -i' do
30 | run_cli('status', '-i', '--skip-completion-check', '-r', 'travis-ci/travis.rb').should be_success
31 | stdout.should be == "build #6180 failed\n"
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/spec/cli/token_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Token do
6 | example 'travis token (access token set)' do
7 | run_cli('token', '-t', 'super-secret').should be_success
8 | stdout.should
9 | stderr.should be_empty
10 | end
11 |
12 | example 'travis token -i (access token set)' do
13 | run_cli('token', '-it', 'super-secret').should be_success
14 | stdout.should
15 | stderr.should be_empty
16 | end
17 |
18 | example 'travis token (no access token set)' do
19 | run_cli('token').should_not be_success
20 |
21 | stdout.should be_empty
22 | stderr.should == "not logged in, please run #{File.basename($PROGRAM_NAME)} login\n"
23 | end
24 | end
25 |
--------------------------------------------------------------------------------
/spec/cli/version_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Version do
6 | example do
7 | run_cli('-v').should be_success
8 | stdout.should be == "#{Travis::VERSION}\n"
9 | end
10 |
11 | example do
12 | run_cli('--version').should be_success
13 | stdout.should be == "#{Travis::VERSION}\n"
14 | end
15 |
16 | example do
17 | run_cli('version').should be_success
18 | stdout.should be == "#{Travis::VERSION}\n"
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/spec/cli/whoami_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::CLI::Whoami do
6 | example 'travis whoami' do
7 | run_cli('whoami').should_not be_success
8 | stdout.should be_empty
9 | stderr.should be == "not logged in, please run #{File.basename $PROGRAM_NAME} login\n"
10 | end
11 |
12 | example 'travis whoami --pro' do
13 | run_cli('whoami', '--pro').should_not be_success
14 | stdout.should be_empty
15 | stderr.should be == "not logged in, please run #{File.basename $PROGRAM_NAME} login\n"
16 | end
17 |
18 | example 'travis whoami -t token' do
19 | run_cli('whoami', '-t', 'token').should be_success
20 | stdout.should be == "rkh\n"
21 | stderr.should be_empty
22 | end
23 |
24 | example 'TRAVIS_TOKEN=token travis whoami' do
25 | ENV['TRAVIS_TOKEN'] = 'token'
26 | run_cli('whoami').should be_success
27 | stdout.should be == "rkh\n"
28 | stderr.should be_empty
29 | end
30 |
31 | example 'travis whoami -t token -i' do
32 | run_cli('whoami', '-t', 'token', '-i').should be_success
33 | stdout.should be == "You are rkh (Konstantin Haase)\n"
34 | stderr.should be_empty
35 | end
36 | end
37 |
--------------------------------------------------------------------------------
/spec/client/account_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client::Account do
6 | context 'with all accounts' do
7 | subject { session.accounts.first }
8 |
9 | let(:session) { Travis::Client.new }
10 |
11 | its(:name) { is_expected.to be == 'Konstantin Haase' }
12 | its(:login) { is_expected.to be == 'rkh' }
13 | its(:type) { is_expected.to be == 'user' }
14 | its(:repos_count) { is_expected.to be == 200 }
15 | its(:inspect) { is_expected.to be == '#<Travis::Client::Account: rkh>' }
16 | end
17 |
18 | context 'with known account' do
19 | subject { session.account('rkh') }
20 |
21 | let(:session) { Travis::Client.new }
22 |
23 | its(:name) { is_expected.to be == 'Konstantin Haase' }
24 | its(:login) { is_expected.to be == 'rkh' }
25 | its(:type) { is_expected.to be == 'user' }
26 | its(:repos_count) { is_expected.to be == 200 }
27 | its(:inspect) { is_expected.to be == '#<Travis::Client::Account: rkh>' }
28 | end
29 |
30 | context 'with known account and nil name' do
31 | subject { session.account('foo') }
32 |
33 | let(:session) { Travis::Client.new }
34 |
35 | its(:name) { is_expected.to be_nil }
36 | its(:login) { is_expected.to be == 'foo' }
37 | its(:type) { is_expected.to be_nil }
38 | its(:inspect) { is_expected.to be == '#<Travis::Client::Account: foo>' }
39 | end
40 | end
41 |
--------------------------------------------------------------------------------
/spec/client/auto_login_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'travis/client/auto_login'
4 | require 'spec_helper'
5 |
6 | describe Travis::Client::AutoLogin do
7 | let(:auto_login_with_token) { described_class.new(Travis::Client.new, { config_file: travis_config }) }
8 | let(:auto_login_without_token) { described_class.new(Travis::Client.new) }
9 | let(:travis_config) { File.expand_path('../support/fake_travis_config.yml', File.dirname(__FILE__)) }
10 |
11 | context 'when user authenticates' do
12 | context 'when user has a token in cli config' do
13 | it 'does not call Tools::Github#with_token' do
14 | expect_any_instance_of(Travis::Tools::Github).not_to receive(:with_token)
15 | auto_login_with_token.authenticate
16 | end
17 | end
18 |
19 | context 'when user does not have a token in cli config' do
20 | before { auto_login_without_token.github.stub(:with_token).and_return(true) }
21 |
22 | it 'calls Tools::Github#with_token' do
23 | expect(auto_login_without_token.github).to receive(:with_token)
24 | auto_login_without_token.authenticate
25 | end
26 | end
27 | end
28 | end
29 |
--------------------------------------------------------------------------------
/spec/client/broadcast_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client::Broadcast do
6 | subject { session.broadcasts.first }
7 |
8 | let(:session) { Travis::Client.new }
9 |
10 | its(:id) { is_expected.to be == 1 }
11 | its(:message) { is_expected.to be == 'Hello!' }
12 | end
13 |
--------------------------------------------------------------------------------
/spec/client/build_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client::Build do
6 | subject { session.build(4_125_095) }
7 |
8 | let(:session) { Travis::Client.new }
9 |
10 | its(:number) { is_expected.to be == '6180' }
11 | its(:state) { is_expected.to be == 'failed' }
12 | its(:duration) { is_expected.to be == 5019 }
13 | its(:started_at) { is_expected.to be_a(Time) }
14 | its(:finished_at) { is_expected.to be_nil }
15 | its(:inspect) { is_expected.to be == '#<Travis::Client::Build: rails/rails#6180>' }
16 | its(:color) { is_expected.to be == 'red' }
17 | its(:commit) { is_expected.to be_a(Travis::Client::Commit) }
18 | its(:jobs) { is_expected.to be_an(Array) }
19 | its(:repository) { is_expected.to be == session.repo('rails/rails') }
20 |
21 | it { is_expected.to be == subject.repository.last_build }
22 |
23 | it { is_expected.not_to be_pending }
24 | it { is_expected.to be_started }
25 | it { is_expected.to be_finished }
26 | it { is_expected.not_to be_passed }
27 | it { is_expected.not_to be_errored }
28 | it { is_expected.to be_failed }
29 | it { is_expected.not_to be_canceled }
30 | it { is_expected.to be_created }
31 | it { is_expected.to be_red }
32 | it { is_expected.not_to be_green }
33 | it { is_expected.not_to be_yellow }
34 | it { is_expected.to be_unsuccessful }
35 | end
36 |
--------------------------------------------------------------------------------
/spec/client/commit_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client::Build do
6 | subject { session.build(4_125_095).commit }
7 |
8 | let(:session) { Travis::Client.new }
9 |
10 | its(:sha) { is_expected.to be == 'a0265b98f16c6e33be32aa3f57231d1189302400' }
11 | its(:short_sha) { is_expected.to be == 'a0265b9' }
12 | its(:branch) { is_expected.to be == 'master' }
13 | its(:message) { is_expected.to be == 'Associaton -> Association' }
14 | its(:committed_at) { is_expected.to be_a(Time) }
15 | its(:author_name) { is_expected.to be == 'Steve Klabnik' }
16 | its(:author_email) { is_expected.to be == 'steve@steveklabnik.com' }
17 | its(:committer_name) { is_expected.to be == 'Steve Klabnik' }
18 | its(:committer_email) { is_expected.to be == 'steve@steveklabnik.com' }
19 | its(:compare_url) { is_expected.to be == 'https://github.com/rails/rails/compare/6581d798e830...a0265b98f16c' }
20 | its(:subject) { is_expected.to be == 'Associaton -> Association' }
21 |
22 | specify 'with missing data' do
23 | session.load('commit' => { 'id' => 12 })['commit'].subject.should be_empty
24 | end
25 | end
26 |
--------------------------------------------------------------------------------
/spec/client/job_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client::Job do
6 | subject { session.job(4_125_097) }
7 |
8 | let(:session) { Travis::Client.new }
9 |
10 | its(:number) { is_expected.to be == '6180.2' }
11 | its(:state) { is_expected.to be == 'passed' }
12 | its(:started_at) { is_expected.to be_a(Time) }
13 | its(:finished_at) { is_expected.to be_a(Time) }
14 | its(:inspect) { is_expected.to be == '#<Travis::Client::Job: rails/rails#6180.2>' }
15 | its(:color) { is_expected.to be == 'green' }
16 | its(:commit) { is_expected.to be_a(Travis::Client::Commit) }
17 | its(:repository) { is_expected.to be == session.repo('rails/rails') }
18 | its(:duration) { is_expected.to be == 905 }
19 |
20 | it { is_expected.to be == subject.build.jobs[1] }
21 |
22 | it { is_expected.not_to be_pending }
23 | it { is_expected.to be_started }
24 | it { is_expected.to be_finished }
25 | it { is_expected.to be_passed }
26 | it { is_expected.not_to be_errored }
27 | it { is_expected.not_to be_failed }
28 | it { is_expected.not_to be_canceled }
29 | it { is_expected.to be_created }
30 | it { is_expected.not_to be_red }
31 | it { is_expected.to be_green }
32 | it { is_expected.not_to be_yellow }
33 | it { is_expected.not_to be_unsuccessful }
34 | end
35 |
--------------------------------------------------------------------------------
/spec/client/methods_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client::Methods do
6 | subject { OpenStruct.new(session:).extend(described_class) }
7 |
8 | let(:session) { Travis::Client.new }
9 |
10 | before { subject.access_token = 'token' }
11 |
12 | its(:api_endpoint) { is_expected.to be == 'https://api.travis-ci.com/' }
13 | its(:repos) { is_expected.to be == session.find_many(Travis::Client::Repository) }
14 | its(:user) { is_expected.to be == session.find_one(Travis::Client::User) }
15 |
16 | it 'fetches a single repo' do
17 | subject.repo(891).slug.should be == 'rails/rails'
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/client/namespace_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client::Namespace do
6 | subject(:namespace) { described_class.new }
7 |
8 | it { is_expected.to be_a(Travis::Client::Methods) }
9 |
10 | it 'creates a dummy for repos' do
11 | repo = namespace::Repository
12 | repo.find_one('rails/rails').should be_a(Travis::Client::Repository)
13 | repo.find_many.should be_an(Array)
14 | repo.current.should be == repo.find_many
15 | end
16 |
17 | it 'creates a dummy for user' do
18 | namespace.access_token = 'token'
19 | user = namespace::User
20 | user.find_one.should be_a(Travis::Client::User)
21 | user.current.should be == user.find_one
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/spec/client/repository_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client::Repository do
6 | subject(:repository) { session.repo('rails/rails') }
7 |
8 | let(:session) { Travis::Client.new }
9 |
10 | its(:slug) { is_expected.to be == 'rails/rails' }
11 | its(:description) { is_expected.not_to be_empty }
12 | its(:last_build_id) { is_expected.to be == 4_125_095 }
13 | its(:last_build_number) { is_expected.to be == '6180' }
14 | its(:last_build_state) { is_expected.to be == 'failed' }
15 | its(:last_build_duration) { is_expected.to be == 5019 }
16 | its(:last_build_started_at) { is_expected.to be_a(Time) }
17 | its(:last_build_finished_at) { is_expected.to be_nil }
18 | its(:inspect) { is_expected.to be == '#<Travis::Client::Repository: rails/rails>' }
19 | its(:key) { is_expected.to be_a(Travis::Client::Repository::Key) }
20 | its(:last_build) { is_expected.to be_a(Travis::Client::Build) }
21 | its(:color) { is_expected.to be == 'red' }
22 | its(:github_language) { is_expected.to be == 'Ruby' }
23 | its(:owner_name) { is_expected.to be == 'rails' }
24 | its(:owner) { is_expected.to be == session.account('rails') }
25 |
26 | it { is_expected.not_to be_pending }
27 | it { is_expected.to be_started }
28 | it { is_expected.to be_finished }
29 | it { is_expected.not_to be_passed }
30 | it { is_expected.not_to be_errored }
31 | it { is_expected.to be_failed }
32 | it { is_expected.not_to be_canceled }
33 | it { is_expected.to be_created }
34 | it { is_expected.to be_red }
35 | it { is_expected.not_to be_green }
36 | it { is_expected.not_to be_yellow }
37 | it { is_expected.to be_unsuccessful }
38 |
39 | it 'exposes the pubkey fingerprint' do
40 | repository.public_key.fingerprint.should be == 'foobar'
41 | end
42 | end
43 |
--------------------------------------------------------------------------------
/spec/client/user_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client::User do
6 | # attributes :login, :name, :email, :gravatar_id, :locale, :is_syncing, :synced_at, :correct_scopes
7 | subject { Travis::Client.new(access_token: 'token').user }
8 |
9 | its(:login) { is_expected.to be == 'rkh' }
10 | its(:name) { is_expected.to be == 'Konstantin Haase' }
11 | its(:email) { is_expected.to be == 'konstantin.haase@gmail.com' }
12 | its(:gravatar_id) { is_expected.to be == '5c2b452f6eea4a6d84c105ebd971d2a4' }
13 | its(:locale) { is_expected.to be == 'en' }
14 | its(:is_syncing) { is_expected.to be false }
15 | its(:synced_at) { is_expected.to be_a(Time) }
16 |
17 | it { is_expected.not_to be_syncing }
18 | it { is_expected.to be_correct_scopes }
19 | end
20 |
--------------------------------------------------------------------------------
/spec/client_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Client do
6 | its(:new) { is_expected.to be_a(Travis::Client::Session) }
7 |
8 | it 'accepts string argument' do
9 | described_class.new('http://foo/').uri.should be == 'http://foo/'
10 | end
11 |
12 | it 'accepts options hash with string keys' do
13 | described_class.new('uri' => 'http://foo/').uri.should be == 'http://foo/'
14 | end
15 |
16 | it 'accepts options hash with symbol keys' do
17 | described_class.new(uri: 'http://foo/').uri.should be == 'http://foo/'
18 | end
19 | end
20 |
--------------------------------------------------------------------------------
/spec/pro_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis::Pro do
6 | it { is_expected.to be_a(Travis::Client::Namespace) }
7 | its(:api_endpoint) { is_expected.to be == 'https://api.travis-ci.com/' }
8 |
9 | it 'has a nice inspect on entities' do
10 | Travis::Pro::Repository.find('rails/rails').inspect.should be == '#<Travis::Pro::Repository: rails/rails>'
11 | end
12 | end
13 |
--------------------------------------------------------------------------------
/spec/spec_helper.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'support/fake_api'
4 | require 'support/fake_github'
5 | require 'support/helpers'
6 |
7 | require 'fileutils'
8 | require 'travis'
9 | require 'highline'
10 | require 'highline/io_console_compatible'
11 | require 'tmpdir'
12 | require 'rspec/its'
13 |
14 | temp_dir = nil
15 |
16 | HighLine.use_color = false
17 | HighLine.define_singleton_method(:use_color=) { |_| }
18 |
19 | RSpec.configure do |c|
20 | c.include Helpers
21 |
22 | c.before do
23 | temp_dir = File.expand_path('travis-spec', Dir.tmpdir)
24 | FileUtils.rm_rf(temp_dir)
25 | FileUtils.mkdir_p(temp_dir)
26 | ENV.delete_if { |k, _v| k.start_with? 'TRAVIS_' }
27 | ENV['TRAVIS_CONFIG_PATH'] = File.expand_path('travis', temp_dir)
28 | end
29 |
30 | c.after do
31 | FileUtils.rm_rf(temp_dir)
32 | end
33 | end
34 |
--------------------------------------------------------------------------------
/spec/support/fake_github.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'gh'
4 |
5 | module GH
6 | class FakeRemote < Remote
7 | def setup(host, options)
8 | @authenticated = options[:password] == 'password'
9 | super
10 | end
11 |
12 | def http(*)
13 | raise NotImplementedError
14 | end
15 |
16 | def post(key, _body)
17 | raise GH::Error unless @authenticated && (key == '/authorizations')
18 |
19 | frontend.load('url' => 'https://api.github.com/authorizations/1', 'token' => 'github_token')
20 | end
21 |
22 | def head(*) end
23 | def delete(*) end
24 | end
25 |
26 | DefaultStack.replace(Remote, FakeRemote)
27 | end
28 |
--------------------------------------------------------------------------------
/spec/support/fake_travis_config.yml:
--------------------------------------------------------------------------------
1 | ---
2 | last_check:
3 | etag: '"fake_etaag"'
4 | version: 1.8.8
5 | at: 1487940199
6 | checked_completion: true
7 | completion_version: 1.8.8
8 | endpoints:
9 | https://api.travis-ci.com/:
10 | access_token: fake-travis-com-token
11 | https://travis-ci-enterprise/api:
12 | access_token: fake-travis-enterprise-token
13 |
--------------------------------------------------------------------------------
/spec/support/helpers.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 | require 'stringio'
5 | require 'ostruct'
6 |
7 | module Helpers
8 | attr_reader :last_run
9 |
10 | def capture
11 | _stdout = $stdout
12 | $stdout = StringIO.new
13 | _stderr = $stderr
14 | $stderr = StringIO.new
15 | _stdin = $stdin
16 | $stdin = StringIO.new
17 | yield
18 | capture_result(true)
19 | rescue SystemExit => e
20 | capture_result(e.success?)
21 | ensure
22 | $stdout = _stdout if _stdout
23 | $stderr = _stderr if _stderr
24 | $stdin = _stdin if _stdin
25 | end
26 |
27 | def run_cli(*args)
28 | args << ENV['TRAVIS_OPTS'] if ENV['TRAVIS_OPTS']
29 | args << '--skip-version-check' << '--skip-completion-check'
30 | capture do
31 | yield $stdin if block_given?
32 | $stdin.rewind
33 | Travis::CLI.run(*args)
34 | end
35 | end
36 |
37 | def stderr
38 | last_run&.err
39 | end
40 |
41 | def stdout
42 | last_run&.out
43 | end
44 |
45 | private
46 |
47 | def capture_result(success)
48 | @last_run = OpenStruct.new(out: $stdout.string, err: $stderr.string, success?: success)
49 | end
50 | end
51 |
--------------------------------------------------------------------------------
/spec/travis_spec.rb:
--------------------------------------------------------------------------------
1 | # frozen_string_literal: true
2 |
3 | require 'spec_helper'
4 |
5 | describe Travis do
6 | its(:api_endpoint) { is_expected.to be == 'https://api.travis-ci.com/' }
7 |
8 | it 'has a nice inspect on entities' do
9 | pending 'does not work on JRuby' if defined? RUBY_ENGINE and RUBY_ENGINE == 'jruby'
10 | Travis::Repository.find('rails/rails').inspect.should be == '#<Travis::Repository: rails/rails>'
11 | end
12 | end
13 |
--------------------------------------------------------------------------------