travis-akerl 1.8.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +2512 -0
- data/Rakefile +64 -0
- data/assets/cacert.pem +69 -0
- data/assets/init/c.yml +4 -0
- data/assets/init/clojure.yml +1 -0
- data/assets/init/cpp.yml +4 -0
- data/assets/init/erlang.yml +3 -0
- data/assets/init/go.yml +4 -0
- data/assets/init/groovy.yml +1 -0
- data/assets/init/haskell.yml +1 -0
- data/assets/init/java.yml +4 -0
- data/assets/init/node_js.yml +5 -0
- data/assets/init/objective-c.yml +1 -0
- data/assets/init/perl.yml +4 -0
- data/assets/init/php.yml +4 -0
- data/assets/init/python.yml +5 -0
- data/assets/init/ruby.yml +6 -0
- data/assets/init/scala.yml +4 -0
- data/assets/notifications/Travis CI.app/Contents/Info.plist +52 -0
- data/assets/notifications/Travis CI.app/Contents/MacOS/Travis CI +0 -0
- data/assets/notifications/Travis CI.app/Contents/PkgInfo +1 -0
- data/assets/notifications/Travis CI.app/Contents/Resources/Travis CI.icns +0 -0
- data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/Credits.rtf +29 -0
- data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/InfoPlist.strings +0 -0
- data/assets/notifications/Travis CI.app/Contents/Resources/en.lproj/MainMenu.nib +0 -0
- data/assets/notifications/Travis CI.app/Contents/_CodeSignature/CodeResources +173 -0
- data/assets/notifications/Travis CI.app/Contents/embedded.provisionprofile +0 -0
- data/assets/notifications/icon.png +0 -0
- data/assets/travis.sh +163 -0
- data/assets/travis.sh.erb +64 -0
- data/bin/travis +18 -0
- data/examples/org_overview.rb +3 -0
- data/examples/pro_auth.rb +23 -0
- data/examples/stream.rb +6 -0
- data/lib/travis/auto_login.rb +3 -0
- data/lib/travis/cli/accounts.rb +31 -0
- data/lib/travis/cli/api_command.rb +182 -0
- data/lib/travis/cli/branches.rb +25 -0
- data/lib/travis/cli/cache.rb +76 -0
- data/lib/travis/cli/cancel.rb +18 -0
- data/lib/travis/cli/command.rb +422 -0
- data/lib/travis/cli/console.rb +33 -0
- data/lib/travis/cli/disable.rb +15 -0
- data/lib/travis/cli/enable.rb +31 -0
- data/lib/travis/cli/encrypt.rb +115 -0
- data/lib/travis/cli/encrypt_file.rb +140 -0
- data/lib/travis/cli/endpoint.rb +35 -0
- data/lib/travis/cli/env.rb +66 -0
- data/lib/travis/cli/help.rb +23 -0
- data/lib/travis/cli/history.rb +49 -0
- data/lib/travis/cli/init.rb +82 -0
- data/lib/travis/cli/lint.rb +49 -0
- data/lib/travis/cli/login.rb +76 -0
- data/lib/travis/cli/logout.rb +14 -0
- data/lib/travis/cli/logs.rb +65 -0
- data/lib/travis/cli/monitor.rb +111 -0
- data/lib/travis/cli/open.rb +39 -0
- data/lib/travis/cli/parser.rb +43 -0
- data/lib/travis/cli/pubkey.rb +30 -0
- data/lib/travis/cli/raw.rb +20 -0
- data/lib/travis/cli/repo_command.rb +154 -0
- data/lib/travis/cli/report.rb +101 -0
- data/lib/travis/cli/repos.rb +53 -0
- data/lib/travis/cli/requests.rb +47 -0
- data/lib/travis/cli/restart.rb +18 -0
- data/lib/travis/cli/settings.rb +79 -0
- data/lib/travis/cli/setup/anynines.rb +21 -0
- data/lib/travis/cli/setup/appfog.rb +19 -0
- data/lib/travis/cli/setup/artifacts.rb +23 -0
- data/lib/travis/cli/setup/biicode.rb +19 -0
- data/lib/travis/cli/setup/cloud_66.rb +20 -0
- data/lib/travis/cli/setup/cloud_control.rb +21 -0
- data/lib/travis/cli/setup/cloud_files.rb +20 -0
- data/lib/travis/cli/setup/cloud_foundry.rb +23 -0
- data/lib/travis/cli/setup/code_deploy.rb +55 -0
- data/lib/travis/cli/setup/deis.rb +20 -0
- data/lib/travis/cli/setup/divshot.rb +18 -0
- data/lib/travis/cli/setup/elastic_beanstalk.rb +23 -0
- data/lib/travis/cli/setup/engine_yard.rb +24 -0
- data/lib/travis/cli/setup/gcs.rb +22 -0
- data/lib/travis/cli/setup/hackage.rb +18 -0
- data/lib/travis/cli/setup/heroku.rb +20 -0
- data/lib/travis/cli/setup/modulus.rb +18 -0
- data/lib/travis/cli/setup/ninefold.rb +20 -0
- data/lib/travis/cli/setup/nodejitsu.rb +27 -0
- data/lib/travis/cli/setup/npm.rb +20 -0
- data/lib/travis/cli/setup/open_shift.rb +20 -0
- data/lib/travis/cli/setup/opsworks.rb +22 -0
- data/lib/travis/cli/setup/pypi.rb +22 -0
- data/lib/travis/cli/setup/releases.rb +35 -0
- data/lib/travis/cli/setup/ruby_gems.rb +25 -0
- data/lib/travis/cli/setup/s3.rb +25 -0
- data/lib/travis/cli/setup/sauce_connect.rb +21 -0
- data/lib/travis/cli/setup/service.rb +73 -0
- data/lib/travis/cli/setup.rb +66 -0
- data/lib/travis/cli/show.rb +57 -0
- data/lib/travis/cli/sshkey.rb +118 -0
- data/lib/travis/cli/status.rb +19 -0
- data/lib/travis/cli/sync.rb +30 -0
- data/lib/travis/cli/token.rb +14 -0
- data/lib/travis/cli/version.rb +17 -0
- data/lib/travis/cli/whatsup.rb +30 -0
- data/lib/travis/cli/whoami.rb +15 -0
- data/lib/travis/cli.rb +126 -0
- data/lib/travis/client/account.rb +56 -0
- data/lib/travis/client/artifact.rb +88 -0
- data/lib/travis/client/auto_login.rb +45 -0
- data/lib/travis/client/broadcast.rb +14 -0
- data/lib/travis/client/build.rb +47 -0
- data/lib/travis/client/cache.rb +25 -0
- data/lib/travis/client/commit.rb +28 -0
- data/lib/travis/client/entity.rb +238 -0
- data/lib/travis/client/env_var.rb +102 -0
- data/lib/travis/client/error.rb +38 -0
- data/lib/travis/client/has_uuid.rb +13 -0
- data/lib/travis/client/job.rb +61 -0
- data/lib/travis/client/lint_result.rb +25 -0
- data/lib/travis/client/listener.rb +183 -0
- data/lib/travis/client/methods.rb +104 -0
- data/lib/travis/client/namespace.rb +85 -0
- data/lib/travis/client/not_loadable.rb +13 -0
- data/lib/travis/client/repository.rb +224 -0
- data/lib/travis/client/request.rb +36 -0
- data/lib/travis/client/restartable.rb +23 -0
- data/lib/travis/client/session.rb +339 -0
- data/lib/travis/client/settings.rb +25 -0
- data/lib/travis/client/singleton_setting.rb +36 -0
- data/lib/travis/client/ssh_key.rb +11 -0
- data/lib/travis/client/states.rb +98 -0
- data/lib/travis/client/user.rb +67 -0
- data/lib/travis/client/weak_entity.rb +26 -0
- data/lib/travis/client.rb +38 -0
- data/lib/travis/pro/auto_login.rb +3 -0
- data/lib/travis/pro.rb +5 -0
- data/lib/travis/tools/assets.rb +21 -0
- data/lib/travis/tools/completion.rb +54 -0
- data/lib/travis/tools/formatter.rb +50 -0
- data/lib/travis/tools/github.rb +293 -0
- data/lib/travis/tools/notification.rb +69 -0
- data/lib/travis/tools/safe_string.rb +22 -0
- data/lib/travis/tools/ssl_key.rb +48 -0
- data/lib/travis/tools/system.rb +88 -0
- data/lib/travis/version.rb +3 -0
- data/lib/travis.rb +8 -0
- data/spec/cli/api_command_spec.rb +38 -0
- data/spec/cli/cancel_spec.rb +15 -0
- data/spec/cli/encrypt_spec.rb +49 -0
- data/spec/cli/endpoint_spec.rb +39 -0
- data/spec/cli/help_spec.rb +33 -0
- data/spec/cli/history_spec.rb +38 -0
- data/spec/cli/init_spec.rb +227 -0
- data/spec/cli/login_spec.rb +13 -0
- data/spec/cli/logs_spec.rb +8 -0
- data/spec/cli/open_spec.rb +33 -0
- data/spec/cli/repo_command_spec.rb +25 -0
- data/spec/cli/restart_spec.rb +15 -0
- data/spec/cli/setup_spec.rb +5 -0
- data/spec/cli/show_spec.rb +9 -0
- data/spec/cli/status_spec.rb +28 -0
- data/spec/cli/token_spec.rb +22 -0
- data/spec/cli/version_spec.rb +18 -0
- data/spec/cli/whoami_spec.rb +34 -0
- data/spec/client/account_spec.rb +32 -0
- data/spec/client/auto_login_spec.rb +25 -0
- data/spec/client/broadcast_spec.rb +10 -0
- data/spec/client/build_spec.rb +31 -0
- data/spec/client/commit_spec.rb +22 -0
- data/spec/client/job_spec.rb +30 -0
- data/spec/client/methods_spec.rb +15 -0
- data/spec/client/namespace_spec.rb +19 -0
- data/spec/client/repository_spec.rb +39 -0
- data/spec/client/session_spec.rb +165 -0
- data/spec/client/user_spec.rb +16 -0
- data/spec/client_spec.rb +17 -0
- data/spec/pro_spec.rb +10 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/support/fake_api.rb +731 -0
- data/spec/support/fake_github.rb +24 -0
- data/spec/support/fake_travis_config.yml +14 -0
- data/spec/support/helpers.rb +45 -0
- data/spec/travis_spec.rb +10 -0
- data/travis.gemspec +371 -0
- metadata +534 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require 'travis/client'
|
|
2
|
+
|
|
3
|
+
module Travis
|
|
4
|
+
module Client
|
|
5
|
+
class Job < Entity
|
|
6
|
+
include States, Restartable
|
|
7
|
+
preloadable
|
|
8
|
+
|
|
9
|
+
# @!parse attr_reader :repository_id, :build_id, :commit_id, :log_id, :number, :config, :state, :started_at, :finished_at, :queue, :allow_failure, :tags
|
|
10
|
+
attributes :repository_id, :build_id, :commit_id, :log_id, :number, :config, :state, :started_at, :finished_at, :queue, :allow_failure, :tags
|
|
11
|
+
time :started_at, :finished_at
|
|
12
|
+
|
|
13
|
+
alias allow_failure? allow_failure
|
|
14
|
+
|
|
15
|
+
# @!parse attr_reader :commit, :repository, :build
|
|
16
|
+
has :commit, :repository, :build, :log
|
|
17
|
+
|
|
18
|
+
one :job
|
|
19
|
+
many :jobs
|
|
20
|
+
|
|
21
|
+
def pull_request?
|
|
22
|
+
build.pull_request?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def push?
|
|
26
|
+
build.push?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def branch_info
|
|
30
|
+
build.branch_info
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def allow_failures?
|
|
34
|
+
return false unless config.include? 'matrix' and config['matrix'].include? 'allow_failures'
|
|
35
|
+
config['matrix']['allow_failures'].any? do |allow|
|
|
36
|
+
allow.all? { |key, value| config[key] == value }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def duration
|
|
41
|
+
attributes['duration'] ||= begin
|
|
42
|
+
start = started_at || Time.now
|
|
43
|
+
finish = finished_at || Time.now
|
|
44
|
+
(finish - start).to_i
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def delete_log(reason = {})
|
|
49
|
+
log.delete_body(reason)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def pusher_channels
|
|
53
|
+
build.pusher_channels + ["job-#{id}"]
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def inspect_info
|
|
57
|
+
"#{repository.slug}##{number}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Travis
|
|
2
|
+
module Client
|
|
3
|
+
class LintResult
|
|
4
|
+
Warning = Struct.new(:key, :message)
|
|
5
|
+
attr_accessor :warnings
|
|
6
|
+
|
|
7
|
+
def initialize(payload)
|
|
8
|
+
@warnings = []
|
|
9
|
+
payload = payload['lint'] if payload['lint']
|
|
10
|
+
|
|
11
|
+
Array(payload['warnings']).each do |warning|
|
|
12
|
+
@warnings << Warning.new(warning['key'], warning['message'])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def warnings?
|
|
17
|
+
warnings.any?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def ok?
|
|
21
|
+
!warnings?
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
require 'travis/client'
|
|
2
|
+
require 'forwardable'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
if require 'pusher-client'
|
|
6
|
+
# it's us that has been loading pusher-client
|
|
7
|
+
# so let's assume we can mess with it - yay for global state
|
|
8
|
+
PusherClient.logger.level = 5
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
module Travis
|
|
12
|
+
module Client
|
|
13
|
+
class Listener
|
|
14
|
+
class Socket < PusherClient::Socket
|
|
15
|
+
attr_accessor :session, :signatures
|
|
16
|
+
def initialize(application_key, options = {})
|
|
17
|
+
@session = options.fetch(:session)
|
|
18
|
+
@signatures = {}
|
|
19
|
+
super
|
|
20
|
+
|
|
21
|
+
bind('pusher:error') do |data|
|
|
22
|
+
handle_error(data)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def subscribe_all
|
|
27
|
+
# bulk auth on connect
|
|
28
|
+
fetch_auth(*channels.channels.keys)
|
|
29
|
+
super
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def fetch_auth(*channels)
|
|
33
|
+
channels.select! { |c| signatures[c].nil? if c.start_with? 'private-' }
|
|
34
|
+
signatures.merge! session.post_raw('/pusher/auth', :channels => channels, :socket_id => socket_id)['channels'] if channels.any?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def get_private_auth(channel)
|
|
38
|
+
fetch_auth(channel.name)
|
|
39
|
+
signatures[channel.name]
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def handle_error(data)
|
|
43
|
+
code, message = data["code"], data["message"] if data.is_a? Hash
|
|
44
|
+
message ||= data.inspect
|
|
45
|
+
|
|
46
|
+
case code
|
|
47
|
+
when 4100 then reconnect(1)
|
|
48
|
+
when 4200, 4201, 4202 then reconnect
|
|
49
|
+
else raise Travis::Client::Error, "Pusher error: %s (code: %p)" % [message, code]
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def reconnect(delay = nil)
|
|
54
|
+
disconnect if connected
|
|
55
|
+
sleep delay if delay and delay > 0
|
|
56
|
+
connect
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
EVENTS = %w[
|
|
61
|
+
build:created build:started build:finished
|
|
62
|
+
job:created job:started job:log job:finished
|
|
63
|
+
]
|
|
64
|
+
|
|
65
|
+
Event = Struct.new(:type, :repository, :build, :job, :payload)
|
|
66
|
+
|
|
67
|
+
class EntityListener
|
|
68
|
+
attr_reader :listener, :entities
|
|
69
|
+
|
|
70
|
+
extend Forwardable
|
|
71
|
+
def_delegators :listener, :disconnect, :on_connect, :subscribe
|
|
72
|
+
|
|
73
|
+
def initialize(listener, entities)
|
|
74
|
+
@listener, @entities = listener, Array(entities)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def on(*events)
|
|
78
|
+
listener.on(*events) { |e| yield(e) if dispatch?(e) }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
def dispatch?(event)
|
|
84
|
+
entities.include? event.repository or
|
|
85
|
+
entities.include? event.build or
|
|
86
|
+
entities.include? event.job
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
attr_reader :session, :socket
|
|
91
|
+
|
|
92
|
+
def initialize(session)
|
|
93
|
+
@session = session
|
|
94
|
+
@socket = Socket.new(pusher_key, pusher_options)
|
|
95
|
+
@channels = []
|
|
96
|
+
@callbacks = []
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def subscribe(*entities)
|
|
100
|
+
entities = entities.map do |entity|
|
|
101
|
+
entity = entity.pusher_entity while entity.respond_to? :pusher_entity
|
|
102
|
+
@channels.concat(entity.pusher_channels)
|
|
103
|
+
entity
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
yield entities.any? ? EntityListener.new(self, entities) : self if block_given?
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def on(*events, &block)
|
|
110
|
+
events = events.flat_map { |e| e.respond_to?(:to_str) ? e.to_str : EVENTS.grep(e) }.uniq
|
|
111
|
+
events.each { |e| @callbacks << [e, block] }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def on_connect
|
|
115
|
+
socket.bind('pusher:connection_established') { yield }
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def listen
|
|
119
|
+
@channels = default_channels if @channels.empty?
|
|
120
|
+
@channels.map! { |c| c.start_with?('private-') ? c : "private-#{c}" } if session.private_channels?
|
|
121
|
+
@channels.uniq.each { |c| socket.subscribe(c) }
|
|
122
|
+
@callbacks.each { |e,b| socket.bind(e) { |d| dispatch(e, d, &b) } }
|
|
123
|
+
socket.connect
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def disconnect
|
|
127
|
+
socket.disconnect
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
private
|
|
131
|
+
|
|
132
|
+
def dispatch(type, json)
|
|
133
|
+
payload = JSON.parse(json)
|
|
134
|
+
entities = session.load format_payload(type, payload)
|
|
135
|
+
yield Event.new(type, entities['repository'], entities['build'], entities['job'], payload)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def format_payload(type, payload)
|
|
139
|
+
case type
|
|
140
|
+
when "job:log" then format_log(payload)
|
|
141
|
+
when /job:/ then format_job(payload)
|
|
142
|
+
else payload
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def format_job(payload)
|
|
147
|
+
build = { "id" => payload["build_id"], "repository_id" => payload["repository_id"] }
|
|
148
|
+
repo = { "id" => payload["repository_id"], "slug" => payload["repository_slug"] }
|
|
149
|
+
build["number"] = payload["number"][/^[^\.]+/] if payload["number"]
|
|
150
|
+
{ "job" => payload, "build" => build, "repository" => repo }
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def format_log(payload)
|
|
154
|
+
job = session.job(payload['id'])
|
|
155
|
+
{ "job" => { "id" => job.id }, "build" => { "id" => job.build.id }, "repository" => { "id" => job.repository.id } }
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def default_channels
|
|
159
|
+
return ['common'] if session.access_token.nil?
|
|
160
|
+
session.user.channels
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def pusher_options
|
|
164
|
+
pusher_options = session.config['pusher'] || {}
|
|
165
|
+
encrypted = pusher_options['scheme'] != 'http'
|
|
166
|
+
options = { :encrypted => encrypted, :session => session }
|
|
167
|
+
options[:ws_host] = pusher_options['host'] if pusher_options['host']
|
|
168
|
+
options[:wss_port] = pusher_options['port'] if encrypted and pusher_options['port']
|
|
169
|
+
options[:ws_port] = pusher_options['port'] if !encrypted and pusher_options['port']
|
|
170
|
+
options[:ws_path] = pusher_options['path'] if pusher_options['path']
|
|
171
|
+
options[:ws_path] = '/' << options[:ws_path] unless options[:ws_path].nil? or options[:ws_path].start_with? '/'
|
|
172
|
+
options[:ssl_verify] = session.ssl.fetch(:verify, true)
|
|
173
|
+
options
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def pusher_key
|
|
177
|
+
session.config.fetch('pusher').fetch('key')
|
|
178
|
+
rescue IndexError
|
|
179
|
+
raise Travis::Client::Error, "#{session.api_endpoint} is missing pusher key"
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
require 'travis/client'
|
|
2
|
+
require 'yaml'
|
|
3
|
+
|
|
4
|
+
module Travis
|
|
5
|
+
module Client
|
|
6
|
+
module Methods
|
|
7
|
+
def access_token
|
|
8
|
+
session.access_token
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def access_token=(token)
|
|
12
|
+
session.access_token = token
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def api_endpoint
|
|
16
|
+
session.uri
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def github_auth(github_token)
|
|
20
|
+
reply = session.post_raw("/auth/github", :github_token => github_token)
|
|
21
|
+
session.access_token = reply["access_token"]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def explicit_api_endpoint?
|
|
25
|
+
@explicit_api_endpoint ||= false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def api_endpoint=(uri)
|
|
29
|
+
@explicit_api_endpoint = true
|
|
30
|
+
session.uri = uri
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def repos(params = {})
|
|
34
|
+
session.find_many(Repository, params)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def repo(id_or_slug)
|
|
38
|
+
session.find_one(Repository, id_or_slug)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def build(id)
|
|
42
|
+
session.find_one(Build, id)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def job(id)
|
|
46
|
+
session.find_one(Job, id)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def artifact(id)
|
|
50
|
+
session.find_one(Artifact, id)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
alias log artifact
|
|
54
|
+
|
|
55
|
+
def user
|
|
56
|
+
session.find_one(User)
|
|
57
|
+
rescue NotFound
|
|
58
|
+
raise NotLoggedIn, 'currently not logged in'
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def account(name)
|
|
62
|
+
session.find_one(Account, name)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def accounts
|
|
66
|
+
session.find_many(Account, :all => true)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def broadcasts
|
|
70
|
+
session.find_many(Broadcast)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def restart(entity)
|
|
74
|
+
# btw, internally we call this reset, not restart, as it resets the state machine
|
|
75
|
+
# but we thought that would be too confusing
|
|
76
|
+
raise Error, "cannot restart a #{entity.class.one}" unless entity.restartable?
|
|
77
|
+
session.post_raw('/requests', "#{entity.class.one}_id" => entity.id)
|
|
78
|
+
entity.reload
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def cancel(entity)
|
|
82
|
+
raise Error, "cannot cancel a #{entity.class.one}" unless entity.cancelable?
|
|
83
|
+
session.post_raw("/#{entity.class.many}/#{entity.id}/cancel")
|
|
84
|
+
entity.reload
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def listen(*entities, &block)
|
|
88
|
+
listener = Listener.new(session)
|
|
89
|
+
listener.subscribe(*entities, &block)
|
|
90
|
+
listener.listen
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def lint(body)
|
|
94
|
+
body = body.to_yaml unless body.is_a? String
|
|
95
|
+
result = session.post_raw('/lint', 'content' => body)
|
|
96
|
+
LintResult.new(result)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def hooks
|
|
100
|
+
session.get('hooks')['hooks']
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require 'travis/client'
|
|
2
|
+
|
|
3
|
+
module Travis
|
|
4
|
+
module Client
|
|
5
|
+
class Namespace < Module
|
|
6
|
+
class Curry < Module
|
|
7
|
+
attr_accessor :namespace, :type
|
|
8
|
+
|
|
9
|
+
def initialize(namespace, type)
|
|
10
|
+
@namespace, @type = namespace, type
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def find_one(id = nil)
|
|
14
|
+
result = session.find_one(type, id)
|
|
15
|
+
result.curry = self
|
|
16
|
+
result
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def current
|
|
20
|
+
result = session.find_one_or_many(type)
|
|
21
|
+
Array(result).each { |e| e.curry = self }
|
|
22
|
+
result
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def find_many(params = {})
|
|
26
|
+
session.find_many(type, params).each do |entity|
|
|
27
|
+
entity.curry = self
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
alias find find_one
|
|
32
|
+
alias find_all find_many
|
|
33
|
+
|
|
34
|
+
def clear_cache
|
|
35
|
+
session.clear_cache
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def clear_cache!
|
|
39
|
+
session.clear_cache!
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def session
|
|
45
|
+
namespace.session
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
include Methods
|
|
50
|
+
attr_accessor :session
|
|
51
|
+
|
|
52
|
+
def initialize(session = nil)
|
|
53
|
+
session = Travis::Client.new(session || {}) unless session.is_a? Session
|
|
54
|
+
@session = session
|
|
55
|
+
|
|
56
|
+
Entity.subclasses.each do |subclass|
|
|
57
|
+
name = subclass.name[/[^:]+$/]
|
|
58
|
+
const_set(name, Curry.new(self, subclass))
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def included(klass)
|
|
63
|
+
fix_names(klass)
|
|
64
|
+
delegate_session(klass)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def fix_names(klass)
|
|
70
|
+
constants.each do |name|
|
|
71
|
+
const = klass.const_get(name)
|
|
72
|
+
klass.const_set(name, const) if const == const_get(name)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def delegate_session(klass)
|
|
77
|
+
return if klass == Object or klass == Kernel
|
|
78
|
+
klass.extend(Methods)
|
|
79
|
+
namespace = self
|
|
80
|
+
klass.define_singleton_method(:session) { namespace.session }
|
|
81
|
+
klass.define_singleton_method(:session=) { |value| namespace.session = value }
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
require 'travis/client'
|
|
2
|
+
require 'travis/tools/ssl_key'
|
|
3
|
+
|
|
4
|
+
module Travis
|
|
5
|
+
module Client
|
|
6
|
+
class Repository < Entity
|
|
7
|
+
class Key
|
|
8
|
+
attr_reader :to_s, :fingerprint
|
|
9
|
+
|
|
10
|
+
def initialize(data, fingerprint)
|
|
11
|
+
@to_s = data
|
|
12
|
+
@fingerprint = fingerprint
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def encrypt(value)
|
|
16
|
+
encrypted = to_rsa.public_encrypt(value)
|
|
17
|
+
Base64.encode64(encrypted).gsub(/\s+/, "")
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_rsa
|
|
21
|
+
Tools::SSLKey.public_rsa_key(to_s)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def to_ssh
|
|
25
|
+
Tools::SSLKey.rsa_ssh(to_rsa)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def ==(other)
|
|
29
|
+
other.to_s == self
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
include States
|
|
34
|
+
preloadable
|
|
35
|
+
|
|
36
|
+
# @!parse attr_reader :slug, :description
|
|
37
|
+
attributes :slug, :active, :private, :admin, :description, :last_build_id, :last_build_number, :last_build_state, :last_build_duration, :last_build_started_at, :last_build_finished_at, :github_language
|
|
38
|
+
inspect_info :slug
|
|
39
|
+
|
|
40
|
+
time :last_build_finished_at, :last_build_started_at
|
|
41
|
+
|
|
42
|
+
one :repo
|
|
43
|
+
many :repos
|
|
44
|
+
aka :repository, :permissions, :admin, :pull, :push, :hooks
|
|
45
|
+
|
|
46
|
+
has_singleton :ssh_key
|
|
47
|
+
|
|
48
|
+
def initialize(*)
|
|
49
|
+
super
|
|
50
|
+
attributes['active'] = attributes['private'] = attributes['admin'] = nil
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def public_key
|
|
54
|
+
attributes["public_key"] ||= begin
|
|
55
|
+
payload = session.get_raw("/repos/#{id}/key")
|
|
56
|
+
Key.new(payload.fetch('key'), payload['fingerprint'])
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def name
|
|
61
|
+
slug[/[^\/]+$/]
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def public_key=(key)
|
|
65
|
+
# ignored
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
alias key public_key
|
|
69
|
+
alias key= public_key=
|
|
70
|
+
|
|
71
|
+
def encrypt(value)
|
|
72
|
+
key.encrypt(value)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @!parse attr_reader :last_build
|
|
76
|
+
def last_build
|
|
77
|
+
return unless last_build_id
|
|
78
|
+
attributes['last_build'] ||= begin
|
|
79
|
+
last_build = session.find_one(Build, last_build_id)
|
|
80
|
+
last_build.number = last_build_number
|
|
81
|
+
last_build.state = last_build_state
|
|
82
|
+
last_build.duration = last_build_duration
|
|
83
|
+
last_build.started_at = last_build_started_at
|
|
84
|
+
last_build.finished_at = last_build_finished_at
|
|
85
|
+
last_build.repository_id = id
|
|
86
|
+
last_build
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def builds(params = nil)
|
|
91
|
+
return each_build unless params
|
|
92
|
+
session.find_many(Build, params.merge(:repository_id => id))
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def build(number)
|
|
96
|
+
builds(:number => number.to_s).first
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def recent_builds
|
|
100
|
+
builds({})
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def last_on_branch(name = nil)
|
|
104
|
+
return branch(name) if name
|
|
105
|
+
attributes['last_on_branch'] ||= session.get('branches', :repository_id => id)['branches']
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def branches
|
|
109
|
+
last_on_branch.map { |b| { b.commit.branch => b } }.inject(:merge)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def branch(name)
|
|
113
|
+
attributes['branches'] ||= {}
|
|
114
|
+
attributes['branches'][name] ||= begin
|
|
115
|
+
build = attributes['last_on_branch'].detect { |b| b.commit.branch == name.to_s } if attributes['last_on_branch']
|
|
116
|
+
build || session.get("/repos/#{id}/branches/#{name}")['branch']
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def each_build(params = nil, &block)
|
|
121
|
+
return enum_for(__method__, params) unless block_given?
|
|
122
|
+
params ||= {}
|
|
123
|
+
chunk = builds(params)
|
|
124
|
+
until chunk.empty?
|
|
125
|
+
chunk.each(&block)
|
|
126
|
+
number = chunk.last.number
|
|
127
|
+
chunk = number == '1' ? [] : builds(params.merge(:after_number => number))
|
|
128
|
+
end
|
|
129
|
+
self
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def job(number)
|
|
133
|
+
build_number = number.to_s[/^\d+/] or return nil
|
|
134
|
+
build = build(build_number) or return nil
|
|
135
|
+
job = build.jobs.detect { |j| j.number == number } if number != build_number
|
|
136
|
+
job ||= build.jobs.first if build and build.jobs.size == 1
|
|
137
|
+
job
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def set_hook(flag)
|
|
141
|
+
result = session.put_raw('/hooks/', :hook => { :id => id, :active => flag })
|
|
142
|
+
result['result']
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def disable
|
|
146
|
+
set_hook(false)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def enable
|
|
150
|
+
set_hook(true)
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def pusher_channels
|
|
154
|
+
attributes['pusher_channels'] ||= if session.private_channels?
|
|
155
|
+
["user-#{session.user.id}", "repo-#{id}"]
|
|
156
|
+
else
|
|
157
|
+
["common"]
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def member?
|
|
162
|
+
session.user.repositories.include? self
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def owner_name
|
|
166
|
+
slug[/^[^\/]+/]
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def owner
|
|
170
|
+
session.account(owner_name)
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def requests
|
|
174
|
+
attributes['requests'] ||= session.find_many(Request, :repository_id => id)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def settings
|
|
178
|
+
attributes['settings'] ||= begin
|
|
179
|
+
settings = session.get("/repos/#{id}/settings")['settings']
|
|
180
|
+
settings.repository = self
|
|
181
|
+
settings
|
|
182
|
+
end
|
|
183
|
+
rescue Travis::Client::NotFound
|
|
184
|
+
raise Travis::Client::Error, "not allowed to access settings"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def caches(params = {})
|
|
188
|
+
session.get("/repos/#{id}/caches", params)['caches']
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def delete_caches(params = {})
|
|
192
|
+
session.delete("/repos/#{id}/caches", params)['caches']
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def active?
|
|
196
|
+
# TODO remove once active is properly synced and exposed by api
|
|
197
|
+
return active unless active.nil?
|
|
198
|
+
last_build_id?
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def admin?(user = session.user)
|
|
202
|
+
user.admin_access? self
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def push?(user = session.user)
|
|
206
|
+
user.push_access? self
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
def pull?(user = session.user)
|
|
210
|
+
user.pull_access? self
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
def env_vars
|
|
214
|
+
attributes['env_vars'] ||= EnvVar::List.new(self)
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
private
|
|
218
|
+
|
|
219
|
+
def state
|
|
220
|
+
last_build_state
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
end
|