Merge branch 'master' into hh-add-metadata-endpoint

Update Gemfile.lock to point to the updated travis-core PR

Conflicts:
	Gemfile.lock
	lib/travis/api/app/endpoint/jobs.rb
	spec/integration/v2/jobs_spec.rb
This commit is contained in:
Hiro Asari 2014-01-17 09:16:41 -05:00
commit a622de2a9f
89 changed files with 1475 additions and 17659 deletions

View File

@ -1,2 +1,3 @@
https://github.com/heroku/heroku-buildpack-ruby.git
https://github.com/drogus/last-commit-sha-buildpack.git
https://github.com/ryandotsmith/nginx-buildpack.git

View File

@ -1,7 +1,15 @@
language: ruby
env:
global:
- RUBY_GC_MALLOC_LIMIT=90000000
- RUBY_FREE_MIN=200000
rvm:
- 1.9.3
- 2.0.0
addons:
postgresql: 9.3
before_script:
- 'RAILS_ENV=test rake db:create db:schema:load --trace'
- 'RAILS_ENV=test bundle exec rake db:create db:structure:load --trace'
notifications:
irc: "irc.freenode.org#travis"
services:
- redis

10
Gemfile
View File

@ -1,4 +1,4 @@
ruby '1.9.3' rescue nil
ruby '2.0.0'
source 'https://rubygems.org'
gemspec
@ -9,22 +9,20 @@ gem 'travis-sidekiqs', github: 'travis-ci/travis-sidekiqs', require: nil, ref: '
gem 'sinatra'
gem 'sinatra-contrib', require: nil #github: 'sinatra/sinatra-contrib', require: nil
gem 'puma', '2.3.1'
gem 'unicorn'
gem 'sentry-raven', github: 'getsentry/raven-ruby'
gem 'yard-sinatra', github: 'rkh/yard-sinatra'
gem 'rack-contrib', github: 'rack/rack-contrib'
gem 'rack-cache', '~> 1.2'
gem 'rack-attack'
gem 'gh'
gem 'bunny'
gem 'bunny', '~> 0.8.0'
gem 'dalli'
gem 'pry'
gem 'metriks', '0.9.9.5'
gem 'ar-octopus', github: 'travis-ci/octopus', require: nil
group :test do
gem 'rspec', '~> 2.13.0'
gem 'rspec', '~> 2.13'
gem 'factory_girl', '~> 2.4.0'
gem 'mocha', '~> 0.12'
gem 'database_cleaner', '~> 0.8.0'

View File

@ -1,11 +1,10 @@
GIT
remote: git://github.com/getsentry/raven-ruby.git
revision: 299f326b420f9d80cfeea9d4e7bfd66ac93f5ad2
revision: f6c79103e1ff07abc8a1863b5d2ec43d9527e0ed
specs:
sentry-raven (0.5.0)
sentry-raven (0.6.0)
faraday (>= 0.7.6)
hashie (>= 1.1.0)
multi_json (~> 1.0)
uuidtools
GIT
@ -17,22 +16,14 @@ GIT
GIT
remote: git://github.com/rkh/yard-sinatra.git
revision: e61831bca0431b35eaa62fdd18acbc65f81322af
revision: cebeb4fc5c0ddddb8e46b0a2222900b3df9150ac
specs:
yard-sinatra (1.0.0)
yard (~> 0.7)
GIT
remote: git://github.com/travis-ci/octopus.git
revision: 2d4cca475479516f47c3144971205f50c335ad35
specs:
ar-octopus (0.5.0beta)
activerecord (>= 2.3.0)
activesupport (>= 2.3.0)
GIT
remote: git://github.com/travis-ci/travis-core.git
revision: d57da369012458ccd513a5a91f20a807e50d41fd
revision: c251a6e0fa1c98723fa877a0bc4ee1d27190a12c
specs:
travis-core (0.0.1)
actionmailer (~> 3.2.12)
@ -48,6 +39,7 @@ GIT
rake
redis (~> 3.0)
rollout (~> 1.1.0)
s3 (~> 0.3)
simple_states (~> 1.0.0)
thor (~> 0.14.6)
@ -61,7 +53,7 @@ GIT
GIT
remote: git://github.com/travis-ci/travis-support.git
revision: c0add49c71ff3c788b4b7e5b63c11d3896d9847d
revision: d2cce5dbbee64fb1574386b16da3768feadb372a
specs:
travis-support (0.0.1)
@ -76,7 +68,8 @@ PATH
specs:
travis-api (0.0.1)
backports (~> 2.5)
newrelic_rpm (~> 3.6.1.88)
memcachier
newrelic_rpm (~> 3.6.6)
pg (~> 0.13.2)
rack-contrib (~> 1.1)
rack-ssl (~> 1.3, >= 1.3.3)
@ -90,12 +83,12 @@ PATH
GEM
remote: https://rubygems.org/
specs:
actionmailer (3.2.13)
actionpack (= 3.2.13)
mail (~> 2.5.3)
actionpack (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
actionmailer (3.2.16)
actionpack (= 3.2.16)
mail (~> 2.5.4)
actionpack (3.2.16)
activemodel (= 3.2.16)
activesupport (= 3.2.16)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.4)
@ -103,20 +96,20 @@ GEM
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.2.1)
activemodel (3.2.13)
activesupport (= 3.2.13)
activemodel (3.2.16)
activesupport (= 3.2.16)
builder (~> 3.0.0)
activerecord (3.2.13)
activemodel (= 3.2.13)
activesupport (= 3.2.13)
activerecord (3.2.16)
activemodel (= 3.2.16)
activesupport (= 3.2.16)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activesupport (3.2.13)
i18n (= 0.6.1)
activesupport (3.2.16)
i18n (~> 0.6, >= 0.6.4)
multi_json (~> 1.0)
addressable (2.3.5)
arel (3.0.2)
atomic (1.1.10)
arel (3.0.3)
atomic (1.1.14)
avl_tree (1.1.3)
backports (2.8.2)
builder (3.0.4)
@ -125,7 +118,7 @@ GEM
facter (>= 1.6.12)
timers (>= 1.0.0)
coder (0.4.0)
coderay (1.0.9)
coderay (1.1.0)
connection_pool (0.9.3)
daemons (1.1.9)
dalli (2.6.4)
@ -133,20 +126,20 @@ GEM
activerecord
rake
database_cleaner (0.8.0)
diff-lcs (1.2.4)
dotenv (0.8.0)
diff-lcs (1.2.5)
dotenv (0.9.0)
erubis (2.7.0)
eventmachine (1.0.3)
facter (1.7.1)
facter (1.7.3)
factory_girl (2.4.2)
activesupport
faraday (0.8.7)
multipart-post (~> 1.1)
ffi (1.9.0)
faraday (0.9.0)
multipart-post (>= 1.2, < 3)
ffi (1.9.3)
foreman (0.63.0)
dotenv (>= 0.7)
thor (>= 0.13.6)
gh (0.11.3)
gh (0.13.0)
addressable
backports
faraday (~> 0.8)
@ -157,82 +150,86 @@ GEM
hashr (0.0.22)
hike (1.2.3)
hitimes (1.2.1)
i18n (0.6.1)
i18n (0.6.9)
journey (1.0.4)
json (1.8.0)
listen (1.2.2)
json (1.8.1)
kgio (2.8.0)
listen (1.0.3)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
rb-kqueue (>= 0.2)
mail (2.5.4)
mime-types (~> 1.16)
treetop (~> 1.4.8)
memcachier (0.0.2)
metaclass (0.0.1)
method_source (0.8.1)
method_source (0.8.2)
metriks (0.9.9.5)
atomic (~> 1.0)
avl_tree (~> 1.1.2)
hitimes (~> 1.1)
mime-types (1.23)
mime-types (1.25.1)
mocha (0.14.0)
metaclass (~> 0.0.1)
multi_json (1.7.7)
multipart-post (1.2.0)
net-http-persistent (2.8)
multi_json (1.8.4)
multipart-post (2.0.0)
net-http-persistent (2.9)
net-http-pipeline (1.0.1)
newrelic_rpm (3.6.1.88)
newrelic_rpm (3.6.9.171)
pg (0.13.2)
polyglot (0.3.3)
pry (0.9.12.2)
coderay (~> 1.0.5)
proxies (0.2.1)
pry (0.9.12.4)
coderay (~> 1.0)
method_source (~> 0.8)
slop (~> 3.4)
puma (2.3.1)
rack (>= 1.1, < 2.0)
pusher (0.11.3)
multi_json (~> 1.0)
signature (~> 0.1.6)
rack (1.4.5)
rack-attack (2.2.0)
rack-attack (2.3.0)
rack
rack-cache (1.2)
rack (>= 0.4)
rack-protection (1.5.0)
rack-protection (1.5.1)
rack
rack-ssl (1.3.3)
rack
rack-test (0.6.2)
rack (>= 1.0)
railties (3.2.13)
actionpack (= 3.2.13)
activesupport (= 3.2.13)
railties (3.2.16)
actionpack (= 3.2.16)
activesupport (= 3.2.16)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
raindrops (0.12.0)
rake (0.9.6)
rb-fsevent (0.9.3)
rb-inotify (0.9.0)
rb-inotify (0.9.2)
ffi (>= 0.5.0)
rb-kqueue (0.2.0)
ffi (>= 0.5.0)
rdoc (3.12.2)
json (~> 1.4)
redcarpet (2.3.0)
redis (3.0.4)
redis-namespace (1.3.0)
redis (~> 3.0.0)
rerun (0.8.1)
listen (>= 1.0.3)
redis (3.0.6)
redis-namespace (1.3.2)
redis (~> 3.0.4)
rerun (0.8.2)
listen (~> 1.0.3)
rollout (1.1.0)
rspec (2.13.0)
rspec-core (~> 2.13.0)
rspec-expectations (~> 2.13.0)
rspec-mocks (~> 2.13.0)
rspec-core (2.13.1)
rspec-expectations (2.13.0)
rspec (2.14.1)
rspec-core (~> 2.14.0)
rspec-expectations (~> 2.14.0)
rspec-mocks (~> 2.14.0)
rspec-core (2.14.7)
rspec-expectations (2.14.4)
diff-lcs (>= 1.1.3, < 2.0)
rspec-mocks (2.13.1)
rspec-mocks (2.14.4)
s3 (0.3.18)
proxies (~> 0.2.0)
sidekiq (2.5.4)
celluloid (~> 0.12.0)
connection_pool (~> 0.9.2)
@ -243,43 +240,46 @@ GEM
simple_states (1.0.0)
activesupport
hashr (~> 0.0.10)
sinatra (1.4.3)
sinatra (1.4.4)
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (~> 1.3, >= 1.3.4)
sinatra-contrib (1.4.0)
sinatra-contrib (1.4.1)
backports (>= 2.0)
eventmachine
multi_json
rack-protection
rack-test
sinatra (~> 1.4.2)
sinatra (~> 1.4.0)
tilt (~> 1.3)
slop (3.4.5)
slop (3.4.7)
sprockets (2.2.2)
hike (~> 1.2)
multi_json (~> 1.0)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
thin (1.5.1)
thin (1.6.1)
daemons (>= 1.0.9)
eventmachine (>= 0.12.6)
eventmachine (>= 1.0.0)
rack (>= 1.0.0)
thor (0.14.6)
tilt (1.4.1)
timers (1.1.0)
treetop (1.4.14)
treetop (1.4.15)
polyglot
polyglot (>= 0.3.1)
tzinfo (0.3.37)
tzinfo (0.3.38)
unicorn (4.7.0)
kgio (~> 2.6)
rack
raindrops (~> 0.7)
uuidtools (2.1.4)
yard (0.8.6.2)
yard (0.8.7.3)
PLATFORMS
ruby
DEPENDENCIES
ar-octopus!
bunny
bunny (~> 0.8.0)
dalli
database_cleaner (~> 0.8.0)
factory_girl (~> 2.4.0)
@ -289,14 +289,13 @@ DEPENDENCIES
micro_migrations!
mocha (~> 0.12)
pry
puma (= 2.3.1)
rack-attack
rack-cache (~> 1.2)
rack-contrib!
rake (~> 0.9.2)
rb-fsevent (~> 0.9.1)
rerun
rspec (~> 2.13.0)
rspec (~> 2.13)
sentry-raven!
sinatra
sinatra-contrib
@ -304,4 +303,5 @@ DEPENDENCIES
travis-core!
travis-sidekiqs!
travis-support!
unicorn
yard-sinatra!

View File

@ -1,2 +1,2 @@
web: bundle exec ./script/server
web: bin/start-nginx bundle exec ./script/server
console: bundle exec ./script/console

View File

@ -10,12 +10,12 @@ Setup:
Run tests:
$ RAILS_ENV=test rake db:create db:schema:load
$ RAILS_ENV=test rake db:create db:structure:load
$ rake spec
Run the server:
$ rake db:create db:schema:load
$ rake db:create db:structure:load
$ foreman start
## Contributing

View File

@ -1,5 +1,5 @@
require 'bundler/setup'
ENV['SCHEMA'] = "#{Gem.loaded_specs['travis-core'].full_gem_path}/db/schema.rb"
ENV['DB_STRUCTURE'] = "#{Gem.loaded_specs['travis-core'].full_gem_path}/db/structure.sql"
begin
require 'micro_migrations'

3
bin/start-nginx Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
"$@"

View File

@ -9,10 +9,26 @@ require 'core_ext/module/load_constants'
models = Travis::Model.constants.map(&:to_s)
only = [/^(ActiveRecord|ActiveModel|Travis|GH|#{models.join('|')})/]
skip = ['Travis::Memory', 'GH::ResponseWrapper', 'Travis::NewRelic']
skip = ['Travis::Memory', 'GH::ResponseWrapper', 'Travis::NewRelic', 'Travis::Helpers::Legacy', 'GH::FaradayAdapter::EMSynchrony']
[Travis::Api, Travis, GH].each do |target|
target.load_constants! :only => only, :skip => skip, :debug => false
end
# https://help.heroku.com/tickets/92756
class RackTimer
def initialize(app)
@app = app
end
def call(env)
start_request = Time.now
status, headers, body = @app.call(env)
elapsed = (Time.now - start_request) * 1000
$stdout.puts("request-id=#{env['HTTP_HEROKU_REQUEST_ID']} measure.rack-request=#{elapsed.round}ms")
[status, headers, body]
end
end
use RackTimer
run Travis::Api::App.new

View File

@ -7,6 +7,7 @@ defaults: &defaults
pool: 5
min_messages: warning
username: <%= ENV['USER'] %>
host: localhost
production:
<<: *defaults

64
config/nginx.conf.erb Normal file
View File

@ -0,0 +1,64 @@
daemon off;
#Heroku dynos have 4 cores.
worker_processes 4;
events {
use epoll;
accept_mutex on;
worker_connections 1024;
}
http {
gzip on;
gzip_comp_level 2;
gzip_min_length 512;
log_format l2met 'measure.nginx.service=$request_time request_id=$http_heroku_request_id';
access_log logs/nginx/access.log l2met;
error_log logs/nginx/error.log;
include mime.types;
default_type application/octet-stream;
sendfile on;
#Must read the body in 5 seconds.
client_body_timeout 5;
upstream app_server {
server unix:/tmp/nginx.socket fail_timeout=0;
}
server {
listen <%= ENV["PORT"] %>;
server_name _;
keepalive_timeout 5;
location / {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Expose-Headers' 'Content-Type, Cache-Control, Expires, Etag, Last-Modified';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Expose-Headers' 'Content-Type, Cache-Control, Expires, Etag, Last-Modified';
# Tell browser to cache this pre-flight info for 20 days
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Methods' 'HEAD, GET, POST, PATCH, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, Accept, If-None-Match, If-Modified-Since';
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain charset=UTF-8';
return 204;
}
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://app_server;
}
}
}

9
config/puma-config.rb Normal file
View File

@ -0,0 +1,9 @@
root = File.expand_path('../..', __FILE__)
rackup "#{root}/config.ru"
bind 'unix:///tmp/nginx.socket'
environment ENV['RACK_ENV'] || 'development'
threads 0, 16

View File

@ -2,3 +2,18 @@
worker_processes 4 # amount of unicorn workers to spin up
timeout 30 # restarts workers that hang for 15 seconds
listen '/tmp/nginx.socket', backlog: 1024
require 'fileutils'
before_fork do |server,worker|
FileUtils.touch('/tmp/app-initialized')
end
before_exec do |server|
ENV['RUBY_HEAP_MIN_SLOTS']=800000
ENV['RUBY_GC_MALLOC_LIMIT']=59000000
ENV['RUBY_HEAP_SLOTS_INCREMENT']=10000
ENV['RUBY_HEAP_SLOTS_GROWTH_FACTOR']=1
ENV['RUBY_HEAP_FREE_MIN']=100000
end

View File

@ -1,9 +1,9 @@
# Overview
**This documentation is for the v2 API. However, this endpoint does also serve the [v1 API](http://about.travis-ci.org/docs/dev/api/).**
**This documentation is for the v2 API. However, this endpoint does also serve the v1 API (undocumented).**
Welcome to the Travis API documentation. This is the API used by the official
[Travis CI](https://next.travis-ci.org) web interface, so everything the web
Welcome to the Travis CI API documentation. This is the API used by the official
[Travis CI](https://travis-ci.org) web interface, so everything the web
interface is able to do is also accomplishable via the API.
## Media Types
@ -12,4 +12,15 @@ The API is currently [JSON](http://en.wikipedia.org/wiki/JSON) only.
## Clients and Libraries
* **[Travis Web](https://github.com/travis-ci/travis-web)**: The official Travis CI client, using [Ember.js](http://emberjs.com/).
Official, maintained by the Travis CI team:
* **[Travis Web](https://github.com/travis-ci/travis-web)**: Web interface and JavaScript library, using [Ember.js](http://emberjs.com/)
* **[travis](https://github.com/travis-ci/travis)**: Command line client and Ruby library
Unofficial:
* **[PHP Travis Client](https://github.com/l3l0/php-travis-client)**: PHP client library
* **[Travis Node.js](https://github.com/pwmckenna/node-travis-ci)**: Node.js client library
* **[travis-api-wrapper](https://github.com/cmaujean/travis-api-wrapper)**: Asynchronous Node.js wrapper
* **[travis-ci](https://github.com/mmalecki/node-travis-ci)**: Thin Node.js wrapper
* **[TravisMiner](https://github.com/smcintosh/travisminer)**: Ruby library for mining the Travis API

View File

@ -4,7 +4,6 @@ namespace :db do
Travis::Database.connect
to_encrypt = {
Request => [:token],
SslKey => [:private_key],
Token => [:token],
User => [:github_oauth_token]
@ -12,9 +11,9 @@ namespace :db do
encrypted_column = Travis::Model::EncryptedColumn.new
to_encrypt.each do |model, column_names|
model.find_in_batches(batch_size: 10000) do |records|
model.find_in_batches(batch_size: 500) do |records|
ActiveRecord::Base.transaction do
puts "Encrypted 10000 of #{model} (last_id: #{records.last.id})"
puts "Encrypted 500 of #{model} (last_id: #{records.last.id})"
records.each do |record|
column_names.each do |column|
@ -25,6 +24,8 @@ namespace :db do
end
end
end
sleep 10
end
end
end

View File

@ -1,8 +1,13 @@
require 'travis'
require 'travis/model'
require 'travis/support/amqp'
require 'travis/states_cache'
require 'backports'
require 'rack'
require 'rack/protection'
require 'rack/contrib'
require 'dalli'
require 'memcachier'
require 'rack/cache'
require 'rack/attack'
require 'active_record'
@ -12,6 +17,7 @@ require 'raven'
require 'sidekiq'
require 'metriks/reporter/logger'
require 'travis/support/log_subscriber/active_record_metrics'
require 'fileutils'
# Rack class implementing the HTTP API.
# Instances respond to #call.
@ -32,6 +38,8 @@ module Travis::Api
Rack.autoload :SSL, 'rack/ssl'
ERROR_RESPONSE = JSON.generate(error: 'Travis encountered an error, sorry :(')
# Used to track if setup already ran.
def self.setup?
@setup ||= false
@ -45,6 +53,7 @@ module Travis::Api
def self.setup(options = {})
setup! unless setup?
Endpoint.set(options) if options
FileUtils.touch('/tmp/app-initialized')
end
def self.new(options = {})
@ -64,6 +73,8 @@ module Travis::Api
def initialize
@app = Rack::Builder.app do
use(Rack::Config) { |env| env['metriks.request.start'] ||= Time.now.utc }
Rack::Utils::HTTP_STATUS_CODES[420] = "Enhance Your Calm"
use Rack::Attack
Rack::Attack.blacklist('block client requesting ruby builds') do |req|
@ -74,19 +85,19 @@ module Travis::Api
[ 420, {}, ['Enhance Your Calm']]
end
use Travis::Api::App::Cors
use Travis::Api::App::Cors if Travis.env == 'development'
use Raven::Rack if Endpoint.production?
use Rack::Protection::PathTraversal
use Rack::SSL if Endpoint.production?
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
memcache_servers = ENV['MEMCACHE_SERVERS']
if Travis::Features.feature_active?(:use_rack_cache) && memcache_server
memcache_servers = ENV['MEMCACHIER_SERVERS']
if Travis::Features.feature_active?(:use_rack_cache) && memcache_servers
use Rack::Cache,
verbose: true,
metastore: "memcached://#{memcache_servers}/#{Travis::Api::App.deploy_sha}",
entitystore: "memcached://#{memcache_servers}/#{Travis::Api::App.deploy_sha}"
metastore: "memcached://#{memcache_servers}/meta-#{Travis::Api::App.deploy_sha}",
entitystore: "memcached://#{memcache_servers}/body-#{Travis::Api::App.deploy_sha}"
end
use Rack::Deflater
@ -111,7 +122,7 @@ module Travis::Api
app.call(env)
rescue
if Endpoint.production?
[500, {'Content-Type' => 'text/plain'}, ['Travis encountered an error, sorry :(']]
[500, {'Content-Type' => 'application/json'}, [ERROR_RESPONSE]]
else
raise
end
@ -135,8 +146,6 @@ module Travis::Api
setup_database_connections
Travis::Features.start
if Travis.env == 'production' || Travis.env == 'staging'
Sidekiq.configure_client do |config|
config.redis = Travis.config.redis.merge(size: 1, namespace: Travis.config.sidekiq.namespace)
@ -156,25 +165,9 @@ module Travis::Api
def self.setup_database_connections
Travis::Database.connect
return unless Travis.config.use_database_follower?
require 'octopus'
if Travis.env == 'production' || Travis.env == 'staging'
puts "Setting up the DB follower as a read slave"
# Octopus checks for Rails.env, just hardcode enabled?
Octopus.instance_eval do
def enabled?
true
end
end
ActiveRecord::Base.custom_octopus_connection = false
::Octopus.setup do |config|
config.shards = { :follower => Travis.config.database_follower }
config.environments = ['production', 'staging']
end
if Travis.config.logs_database
Log.establish_connection 'logs_database'
Log::Part.establish_connection 'logs_database'
end
end

View File

@ -9,6 +9,8 @@ class Travis::Api::App
configure :production do
require 'newrelic_rpm'
::NewRelic::Agent.manual_start()
::NewRelic::Agent.after_fork(:force_reconnect => true)
end
error NotImplementedError do
@ -17,6 +19,11 @@ class Travis::Api::App
"This feature has not yet been implemented. Sorry :(\n\nPull Requests welcome!"
end
error JSON::ParserError do
status 400
"Invalid JSON in request body"
end
# hotfix??
def route_missing
@app ? forward : halt(404)

View File

@ -14,7 +14,7 @@ class Travis::Api::App
# TODO hmmm?
before { flash.clear }
before { content_type :json }
after { content_type :json unless content_type }
error(ActiveRecord::RecordNotFound, Sinatra::NotFound) { not_found }
not_found { content_type =~ /json/ ? { 'file' => 'not found' } : 'file not found' }

View File

@ -1,16 +0,0 @@
require 'travis/api/app'
class Travis::Api::App
class Endpoint
# Artifacts are generated by builds. Currently we only expose logs as
# artifacts
#
# **DEPRECATED** will be removed as soon as the client uses /logs/:id
class Artifacts < Endpoint
# Fetches an artifact by it's *id*.
get '/:id' do |id|
respond_with service(:find_log, params)
end
end
end
end

View File

@ -78,6 +78,10 @@ class Travis::Api::App
#
# * **github_token**: GitHub token for checking authorization (required)
post '/github' do
unless params[:github_token]
halt 422, { "error" => "Must pass 'github_token' parameter" }
end
{ 'access_token' => github_to_travis(params[:github_token], app_id: 1, drop_token: true) }
end
@ -196,6 +200,16 @@ class Travis::Api::App
end
class UserManager < Struct.new(:data, :token, :drop_token)
include User::Renaming
attr_accessor :user
def initialize(*)
super
@user = ::User.find_by_github_id(data['id'])
end
def info(attributes = {})
info = data.to_hash.slice('name', 'login', 'gravatar_id')
info.merge! attributes.stringify_keys
@ -203,26 +217,49 @@ class Travis::Api::App
info
end
def fetch
user = ::User.find_by_github_id(data['id'])
info = drop_token ? info : info(github_oauth_token: token)
def user_exists?
user
end
if user
user.update_attributes info
else
user = ::User.create! info
def fetch
retried ||= false
info = drop_token ? self.info : self.info(github_oauth_token: token)
ActiveRecord::Base.transaction do
if user
rename_repos_owner(user.login, info['login'])
user.update_attributes info
else
self.user = ::User.create! info
end
nullify_logins(user.github_id, user.login)
end
user
rescue ActiveRecord::RecordNotUnique
unless retried
retried = true
retry
end
end
end
def user_for_github_token(token, drop_token = false)
data = GH.with(token: token.to_s, client_id: nil) { GH['user'] }
scopes = parse_scopes data.headers['x-oauth-scopes']
halt 403, 'insufficient access: %p' unless acceptable? scopes
data = GH.with(token: token.to_s, client_id: nil) { GH['user'] }
scopes = parse_scopes data.headers['x-oauth-scopes']
manager = UserManager.new(data, token, drop_token)
user = UserManager.new(data, token, drop_token).fetch
unless acceptable? scopes
# TODO: we should probably only redirect if this is a web
# oauth request, are there any other possibilities to
# consider?
url = Travis.config.oauth2.insufficient_access_redirect_url
url += "#existing-user" if manager.user_exists?
redirect to(url)
end
user = manager.fetch
halt 403, 'not a Travis user' if user.nil?
user
end

View File

@ -4,14 +4,50 @@ class Travis::Api::App
class Endpoint
class Builds < Endpoint
get '/' do
name = params[:branches] ? :find_branches : :find_builds
params['ids'] = params['ids'].split(',') if params['ids'].respond_to?(:split)
respond_with service(name, params)
prefer_follower do
name = params[:branches] ? :find_branches : :find_builds
params['ids'] = params['ids'].split(',') if params['ids'].respond_to?(:split)
respond_with service(name, params)
end
end
get '/:id' do
respond_with service(:find_build, params)
end
post '/:id/cancel' do
Metriks.meter("api.request.cancel_build").mark
service = self.service(:cancel_build, params.merge(source: 'api'))
if !service.authorized?
json = { error: {
message: "You don't have access to cancel build(#{params[:id]})"
} }
Metriks.meter("api.request.cancel_build.unauthorized").mark
status 403
respond_with json
elsif !service.can_cancel?
json = { error: {
message: "The build(#{params[:id]}) can't be canceled",
code: 'cant_cancel'
} }
Metriks.meter("api.request.cancel_build.cant_cancel").mark
status 422
respond_with json
else
service.run
Metriks.meter("api.request.cancel_build.success").mark
status 204
end
end
post '/:id/restart' do
Metriks.meter("api.request.restart_build").mark
respond_with service(:reset_model, build_id: params[:id])
end
end
end
end

View File

@ -84,39 +84,29 @@ __END__
<html lang="en">
<head>
<meta charset="utf-8">
<title>Travis API documentation</title>
<!-- we might wanna change this -->
<!-- <link href="<%= url('/css/bootstrap.css') %>" rel="stylesheet" /> -->
<!-- <link href="<%= url('/css/prettify.css') %>" rel="stylesheet" /> -->
<link href="<%= url('/css/style.css') %>" rel="stylesheet" />
<!-- <script src="<%= url('/js/jquery.js') %>"></script> -->
<!-- <script src="<%= url('/js/prettify.js') %>"></script> -->
<!-- <script src="<%= url('/js/bootstrap.min.js') %>"></script> -->
<title>Travis CI API documentation</title>
<link rel="stylesheet" href="<%= url('/css/style.css') %>" media="screen">
<link href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:400,600,800" rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
</head>
<body onload="prettyPrint()">
<body>
<div id="navigation">
<div class="wrapper">
<a href="http://travis-ci.org" id="logo">travis-ci<span>.org</span></a>
<a href="http://travis-ci.org/" class="logo-home"><img src="http://about.travis-ci.org/images/travisci-small.png" alt="Travis Logo"></a>
<ul>
<li><a href="http://about.travis-ci.org/blog/">Blog</a></li>
<li><a href="http://about.travis-ci.org/docs/">User Documentation</a></li>
<li><a href="http://about.travis-ci.org/docs/">Documentation</a></li>
</ul>
</div>
</div>
<div id="header">
<div class="wrapper">
<h1 class="riddle"><a href="/docs" title="Travis API">The Travis API</a></h1>
<p>All the routes, just waiting for you to build something awesome.</p>
</div>
</div>
<div id="content">
<div class="wrapper">
<div class="pad">
<div id="main">
<h2 class="title">The Travis CI API</h2>
<% general_docs.each do |doc| %>
<%= erb :entry, locals: doc %>
<% end %>
@ -163,22 +153,33 @@ __END__
</div>
</div>
</div>
<div id="footer">
<footer>
<div class="wrapper">
<div class="box">
<p>This site is maintained by the <a href="http://github.com/travis-ci">Travis CI community</a>. Feel free to <a href="http://github.com/travis-ci/travis-api">contribute</a>!</p>
<div class="large-6 columns left">
<div id="travis-logo">
<img src="http://about.travis-ci.org/images/travis-mascot-200px.png" id="travis-mascot">
</div>
<div id="travis-address">
<p>© 2013 Travis CI GmbH,<br>Prinzessinnenstr. 20, 10969 berlin, Germany</p>
</div>
</div>
<div class="box">
<p>This design was kindly provided by the talented Ben Webster of <a href="http://www.plus2.com.au">Plus2</a>.</p>
</div>
<div class="box last">
<ul>
<li><a href="https://github.com/travis-ci" title="">Travis CI on GitHub</a></li>
<li><a href="https://twitter.com/travisci" title="">Travis CI on Twitter</a></li>
</ul>
<div class="large-6 columns right">
<div id="footer-nav">
<ul class="left">
<li><a href="mailto:contact@travis-ci.com">Email</a></li>
<li><a href="http://chat.travis-ci.com">Live Chat</a></li>
<li><a href="http://about.travis-ci.org/docs">Docs</a></li>
<li><a href="http://status.travis-ci.com">Status</a></li>
</ul>
</div>
<div id="berlin-sticker">
<img src="http://about.travis-ci.org/images/made-in-berlin-badge.png" id="made-in-berlin">
</div>
</div>
</div>
</div>
</footer>
</body>
</html>

View File

@ -1,808 +0,0 @@
/*!
* Bootstrap Responsive v2.0.3
*
* Copyright 2012 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world @twitter by @mdo and @fat.
*/
.clearfix {
*zoom: 1;
}
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
.hide-text {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
.input-block-level {
display: block;
width: 100%;
min-height: 28px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.hidden {
display: none;
visibility: hidden;
}
.visible-phone {
display: none !important;
}
.visible-tablet {
display: none !important;
}
.hidden-desktop {
display: none !important;
}
@media (max-width: 767px) {
.visible-phone {
display: inherit !important;
}
.hidden-phone {
display: none !important;
}
.hidden-desktop {
display: inherit !important;
}
.visible-desktop {
display: none !important;
}
}
@media (min-width: 768px) and (max-width: 979px) {
.visible-tablet {
display: inherit !important;
}
.hidden-tablet {
display: none !important;
}
.hidden-desktop {
display: inherit !important;
}
.visible-desktop {
display: none !important ;
}
}
@media (max-width: 480px) {
.nav-collapse {
-webkit-transform: translate3d(0, 0, 0);
}
.page-header h1 small {
display: block;
line-height: 18px;
}
input[type="checkbox"],
input[type="radio"] {
border: 1px solid #ccc;
}
.form-horizontal .control-group > label {
float: none;
width: auto;
padding-top: 0;
text-align: left;
}
.form-horizontal .controls {
margin-left: 0;
}
.form-horizontal .control-list {
padding-top: 0;
}
.form-horizontal .form-actions {
padding-right: 10px;
padding-left: 10px;
}
.modal {
position: absolute;
top: 10px;
right: 10px;
left: 10px;
width: auto;
margin: 0;
}
.modal.fade.in {
top: auto;
}
.modal-header .close {
padding: 10px;
margin: -10px;
}
.carousel-caption {
position: static;
}
}
@media (max-width: 767px) {
body {
padding-right: 20px;
padding-left: 20px;
}
.navbar-fixed-top,
.navbar-fixed-bottom {
margin-right: -20px;
margin-left: -20px;
}
.container-fluid {
padding: 0;
}
.dl-horizontal dt {
float: none;
width: auto;
clear: none;
text-align: left;
}
.dl-horizontal dd {
margin-left: 0;
}
.container {
width: auto;
}
.row-fluid {
width: 100%;
}
.row,
.thumbnails {
margin-left: 0;
}
[class*="span"],
.row-fluid [class*="span"] {
display: block;
float: none;
width: auto;
margin-left: 0;
}
.input-large,
.input-xlarge,
.input-xxlarge,
input[class*="span"],
select[class*="span"],
textarea[class*="span"],
.uneditable-input {
display: block;
width: 100%;
min-height: 28px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.input-prepend input,
.input-append input,
.input-prepend input[class*="span"],
.input-append input[class*="span"] {
display: inline-block;
width: auto;
}
}
@media (min-width: 768px) and (max-width: 979px) {
.row {
margin-left: -20px;
*zoom: 1;
}
.row:before,
.row:after {
display: table;
content: "";
}
.row:after {
clear: both;
}
[class*="span"] {
float: left;
margin-left: 20px;
}
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
width: 724px;
}
.span12 {
width: 724px;
}
.span11 {
width: 662px;
}
.span10 {
width: 600px;
}
.span9 {
width: 538px;
}
.span8 {
width: 476px;
}
.span7 {
width: 414px;
}
.span6 {
width: 352px;
}
.span5 {
width: 290px;
}
.span4 {
width: 228px;
}
.span3 {
width: 166px;
}
.span2 {
width: 104px;
}
.span1 {
width: 42px;
}
.offset12 {
margin-left: 764px;
}
.offset11 {
margin-left: 702px;
}
.offset10 {
margin-left: 640px;
}
.offset9 {
margin-left: 578px;
}
.offset8 {
margin-left: 516px;
}
.offset7 {
margin-left: 454px;
}
.offset6 {
margin-left: 392px;
}
.offset5 {
margin-left: 330px;
}
.offset4 {
margin-left: 268px;
}
.offset3 {
margin-left: 206px;
}
.offset2 {
margin-left: 144px;
}
.offset1 {
margin-left: 82px;
}
.row-fluid {
width: 100%;
*zoom: 1;
}
.row-fluid:before,
.row-fluid:after {
display: table;
content: "";
}
.row-fluid:after {
clear: both;
}
.row-fluid [class*="span"] {
display: block;
float: left;
width: 100%;
min-height: 28px;
margin-left: 2.762430939%;
*margin-left: 2.709239449638298%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.row-fluid [class*="span"]:first-child {
margin-left: 0;
}
.row-fluid .span12 {
width: 99.999999993%;
*width: 99.9468085036383%;
}
.row-fluid .span11 {
width: 91.436464082%;
*width: 91.38327259263829%;
}
.row-fluid .span10 {
width: 82.87292817100001%;
*width: 82.8197366816383%;
}
.row-fluid .span9 {
width: 74.30939226%;
*width: 74.25620077063829%;
}
.row-fluid .span8 {
width: 65.74585634900001%;
*width: 65.6926648596383%;
}
.row-fluid .span7 {
width: 57.182320438000005%;
*width: 57.129128948638304%;
}
.row-fluid .span6 {
width: 48.618784527%;
*width: 48.5655930376383%;
}
.row-fluid .span5 {
width: 40.055248616%;
*width: 40.0020571266383%;
}
.row-fluid .span4 {
width: 31.491712705%;
*width: 31.4385212156383%;
}
.row-fluid .span3 {
width: 22.928176794%;
*width: 22.874985304638297%;
}
.row-fluid .span2 {
width: 14.364640883%;
*width: 14.311449393638298%;
}
.row-fluid .span1 {
width: 5.801104972%;
*width: 5.747913482638298%;
}
input,
textarea,
.uneditable-input {
margin-left: 0;
}
input.span12,
textarea.span12,
.uneditable-input.span12 {
width: 714px;
}
input.span11,
textarea.span11,
.uneditable-input.span11 {
width: 652px;
}
input.span10,
textarea.span10,
.uneditable-input.span10 {
width: 590px;
}
input.span9,
textarea.span9,
.uneditable-input.span9 {
width: 528px;
}
input.span8,
textarea.span8,
.uneditable-input.span8 {
width: 466px;
}
input.span7,
textarea.span7,
.uneditable-input.span7 {
width: 404px;
}
input.span6,
textarea.span6,
.uneditable-input.span6 {
width: 342px;
}
input.span5,
textarea.span5,
.uneditable-input.span5 {
width: 280px;
}
input.span4,
textarea.span4,
.uneditable-input.span4 {
width: 218px;
}
input.span3,
textarea.span3,
.uneditable-input.span3 {
width: 156px;
}
input.span2,
textarea.span2,
.uneditable-input.span2 {
width: 94px;
}
input.span1,
textarea.span1,
.uneditable-input.span1 {
width: 32px;
}
}
@media (min-width: 1200px) {
.row {
margin-left: -30px;
*zoom: 1;
}
.row:before,
.row:after {
display: table;
content: "";
}
.row:after {
clear: both;
}
[class*="span"] {
float: left;
margin-left: 30px;
}
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container {
width: 1170px;
}
.span12 {
width: 1170px;
}
.span11 {
width: 1070px;
}
.span10 {
width: 970px;
}
.span9 {
width: 870px;
}
.span8 {
width: 770px;
}
.span7 {
width: 670px;
}
.span6 {
width: 570px;
}
.span5 {
width: 470px;
}
.span4 {
width: 370px;
}
.span3 {
width: 270px;
}
.span2 {
width: 170px;
}
.span1 {
width: 70px;
}
.offset12 {
margin-left: 1230px;
}
.offset11 {
margin-left: 1130px;
}
.offset10 {
margin-left: 1030px;
}
.offset9 {
margin-left: 930px;
}
.offset8 {
margin-left: 830px;
}
.offset7 {
margin-left: 730px;
}
.offset6 {
margin-left: 630px;
}
.offset5 {
margin-left: 530px;
}
.offset4 {
margin-left: 430px;
}
.offset3 {
margin-left: 330px;
}
.offset2 {
margin-left: 230px;
}
.offset1 {
margin-left: 130px;
}
.row-fluid {
width: 100%;
*zoom: 1;
}
.row-fluid:before,
.row-fluid:after {
display: table;
content: "";
}
.row-fluid:after {
clear: both;
}
.row-fluid [class*="span"] {
display: block;
float: left;
width: 100%;
min-height: 28px;
margin-left: 2.564102564%;
*margin-left: 2.510911074638298%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
-ms-box-sizing: border-box;
box-sizing: border-box;
}
.row-fluid [class*="span"]:first-child {
margin-left: 0;
}
.row-fluid .span12 {
width: 100%;
*width: 99.94680851063829%;
}
.row-fluid .span11 {
width: 91.45299145300001%;
*width: 91.3997999636383%;
}
.row-fluid .span10 {
width: 82.905982906%;
*width: 82.8527914166383%;
}
.row-fluid .span9 {
width: 74.358974359%;
*width: 74.30578286963829%;
}
.row-fluid .span8 {
width: 65.81196581200001%;
*width: 65.7587743226383%;
}
.row-fluid .span7 {
width: 57.264957265%;
*width: 57.2117657756383%;
}
.row-fluid .span6 {
width: 48.717948718%;
*width: 48.6647572286383%;
}
.row-fluid .span5 {
width: 40.170940171000005%;
*width: 40.117748681638304%;
}
.row-fluid .span4 {
width: 31.623931624%;
*width: 31.5707401346383%;
}
.row-fluid .span3 {
width: 23.076923077%;
*width: 23.0237315876383%;
}
.row-fluid .span2 {
width: 14.529914530000001%;
*width: 14.4767230406383%;
}
.row-fluid .span1 {
width: 5.982905983%;
*width: 5.929714493638298%;
}
input,
textarea,
.uneditable-input {
margin-left: 0;
}
input.span12,
textarea.span12,
.uneditable-input.span12 {
width: 1160px;
}
input.span11,
textarea.span11,
.uneditable-input.span11 {
width: 1060px;
}
input.span10,
textarea.span10,
.uneditable-input.span10 {
width: 960px;
}
input.span9,
textarea.span9,
.uneditable-input.span9 {
width: 860px;
}
input.span8,
textarea.span8,
.uneditable-input.span8 {
width: 760px;
}
input.span7,
textarea.span7,
.uneditable-input.span7 {
width: 660px;
}
input.span6,
textarea.span6,
.uneditable-input.span6 {
width: 560px;
}
input.span5,
textarea.span5,
.uneditable-input.span5 {
width: 460px;
}
input.span4,
textarea.span4,
.uneditable-input.span4 {
width: 360px;
}
input.span3,
textarea.span3,
.uneditable-input.span3 {
width: 260px;
}
input.span2,
textarea.span2,
.uneditable-input.span2 {
width: 160px;
}
input.span1,
textarea.span1,
.uneditable-input.span1 {
width: 60px;
}
.thumbnails {
margin-left: -30px;
}
.thumbnails > li {
margin-left: 30px;
}
.row-fluid .thumbnails {
margin-left: 0;
}
}
@media (max-width: 979px) {
body {
padding-top: 0;
}
.navbar-fixed-top {
position: static;
margin-bottom: 18px;
}
.navbar-fixed-top .navbar-inner {
padding: 5px;
}
.navbar .container {
width: auto;
padding: 0;
}
.navbar .brand {
padding-right: 10px;
padding-left: 10px;
margin: 0 0 0 -5px;
}
.nav-collapse {
clear: both;
}
.nav-collapse .nav {
float: none;
margin: 0 0 9px;
}
.nav-collapse .nav > li {
float: none;
}
.nav-collapse .nav > li > a {
margin-bottom: 2px;
}
.nav-collapse .nav > .divider-vertical {
display: none;
}
.nav-collapse .nav .nav-header {
color: #999999;
text-shadow: none;
}
.nav-collapse .nav > li > a,
.nav-collapse .dropdown-menu a {
padding: 6px 15px;
font-weight: bold;
color: #999999;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
border-radius: 3px;
}
.nav-collapse .btn {
padding: 4px 10px 4px;
font-weight: normal;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
border-radius: 4px;
}
.nav-collapse .dropdown-menu li + li a {
margin-bottom: 2px;
}
.nav-collapse .nav > li > a:hover,
.nav-collapse .dropdown-menu a:hover {
background-color: #222222;
}
.nav-collapse.in .btn-group {
padding: 0;
margin-top: 5px;
}
.nav-collapse .dropdown-menu {
position: static;
top: auto;
left: auto;
display: block;
float: none;
max-width: none;
padding: 0;
margin: 0 15px;
background-color: transparent;
border: none;
-webkit-border-radius: 0;
-moz-border-radius: 0;
border-radius: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.nav-collapse .dropdown-menu:before,
.nav-collapse .dropdown-menu:after {
display: none;
}
.nav-collapse .dropdown-menu .divider {
display: none;
}
.nav-collapse .navbar-form,
.nav-collapse .navbar-search {
float: none;
padding: 9px 15px;
margin: 9px 0;
border-top: 1px solid #222222;
border-bottom: 1px solid #222222;
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
-moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
}
.navbar .nav-collapse .nav.pull-right {
float: none;
margin-left: 0;
}
.nav-collapse,
.nav-collapse.collapse {
height: 0;
overflow: hidden;
}
.navbar .btn-navbar {
display: block;
}
.navbar-static .navbar-inner {
padding-right: 10px;
padding-left: 10px;
}
}
@media (min-width: 980px) {
.nav-collapse.collapse {
height: auto !important;
overflow: visible !important;
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -1,31 +0,0 @@
.com { color: #93a1a1; }
.lit { color: #195f91; }
.pun, .opn, .clo { color: #93a1a1; }
.fun { color: #dc322f; }
.str, .atv { color: #D14; white-space: nowrap; }
.kwd, .linenums .tag { color: #1e347b; }
.typ, .atn, .dec, .var { color: teal; }
.pln { color: #48484c; }
.prettyprint {
padding: 8px;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
white-space: pre;
}
.prettyprint.linenums {
-webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
-moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
}
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin: 0 0 0 40px; /* IE indents via margin-left */
}
ol.linenums li {
padding-left: 12px;
color: #bebec5;
line-height: 18px;
text-shadow: 0 1px 0 #fff;
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 405 B

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,2 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["com",/^#[^\n\r]*/,null,"#"],["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,null,'"']],[["kwd",/^(?:ADS|AD|AUG|BZF|BZMF|CAE|CAF|CA|CCS|COM|CS|DAS|DCA|DCOM|DCS|DDOUBL|DIM|DOUBLE|DTCB|DTCF|DV|DXCH|EDRUPT|EXTEND|INCR|INDEX|NDX|INHINT|LXCH|MASK|MSK|MP|MSU|NOOP|OVSK|QXCH|RAND|READ|RELINT|RESUME|RETURN|ROR|RXOR|SQUARE|SU|TCR|TCAA|OVSK|TCF|TC|TS|WAND|WOR|WRITE|XCH|XLQ|XXALQ|ZL|ZQ|ADD|ADZ|SUB|SUZ|MPY|MPR|MPZ|DVP|COM|ABS|CLA|CLZ|LDQ|STO|STQ|ALS|LLS|LRS|TRA|TSQ|TMI|TOV|AXT|TIX|DLY|INP|OUT)\s/,
null],["typ",/^(?:-?GENADR|=MINUS|2BCADR|VN|BOF|MM|-?2CADR|-?[1-6]DNADR|ADRES|BBCON|[ES]?BANK=?|BLOCK|BNKSUM|E?CADR|COUNT\*?|2?DEC\*?|-?DNCHAN|-?DNPTR|EQUALS|ERASE|MEMORY|2?OCT|REMADR|SETLOC|SUBRO|ORG|BSS|BES|SYN|EQU|DEFINE|END)\s/,null],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[!-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["apollo","agc","aea"]);

View File

@ -1,18 +0,0 @@
/*
Copyright (C) 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
var a=null;
PR.registerLangHandler(PR.createSimpleLexer([["opn",/^[([{]+/,a,"([{"],["clo",/^[)\]}]+/,a,")]}"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:def|if|do|let|quote|var|fn|loop|recur|throw|try|monitor-enter|monitor-exit|defmacro|defn|defn-|macroexpand|macroexpand-1|for|doseq|dosync|dotimes|and|or|when|not|assert|doto|proxy|defstruct|first|rest|cons|defprotocol|deftype|defrecord|reify|defmulti|defmethod|meta|with-meta|ns|in-ns|create-ns|import|intern|refer|alias|namespace|resolve|ref|deref|refset|new|set!|memfn|to-array|into-array|aset|gen-class|reduce|map|filter|find|nil?|empty?|hash-map|hash-set|vec|vector|seq|flatten|reverse|assoc|dissoc|list|list?|disj|get|union|difference|intersection|extend|extend-type|extend-protocol|prn)\b/,a],
["typ",/^:[\dA-Za-z-]+/]]),["clj"]);

View File

@ -1,2 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com",
/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]);

View File

@ -1 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["pln",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])+(?:'|$)|`[^`]*(?:`|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\/\*[\S\s]*?\*\/)/],["pln",/^(?:[^"'/`]|\/(?![*/]))+/]]),["go"]);

View File

@ -1,2 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t-\r ]+/,null,"\t\n \r "],["str",/^"(?:[^\n\f\r"\\]|\\[\S\s])*(?:"|$)/,null,'"'],["str",/^'(?:[^\n\f\r'\\]|\\[^&])'?/,null,"'"],["lit",/^(?:0o[0-7]+|0x[\da-f]+|\d+(?:\.\d+)?(?:e[+-]?\d+)?)/i,null,"0123456789"]],[["com",/^(?:--+[^\n\f\r]*|{-(?:[^-]|-+[^}-])*-})/],["kwd",/^(?:case|class|data|default|deriving|do|else|if|import|in|infix|infixl|infixr|instance|let|module|newtype|of|then|type|where|_)(?=[^\d'A-Za-z]|$)/,
null],["pln",/^(?:[A-Z][\w']*\.)*[A-Za-z][\w']*/],["pun",/^[^\d\t-\r "'A-Za-z]+/]]),["hs"]);

View File

@ -1,3 +0,0 @@
var a=null;
PR.registerLangHandler(PR.createSimpleLexer([["opn",/^\(+/,a,"("],["clo",/^\)+/,a,")"],["com",/^;[^\n\r]*/,a,";"],["pln",/^[\t\n\r \xa0]+/,a,"\t\n\r \xa0"],["str",/^"(?:[^"\\]|\\[\S\s])*(?:"|$)/,a,'"']],[["kwd",/^(?:block|c[ad]+r|catch|con[ds]|def(?:ine|un)|do|eq|eql|equal|equalp|eval-when|flet|format|go|if|labels|lambda|let|load-time-value|locally|macrolet|multiple-value-call|nil|progn|progv|quote|require|return-from|setq|symbol-macrolet|t|tagbody|the|throw|unwind)\b/,a],
["lit",/^[+-]?(?:[#0]x[\da-f]+|\d+\/\d+|(?:\.\d+|\d+(?:\.\d*)?)(?:[de][+-]?\d+)?)/i],["lit",/^'(?:-*(?:\w|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?)?/],["pln",/^-*(?:[_a-z]|\\[!-~])(?:[\w-]*|\\[!-~])[!=?]?/i],["pun",/^[^\w\t\n\r "'-);\\\xa0]+/]]),["cl","el","lisp","scm"]);

View File

@ -1,2 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$))/,null,"\"'"]],[["com",/^--(?:\[(=*)\[[\S\s]*?(?:]\1]|$)|[^\n\r]*)/],["str",/^\[(=*)\[[\S\s]*?(?:]\1]|$)/],["kwd",/^(?:and|break|do|else|elseif|end|false|for|function|if|in|local|nil|not|or|repeat|return|then|true|until|while)\b/,null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],
["pln",/^[_a-z]\w*/i],["pun",/^[^\w\t\n\r \xa0][^\w\t\n\r "'+=\xa0-]*/]]),["lua"]);

View File

@ -1,2 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["com",/^#(?:if[\t\n\r \xa0]+(?:[$_a-z][\w']*|``[^\t\n\r`]*(?:``|$))|else|endif|light)/i,null,"#"],["str",/^(?:"(?:[^"\\]|\\[\S\s])*(?:"|$)|'(?:[^'\\]|\\[\S\s])(?:'|$))/,null,"\"'"]],[["com",/^(?:\/\/[^\n\r]*|\(\*[\S\s]*?\*\))/],["kwd",/^(?:abstract|and|as|assert|begin|class|default|delegate|do|done|downcast|downto|elif|else|end|exception|extern|false|finally|for|fun|function|if|in|inherit|inline|interface|internal|lazy|let|match|member|module|mutable|namespace|new|null|of|open|or|override|private|public|rec|return|static|struct|then|to|true|try|type|upcast|use|val|void|when|while|with|yield|asr|land|lor|lsl|lsr|lxor|mod|sig|atomic|break|checked|component|const|constraint|constructor|continue|eager|event|external|fixed|functor|global|include|method|mixin|object|parallel|process|protected|pure|sealed|trait|virtual|volatile)\b/],
["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^(?:[_a-z][\w']*[!#?]?|``[^\t\n\r`]*(?:``|$))/i],["pun",/^[^\w\t\n\r "'\xa0]+/]]),["fs","ml"]);

View File

@ -1,4 +0,0 @@
var a=null;
PR.registerLangHandler(PR.createSimpleLexer([["str",/^(?:'(?:[^\n\r'\\]|\\.)*'|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,a,'"'],["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,a,"#"],["pln",/^\s+/,a," \r\n\t\xa0"]],[["str",/^@"(?:[^"]|"")*(?:"|$)/,a],["str",/^<#[^#>]*(?:#>|$)/,a],["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,a],["com",/^\/\/[^\n\r]*/,a],["com",/^\/\*[\S\s]*?(?:\*\/|$)/,
a],["kwd",/^(?:abstract|and|as|base|catch|class|def|delegate|enum|event|extern|false|finally|fun|implements|interface|internal|is|macro|match|matches|module|mutable|namespace|new|null|out|override|params|partial|private|protected|public|ref|sealed|static|struct|syntax|this|throw|true|try|type|typeof|using|variant|virtual|volatile|when|where|with|assert|assert2|async|break|checked|continue|do|else|ensures|for|foreach|if|late|lock|new|nolate|otherwise|regexp|repeat|requires|return|surroundwith|unchecked|unless|using|while|yield)\b/,
a],["typ",/^(?:array|bool|byte|char|decimal|double|float|int|list|long|object|sbyte|short|string|ulong|uint|ufloat|ulong|ushort|void)\b/,a],["lit",/^@[$_a-z][\w$@]*/i,a],["typ",/^@[A-Z]+[a-z][\w$@]*/,a],["pln",/^'?[$_a-z][\w$@]*/i,a],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,a,"0123456789"],["pun",/^.[^\s\w"-$'./@`]*/,a]]),["n","nemerle"]);

View File

@ -1 +0,0 @@
PR.registerLangHandler(PR.sourceDecorator({keywords:"bytes,default,double,enum,extend,extensions,false,group,import,max,message,option,optional,package,repeated,required,returns,rpc,service,syntax,to,true",types:/^(bool|(double|s?fixed|[su]?int)(32|64)|float|string)\b/,cStyleComments:!0}),["proto"]);

View File

@ -1,2 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^"(?:""(?:""?(?!")|[^"\\]|\\.)*"{0,3}|(?:[^\n\r"\\]|\\.)*"?)/,null,'"'],["lit",/^`(?:[^\n\r\\`]|\\.)*`?/,null,"`"],["pun",/^[!#%&(--:-@[-^{-~]+/,null,"!#%&()*+,-:;<=>?@[\\]^{|}~"]],[["str",/^'(?:[^\n\r'\\]|\\(?:'|[^\n\r']+))'/],["lit",/^'[$A-Z_a-z][\w$]*(?![\w$'])/],["kwd",/^(?:abstract|case|catch|class|def|do|else|extends|final|finally|for|forSome|if|implicit|import|lazy|match|new|object|override|package|private|protected|requires|return|sealed|super|throw|trait|try|type|val|var|while|with|yield)\b/],
["lit",/^(?:true|false|null|this)\b/],["lit",/^(?:0(?:[0-7]+|x[\da-f]+)l?|(?:0|[1-9]\d*)(?:(?:\.\d+)?(?:e[+-]?\d+)?f?|l?)|\\.\d+(?:e[+-]?\d+)?f?)/i],["typ",/^[$_]*[A-Z][\d$A-Z_]*[a-z][\w$]*/],["pln",/^[$A-Z_a-z][\w$]*/],["com",/^\/(?:\/.*|\*(?:\/|\**[^*/])*(?:\*+\/?)?)/],["pun",/^(?:\.+|\/)/]]),["scala"]);

View File

@ -1,2 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["str",/^(?:"(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/,null,"\"'"]],[["com",/^(?:--[^\n\r]*|\/\*[\S\s]*?(?:\*\/|$))/],["kwd",/^(?:add|all|alter|and|any|as|asc|authorization|backup|begin|between|break|browse|bulk|by|cascade|case|check|checkpoint|close|clustered|coalesce|collate|column|commit|compute|constraint|contains|containstable|continue|convert|create|cross|current|current_date|current_time|current_timestamp|current_user|cursor|database|dbcc|deallocate|declare|default|delete|deny|desc|disk|distinct|distributed|double|drop|dummy|dump|else|end|errlvl|escape|except|exec|execute|exists|exit|fetch|file|fillfactor|for|foreign|freetext|freetexttable|from|full|function|goto|grant|group|having|holdlock|identity|identitycol|identity_insert|if|in|index|inner|insert|intersect|into|is|join|key|kill|left|like|lineno|load|match|merge|national|nocheck|nonclustered|not|null|nullif|of|off|offsets|on|open|opendatasource|openquery|openrowset|openxml|option|or|order|outer|over|percent|plan|precision|primary|print|proc|procedure|public|raiserror|read|readtext|reconfigure|references|replication|restore|restrict|return|revoke|right|rollback|rowcount|rowguidcol|rule|save|schema|select|session_user|set|setuser|shutdown|some|statistics|system_user|table|textsize|then|to|top|tran|transaction|trigger|truncate|tsequal|union|unique|update|updatetext|use|user|using|values|varying|view|waitfor|when|where|while|with|writetext)(?=[^\w-]|$)/i,
null],["lit",/^[+-]?(?:0x[\da-f]+|(?:\.\d+|\d+(?:\.\d*)?)(?:e[+-]?\d+)?)/i],["pln",/^[_a-z][\w-]*/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'+\xa0-]*/]]),["sql"]);

View File

@ -1 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"],["com",/^%[^\n\r]*/,null,"%"]],[["kwd",/^\\[@-Za-z]+/],["kwd",/^\\./],["typ",/^[$&]/],["lit",/[+-]?(?:\.\d+|\d+(?:\.\d*)?)(cm|em|ex|in|pc|pt|bp|mm)/i],["pun",/^[()=[\]{}]+/]]),["latex","tex"]);

View File

@ -1,2 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0\u2028\u2029]+/,null,"\t\n\r Â\xa0

"],["str",/^(?:["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})(?:["\u201c\u201d]c|$)|["\u201c\u201d](?:[^"\u201c\u201d]|["\u201c\u201d]{2})*(?:["\u201c\u201d]|$))/i,null,'"“â€<C3A2>'],["com",/^['\u2018\u2019].*/,null,"'‘’"]],[["kwd",/^(?:addhandler|addressof|alias|and|andalso|ansi|as|assembly|auto|boolean|byref|byte|byval|call|case|catch|cbool|cbyte|cchar|cdate|cdbl|cdec|char|cint|class|clng|cobj|const|cshort|csng|cstr|ctype|date|decimal|declare|default|delegate|dim|directcast|do|double|each|else|elseif|end|endif|enum|erase|error|event|exit|finally|for|friend|function|get|gettype|gosub|goto|handles|if|implements|imports|in|inherits|integer|interface|is|let|lib|like|long|loop|me|mod|module|mustinherit|mustoverride|mybase|myclass|namespace|new|next|not|notinheritable|notoverridable|object|on|option|optional|or|orelse|overloads|overridable|overrides|paramarray|preserve|private|property|protected|public|raiseevent|readonly|redim|removehandler|resume|return|select|set|shadows|shared|short|single|static|step|stop|string|structure|sub|synclock|then|throw|to|try|typeof|unicode|until|variant|wend|when|while|with|withevents|writeonly|xor|endif|gosub|let|variant|wend)\b/i,
null],["com",/^rem.*/i],["lit",/^(?:true\b|false\b|nothing\b|\d+(?:e[+-]?\d+[dfr]?|[dfilrs])?|(?:&h[\da-f]+|&o[0-7]+)[ils]?|\d*\.\d+(?:e[+-]?\d+)?[dfr]?|#\s+(?:\d+[/-]\d+[/-]\d+(?:\s+\d+:\d+(?::\d+)?(\s*(?:am|pm))?)?|\d+:\d+(?::\d+)?(\s*(?:am|pm))?)\s+#)/i],["pln",/^(?:(?:[a-z]|_\w)\w*|\[(?:[a-z]|_\w)\w*])/i],["pun",/^[^\w\t\n\r "'[\]\xa0\u2018\u2019\u201c\u201d\u2028\u2029]+/],["pun",/^(?:\[|])/]]),["vb","vbs"]);

View File

@ -1,3 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\r \xa0]+/,null,"\t\n\r Â\xa0"]],[["str",/^(?:[box]?"(?:[^"]|"")*"|'.')/i],["com",/^--[^\n\r]*/],["kwd",/^(?:abs|access|after|alias|all|and|architecture|array|assert|attribute|begin|block|body|buffer|bus|case|component|configuration|constant|disconnect|downto|else|elsif|end|entity|exit|file|for|function|generate|generic|group|guarded|if|impure|in|inertial|inout|is|label|library|linkage|literal|loop|map|mod|nand|new|next|nor|not|null|of|on|open|or|others|out|package|port|postponed|procedure|process|pure|range|record|register|reject|rem|report|return|rol|ror|select|severity|shared|signal|sla|sll|sra|srl|subtype|then|to|transport|type|unaffected|units|until|use|variable|wait|when|while|with|xnor|xor)(?=[^\w-]|$)/i,
null],["typ",/^(?:bit|bit_vector|character|boolean|integer|real|time|string|severity_level|positive|natural|signed|unsigned|line|text|std_u?logic(?:_vector)?)(?=[^\w-]|$)/i,null],["typ",/^'(?:active|ascending|base|delayed|driving|driving_value|event|high|image|instance_name|last_active|last_event|last_value|left|leftof|length|low|path_name|pos|pred|quiet|range|reverse_range|right|rightof|simple_name|stable|succ|transaction|val|value)(?=[^\w-]|$)/i,null],["lit",/^\d+(?:_\d+)*(?:#[\w.\\]+#(?:[+-]?\d+(?:_\d+)*)?|(?:\.\d+(?:_\d+)*)?(?:e[+-]?\d+(?:_\d+)*)?)/i],
["pln",/^(?:[a-z]\w*|\\[^\\]*\\)/i],["pun",/^[^\w\t\n\r "'\xa0][^\w\t\n\r "'\xa0-]*/]]),["vhdl","vhd"]);

View File

@ -1,2 +0,0 @@
PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\d\t a-gi-z\xa0]+/,null,"\t Â\xa0abcdefgijklmnopqrstuvwxyz0123456789"],["pun",/^[*=[\]^~]+/,null,"=*~^[]"]],[["lang-wiki.meta",/(?:^^|\r\n?|\n)(#[a-z]+)\b/],["lit",/^[A-Z][a-z][\da-z]+[A-Z][a-z][^\W_]+\b/],["lang-",/^{{{([\S\s]+?)}}}/],["lang-",/^`([^\n\r`]+)`/],["str",/^https?:\/\/[^\s#/?]*(?:\/[^\s#?]*)?(?:\?[^\s#]*)?(?:#\S*)?/i],["pln",/^(?:\r\n|[\S\s])[^\n\r#*=A-[^`h{~]*/]]),["wiki"]);
PR.registerLangHandler(PR.createSimpleLexer([["kwd",/^#[a-z]+/i,null,"#"]],[]),["wiki.meta"]);

File diff suppressed because one or more lines are too long

View File

@ -1,2 +0,0 @@
var a=null;
PR.registerLangHandler(PR.createSimpleLexer([["pun",/^[:>?|]+/,a,":|>?"],["dec",/^%(?:YAML|TAG)[^\n\r#]+/,a,"%"],["typ",/^&\S+/,a,"&"],["typ",/^!\S*/,a,"!"],["str",/^"(?:[^"\\]|\\.)*(?:"|$)/,a,'"'],["str",/^'(?:[^']|'')*(?:'|$)/,a,"'"],["com",/^#[^\n\r]*/,a,"#"],["pln",/^\s+/,a," \t\r\n"]],[["dec",/^(?:---|\.\.\.)(?:[\n\r]|$)/],["pun",/^-/],["kwd",/^\w+:[\n\r ]/],["pln",/^\w+/]]),["yaml","yml"]);

View File

@ -1,28 +0,0 @@
var q=null;window.PR_SHOULD_USE_CONTINUATION=!0;
(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a=
[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c<i;++c){var j=f[c];if(/\\[bdsw]/i.test(j))a.push(j);else{var j=m(j),d;c+2<i&&"-"===f[c+1]?(d=m(f[c+2]),c+=2):d=j;b.push([j,d]);d<65||j>122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;c<b.length;++c)i=b[c],i[0]<=j[1]+1?j[1]=Math.max(j[1],i[1]):f.push(j=i);b=["["];o&&b.push("^");b.push.apply(b,a);for(c=0;c<
f.length;++c)i=f[c],b.push(e(i[0])),i[1]>i[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c<b;++c){var j=f[c];j==="("?++i:"\\"===j.charAt(0)&&(j=+j.substring(1))&&j<=i&&(d[j]=-1)}for(c=1;c<d.length;++c)-1===d[c]&&(d[c]=++t);for(i=c=0;c<b;++c)j=f[c],j==="("?(++i,d[i]===void 0&&(f[c]="(?:")):"\\"===j.charAt(0)&&
(j=+j.substring(1))&&j<=i&&(f[c]="\\"+d[i]);for(i=c=0;c<b;++c)"^"===f[c]&&"^"!==f[c+1]&&(f[c]="");if(a.ignoreCase&&s)for(c=0;c<b;++c)j=f[c],a=j.charAt(0),j.length>=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p<d;++p){var g=a[p];if(g.ignoreCase)l=!0;else if(/[a-z]/i.test(g.source.replace(/\\u[\da-f]{4}|\\x[\da-f]{2}|\\[^UXux]/gi,""))){s=!0;l=!1;break}}for(var r=
{b:8,t:9,n:10,v:11,f:12,r:13},n=[],p=0,d=a.length;p<d;++p){g=a[p];if(g.global||g.multiline)throw Error(""+g);n.push("(?:"+y(g)+")")}return RegExp(n.join("|"),l?"gi":"g")}function M(a){function m(a){switch(a.nodeType){case 1:if(e.test(a.className))break;for(var g=a.firstChild;g;g=g.nextSibling)m(g);g=a.nodeName;if("BR"===g||"LI"===g)h[s]="\n",t[s<<1]=y++,t[s++<<1|1]=a;break;case 3:case 4:g=a.nodeValue,g.length&&(g=p?g.replace(/\r\n?/g,"\n"):g.replace(/[\t\n\r ]+/g," "),h[s]=g,t[s<<1]=y,y+=g.length,
t[s++<<1|1]=a)}}var e=/(?:^|\s)nocode(?:\s|$)/,h=[],y=0,t=[],s=0,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=document.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);m(a);return{a:h.join("").replace(/\n$/,""),c:t}}function B(a,m,e,h){m&&(a={a:m,d:a},e(a),h.push.apply(h,a.e))}function x(a,m){function e(a){for(var l=a.d,p=[l,"pln"],d=0,g=a.a.match(y)||[],r={},n=0,z=g.length;n<z;++n){var f=g[n],b=r[f],o=void 0,c;if(typeof b===
"string")c=!1;else{var i=h[f.charAt(0)];if(i)o=f.match(i[1]),b=i[0];else{for(c=0;c<t;++c)if(i=m[c],o=f.match(i[1])){b=i[0];break}o||(b="pln")}if((c=b.length>=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m),
l=[],p={},d=0,g=e.length;d<g;++d){var r=e[d],n=r[3];if(n)for(var k=n.length;--k>=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/,
q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/,
q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g,
"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a),
a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e}
for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g<d.length;++g)e(d[g]);m===(m|0)&&d[0].setAttribute("value",
m);var r=s.createElement("OL");r.className="linenums";for(var n=Math.max(0,m-1|0)||0,g=0,z=d.length;g<z;++g)l=d[g],l.className="L"+(g+n)%10,l.firstChild||l.appendChild(s.createTextNode("\xa0")),r.appendChild(l);a.appendChild(r)}function k(a,m){for(var e=m.length;--e>=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*</.test(m)?"default-markup":"default-code";return A[a]}function E(a){var m=
a.g;try{var e=M(a.h),h=e.a;a.a=h;a.c=e.c;a.d=0;C(m,h)(a);var k=/\bMSIE\b/.test(navigator.userAgent),m=/\n/g,t=a.a,s=t.length,e=0,l=a.c,p=l.length,h=0,d=a.e,g=d.length,a=0;d[g]=s;var r,n;for(n=r=0;n<g;)d[n]!==d[n+2]?(d[r++]=d[n++],d[r++]=d[n++]):n+=2;g=r;for(n=r=0;n<g;){for(var z=d[n],f=d[n+1],b=n+2;b+2<=g&&d[b+1]===f;)b+=2;d[r++]=z;d[r++]=f;n=b}for(d.length=r;h<p;){var o=l[h+2]||s,c=d[a+2]||s,b=Math.min(o,c),i=l[h+1],j;if(i.nodeType!==1&&(j=t.substring(e,b))){k&&(j=j.replace(m,"\r"));i.nodeValue=
j;var u=i.ownerDocument,v=u.createElement("SPAN");v.className=d[a+1];var x=i.parentNode;x.replaceChild(v,i);v.appendChild(i);e<o&&(l[h+1]=i=u.createTextNode(t.substring(b,o)),x.insertBefore(i,v.nextSibling))}e=b;e>=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"],
"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"],
H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"],
J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+
I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^<?]+/],["dec",/^<!\w[^>]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^<xmp\b[^>]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^<script\b[^>]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^<style\b[^>]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),
["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css",
/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}),
["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes",
hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p<h.length&&l.now()<e;p++){var n=h[p],k=n.className;if(k.indexOf("prettyprint")>=0){var k=k.match(g),f,b;if(b=
!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p<h.length?setTimeout(m,
250):a&&a()}for(var e=[document.getElementsByTagName("pre"),document.getElementsByTagName("code"),document.getElementsByTagName("xmp")],h=[],k=0;k<e.length;++k)for(var t=0,s=e[k].length;t<s;++t)h.push(e[k][t]);var e=q,l=Date;l.now||(l={now:function(){return+new Date}});var p=0,d,g=/\blang(?:uage)?-([\w.]+)(?!\S)/;m()};window.PR={createSimpleLexer:x,registerLangHandler:k,sourceDecorator:u,PR_ATTRIB_NAME:"atn",PR_ATTRIB_VALUE:"atv",PR_COMMENT:"com",PR_DECLARATION:"dec",PR_KEYWORD:"kwd",PR_LITERAL:"lit",
PR_NOCODE:"nocode",PR_PLAIN:"pln",PR_PUNCTUATION:"pun",PR_SOURCE:"src",PR_STRING:"str",PR_TAG:"tag",PR_TYPE:"typ"}})();

View File

@ -16,7 +16,7 @@ class Travis::Api::App
namespace = route.namespace
controller = namespace.to_s.constantize
route_info = {
'uri' => (controller.prefix + route.http_path[1..-2]).gsub('//', '/'),
'uri' => (controller.prefix + route.http_path).gsub('//', '/'),
'verb' => route.http_verb,
'doc' => route.docstring,
'scope' => /scope\W+(\w+)/.match(route.source).try(:[], 1) || controller.default_scope.to_s

View File

@ -1,12 +0,0 @@
require 'travis/api/app'
class Travis::Api::App
class Endpoint
class Events < Endpoint
get '/' do
respond_with service(:find_events, params), type: :events
end
end
end
end

View File

@ -5,10 +5,11 @@ class Travis::Api::App
class Home < Endpoint
set :prefix, '/'
set :client_config,
host: Travis.config.host,
host: Travis.config.client_domain,
shorten_host: Travis.config.shorten_host,
assets: Travis.config.assets,
pusher: { key: Travis.config.pusher.try(:key) }
pusher: { key: Travis.config.pusher.try(:key) },
github: { api_url: GH.current.api_host.to_s, scopes: Travis.config.oauth2.try(:scope).to_s.split(?,) }
# Landing point. Redirects web browsers to [API documentation](#/docs/).
get '/' do

View File

@ -4,13 +4,49 @@ class Travis::Api::App
class Endpoint
class Jobs < Endpoint
get '/' do
respond_with service(:find_jobs, params)
prefer_follower do
respond_with service(:find_jobs, params)
end
end
get '/:id' do
respond_with service(:find_job, params)
end
post '/:id/cancel' do
Metriks.meter("api.request.cancel_job").mark
service = self.service(:cancel_job, params.merge(source: 'api'))
if !service.authorized?
json = { error: {
message: "You don't have access to cancel job(#{params[:id]})"
} }
Metriks.meter("api.request.cancel_job.unauthorized").mark
status 403
respond_with json
elsif !service.can_cancel?
json = { error: {
message: "The job(#{params[:id]}) can't be canceled",
code: 'cant_cancel'
} }
Metriks.meter("api.request.cancel_job.cant_cancel").mark
status 422
respond_with json
else
service.run
Metriks.meter("api.request.cancel_job.success").mark
status 204
end
end
post '/:id/restart' do
Metriks.meter("api.request.restart_job").mark
respond_with service(:reset_model, job_id: params[:id])
end
get '/:job_id/log' do
resource = service(:find_log, params).run
if !resource || resource.archived?

View File

@ -4,18 +4,10 @@ class Travis::Api::App
class Endpoint
# Logs are generated by builds.
class Logs < Endpoint
# Fetches a log by it's *id*.
# Fetches a log by its *id*.
get '/:id' do |id|
respond_with service(:find_log, params)
end
put '/:id' do |id|
# TODO @rkh ... rather lost in the auth/scopes code.
token = env['HTTP_TOKEN']
halt 403, 'no token' unless token
halt 403, 'internal' unless token == Travis.config.tokens.internal
respond_with service(:update_log, params)
end
end
end
end

View File

@ -13,7 +13,17 @@ class Travis::Api::App
#
# json(:repositories)
get '/' do
respond_with service(:find_repos, params)
prefer_follower do
respond_with service(:find_repos, params)
end
end
# Retrieves repositories for a given owner.
get '/:owner_name' do
pass if params[:owner_name] =~ /^\d+$/ # so we don't capture '/:id'
prefer_follower do
respond_with service(:find_repos, params)
end
end
# Gets the repository with the given id.
@ -22,13 +32,45 @@ class Travis::Api::App
#
# json(:repository)
get '/:id' do
respond_with service(:find_repo, params)
prefer_follower do
respond_with service(:find_repo, params)
end
end
get '/:id/cc' do
respond_with service(:find_repo, params.merge(schema: 'cc'))
end
# Get settings for a given repository
#
get '/:id/settings' do
settings = service(:find_repo_settings, params).run
if settings
respond_with({ settings: settings.obfuscated }, version: :v2)
else
status 404
end
end
patch '/:id/settings' do
payload = JSON.parse request.body.read
if payload['settings'].blank? || !payload['settings'].is_a?(Hash)
halt 422, { "error" => "Settings must be passed with a request" }
end
settings = service(:find_repo_settings, params).run
if settings
settings.merge(payload['settings'])
# TODO: I would like to have better API here, but leaving this
# for testing to not waste too much time before I can play with it
settings.repository.save
respond_with({ settings: settings.obfuscated }, version: :v2)
else
status 404
end
end
# Get the public key for the repository with the given id.
#
# This can be used to encrypt secure variables in the build configuration. See
@ -46,6 +88,26 @@ class Travis::Api::App
respond_with service(:regenerate_repo_key, params), version: :v2
end
# Gets list of branches
get '/:repository_id/branches' do
respond_with service(:find_branches, params), type: :branches, version: :v2
end
# Gets lastest build on a branch branches
get '/:repository_id/branches/:branch' do
respond_with service(:find_branch, params), type: :branch, version: :v2
end
# List caches for a given repo. Can be filtered with `branch` and `match` query parameter.
get '/:repository_id/caches', scope: :private do
respond_with service(:find_caches, params), type: :caches, version: :v2
end
# Delete caches for a given repo. Can be filtered with `branch` and `match` query parameter.
delete '/:repository_id/caches', scope: :private do
respond_with service(:delete_caches, params), type: :caches, version: :v2
end
# Gets the repository with the given name.
#
# ### Response
@ -97,6 +159,26 @@ class Travis::Api::App
post '/:owner_name/:name/key' do
respond_with service(:regenerate_repo_key, params), version: :v2
end
# Gets list of branches
get '/:owner_name/:name/branches' do
respond_with service(:find_branches, params), type: :branches, version: :v2
end
# Gets lastest build on a branch branches
get '/:owner_name/:name/branches/:branch' do
respond_with service(:find_branch, params), type: :branch, version: :v2
end
# List caches for a given repo. Can be filtered with `branch` and `match` query parameter.
get '/:owner_name/:name/caches', scope: :private do
respond_with service(:find_caches, params), type: :caches, version: :v2
end
# Delete caches for a given repo. Can be filtered with `branch` and `match` query parameter.
delete '/:owner_name/:name/caches', scope: :private do
respond_with service(:delete_caches, params), type: :caches, version: :v2
end
end
end
end

View File

@ -3,7 +3,9 @@ require 'travis/api/app'
class Travis::Api::App
class Endpoint
class Requests < Endpoint
# DEPRECATED: this will be removed by 1st of December
post '/' do
Metriks.meter("api.request.restart").mark
respond_with service(:reset_model, params)
end
end

View File

@ -1,15 +0,0 @@
require 'travis/api/app'
class Travis::Api::App
class Endpoint
class Stats < Endpoint
get '/repos' do
{ :stats => service(:find_daily_repos_stats) }
end
get '/tests' do
{ :stats => service(:find_daily_tests_stats) }
end
end
end
end

View File

@ -0,0 +1,16 @@
require 'travis/api/app'
class Travis::Api::App
class Endpoint
class Uptime < Endpoint
get '/' do
begin
ActiveRecord::Base.connection.execute('select 1')
[200, "OK"]
rescue Exception => e
return [500, "Error: #{e.message}"]
end
end
end
end
end

View File

@ -1,15 +0,0 @@
require 'travis/api/app'
class Travis::Api::App
class Endpoint
class Workers < Endpoint
get '/' do
respond_with service(:find_workers, params), type: :workers
end
get '/:id' do
respond_with service(:find_worker, params), type: :worker
end
end
end
end

View File

@ -4,13 +4,7 @@ class Travis::Api::App
module Helpers
module DbFollower
def prefer_follower
if Travis.config.use_database_follower?
Octopus.using(:follower) do
yield
end
else
yield
end
yield
end
end
end

View File

@ -18,6 +18,10 @@ class Travis::Api::App
def png?
request.accept =~ %r(image/png)
end
def atom?
request.accept =~ %r(application/atom+xml)
end
end
end
end

View File

@ -10,7 +10,13 @@ class Travis::Api::App
def respond_with(resource, options = {})
result = respond(resource, options)
result = result.to_json if result && response.content_type =~ /application\/json/
if result && response.content_type =~ /application\/json/
if !params[:pretty].nil? && (params[:pretty].downcase == 'true' || params[:pretty].to_i > 0)
result = JSON.pretty_generate(result)
else
result = result.to_json
end
end
halt result || 404
end
@ -49,7 +55,7 @@ class Travis::Api::App
end
def responders(resource, options)
[:Json, :Image, :Xml, :Plain].map do |name|
[:Json, :Atom, :Image, :Xml, :Plain].map do |name|
Responders.const_get(name)
end
end

View File

@ -7,10 +7,15 @@ class Travis::Api::App
include Helpers::Accept
before do
env['metriks.request.start'] = Time.now.utc
env['metriks.request.start'] ||= Time.now.utc
end
after do
if queue_start = time(env['HTTP_X_QUEUE_START']) || time(env['HTTP_X_REQUEST_START'])
time = env['metriks.request.start'] - queue_start
::Metriks.timer('api.request_queue').update(time)
end
if response.status < 400
time = Time.now.utc - env['metriks.request.start']
if headers['X-Pattern'].present? and headers['X-Endpoint'].present?
@ -19,11 +24,25 @@ class Travis::Api::App
::Metriks.timer(metric).update(time)
::Metriks.timer('api.requests').update(time)
end
if content_type.present?
type = content_type.split(';', 2).first.to_s.gsub(/\s/,'').gsub(/[^A-z\/]+/, '_').gsub('/', '.')
::Metriks.timer("api.request.content_type.#{type}").update(time)
else
::Metriks.timer("api.request.content_type.none").update(time)
end
::Metriks.meter("api.request.#{request.request_method.downcase}").mark
end
::Metriks.meter("api.request.status.#{response.status.to_s[0]}").mark
::Metriks.meter("api.request.version.#{accept_version}").mark
end
def time(value)
value = value.to_f
start = env['metriks.request.start'].to_f
value /= 1000 while value > start
Time.at(value) if value > 946684800
end
end
end
end

View File

@ -3,7 +3,7 @@ require 'travis/api/app'
class Travis::Api::App
class Middleware
class Rewrite < Middleware
FORMAT = %r(\.(json|xml|png|txt)$)
FORMAT = %r(\.(json|xml|png|txt|atom)$)
V1_REPO_URL = %r(^(/[^/]+/[^/]+(?:/builds(?:/[\d]+)?|/cc)?)$)
helpers :accept
@ -56,6 +56,10 @@ class Travis::Api::App
env['travis.format'] == 'xml'
end
def atom?
env['travis.format'] == 'atom'
end
def v1?
accept_version == 'v1'
end

View File

@ -2,6 +2,7 @@ require 'travis/api/app'
class Travis::Api::App
module Responders
autoload :Atom, 'travis/api/app/responders/atom'
autoload :Base, 'travis/api/app/responders/base'
autoload :Image, 'travis/api/app/responders/image'
autoload :Json, 'travis/api/app/responders/json'

View File

@ -0,0 +1,60 @@
module Travis::Api::App::Responders
require 'date'
class Atom < Base
ATOM_FEED_ERB = ERB.new <<-EOF
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><%= resource.first.repository.slug %> Builds</title>
<link href="<%= endpoint.url %>" type="application/atom+xml" rel = "self" />
<id>repo:<%= resource.first.repository.id %></id>
<rights>Copyright (c) <%= DateTime.now.strftime("%Y") %> Travis CI GmbH</rights>
<updated><%= DateTime.now.rfc3339 %></updated>
<% resource.each do |build| %>
<entry>
<title><%= build.repository.slug %> Build #<%= build.number %></title>
<link href="<%= File.join("https://", Travis.config.host, build.repository.slug, "builds", build.id.to_s) %>" />
<id>repo:<%= build.repository.id %>:build:<%= build.id %></id>
<updated><%= ::DateTime.parse(build.updated_at.to_s).rfc3339 %></updated>
<summary type="html">
&lt;p&gt;
<%= build.commit.message.encode(:xml => :text) %> (<%= build.commit.committer_name %>)
&lt;br/&gt;&lt;br/&gt;
State: <%= build.state %>
&lt;br/&gt;
Started at: <%= build.started_at ? build.started_at : 'not started' %>
&lt;br/&gt;
Finished at: <%= build.finished_at ? build.finished_at :
build.started_at ? 'still running' : 'not started' %>
&lt;/p&gt;
</summary>
<author>
<name><%= build.commit.committer_name %></name>
</author>
</entry>
<% end %>
</feed>
EOF
def apply?
super && resource.is_a?(ActiveRecord::Relation) && resource.first.is_a?(Build)
end
def apply
super
ATOM_FEED_ERB.result(binding)
end
private
def content_type
'application/atom+xml;charset=utf-8'
end
end
end

View File

@ -11,6 +11,10 @@ module Travis::Api::App::Responders
send_file(filename, type: :png, last_modified: last_modified)
end
def apply?
super && resource.is_a?(Repository)
end
private
def content_type

View File

@ -16,7 +16,7 @@ module Travis::Api::App::Responders
}
def apply?
super && resource.is_a?(Repository)
super && resource.is_a?(Repository) && last_build
end
def apply

View File

@ -3,6 +3,6 @@ cd "$(dirname "$0")/.."
[ $PORT ] || PORT=3000
[ $RACK_ENV ] || RACK_ENV=development
cmd="ruby -I lib -S bundle exec ruby -I lib -S puma config.ru -p $PORT -e $RACK_ENV --threads 0:16"
[[ $RACK_ENV == "development" ]] && exec rerun "$cmd -b tcp://127.0.0.1:$PORT"
cmd="ruby -I lib -S bundle exec ruby -I lib -S unicorn config.ru -E $RACK_ENV -c config/unicorn.rb"
[[ $RACK_ENV == "development" ]] && exec rerun "$cmd -l 127.0.0.1:$PORT"
exec $cmd

View File

@ -31,7 +31,7 @@ describe 'App' do
token = Travis::Api::App::AccessToken.new(app_id: 1, user_id: 2, scopes: [:baz]).tap(&:save)
response = get '/foo/1/bar', {}, 'HTTP_ACCEPT' => 'application/json; version=2', 'HTTP_AUTHORIZATION' => "token #{token.token}"
response.status.should == 404
response.status.should == 403
end
it 'checks if required_params match the from the request' do

View File

@ -0,0 +1,20 @@
require 'spec_helper'
describe 'Uptime' do
after do
ActiveRecord::Base.connection.unstub(:execute)
end
it 'returns a 200 and ok when the request was successful' do
response = get '/uptime'
response.status.should == 200
response.body.should == "OK"
end
it "returns a 500 when the query wasn't successful" do
ActiveRecord::Base.connection.stubs(:execute).raises(StandardError, 'error!')
response = get '/uptime'
response.status.should == 500
response.body.should == "Error: error!"
end
end

View File

@ -95,4 +95,20 @@ describe 'v1 repos' do
get('/svenfuchs/minimal.png?branch=foo,bar').should deliver_result_image_for('passing')
end
end
context 'with "Accept: application/atom+xml" header' do
let(:headers) { { 'HTTP_ACCEPT' => 'application/atom+xml' } }
it 'GET /repositories/svenfuchs/minimal/builds' do
response = get '/repositories/svenfuchs/minimal/builds', {}, headers
response.content_type.should =~ /^application\/atom\+xml/
end
end
context 'with .atom extension and "Accept: */*" header' do
let(:headers) { { 'HTTP_ACCEPT' => '*/*' } }
it 'GET /repositories/svenfuchs/minimal/builds.atom' do
response = get '/repositories/svenfuchs/minimal/builds.atom', {}, headers
response.content_type.should =~ /^application\/atom\+xml/
end
end
end

View File

@ -1,12 +0,0 @@
require 'spec_helper'
describe 'Workers' do
let!(:workers) { [Worker.create(full_name: 'one'), Worker.create(full_name: 'two')] }
let(:headers) { { 'HTTP_ACCEPT' => 'application/vnd.travis-ci.1+json' } }
it 'GET /workers' do
response = get '/workers', {}, headers
response.should deliver_json_for(Worker.all, version: 'v1', type: 'workers')
end
end

View File

@ -46,4 +46,47 @@ describe 'Builds' do
response = get "/builds?repository_id=#{repo.id}&branches=true", {}, headers
response.should deliver_json_for(repo.last_finished_builds_by_branches, version: 'v2')
end
describe 'POST /builds/:id/cancel' do
let(:user) { User.where(login: 'svenfuchs').first }
let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: -1) }
before {
headers.merge! 'HTTP_AUTHORIZATION' => "token #{token}"
user.permissions.create!(repository_id: build.repository.id, :pull => true, :push => true)
}
context 'when user does not have rights to cancel the build' do
before { user.permissions.destroy_all }
it 'responds with 403' do
response = post "/builds/#{build.id}/cancel", {}, headers
response.status.should == 403
end
end
context 'when build is not cancelable' do
before { build.matrix.each { |j| j.update_attribute(:state, 'passed') } }
it 'responds with 422' do
response = post "/builds/#{build.id}/cancel", {}, headers
response.status.should == 422
end
end
context 'when build can be canceled' do
it 'cancels the build and responds with 204' do
build.matrix.each { |j| j.update_attribute(:state, 'created') }
build.update_attribute(:state, 'created')
response = nil
expect {
response = post "/builds/#{build.id}/cancel", {}, headers
}.to change { build.reload.state }
response.status.should == 204
build.state.should == 'canceled'
end
end
end
end

View File

@ -107,4 +107,46 @@ describe 'Jobs' do
end
end
end
describe 'POST /jobs/:id/cancel' do
let(:user) { User.where(login: 'svenfuchs').first }
let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: -1) }
before {
headers.merge! 'HTTP_AUTHORIZATION' => "token #{token}"
user.permissions.create!(repository_id: job.repository.id, :push => true, :pull => true)
}
context 'when user does not have rights to cancel the job' do
before { user.permissions.destroy_all }
it 'responds with 403' do
response = post "/jobs/#{job.id}/cancel", {}, headers
response.status.should == 403
end
end
context 'when job is not cancelable' do
before { job.update_attribute(:state, 'passed') }
it 'responds with 422' do
response = post "/jobs/#{job.id}/cancel", {}, headers
response.status.should == 422
end
end
context 'when job can be canceled' do
it 'cancels the job and responds with 204' do
job.update_attribute(:state, 'created')
response = nil
expect {
response = post "/jobs/#{job.id}/cancel", {}, headers
}.to change { job.reload.state }
response.status.should == 204
job.state.should == 'canceled'
end
end
end
end

View File

@ -1,3 +1,4 @@
# encoding: utf-8
require 'spec_helper'
describe 'Repos' do
@ -9,7 +10,7 @@ describe 'Repos' do
let(:token) { Travis::Api::App::AccessToken.create(user: user, app_id: -1) }
let(:headers) { { 'HTTP_ACCEPT' => 'application/vnd.travis-ci.2+json', 'HTTP_AUTHORIZATION' => "token #{token}" } }
before { user.permissions.create!(:repository_id => repo.id, :admin => true) }
before { user.permissions.create!(:repository_id => repo.id, :admin => true, :push => true) }
it 'POST /repos/:id/key' do
expect {
@ -22,6 +23,25 @@ describe 'Repos' do
response = post "/repos/#{repo.slug}/key", {}, headers
}.to change { repo.reload.key.private_key }
end
it 'allows to update settings' do
json = { 'settings' => { 'a-new-setting' => 'value' } }.to_json
response = patch "repos/#{repo.id}/settings", json, headers
repo.reload.settings['a-new-setting'].should == 'value'
body = JSON.parse(response.body)
body['settings']['a-new-setting'].should == 'value'
end
it 'allows to get settings' do
repo.settings.replace('foo' => { 'type' => 'password', 'value' => 'abc123' })
repo.save
response = get "repos/#{repo.id}/settings", {}, headers
settings = Repository::Settings.defaults.deep_merge({ 'foo' => { 'type' => 'password', 'value' => '' } })
JSON.parse(response.body).should == { 'settings' => settings }
end
end
describe 'without authenticated user' do
@ -139,4 +159,20 @@ describe 'Repos' do
result.should deliver_result_image_for('passing')
end
end
context 'with "Accept: application/atom+xml" header' do
let(:headers) { { 'HTTP_ACCEPT' => 'application/atom+xml' } }
it 'GET /repositories/svenfuchs/minimal/builds' do
response = get '/repositories/svenfuchs/minimal/builds', {}, headers
response.content_type.should =~ /^application\/atom\+xml/
end
end
context 'with .atom extension' do
let(:headers) { { 'HTTP_ACCEPT' => '*/*' } }
it 'GET /repositories/svenfuchs/minimal/builds.atom' do
response = get '/repositories/svenfuchs/minimal/builds.atom', {}, headers
response.content_type.should =~ /^application\/atom\+xml/
end
end
end

View File

@ -1,12 +0,0 @@
require 'spec_helper'
describe 'Workers' do
let!(:workers) { [Worker.create(full_name: 'one'), Worker.create(full_name: 'two')] }
let(:headers) { { 'HTTP_ACCEPT' => 'application/vnd.travis-ci.2+json' } }
it 'GET /workers' do
response = get '/workers', {}, headers
response.should deliver_json_for(Worker.all, version: 'v2', type: 'workers')
end
end

View File

@ -8,6 +8,7 @@ require 'gh'
require 'multi_json'
require 'travis/api/app'
require 'travis/testing'
require 'travis/testing/scenario'
require 'travis/testing/factories'
require 'support/matchers'

View File

@ -1,44 +0,0 @@
require 'spec_helper'
describe Travis::Api::App::Endpoint::Artifacts do
let(:artifact) { Factory(:log) }
let(:id) { artifact.id }
describe 'GET /artifacts/:id' do
it 'loads the artifact' do
get("/artifacts/#{id}", {}, 'HTTP_ACCEPT' => 'application/vnd.travis-ci.2+json, */*; q=0.01').should be_ok
end
end
describe 'GET /artifacts/:id.txt' do
it 'loads the artifact' do
response = get("/artifacts/#{id}.txt", {})
response.should be_ok
response.body.should == artifact.content
response.headers['Content-Disposition'].should == "inline; filename=\"#{artifact.id}\""
end
it 'sets Content-Disposition to attachment with attachment=true param' do
response = get("/artifacts/#{id}.txt", {'attachment' => true})
response.should be_ok
response.body.should == artifact.content
response.headers['Content-Disposition'].should == "attachment; filename=\"#{artifact.id}\""
end
describe 'with deansi param' do
let(:content) {
"Fetching (0%)\rFetching (10%)\rFetching (100%)\n\e[32m"
}
let(:artifact) { Factory(:log, :content => content) }
it 'clears ansi escape control characters' do
response = get("/artifacts/#{id}.txt", {'deansi' => true})
response.should be_ok
response.body.should == "Fetching (100%)\n"
end
end
end
end

View File

@ -29,9 +29,22 @@ describe Travis::Api::App::Endpoint::Authorization::UserManager do
{ login: 'drogus', id: 456 }.stringify_keys
}
it 'drops the token when drop_token is set to true' do
user = stub('user', login: 'drogus', github_id: 456)
User.expects(:find_by_github_id).with(456).returns(user)
manager = described_class.new(data, 'abc123', true)
attributes = { login: 'drogus', github_id: 456 }.stringify_keys
user.expects(:update_attributes).with(attributes)
manager.fetch.should == user
end
context 'with existing user' do
it 'updates user data' do
user = mock('user')
user = stub('user', login: 'drogus', github_id: 456)
User.expects(:find_by_github_id).with(456).returns(user)
attributes = { login: 'drogus', github_id: 456, github_oauth_token: 'abc123' }.stringify_keys
user.expects(:update_attributes).with(attributes)
@ -42,7 +55,7 @@ describe Travis::Api::App::Endpoint::Authorization::UserManager do
context 'without existing user' do
it 'creates new user' do
user = mock('user')
user = stub('user', login: 'drogus', github_id: 456)
User.expects(:find_by_github_id).with(456).returns(nil)
attributes = { login: 'drogus', github_id: 456, github_oauth_token: 'abc123' }.stringify_keys
User.expects(:create!).with(attributes).returns(user)

View File

@ -23,6 +23,62 @@ describe Travis::Api::App::Endpoint::Authorization do
pending "not yet implemented"
end
describe "GET /auth/handshake" do
describe 'with insufficient oauth permissions' do
before do
# TODO: this is a first try of writing tests for authorization, it does not look pretty
# but I wanted to have something to start with, later on I would like to extract
# this flow to a class, which would be easier to test.
@original_config = Travis.config.oauth2
Travis.config.oauth2 = {
authorization_server: 'https://foobar.com',
access_token_path: '/access_token_path',
client_id: 'client-id',
client_secret: 'client-secret',
scope: 'public_repo,user:email,new_scope',
insufficient_access_redirect_url: 'https://travis-ci.org/insufficient_access'
}
Travis.redis.sadd('github:states', 'github-state')
response = mock('response')
response.expects(:body).returns('access_token=foobarbaz-token')
Faraday.expects(:post).with('https://foobar.com/access_token_path',
client_id: 'client-id',
client_secret: 'client-secret',
scope: 'public_repo,user:email,new_scope',
redirect_uri: 'http://example.org/auth/handshake',
state: 'github-state',
code: 'oauth-code').returns(response)
data = { 'id' => 111 }
data.expects(:headers).returns('x-oauth-scopes' => 'public_repo,user:email')
GH.expects(:with).with(token: 'foobarbaz-token', client_id: nil).returns(data)
end
after do
Travis.config.oauth2 = @original_config
Travis.redis.srem('github:states', 'github-state')
# this is cached after first run, so if we change scopes, it will stay
# like that for the rest of the run
User::Oauth.instance_variable_set("@wanted_scopes", nil)
end
it 'redirects to insufficient access page' do
response = get '/auth/handshake?state=github-state&code=oauth-code'
response.should redirect_to('https://travis-ci.org/insufficient_access')
end
it 'redirects to insufficient access page for existing user' do
user = mock('user')
User.expects(:find_by_github_id).with(111).returns(user)
expect {
response = get '/auth/handshake?state=github-state&code=oauth-code'
response.should redirect_to('https://travis-ci.org/insufficient_access#existing-user')
}.to_not change { User.count }
end
end
end
describe 'POST /auth/github' do
before do
data = { 'id' => user.github_id, 'name' => user.name, 'login' => user.login, 'gravatar_id' => user.gravatar_id }
@ -64,5 +120,11 @@ describe Travis::Api::App::Endpoint::Authorization do
it 'does not store the token' do
user_for('public repos').github_oauth_token.should_not == 'public repos'
end
it "errors if no token is given" do
post("/auth/github").should_not be_ok
last_response.status.should == 422
body.should_not include("access_token")
end
end
end

View File

@ -1,5 +1,42 @@
require 'spec_helper'
describe Travis::Api::App::Endpoint::Builds do
it 'has to be tested'
include Travis::Testing::Stubs
it 'works with default options' do
get('/repos.json', {}).should be_ok
end
context '/repos.json is requested' do
before :each do
@plain_response_body = get('/repos.json').body
end
context 'when `pretty=true` is given' do
it 'prints pretty formatted data' do
response = get('/repos.json?pretty=true')
response.should be_ok
response.body.should_not eq(@plain_response_body)
response.body.should match(/\n/)
end
end
context 'when `pretty=1` is given' do
it 'prints pretty formatted data' do
response = get('/repos.json?pretty=1')
response.should be_ok
response.body.should_not eq(@plain_response_body)
response.body.should match(/\n/)
end
end
context 'when `pretty=bogus` is given' do
it 'prints plain-formatted data' do
response = get('/repos.json?pretty=bogus')
response.should be_ok
response.body.should eq(@plain_response_body)
end
end
end
end

View File

@ -24,6 +24,7 @@ describe Travis::Api::App::Endpoint::Users do
'gravatar_id' => user.gravatar_id,
'locale' => user.locale,
'is_syncing' => user.is_syncing,
'created_at' => user.created_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
'synced_at' => user.synced_at.strftime('%Y-%m-%dT%H:%M:%SZ'),
'correct_scopes' => true,
}

View File

@ -1,5 +0,0 @@
require 'spec_helper'
describe Travis::Api::App::Endpoint::Workers do
it 'has to be tested'
end

View File

@ -9,35 +9,42 @@ Gem::Specification.new do |s|
s.require_path = 'lib'
s.authors = [
"Sven Fuchs",
"Konstantin Haase",
"Piotr Sarnacki",
"Konstantin Haase",
"Sven Fuchs",
"Josh Kalderimis",
"Henrik Hodne",
"Mathias Meyer",
"Henrik Hodne",
"Hiro Asari",
"Andre Arko",
"Erik Michaels-Ober",
"Steve Richert",
"Brian Ford",
"Nick Schonning",
"James Dennes"
"Patrick Williams",
"James Dennes",
"Tim Carey-Smith"
]
s.email = [
"me@svenfuchs.com",
"konstantin.mailinglists@googlemail.com",
"drogus@gmail.com",
"konstantin.mailinglists@googlemail.com",
"me@svenfuchs.com",
"josh.kalderimis@gmail.com",
"me@henrikhodne.com",
"meyer@paperplanes.de",
"svenfuchs@artweb-design.de",
"me@henrikhodne.com",
"asari.ruby@gmail.com",
"konstantin.haase@gmail.com",
"henrik@hodne.io",
"andre@arko.net",
"svenfuchs@artweb-design.de",
"sferik@gmail.com",
"steve.richert@gmail.com",
"bford@engineyard.com",
"jdennes@gmail.com",
"nschonni@gmail.com",
"konstantin.haase@gmail.com"
"jdennes@gmail.com",
"tim@spork.in",
"patrick@bittorrent.com"
]
s.files = [
@ -45,70 +52,42 @@ Gem::Specification.new do |s|
"Procfile",
"README.md",
"Rakefile",
"bin/start-nginx",
"config.ru",
"config/database.yml",
"config/newrelic.yml",
"config/nginx.conf.erb",
"config/puma-config.rb",
"config/unicorn.rb",
"docs/00_overview.md",
"docs/01_cross_origin.md",
"lib/tasks/build_update_branch.rake",
"lib/tasks/build_update_pull_request_data.rake",
"lib/tasks/encyrpt_all_data.rake",
"lib/travis/api/app.rb",
"lib/travis/api/app/access_token.rb",
"lib/travis/api/app/base.rb",
"lib/travis/api/app/cors.rb",
"lib/travis/api/app/endpoint.rb",
"lib/travis/api/app/endpoint/accounts.rb",
"lib/travis/api/app/endpoint/artifacts.rb",
"lib/travis/api/app/endpoint/authorization.rb",
"lib/travis/api/app/endpoint/branches.rb",
"lib/travis/api/app/endpoint/broadcasts.rb",
"lib/travis/api/app/endpoint/builds.rb",
"lib/travis/api/app/endpoint/documentation.rb",
"lib/travis/api/app/endpoint/documentation/css/bootstrap-responsive.css",
"lib/travis/api/app/endpoint/documentation/css/bootstrap-responsive.min.css",
"lib/travis/api/app/endpoint/documentation/css/bootstrap.css",
"lib/travis/api/app/endpoint/documentation/css/bootstrap.min.css",
"lib/travis/api/app/endpoint/documentation/css/prettify.css",
"lib/travis/api/app/endpoint/documentation/css/style.css",
"lib/travis/api/app/endpoint/documentation/img/glyphicons-halflings-white.png",
"lib/travis/api/app/endpoint/documentation/img/glyphicons-halflings.png",
"lib/travis/api/app/endpoint/documentation/img/grid-18px-masked.png",
"lib/travis/api/app/endpoint/documentation/js/bootstrap.js",
"lib/travis/api/app/endpoint/documentation/js/bootstrap.min.js",
"lib/travis/api/app/endpoint/documentation/js/jquery.js",
"lib/travis/api/app/endpoint/documentation/js/lang-apollo.js",
"lib/travis/api/app/endpoint/documentation/js/lang-clj.js",
"lib/travis/api/app/endpoint/documentation/js/lang-css.js",
"lib/travis/api/app/endpoint/documentation/js/lang-go.js",
"lib/travis/api/app/endpoint/documentation/js/lang-hs.js",
"lib/travis/api/app/endpoint/documentation/js/lang-lisp.js",
"lib/travis/api/app/endpoint/documentation/js/lang-lua.js",
"lib/travis/api/app/endpoint/documentation/js/lang-ml.js",
"lib/travis/api/app/endpoint/documentation/js/lang-n.js",
"lib/travis/api/app/endpoint/documentation/js/lang-proto.js",
"lib/travis/api/app/endpoint/documentation/js/lang-scala.js",
"lib/travis/api/app/endpoint/documentation/js/lang-sql.js",
"lib/travis/api/app/endpoint/documentation/js/lang-tex.js",
"lib/travis/api/app/endpoint/documentation/js/lang-vb.js",
"lib/travis/api/app/endpoint/documentation/js/lang-vhdl.js",
"lib/travis/api/app/endpoint/documentation/js/lang-wiki.js",
"lib/travis/api/app/endpoint/documentation/js/lang-xq.js",
"lib/travis/api/app/endpoint/documentation/js/lang-yaml.js",
"lib/travis/api/app/endpoint/documentation/js/prettify.js",
"lib/travis/api/app/endpoint/documentation/resources.rb",
"lib/travis/api/app/endpoint/endpoints.rb",
"lib/travis/api/app/endpoint/events.rb",
"lib/travis/api/app/endpoint/home.rb",
"lib/travis/api/app/endpoint/hooks.rb",
"lib/travis/api/app/endpoint/jobs.rb",
"lib/travis/api/app/endpoint/logs.rb",
"lib/travis/api/app/endpoint/repos.rb",
"lib/travis/api/app/endpoint/requests.rb",
"lib/travis/api/app/endpoint/stats.rb",
"lib/travis/api/app/endpoint/uptime.rb",
"lib/travis/api/app/endpoint/users.rb",
"lib/travis/api/app/endpoint/workers.rb",
"lib/travis/api/app/extensions.rb",
"lib/travis/api/app/extensions/expose_pattern.rb",
"lib/travis/api/app/extensions/scoping.rb",
"lib/travis/api/app/extensions/smart_constants.rb",
"lib/travis/api/app/extensions/subclass_tracker.rb",
@ -121,9 +100,11 @@ Gem::Specification.new do |s|
"lib/travis/api/app/helpers/respond_with.rb",
"lib/travis/api/app/middleware.rb",
"lib/travis/api/app/middleware/logging.rb",
"lib/travis/api/app/middleware/metriks.rb",
"lib/travis/api/app/middleware/rewrite.rb",
"lib/travis/api/app/middleware/scope_check.rb",
"lib/travis/api/app/responders.rb",
"lib/travis/api/app/responders/atom.rb",
"lib/travis/api/app/responders/base.rb",
"lib/travis/api/app/responders/image.rb",
"lib/travis/api/app/responders/json.rb",
@ -142,12 +123,12 @@ Gem::Specification.new do |s|
"spec/integration/responders_spec.rb",
"spec/integration/routes.backup.rb",
"spec/integration/scopes_spec.rb",
"spec/integration/uptime_spec.rb",
"spec/integration/v1/branches_spec.rb",
"spec/integration/v1/builds_spec.rb",
"spec/integration/v1/hooks_spec.rb",
"spec/integration/v1/jobs_spec.rb",
"spec/integration/v1/repositories_spec.rb",
"spec/integration/v1/workers_spec.rb",
"spec/integration/v1_spec.backup.rb",
"spec/integration/v2/branches_spec.rb",
"spec/integration/v2/builds_spec.rb",
@ -155,7 +136,6 @@ Gem::Specification.new do |s|
"spec/integration/v2/jobs_spec.rb",
"spec/integration/v2/repositories_spec.rb",
"spec/integration/v2/users_spec.rb",
"spec/integration/v2/workers_spec.rb",
"spec/integration/v2_spec.backup.rb",
"spec/integration/version_spec.rb",
"spec/spec_helper.rb",
@ -165,7 +145,6 @@ Gem::Specification.new do |s|
"spec/unit/cors_spec.rb",
"spec/unit/default_spec.rb",
"spec/unit/endpoint/accounts_spec.rb",
"spec/unit/endpoint/artifacts_spec.rb",
"spec/unit/endpoint/authorization/user_manager_spec.rb",
"spec/unit/endpoint/authorization_spec.rb",
"spec/unit/endpoint/branches_spec.rb",
@ -176,8 +155,8 @@ Gem::Specification.new do |s|
"spec/unit/endpoint/jobs_spec.rb",
"spec/unit/endpoint/repos_spec.rb",
"spec/unit/endpoint/users_spec.rb",
"spec/unit/endpoint/workers_spec.rb",
"spec/unit/endpoint_spec.rb",
"spec/unit/extensions/expose_pattern_spec.rb",
"spec/unit/extensions/scoping_spec.rb",
"spec/unit/extensions/smart_constants_spec.rb",
"spec/unit/extensions/subclass_tracker_spec.rb",
@ -185,7 +164,6 @@ Gem::Specification.new do |s|
"spec/unit/helpers/json_renderer_spec.rb",
"spec/unit/middleware/logging_spec.rb",
"spec/unit/middleware/scope_check_spec.rb",
"spec/unit/middleware_spec.rb",
"spec/unit/responders/json_spec.rb",
"spec/unit/responders/service_spec.rb",
"travis-api.gemspec"
@ -196,12 +174,13 @@ Gem::Specification.new do |s|
s.add_dependency 'backports', '~> 2.5'
s.add_dependency 'pg', '~> 0.13.2'
s.add_dependency 'newrelic_rpm', '~> 3.6.1.88'
s.add_dependency 'newrelic_rpm', '~> 3.6.6'
s.add_dependency 'thin', '~> 1.4'
s.add_dependency 'sinatra', '~> 1.3'
s.add_dependency 'sinatra-contrib', '~> 1.3'
s.add_dependency 'redcarpet', '~> 2.1'
s.add_dependency 'rack-ssl', '~> 1.3', '>= 1.3.3'
s.add_dependency 'rack-contrib', '~> 1.1'
s.add_dependency 'memcachier'
end