Skip to content

Commit f52a036

Browse files
authored
Switch to VCS instead of direct GH calls (#1168)
1 parent 1d3a6c1 commit f52a036

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+332
-1481
lines changed

Gemfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ gem 'rack', '>= 2.1.4'
2828
gem 'rack-contrib'
2929
gem 'rack-cache', git: 'https://github.com/rtomayko/rack-cache'
3030
gem 'rack-attack', '~> 5.0'
31-
gem 'gh', git: 'https://github.com/travis-ci/gh'
3231
gem 'bunny', '~> 2.9.2'
3332
gem 'dalli'
3433
gem 'pry'
@@ -56,6 +55,7 @@ gem 'opencensus-stackdriver'
5655

5756
gem 'faraday'
5857
gem 'faraday_middleware'
58+
gem 'net-http-persistent'
5959

6060
gem 'knapsack'
6161

Gemfile.lock

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,6 @@ GIT
1919
rack-cache (1.11.0)
2020
rack (>= 0.4)
2121

22-
GIT
23-
remote: https://github.com/travis-ci/gh
24-
revision: 66449dc14db5eee0a24a4dbcb85e52dd5b63513f
25-
specs:
26-
gh (0.15.2)
27-
addressable (~> 2.4)
28-
backports
29-
faraday (~> 0.8)
30-
multi_json (~> 1.0)
31-
net-http-persistent (~> 2.9)
32-
net-http-pipeline
33-
3422
GIT
3523
remote: https://github.com/travis-ci/marginalia
3624
revision: 46bbe301640efb5ea81828cb7deeaf874516de78
@@ -283,8 +271,8 @@ GEM
283271
mustermann (1.1.1)
284272
ruby2_keywords (~> 0.0.1)
285273
nakayoshi_fork (0.0.4)
286-
net-http-persistent (2.9.4)
287-
net-http-pipeline (1.0.1)
274+
net-http-persistent (4.0.0)
275+
connection_pool (~> 2.2)
288276
nokogiri (1.10.9)
289277
mini_portile2 (~> 2.4.0)
290278
opencensus (0.5.0)
@@ -439,7 +427,6 @@ DEPENDENCIES
439427
fog-aws (~> 0.12.0)
440428
fog-google (~> 0.4.2)
441429
foreman
442-
gh!
443430
google-api-client (~> 0.9.4)
444431
hashdiff
445432
hashr
@@ -457,6 +444,7 @@ DEPENDENCIES
457444
multi_json
458445
mustermann
459446
nakayoshi_fork
447+
net-http-persistent
460448
opencensus
461449
opencensus-stackdriver
462450
pg (~> 0.21)

bin/migrate-hooks

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ require 'date'
1313
require 'stringio'
1414
require 'thread'
1515
require 'travis'
16-
require 'travis/api/v3/github'
1716
require 'travis/config/defaults'
1817
require 'travis/model/repository'
1918

@@ -55,7 +54,7 @@ class Migrate
5554
ids = query.ids
5655
ids.sort.reverse.each { |id| queue.push(id) }
5756
puts "Queued #{ids.size} repos"
58-
57+
5958
sleep 5
6059

6160
# Start num_workers threads and start running off the queue
@@ -115,13 +114,13 @@ class Migrate
115114
puts "No webhook found but service hook found, syncing repo #{repo.slug} active attr"
116115
puts "Save failed" unless repo.update(active: service_hook['active'])
117116
end
118-
117+
119118
# Only set webhook for repos with an active service hook
120119
if (service_hook && service_hook['active'])
121120
puts "Found active service hook for #{repo.slug}, setting webhook"
122121
gh.set_hook(repo, true)
123122
end
124-
123+
125124
migrated = true
126125
break
127126
rescue => e

config.ru

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ require 'travis/api/app'
1010
require 'core_ext/module/load_constants'
1111

1212
models = Travis::Model.constants.map(&:to_s)
13-
only = [/^(ActiveRecord|ActiveModel|Travis|GH|#{models.join('|')})/]
14-
skip = ['Travis::Memory', 'GH::ResponseWrapper', 'Travis::Helpers::Legacy', 'GH::FaradayAdapter::EMSynchrony']
13+
only = [/^(ActiveRecord|ActiveModel|Travis|#{models.join('|')})/]
14+
skip = ['Travis::Memory', 'Travis::Helpers::Legacy']
1515

16-
[Travis::Api, Travis, GH].each do |target|
16+
[Travis::Api, Travis].each do |target|
1717
target.load_constants! :only => only, :skip => skip, :debug => false
1818
end
1919

lib/travis.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ def setup(options = {})
4242

4343
Travis.logger.info("Setting up module Travis")
4444

45-
Github.setup
4645
Services.register
4746
Github::Services.register
4847
end

lib/travis/api/app.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
require 'travis/api/attack'
1818
require 'active_record'
1919
require 'redis'
20-
require 'gh'
2120
require 'raven'
2221
require 'raven/integrations/rack'
2322
require 'sidekiq'

lib/travis/api/app/endpoint/authorization.rb

Lines changed: 4 additions & 204 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
require 'faraday_middleware'
44
require 'securerandom'
55
require 'travis/api/app'
6-
require 'travis/github/education'
7-
require 'travis/github/oauth'
86
require 'travis/remote_vcs/user'
97
require 'travis/remote_vcs/response_error'
108
require 'uri'
@@ -92,22 +90,20 @@ class Authorization < Endpoint
9290
end
9391

9492
# For new provider method
95-
# renew_access_token(token: params[:github_token], app_id: 1, provider: :github)
96-
{ 'access_token' => github_to_travis(params[:github_token], app_id: 1, drop_token: true) }
93+
renew_access_token(token: params[:github_token], app_id: 1, provider: :github)
9794
end
9895

99-
# Endpoint for making sure user authorized Travis CI to access GitHub.
96+
# Endpoint for making sure user authorized Travis CI to access VCS provider.
10097
# There are no restrictions on where to redirect to after handshake.
10198
# However, no information whatsoever is being sent with the redirect.
10299
#
103100
# Parameters:
104101
#
105102
# * **redirect_uri**: URI to redirect to after handshake.
106103
get '/handshake/?:provider?' do
107-
method = org? ? :handshake : :vcs_handshake
108104
params[:provider] ||= 'github'
109-
send(method) do |user, token, redirect_uri|
110-
if target_ok? redirect_uri
105+
vcs_handshake do |user, token, redirect_uri|
106+
if target_ok?(redirect_uri)
111107
content_type :html
112108
data = { user: user, token: token, uri: redirect_uri }
113109
erb(:post_payload, locals: data)
@@ -151,42 +147,6 @@ def log_with_request_id(line)
151147
Travis.logger.info "#{line} <request_id=#{request_id}>"
152148
end
153149

154-
def handshake
155-
config = Travis.config.oauth2.to_h
156-
endpoint = Addressable::URI.parse(config[:authorization_server])
157-
values = {
158-
client_id: config[:client_id],
159-
scope: config[:scope],
160-
redirect_uri: oauth_endpoint
161-
}
162-
163-
log_with_request_id("[handshake] Starting handshake")
164-
165-
if params[:code]
166-
unless state_ok?(params[:state])
167-
log_with_request_id("[handshake] Handshake failed (state mismatch)")
168-
handle_invalid_response
169-
return
170-
end
171-
172-
endpoint.path = config[:access_token_path]
173-
values[:state] = params[:state]
174-
values[:code] = params[:code]
175-
values[:client_secret] = config[:client_secret]
176-
github_token = get_token(endpoint.to_s, values)
177-
user = user_for_github_token(github_token)
178-
token = generate_token(user: user, app_id: 0)
179-
payload = params[:state].split(":::", 2)[1]
180-
update_first_login(user)
181-
yield serialize_user(user), token, payload
182-
else
183-
values[:state] = create_state
184-
endpoint.path = config[:authorize_path]
185-
endpoint.query_values = values
186-
redirect to(endpoint.to_s)
187-
end
188-
end
189-
190150
# VCS HANDSHAKE START
191151

192152
def remote_vcs_user
@@ -274,171 +234,11 @@ def handle_invalid_response
274234
redirect to("https://#{Travis.config.host}/")
275235
end
276236

277-
def create_state
278-
state = SecureRandom.urlsafe_base64(16)
279-
redis.sadd('github:states', state)
280-
redis.expire('github:states', 1800)
281-
payload = params[:origin] || params[:redirect_uri]
282-
state << ":::" << payload if payload
283-
response.set_cookie(cookie_name, state)
284-
state
285-
end
286-
287237
def state_ok?(state, provider = :github)
288238
cookie_state = request.cookies[cookie_name(provider)]
289239
state == cookie_state and redis.srem('github:states', state.to_s.split(":::", 1))
290240
end
291241

292-
def github_to_travis(token, options = {})
293-
drop_token = options.delete(:drop_token)
294-
generate_token options.merge(user: user_for_github_token(token, drop_token))
295-
end
296-
297-
class UserManager < Struct.new(:data, :token, :drop_token)
298-
include User::Renaming
299-
300-
attr_accessor :user
301-
302-
def initialize(*)
303-
super
304-
305-
@user = ::User.find_by_github_id(data['id'])
306-
end
307-
308-
def info(attributes = {})
309-
info = data.to_hash.slice('name', 'login', 'gravatar_id')
310-
info.merge! attributes.stringify_keys
311-
if Travis::Features.feature_active?(:education_data_sync) ||
312-
(user && Travis::Features.owner_active?(:education_data_sync, user))
313-
info['education'] = education
314-
end
315-
info['github_id'] ||= data['id']
316-
info['vcs_id'] ||= data['id']
317-
info
318-
end
319-
320-
def user_exists?
321-
user
322-
end
323-
324-
def education
325-
Travis::Github::Education.new(token.to_s).student?
326-
end
327-
328-
def fetch
329-
retried ||= false
330-
info = drop_token ? self.info : self.info(github_oauth_token: token)
331-
332-
ActiveRecord::Base.transaction do
333-
if user
334-
ensure_token_is_available
335-
rename_repos_owner(user.login, info['login'])
336-
user.update_attributes info
337-
else
338-
self.user = ::User.create! info
339-
end
340-
341-
Travis::Github::Oauth.update_scopes(user) # unless Travis.env == 'test'
342-
343-
nullify_logins(user.github_id, user.login)
344-
end
345-
346-
user
347-
rescue ActiveRecord::RecordNotUnique
348-
unless retried
349-
retried = true
350-
retry
351-
end
352-
end
353-
354-
def ensure_token_is_available
355-
unless user.tokens.first
356-
user.create_a_token
357-
end
358-
end
359-
end
360-
361-
def user_for_github_token(token, drop_token = false)
362-
data = GH.with(token: token.to_s, client_id: nil) { GH['user'] }
363-
scopes = parse_scopes data.headers['x-oauth-scopes']
364-
manager = UserManager.new(data, token, drop_token)
365-
366-
unless acceptable?(scopes, drop_token)
367-
# TODO: we should probably only redirect if this is a web
368-
# oauth request, are there any other possibilities to
369-
# consider?
370-
url = Travis.config.oauth2.insufficient_access_redirect_url
371-
url += "#existing-user" if manager.user_exists?
372-
redirect to(url)
373-
end
374-
375-
user = manager.fetch
376-
if user.nil?
377-
log_with_request_id("[handshake] Fetching user failed")
378-
halt 403, 'not a Travis user'
379-
end
380-
381-
Travis.run_service(:sync_user, user)
382-
383-
user
384-
rescue GH::Error
385-
# not a valid token actually, but we don't want to expose that info
386-
halt 403, 'not a Travis user'
387-
end
388-
389-
def get_token(endpoint, values)
390-
# Get base URL for when we setup Faraday since otherwise it'll ignore no_proxy
391-
url = URI.parse(endpoint)
392-
base_url = "#{url.scheme}://#{url.host}"
393-
http_options = {url: base_url, ssl: Travis.config.ssl.to_h.merge(Travis.config.github.ssl || {}).compact}
394-
395-
conn = Faraday.new(http_options) do |conn|
396-
conn.request :json
397-
conn.use :instrumentation
398-
conn.use OpenCensus::Trace::Integrations::FaradayMiddleware if Travis::Api::App::Middleware::OpenCensus.enabled?
399-
conn.adapter :net_http_persistent
400-
end
401-
response = conn.post(endpoint, values)
402-
403-
parameters = Addressable::URI.form_unencode(response.body)
404-
token_info = parameters.assoc("access_token")
405-
406-
unless token_info
407-
log_with_request_id("[handshake] Could not fetch token, github's response: status=#{response.status}, body=#{parameters.inspect} headers=#{response.headers.inspect}")
408-
halt 401, 'could not resolve github token'
409-
end
410-
token_info.last
411-
end
412-
413-
def parse_scopes(data)
414-
data.gsub(/\s/,'').split(',') if data
415-
end
416-
417-
def generate_token(options)
418-
AccessToken.create(options).token
419-
end
420-
421-
def acceptable?(scopes, lossy = false)
422-
Travis::Github::Oauth.wanted_scopes.all? do |scope|
423-
acceptable_scopes_for(scope, lossy).any? { |s| scopes.include? s }
424-
end
425-
end
426-
427-
def acceptable_scopes_for(scope, lossy = false)
428-
scopes = case scope = scope.to_s
429-
when /^(.+):/ then [$1, scope]
430-
when 'public_repo' then [scope, 'repo']
431-
else [scope]
432-
end
433-
434-
if lossy
435-
scopes << 'repo'
436-
scopes << 'public_repo' if lossy and scope != 'repo'
437-
end
438-
439-
scopes
440-
end
441-
442242
def post_message(payload)
443243
content_type :html
444244
erb(:post_message, locals: payload)

lib/travis/api/app/endpoint/home.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ class Home < Endpoint
1212
shorten_host: Travis.config.shorten_host,
1313
assets: Travis.config.assets.to_h,
1414
pusher: (Travis.config.pusher_ws || Travis.config.pusher.to_h || {}).to_hash.slice(:scheme, :host, :port, :path, :key, :secure, :private),
15-
github: { api_url: GH.current.api_host.to_s, scopes: Travis.config.oauth2.try(:scope).to_s.split(?,) },
1615
notifications: { webhook: { public_key: Travis.config.webhook.public_key } }
1716
set :check_auth, false
1817

lib/travis/api/app/services/schedule_request.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def enqueue_build_request
6060

6161
def payload
6262
data = params.merge(user: { id: current_user.id })
63-
data[:repository][:id] = repo.vcs_id || repo.github_id
63+
data[:repository][:id] = repo.vcs_id
6464
data[:repository][:vcs_type] = repo.vcs_type
6565
MultiJson.encode(data)
6666
end

0 commit comments

Comments
 (0)