Merge branch 'master' into rkh-performance

This commit is contained in:
Konstantin Haase 2012-09-28 16:11:28 +02:00
commit 1f3c1ae8ce
12 changed files with 158 additions and 94 deletions

View File

@ -7,6 +7,7 @@ gem 'travis-support', github: 'travis-ci/travis-support'
gem 'travis-core', github: 'travis-ci/travis-core', branch: 'sf-more-services' gem 'travis-core', github: 'travis-ci/travis-core', branch: 'sf-more-services'
gem 'hubble', github: 'roidrage/hubble' gem 'hubble', github: 'roidrage/hubble'
gem 'yard-sinatra', github: 'rkh/yard-sinatra' gem 'yard-sinatra', github: 'rkh/yard-sinatra'
gem 'rack-contrib', github: 'rack/rack-contrib'
gem 'gh', github: 'rkh/gh' gem 'gh', github: 'rkh/gh'
gem 'bunny' gem 'bunny'

View File

@ -4,6 +4,13 @@ GIT
specs: specs:
micro_migrations (0.0.1) micro_migrations (0.0.1)
GIT
remote: git://github.com/rack/rack-contrib.git
revision: b7e7c38fd02c3b5da91aa57af78b3f571c6ebcd0
specs:
rack-contrib (1.1.0)
rack (>= 0.9.1)
GIT GIT
remote: git://github.com/rkh/gh.git remote: git://github.com/rkh/gh.git
revision: affde20a4fecb1023f2e7031734b9386a76d22c2 revision: affde20a4fecb1023f2e7031734b9386a76d22c2
@ -25,15 +32,15 @@ GIT
GIT GIT
remote: git://github.com/roidrage/hubble.git remote: git://github.com/roidrage/hubble.git
revision: 8972b940a4f927927d2a4bdb250b3c98c04692a6 revision: f5e6301ac24eabeebaf8f4485d71cdcf93b2f3f8
specs: specs:
hubble (0.1.2) hubble (0.1.2)
faraday faraday
json (~> 1.6.5) json (~> 1.6)
GIT GIT
remote: git://github.com/travis-ci/travis-core.git remote: git://github.com/travis-ci/travis-core.git
revision: ea7a1678a0388e586ac4778a9b6ee56a11dfb0aa revision: 6c974f0c0ad529748e95222c3145a0f085311ad1
branch: sf-more-services branch: sf-more-services
specs: specs:
travis-core (0.0.1) travis-core (0.0.1)
@ -121,15 +128,15 @@ GEM
activesupport activesupport
faraday (0.8.4) faraday (0.8.4)
multipart-post (~> 1.1) multipart-post (~> 1.1)
foreman (0.59.0) foreman (0.60.0)
thor (>= 0.13.6) thor (>= 0.13.6)
hashr (0.0.22) hashr (0.0.22)
hike (1.2.1) hike (1.2.1)
hitimes (1.1.1) hitimes (1.1.1)
i18n (0.6.1) i18n (0.6.1)
journey (1.0.4) journey (1.0.4)
json (1.6.7) json (1.7.5)
listen (0.5.1) listen (0.5.2)
mail (2.4.4) mail (2.4.4)
i18n (>= 0.4.0) i18n (>= 0.4.0)
mime-types (~> 1.16) mime-types (~> 1.16)
@ -140,7 +147,7 @@ GEM
avl_tree (~> 1.1.2) avl_tree (~> 1.1.2)
hitimes (~> 1.1) hitimes (~> 1.1)
mime-types (1.19) mime-types (1.19)
mocha (0.12.4) mocha (0.12.5)
metaclass (~> 0.0.1) metaclass (~> 0.0.1)
multi_json (1.3.6) multi_json (1.3.6)
multipart-post (1.1.5) multipart-post (1.1.5)
@ -162,13 +169,11 @@ GEM
rack (1.4.1) rack (1.4.1)
rack-cache (1.2) rack-cache (1.2)
rack (>= 0.4) rack (>= 0.4)
rack-contrib (1.1.0)
rack (>= 0.9.1)
rack-protection (1.2.0) rack-protection (1.2.0)
rack rack
rack-ssl (1.3.2) rack-ssl (1.3.2)
rack rack
rack-test (0.6.1) rack-test (0.6.2)
rack (>= 1.0) rack (>= 1.0)
railties (3.2.8) railties (3.2.8)
actionpack (= 3.2.8) actionpack (= 3.2.8)
@ -212,7 +217,7 @@ GEM
hike (~> 1.2) hike (~> 1.2)
rack (~> 1.0) rack (~> 1.0)
tilt (~> 1.1, != 1.3.0) tilt (~> 1.1, != 1.3.0)
thin (1.4.1) thin (1.5.0)
daemons (>= 1.0.9) daemons (>= 1.0.9)
eventmachine (>= 0.12.6) eventmachine (>= 0.12.6)
rack (>= 1.0.0) rack (>= 1.0.0)
@ -235,6 +240,7 @@ DEPENDENCIES
hubble! hubble!
micro_migrations! micro_migrations!
mocha (~> 0.12) mocha (~> 0.12)
rack-contrib!
rake (~> 0.9.2) rake (~> 0.9.2)
rerun rerun
rspec (~> 2.11) rspec (~> 2.11)

39
config/newrelic.yml Normal file
View File

@ -0,0 +1,39 @@
---
staging:
error_collector:
capture_source: true
enabled: true
ignore_errors: ActionController::RoutingError
apdex_t: 0.5
ssl: false
monitor_mode: true
license_key: <%= ENV["NEW_RELIC_LICENSE_KEY"] %>
developer_mode: false
app_name: <%= ENV["NEW_RELIC_APP_NAME"] %>
transaction_tracer:
record_sql: obfuscated
enabled: true
stack_trace_threshold: 0.5
transaction_threshold: apdex_f
capture_params: false
log_level: info
production:
error_collector:
capture_source: true
enabled: true
ignore_errors: ActionController::RoutingError
apdex_t: 0.5
ssl: false
monitor_mode: true
license_key: <%= ENV["NEW_RELIC_LICENSE_KEY"] %>
developer_mode: false
app_name: <%= ENV["NEW_RELIC_APP_NAME"] %>
transaction_tracer:
record_sql: obfuscated
enabled: true
stack_trace_threshold: 0.5
transaction_threshold: apdex_f
capture_params: false
log_level: info

View File

@ -10,6 +10,9 @@ require 'rack/contrib'
require 'active_record' require 'active_record'
require 'redis' require 'redis'
require 'gh' require 'gh'
require 'hubble'
require 'hubble/middleware'
require 'newrelic_rpm'
# Rack class implementing the HTTP API. # Rack class implementing the HTTP API.
# Instances respond to #call. # Instances respond to #call.
@ -51,8 +54,10 @@ class Travis::Api::App
def initialize def initialize
@app = Rack::Builder.app do @app = Rack::Builder.app do
use Hubble::Rescuer, env: Travis.env, codename: ENV['CODENAME'] if Endpoint.production? && ENV['HUBBLE_ENDPOINT']
use Rack::Protection::PathTraversal use Rack::Protection::PathTraversal
use Rack::SSL if Endpoint.production? use Rack::SSL if Endpoint.production?
use Rack::PostBodyContentTypeParser
use Rack::JSONP use Rack::JSONP
use ActiveRecord::ConnectionAdapters::ConnectionManagement use ActiveRecord::ConnectionAdapters::ConnectionManagement
@ -80,6 +85,7 @@ class Travis::Api::App
end end
def self.setup_travis def self.setup_travis
Travis::Amqp.config = Travis.config.amqp
Travis::Database.connect Travis::Database.connect
Travis::Services.constants.each do |name| Travis::Services.constants.each do |name|

View File

@ -0,0 +1,11 @@
require 'travis/api/app'
class Travis::Api::App
class Endpoint
class Accounts < Endpoint
get '/', scope: :private do
body service(:account).find_all, type: :accounts
end
end
end
end

View File

@ -115,7 +115,7 @@ class Travis::Api::App
get '/post_message' do get '/post_message' do
handshake do |user, token, target_origin| handshake do |user, token, target_origin|
halt 403, invalid_target(target_origin) unless target_ok? target_origin halt 403, invalid_target(target_origin) unless target_ok? target_origin
rendered_user = Travis::Api.data(service(:user, user).find_one, type: :user, version: :v2) rendered_user = Travis::Api.data(user, version: :v2)
post_message(token: token, user: rendered_user, target_origin: target_origin) post_message(token: token, user: rendered_user, target_origin: target_origin)
end end
end end
@ -126,13 +126,18 @@ class Travis::Api::App
private private
def oauth_endpoint
proxy = Travis.config.oauth2.proxy
proxy ? File.join(proxy, request.fullpath) : url
end
def handshake def handshake
config = Travis.config.oauth2 config = Travis.config.oauth2
endpoint = Addressable::URI.parse(config.authorization_server) endpoint = Addressable::URI.parse(config.authorization_server)
values = { values = {
client_id: config.client_id, client_id: config.client_id,
scope: config.scope, scope: config.scope,
redirect_uri: url redirect_uri: oauth_endpoint
} }
if params[:code] and state_ok?(params[:state]) if params[:code] and state_ok?(params[:state])
@ -180,8 +185,8 @@ class Travis::Api::App
def user_for_github_token(token) def user_for_github_token(token)
data = GH.with(token: token.to_s) { GH['user'] } data = GH.with(token: token.to_s) { GH['user'] }
scopes = parse_scopes data.headers['x-oauth-scopes'] scopes = parse_scopes data.headers['x-oauth-scopes']
user = User.find_by_github_id(data['id']) user = ::User.find_by_github_id(data['id'])
user ||= User.create! user_info(data, github_oauth_token: token) user ||= ::User.create! user_info(data, github_oauth_token: token)
halt 403, 'not a Travis user' if user.nil? halt 403, 'not a Travis user' if user.nil?
halt 403, 'insufficient access' unless acceptable? scopes halt 403, 'insufficient access' unless acceptable? scopes

View File

@ -5,14 +5,13 @@ class Travis::Api::App
# TODO: Add documentation. # TODO: Add documentation.
class Hooks < Endpoint class Hooks < Endpoint
# TODO: Add implementation and documentation. # TODO: Add implementation and documentation.
# TODO scope: :private get('/', scope: :private) do
get('/') do
body service(:hooks).find_all(params), type: :hooks body service(:hooks).find_all(params), type: :hooks
end end
# TODO: Add implementation and documentation. # TODO: Add implementation and documentation.
put('/:id', scope: :admin) do put('/:id', scope: :private) do
body service(:hooks).update(params) body service(:hooks).update(params[:hook])
end end
end end
end end

View File

@ -1,61 +0,0 @@
require 'travis/api/app'
class Travis::Api::App
class Endpoint
class Profile < Endpoint
# Gives information about the currently logged in user.
#
# Example:
#
# {
# "user": {
# "email": "svenfuchs@artweb-design.de",
# "gravatar_id": "402602a60e500e85f2f5dc1ff3648ecb",
# "is_syncing": false,
# "locale": "de",
# "login": "svenfuchs",
# "name": "Sven Fuchs",
# "synced_at": "2012-08-14T22:11:21Z"
# }
# }
get '/', scope: :private do
body service(:user).find_one, type: :user
end
put '/', scope: :private do
raise NotImplementedError
update_locale if valid_locale?
'ok'
end
# TODO: Add implementation and documentation.
post '/sync', scope: :private do
sync_user(current_user)
204
end
private
def sync_user(user)
unless user.is_syncing?
publisher = Travis::Amqp::Publisher.new('sync.user')
publisher.publish({ user_id: user.id }, type: 'sync')
user.update_column(:is_syncing, true)
end
end
def locale
params[:user][:locale]
end
def valid_locale?
I18n.available_locales.include?(locale.to_sym) # ???
end
def update_locale
current_user.update_attributes!(:locale => locale.to_s)
session[:locale] = locale # ???
end
end
end
end

View File

@ -0,0 +1,43 @@
require 'travis/api/app'
class Travis::Api::App
class Endpoint
class Users < Endpoint
# Gives information about the currently logged in user.
#
# Example:
#
# {
# "user": {
# "name": "Sven Fuchs",
# "login": "svenfuchs",
# "email": "svenfuchs@artweb-design.de",
# "gravatar_id": "402602a60e500e85f2f5dc1ff3648ecb",
# "locale": "de",
# "is_syncing": false,
# "synced_at": "2012-08-14T22:11:21Z"
# }
# }
get '/:id?', scope: :private do
body current_user
end
put '/:id?', scope: :private do
service(:user).update_locale(locale)
204
end
# TODO: Add implementation and documentation.
post '/sync', scope: :private do
service(:user).sync
204
end
private
def locale
params[:user][:locale]
end
end
end
end

View File

@ -20,6 +20,8 @@ class Travis::Api::App
# #
# Logging is set up by custom middleware # Logging is set up by custom middleware
disable :protection, :logging, :setup disable :protection, :logging, :setup
enable :raise_errors
# disable :dump_errors
register :subclass_tracker register :subclass_tracker
helpers :json_renderer helpers :json_renderer
end end

View File

@ -0,0 +1,24 @@
require 'spec_helper'
describe Travis::Api::App::Endpoint::Accounts do
include Travis::Testing::Stubs
let(:access_token) { Travis::Api::App::AccessToken.create(user: user, app_id: -1) }
before do
User.stubs(:find_by_github_id).returns(user)
User.stubs(:find).returns(user)
user.stubs(:repositories).returns(stub(administratable: stub(select: [repository])))
user.stubs(:attributes).returns(:id => user.id, :login => user.login, :name => user.name)
end
it 'includes accounts' do
get('/accounts', access_token: access_token.to_s).should be_ok
parsed_body['accounts'].should == [{
'id' => user.id,
'login' => user.login,
'name' => user.name,
'type' => 'user',
'reposCount' => nil
}]
end
end

View File

@ -1,6 +1,6 @@
require 'spec_helper' require 'spec_helper'
describe Travis::Api::App::Endpoint::Profile do describe Travis::Api::App::Endpoint::Users do
include Travis::Testing::Stubs include Travis::Testing::Stubs
let(:access_token) { Travis::Api::App::AccessToken.create(user: user, app_id: -1) } let(:access_token) { Travis::Api::App::AccessToken.create(user: user, app_id: -1) }
@ -11,11 +11,11 @@ describe Travis::Api::App::Endpoint::Profile do
end end
it 'needs to be authenticated' do it 'needs to be authenticated' do
get('/profile').should_not be_ok get('/users').should_not be_ok
end end
it 'replies with the current user' do it 'replies with the current user' do
get('/profile', access_token: access_token.to_s).should be_ok get('/users', access_token: access_token.to_s).should be_ok
parsed_body['user'].should == { parsed_body['user'].should == {
'id' => user.id, 'id' => user.id,
'login' => user.login, 'login' => user.login,
@ -27,15 +27,4 @@ describe Travis::Api::App::Endpoint::Profile do
'synced_at' => user.synced_at.strftime('%Y-%m-%dT%H:%M:%SZ') 'synced_at' => user.synced_at.strftime('%Y-%m-%dT%H:%M:%SZ')
} }
end end
it 'includes accounts' do
get('/profile', access_token: access_token.to_s).should be_ok
parsed_body['accounts'].should == [{
'id' => user.id,
'login' => user.login,
'name' => user.name,
'type' => 'user',
'reposCount' => nil
}]
end
end end