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:
commit
a622de2a9f
|
@ -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
|
||||
|
|
12
.travis.yml
12
.travis.yml
|
@ -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
10
Gemfile
|
@ -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'
|
||||
|
|
166
Gemfile.lock
166
Gemfile.lock
|
@ -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!
|
||||
|
|
2
Procfile
2
Procfile
|
@ -1,2 +1,2 @@
|
|||
web: bundle exec ./script/server
|
||||
web: bin/start-nginx bundle exec ./script/server
|
||||
console: bundle exec ./script/console
|
||||
|
|
|
@ -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
|
||||
|
|
2
Rakefile
2
Rakefile
|
@ -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
3
bin/start-nginx
Executable file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
"$@"
|
18
config.ru
18
config.ru
|
@ -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
|
||||
|
|
|
@ -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
64
config/nginx.conf.erb
Normal 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
9
config/puma-config.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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' }
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
|
||||
|
|
|
@ -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
|
@ -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
9252
lib/travis/api/app/endpoint/documentation/js/jquery.js
vendored
9252
lib/travis/api/app/endpoint/documentation/js/jquery.js
vendored
File diff suppressed because it is too large
Load Diff
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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"]);
|
|
@ -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
|
@ -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"]);
|
|
@ -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"}})();
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
16
lib/travis/api/app/endpoint/uptime.rb
Normal file
16
lib/travis/api/app/endpoint/uptime.rb
Normal 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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
60
lib/travis/api/app/responders/atom.rb
Normal file
60
lib/travis/api/app/responders/atom.rb
Normal 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">
|
||||
<p>
|
||||
<%= build.commit.message.encode(:xml => :text) %> (<%= build.commit.committer_name %>)
|
||||
<br/><br/>
|
||||
State: <%= build.state %>
|
||||
<br/>
|
||||
Started at: <%= build.started_at ? build.started_at : 'not started' %>
|
||||
<br/>
|
||||
Finished at: <%= build.finished_at ? build.finished_at :
|
||||
build.started_at ? 'still running' : 'not started' %>
|
||||
</p>
|
||||
</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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
20
spec/integration/uptime_spec.rb
Normal file
20
spec/integration/uptime_spec.rb
Normal 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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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'
|
||||
|
|
|
@ -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
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Travis::Api::App::Endpoint::Workers do
|
||||
it 'has to be tested'
|
||||
end
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user