travis-akerl 1.8.9
Sign up to get free protection for your applications and to get access to all the features.
- 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
|