travis 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +22 -0
- data/README.md +154 -0
- data/Rakefile +38 -0
- data/bin/travis +4 -0
- data/lib/travis.rb +8 -0
- data/lib/travis/cacert.pem +3895 -0
- data/lib/travis/cli.rb +83 -0
- data/lib/travis/cli/api_command.rb +65 -0
- data/lib/travis/cli/command.rb +212 -0
- data/lib/travis/cli/encrypt.rb +57 -0
- data/lib/travis/cli/endpoint.rb +13 -0
- data/lib/travis/cli/help.rb +21 -0
- data/lib/travis/cli/login.rb +57 -0
- data/lib/travis/cli/parser.rb +43 -0
- data/lib/travis/cli/raw.rb +16 -0
- data/lib/travis/cli/repo_command.rb +54 -0
- data/lib/travis/cli/version.rb +12 -0
- data/lib/travis/cli/whoami.rb +12 -0
- data/lib/travis/client.rb +20 -0
- data/lib/travis/client/entity.rb +139 -0
- data/lib/travis/client/error.rb +11 -0
- data/lib/travis/client/methods.rb +45 -0
- data/lib/travis/client/namespace.rb +78 -0
- data/lib/travis/client/repository.rb +66 -0
- data/lib/travis/client/session.rb +191 -0
- data/lib/travis/client/user.rb +20 -0
- data/lib/travis/pro.rb +5 -0
- data/lib/travis/tools/token_finder.rb +51 -0
- data/lib/travis/version.rb +3 -0
- data/spec/cli/encrypt_spec.rb +18 -0
- data/spec/cli/endpoint_spec.rb +23 -0
- data/spec/cli/help_spec.rb +33 -0
- data/spec/cli/login_spec.rb +13 -0
- data/spec/cli/version_spec.rb +18 -0
- data/spec/cli/whoami_spec.rb +27 -0
- data/spec/client/methods_spec.rb +15 -0
- data/spec/client/namespace_spec.rb +19 -0
- data/spec/client/repository_spec.rb +15 -0
- data/spec/client/session_spec.rb +145 -0
- data/spec/client/user_spec.rb +16 -0
- data/spec/client_spec.rb +5 -0
- data/spec/pro_spec.rb +10 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/fake_api.rb +89 -0
- data/spec/support/fake_github.rb +20 -0
- data/spec/support/helpers.rb +43 -0
- data/spec/travis_spec.rb +9 -0
- data/travis.gemspec +84 -0
- metadata +240 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'travis/client'
|
2
|
+
require 'openssl'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module Travis
|
6
|
+
module Client
|
7
|
+
class Repository < Entity
|
8
|
+
class Key
|
9
|
+
attr_reader :to_s
|
10
|
+
|
11
|
+
def initialize(data)
|
12
|
+
@to_s = data
|
13
|
+
end
|
14
|
+
|
15
|
+
def encrypt(value)
|
16
|
+
encrypted = to_rsa.public_encrypt(value)
|
17
|
+
Base64.encode64(encrypted).strip
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_rsa
|
21
|
+
@to_rsa ||= OpenSSL::PKey::RSA.new(to_s)
|
22
|
+
rescue OpenSSL::PKey::RSAError
|
23
|
+
public_key = to_s.gsub('RSA PUBLIC KEY', 'PUBLIC KEY')
|
24
|
+
@to_rsa = OpenSSL::PKey::RSA.new(public_key)
|
25
|
+
end
|
26
|
+
|
27
|
+
def ==(other)
|
28
|
+
other.to_s == self
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
attributes :slug, :description, :last_build_id, :last_build_number, :last_build_state, :last_build_duration, :last_build_language, :last_build_started_at, :last_build_finished_at
|
33
|
+
inspect_info :slug
|
34
|
+
|
35
|
+
one :repo
|
36
|
+
many :repos
|
37
|
+
|
38
|
+
def public_key
|
39
|
+
attributes["public_key"] ||= begin
|
40
|
+
payload = session.get_raw("/repos/#{id}/key")
|
41
|
+
Key.new(payload.fetch('key'))
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def public_key=(key)
|
46
|
+
key = Key.new(key) unless key.is_a? Key
|
47
|
+
set_attribute(:public_key, key)
|
48
|
+
end
|
49
|
+
|
50
|
+
alias key public_key
|
51
|
+
alias key= public_key=
|
52
|
+
|
53
|
+
def encrypt(value)
|
54
|
+
key.encrypt(value)
|
55
|
+
end
|
56
|
+
|
57
|
+
def last_build_started_at=(time)
|
58
|
+
set_attribute(:last_build_started_at, time(time))
|
59
|
+
end
|
60
|
+
|
61
|
+
def last_build_finished_at=(time)
|
62
|
+
set_attribute(:last_build_finished_at, time(time))
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,191 @@
|
|
1
|
+
require 'travis/client'
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday_middleware'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
module Travis
|
8
|
+
module Client
|
9
|
+
class Session
|
10
|
+
SSL_OPTIONS = { :ca_file => File.expand_path("../../cacert.pem", __FILE__) }
|
11
|
+
include Methods
|
12
|
+
attr_reader :connection, :headers, :access_token
|
13
|
+
|
14
|
+
def initialize(options = Travis::Client::ORG_URI)
|
15
|
+
@headers = {}
|
16
|
+
@cache = {}
|
17
|
+
|
18
|
+
options = { :uri => options } unless options.respond_to? :each_pair
|
19
|
+
options.each_pair { |key, value| public_send("#{key}=", value) }
|
20
|
+
|
21
|
+
raise ArgumentError, "neither :uri nor :connection specified" unless connection
|
22
|
+
headers['Accept'] ||= 'application/vnd.travis-ci.2+json, */*; q=0.01'
|
23
|
+
end
|
24
|
+
|
25
|
+
def uri
|
26
|
+
connection.url_prefix.to_s if connection
|
27
|
+
end
|
28
|
+
|
29
|
+
def uri=(uri)
|
30
|
+
clear_cache!
|
31
|
+
self.connection = Faraday.new(:url => uri, :ssl => SSL_OPTIONS) do |faraday|
|
32
|
+
faraday.request :json
|
33
|
+
faraday.response :json
|
34
|
+
faraday.response :follow_redirects
|
35
|
+
faraday.response :raise_error
|
36
|
+
faraday.adapter(*faraday_adapter)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def access_token=(token)
|
41
|
+
clear_cache!
|
42
|
+
@access_token = token
|
43
|
+
headers['Authorization'] = "token #{token}"
|
44
|
+
headers.delete('Authorization') unless token
|
45
|
+
end
|
46
|
+
|
47
|
+
def connection=(connection)
|
48
|
+
clear_cache!
|
49
|
+
connection.headers.merge! headers
|
50
|
+
@connection = connection
|
51
|
+
@headers = connection.headers
|
52
|
+
end
|
53
|
+
|
54
|
+
def headers=(headers)
|
55
|
+
clear_cache!
|
56
|
+
connection.headers = headers if connection
|
57
|
+
@headers = headers
|
58
|
+
end
|
59
|
+
|
60
|
+
def find_one(entity, id = nil)
|
61
|
+
raise Travis::Error, "cannot fetch #{entity}" unless entity.respond_to?(:many) and entity.many
|
62
|
+
return create_entity(entity, "id" => id) if id.is_a? Integer
|
63
|
+
cached(entity, :by, id) { fetch_one(entity, id) }
|
64
|
+
end
|
65
|
+
|
66
|
+
def find_many(entity, args = {})
|
67
|
+
raise Travis::Error, "cannot fetch #{entity}" unless entity.respond_to?(:many) and entity.many
|
68
|
+
cached(entity, :many, args) { fetch_many(entity, args) }
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_one_or_many(entity, args = nil)
|
72
|
+
raise Travis::Error, "cannot fetch #{entity}" unless entity.respond_to?(:many) and entity.many
|
73
|
+
cached(entity, :one_or_many, args) do
|
74
|
+
path = "/#{entity.many}"
|
75
|
+
path, args = "#{path}/#{args}", {} unless args.is_a? Hash
|
76
|
+
result = get(path, args)
|
77
|
+
one = result[entity.one]
|
78
|
+
|
79
|
+
if result.include? entity.many
|
80
|
+
Array(one) + Array(result[entity.many])
|
81
|
+
else
|
82
|
+
one
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def reload(entity)
|
88
|
+
result = fetch_one(entity.class, entity.id)
|
89
|
+
entity.update_attributes(result.attributes) if result.attributes != entity.attributes
|
90
|
+
result
|
91
|
+
end
|
92
|
+
|
93
|
+
def get(*args)
|
94
|
+
result = {}
|
95
|
+
get_raw(*args).each_pair do |key, value|
|
96
|
+
type = Entity.subclass_for(key)
|
97
|
+
if value.respond_to? :to_ary
|
98
|
+
result[key] = value.to_ary.map { |e| create_entity(type, e) }
|
99
|
+
else
|
100
|
+
result[key] = create_entity(type, value)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
result
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_raw(*args)
|
107
|
+
connection.get(*args).body
|
108
|
+
rescue Faraday::Error::ClientError => e
|
109
|
+
handle_error(e)
|
110
|
+
end
|
111
|
+
|
112
|
+
def post_raw(*args)
|
113
|
+
connection.post(*args).body
|
114
|
+
rescue Faraday::Error::ClientError => e
|
115
|
+
handle_error(e)
|
116
|
+
end
|
117
|
+
|
118
|
+
def inspect
|
119
|
+
"#<#{self.class}: #{uri}>"
|
120
|
+
end
|
121
|
+
|
122
|
+
def clear_cache
|
123
|
+
reset_entities
|
124
|
+
clear_find_cache
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
def clear_cache!
|
129
|
+
reset_entities
|
130
|
+
@cache.clear
|
131
|
+
self
|
132
|
+
end
|
133
|
+
|
134
|
+
def session
|
135
|
+
self
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
|
140
|
+
def create_entity(type, data)
|
141
|
+
id = Integer(data.fetch('id'))
|
142
|
+
entity = cached(type, :id, id) { type.new(self, id) }
|
143
|
+
entity.update_attributes(data)
|
144
|
+
entity
|
145
|
+
end
|
146
|
+
|
147
|
+
def handle_error(e)
|
148
|
+
message = e.response[:body].to_str rescue e.message
|
149
|
+
klass = Travis::Client::NotFound if e.is_a? Faraday::Error::ResourceNotFound
|
150
|
+
klass ||= Travis::Client::Error
|
151
|
+
raise klass, message, e.backtrace
|
152
|
+
end
|
153
|
+
|
154
|
+
def faraday_adapter
|
155
|
+
Faraday.default_adapter
|
156
|
+
end
|
157
|
+
|
158
|
+
def reset_entities
|
159
|
+
subcaches do |subcache|
|
160
|
+
subcache[:id].each_value { |e| e.attributes.clear } if subcache.include? :id
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def clear_find_cache
|
165
|
+
subcaches do |subcache|
|
166
|
+
subcache.delete_if { |k, v| k != :id }
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def subcaches
|
171
|
+
@cache.each_value do |subcache|
|
172
|
+
yield subcache if subcache.is_a? Hash
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def fetch_one(entity, id = nil)
|
177
|
+
get("/#{entity.many}/#{id}")[entity.one]
|
178
|
+
end
|
179
|
+
|
180
|
+
def fetch_many(entity, params = {})
|
181
|
+
get("/#{entity.many}/", params)[entity.many]
|
182
|
+
end
|
183
|
+
|
184
|
+
def cached(*keys)
|
185
|
+
last = keys.pop
|
186
|
+
cache = keys.inject(@cache) { |store, key| store[key] ||= {} }
|
187
|
+
cache[last] ||= yield
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'travis/client'
|
2
|
+
|
3
|
+
module Travis
|
4
|
+
module Client
|
5
|
+
class User < Entity
|
6
|
+
attributes :login, :name, :email, :gravatar_id, :locale, :is_syncing, :synced_at, :correct_scopes
|
7
|
+
inspect_info :login
|
8
|
+
|
9
|
+
one :user
|
10
|
+
many :users
|
11
|
+
|
12
|
+
def synced_at=(time)
|
13
|
+
set_attribute(:synced_at, time(time))
|
14
|
+
end
|
15
|
+
|
16
|
+
alias syncing? is_syncing
|
17
|
+
alias correct_scopes? correct_scopes
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/travis/pro.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'netrc'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Travis
|
5
|
+
module Tools
|
6
|
+
# This is used when running `travis login --auto`
|
7
|
+
class TokenFinder
|
8
|
+
attr_accessor :netrc, :hub, :explode, :github
|
9
|
+
|
10
|
+
def self.find(options = {})
|
11
|
+
new(options).find
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(options = {})
|
15
|
+
self.netrc = options[:netrc] || Netrc.default_path
|
16
|
+
self.hub = options[:hub] || ENV['HUB_CONFIG'] || '~/.config/hub'
|
17
|
+
self.github = options[:github] || 'github.com'
|
18
|
+
self.explode = options[:explode]
|
19
|
+
end
|
20
|
+
|
21
|
+
def hub=(file)
|
22
|
+
@hub = File.expand_path(file)
|
23
|
+
end
|
24
|
+
|
25
|
+
def netrc=(file)
|
26
|
+
@netrc = File.expand_path(file)
|
27
|
+
end
|
28
|
+
|
29
|
+
def find
|
30
|
+
find_netrc || find_hub
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_netrc
|
34
|
+
return unless File.readable? netrc
|
35
|
+
data = Netrc.read(netrc)[github]
|
36
|
+
data.detect { |e| e.size == 40 } if data
|
37
|
+
rescue => e
|
38
|
+
raise e if explode
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_hub
|
42
|
+
return unless File.readable? hub
|
43
|
+
data = YAML.load_file(File.expand_path(hub))
|
44
|
+
data &&= Array(data[github])
|
45
|
+
data.first['oauth_token'] if data.size == 1
|
46
|
+
rescue => e
|
47
|
+
raise e if explode
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Travis::CLI::Endpoint do
|
4
|
+
example "travis encrypt foo" do
|
5
|
+
run_cli('encrypt', 'foo').should be_success
|
6
|
+
stdout.should match(/^".{60,}"\n$/)
|
7
|
+
end
|
8
|
+
|
9
|
+
example "travis encrypt foo -i" do
|
10
|
+
run_cli('encrypt', 'foo', '-i').should be_success
|
11
|
+
stdout.should start_with("Please add the following to your \e[33m.travis.yml\e[0m file:\n\n secure: ")
|
12
|
+
end
|
13
|
+
|
14
|
+
example "cat foo | travis encrypt" do
|
15
|
+
run_cli('encrypt') { |i| i.puts('foo') }
|
16
|
+
stdout.should match(/^".{60,}"\n$/)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Travis::CLI::Endpoint do
|
4
|
+
example "travis endpoint" do
|
5
|
+
run_cli('endpoint').should be_success
|
6
|
+
stdout.should be == "https://api.travis-ci.org/\n"
|
7
|
+
end
|
8
|
+
|
9
|
+
example "travis endpoint --pro" do
|
10
|
+
run_cli('endpoint', '--pro').should be_success
|
11
|
+
stdout.should be == "https://api.travis-ci.com/\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
example "travis endpoint -e http://localhost:3000/" do
|
15
|
+
run_cli('endpoint', '-e', 'http://localhost:3000/').should be_success
|
16
|
+
stdout.should be == "http://localhost:3000/\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
example "travis endpoint -i" do
|
20
|
+
run_cli('endpoint', '-i').should be_success
|
21
|
+
stdout.should be == "API endpoint: \e[1m\e[4mhttps://api.travis-ci.org/\e[0m\n"
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Travis::CLI::Help do
|
4
|
+
example "travis help" do
|
5
|
+
run_cli('help').should be_success
|
6
|
+
stdout.should start_with("Usage: #$0 COMMAND")
|
7
|
+
end
|
8
|
+
|
9
|
+
example "travis --help" do
|
10
|
+
run_cli('--help').should be_success
|
11
|
+
stdout.should start_with("Usage: #$0 COMMAND")
|
12
|
+
end
|
13
|
+
|
14
|
+
example "travis -h" do
|
15
|
+
run_cli('-h').should be_success
|
16
|
+
stdout.should start_with("Usage: #$0 COMMAND")
|
17
|
+
end
|
18
|
+
|
19
|
+
example "travis -?" do
|
20
|
+
run_cli('-?').should be_success
|
21
|
+
stdout.should start_with("Usage: #$0 COMMAND")
|
22
|
+
end
|
23
|
+
|
24
|
+
example "travis help endpoint" do
|
25
|
+
run_cli('help', 'endpoint').should be_success
|
26
|
+
stdout.should start_with("Usage: #$0 endpoint [options]")
|
27
|
+
end
|
28
|
+
|
29
|
+
example "travis endpoint --help" do
|
30
|
+
run_cli('endpoint', '--help').should be_success
|
31
|
+
stdout.should start_with("Usage: #$0 endpoint [options]")
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Travis::CLI::Login do
|
4
|
+
example "travis login" do
|
5
|
+
run_cli('login') { |i| i.puts('rkh', 'password') }.should be_success
|
6
|
+
run_cli('whoami').out.should be == "rkh\n"
|
7
|
+
end
|
8
|
+
|
9
|
+
example "travis login (with bad credentials)" do
|
10
|
+
run_cli('login') { |i| i.puts('rkh', 'wrong password') }.should_not be_success
|
11
|
+
run_cli('whoami').should_not be_success
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Travis::CLI::Version do
|
4
|
+
example do
|
5
|
+
run_cli('-v').should be_success
|
6
|
+
stdout.should be == "#{Travis::VERSION}\n"
|
7
|
+
end
|
8
|
+
|
9
|
+
example do
|
10
|
+
run_cli('--version').should be_success
|
11
|
+
stdout.should be == "#{Travis::VERSION}\n"
|
12
|
+
end
|
13
|
+
|
14
|
+
example do
|
15
|
+
run_cli('version').should be_success
|
16
|
+
stdout.should be == "#{Travis::VERSION}\n"
|
17
|
+
end
|
18
|
+
end
|