diff --git a/.travis.yml b/.travis.yml index 08c1c58f..3f371b9e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -18,4 +18,7 @@ services: - redis before_script: - - 'RAILS_ENV=test bundle exec rake db:create db:migrate --trace' + - 'RAILS_ENV=test bundle exec rake db:create --trace' + +script: + - bundle exec rspec spec diff --git a/Gemfile b/Gemfile index 69128c93..408250f2 100644 --- a/Gemfile +++ b/Gemfile @@ -37,10 +37,12 @@ gem 'customerio' group :test do gem 'rspec', '~> 2.13' + gem 'rspec-its' gem 'factory_girl', '~> 2.4.0' gem 'mocha', '~> 0.12' gem 'database_cleaner', '~> 0.8.0' gem 'timecop', '~> 0.8.0' + gem 'travis-migrations', github: 'travis-ci/travis-migrations' end group :development do diff --git a/Gemfile.lock b/Gemfile.lock index 62756b3a..f395c830 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,9 +36,9 @@ GIT GIT remote: git://github.com/rtomayko/rack-cache.git - revision: f96febebed7700337e8c362403b081e45b8e4f13 + revision: 2d6618172c39c53dceab2e2946d87496154f3e52 specs: - rack-cache (1.5.1) + rack-cache (1.6.1) rack (>= 0.4) GIT @@ -50,7 +50,7 @@ GIT GIT remote: git://github.com/travis-ci/travis-core.git - revision: 96ee8c449ebe305c5c95633cea13eb88fe978abb + revision: f7b3a76b3f39c28bb5cf7b9dc24acec13908a11a specs: travis-core (0.0.1) actionmailer (~> 3.2.19) @@ -72,6 +72,12 @@ GIT travis-config (~> 0.1.0) virtus (~> 1.0.0) +GIT + remote: git://github.com/travis-ci/travis-migrations.git + revision: fcf6eea3e3122a7cbb857826db835de69974c54d + specs: + travis-migrations (0.0.1) + GIT remote: git://github.com/travis-ci/travis-sidekiqs.git revision: 21a2fee158e25252dd78f5fa31e81b4f6583be23 @@ -87,7 +93,7 @@ GIT GIT remote: git://github.com/travis-ci/travis-yaml.git - revision: 9ebe328e7546c696dd374a8cf773d93276f98e4f + revision: 032caed23af8ed1ed55e9204bb91316f3ada2f74 specs: travis-yaml (0.2.0) @@ -111,12 +117,12 @@ PATH GEM remote: https://rubygems.org/ specs: - actionmailer (3.2.22) - actionpack (= 3.2.22) + actionmailer (3.2.22.2) + actionpack (= 3.2.22.2) mail (~> 2.5.4) - actionpack (3.2.22) - activemodel (= 3.2.22) - activesupport (= 3.2.22) + actionpack (3.2.22.2) + activemodel (= 3.2.22.2) + activesupport (= 3.2.22.2) builder (~> 3.0.0) erubis (~> 2.7.0) journey (~> 1.0.4) @@ -126,15 +132,15 @@ GEM sprockets (~> 2.2.1) active_model_serializers (0.9.0) activemodel (>= 3.2) - activemodel (3.2.22) - activesupport (= 3.2.22) + activemodel (3.2.22.2) + activesupport (= 3.2.22.2) builder (~> 3.0.0) - activerecord (3.2.22) - activemodel (= 3.2.22) - activesupport (= 3.2.22) + activerecord (3.2.22.2) + activemodel (= 3.2.22.2) + activesupport (= 3.2.22.2) arel (~> 3.0.2) tzinfo (~> 0.3.29) - activesupport (3.2.22) + activesupport (3.2.22.2) i18n (~> 0.6, >= 0.6.4) multi_json (~> 1.0) addressable (2.4.0) @@ -145,7 +151,7 @@ GEM descendants_tracker (~> 0.0.4) ice_nine (~> 0.11.0) thread_safe (~> 0.3, >= 0.3.1) - backports (3.6.7) + backports (3.6.8) builder (3.0.4) bunny (0.8.0) celluloid (0.16.0) @@ -193,9 +199,9 @@ GEM httparty (0.11.0) multi_json (~> 1.0) multi_xml (>= 0.5.2) - httpclient (2.7.0.1) + httpclient (2.7.1) i18n (0.7.0) - ice_nine (0.11.1) + ice_nine (0.11.2) jemalloc (1.0.1) journey (1.0.4) json (1.8.3) @@ -246,9 +252,9 @@ GEM rack rack-test (0.6.3) rack (>= 1.0) - railties (3.2.22) - actionpack (= 3.2.22) - activesupport (= 3.2.22) + railties (3.2.22.2) + actionpack (= 3.2.22.2) + activesupport (= 3.2.22.2) rack-ssl (~> 1.3.2) rake (>= 0.8.7) rdoc (~> 3.4) @@ -276,6 +282,9 @@ GEM rspec-core (2.99.2) rspec-expectations (2.99.2) diff-lcs (>= 1.1.3, < 2.0) + rspec-its (1.0.1) + rspec-core (>= 2.99.0.beta1) + rspec-expectations (>= 2.99.0.beta1) rspec-mocks (2.99.2) sidekiq (3.3.0) celluloid (>= 0.16.0) @@ -323,7 +332,7 @@ GEM treetop (1.4.15) polyglot polyglot (>= 0.3.1) - tzinfo (0.3.46) + tzinfo (0.3.47) unicorn (4.8.3) kgio (~> 2.6) rack @@ -363,6 +372,7 @@ DEPENDENCIES rb-fsevent (~> 0.9.1) rerun rspec (~> 2.13) + rspec-its s3! sentry-raven! simplecov @@ -374,8 +384,12 @@ DEPENDENCIES travis-api! travis-config (~> 0.1.0) travis-core! + travis-migrations! travis-sidekiqs! travis-support! travis-yaml! unicorn yard-sinatra! + +BUNDLED WITH + 1.11.2 diff --git a/README.md b/README.md index b72bb7c8..5f6aaee5 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ This is the app running on https://api.travis-ci.org/ 1. PostgreSQL 9.3 or higher 1. Redis 1. RabbitMQ -1. Nginx *NB: If working on Ubuntu please install Nginx manually from source. [This guide](http://www.rackspace.com/knowledge_center/article/ubuntu-and-debian-installing-nginx-from-source) is helpful but make sure you install the [latest stable version](https://www.nginx.com/resources/wiki/start/topics/tutorials/install/#stable), include the user name on your ubuntu machine when compiling (add `--user=[yourusername]` as an option when running `./configure`), and don't follow any subsequent server configuration steps. Travis-api will start and configure its own nginx server when run locally. +1. Nginx *NB: If working on Ubuntu please install Nginx manually from source. [This guide](http://www.rackspace.com/knowledge_center/article/ubuntu-and-debian-installing-nginx-from-source) is helpful but make sure you install the [latest stable version](https://www.nginx.com/resources/wiki/start/topics/tutorials/install/#stable), include the user name on your ubuntu machine when compiling (add `--user=[yourusername]` as an option when running `./configure`), and don't follow any subsequent server configuration steps. Travis-api will start and configure its own nginx server when run locally. ## Installation @@ -17,8 +17,10 @@ This is the app running on https://api.travis-ci.org/ ### Database setup -1. `rake db:create db:migrate` -2. for testing 'RAILS_ENV=test bundle exec rake db:create db:migrate --trace' +NB detail for how `rake` sets up the database can be found in the `Rakefile`. In the `namespace :db` block you will see the database name for development is hardcoded to `travis-development`. If you are using a different configuration you will have to make your own adjustments. + +1. `bundle exec rake db:create` +2. for testing 'RAILS_ENV=test bundle exec rake db:create --trace' 1. Clone `travis-logs` and copy the `logs` database (assume the PostgreSQL user is `postgres`): ```sh-session cd .. @@ -31,7 +33,7 @@ pg_dump -t logs travis_logs_development | psql -U postgres travis_development Repeat the database steps for `RAILS_ENV=test`. ```sh-session -RAILS_ENV=test rake db:create db:structure:load +RAILS_ENV=test bundle exec rake db:create pushd ../travis-logs RAILS_ENV=test rvm jruby do bundle exec rake db:migrate psql -c "DROP TABLE IF EXISTS logs CASCADE" -U postgres travis_test diff --git a/Rakefile b/Rakefile index 866a2958..93c7d171 100644 --- a/Rakefile +++ b/Rakefile @@ -1,127 +1,45 @@ -require 'bundler/setup' -require 'travis' -require 'travis/engine' +require 'rake' +require 'travis/migrations' -begin - ENV['SCHEMA'] = File.expand_path('../db/schema.rb', $:.detect { |p| p.include?('travis-core') }) - require 'micro_migrations' -rescue LoadError - # we can't load micro migrations on production -end -require 'travis' +task default: :spec -begin - require 'rspec/core/rake_task' - RSpec::Core::RakeTask.new - task default: :spec -rescue LoadError - warn "could not load rspec" +namespace :db do + if ENV["RAILS_ENV"] == 'test' + desc 'Create and migrate the test database' + task :create do + sh 'createdb travis_test' rescue nil + sh "psql -q travis_test < #{Gem.loaded_specs['travis-migrations'].full_gem_path}/db/structure.sql" + end + else + desc 'Create and migrate the development database' + task :create do + sh 'createdb travis_development' rescue nil + sh "psql -q travis_development < #{Gem.loaded_specs['travis-migrations'].full_gem_path}/db/structure.sql" + end + end end desc "generate gemspec" task 'travis-api.gemspec' do - content = File.read 'travis-api.gemspec' + content = File.read 'travis-api.gemspec' - fields = { - authors: `git shortlog -sn`.scan(/[^\d\s].*/), - email: `git shortlog -sne`.scan(/[^<]+@[^>]+/), - files: `git ls-files`.split("\n").reject { |f| f =~ /^(\.|Gemfile)/ } - } + fields = { + authors: `git shortlog -sn`.scan(/[^\d\s].*/), + email: `git shortlog -sne`.scan(/[^<]+@[^>]+/), + files: `git ls-files`.split("\n").reject { |f| f =~ /^(\.|Gemfile)/ } + } - fields.each do |field, values| - updated = " s.#{field} = [" - updated << values.map { |v| "\n %p" % v }.join(',') - updated << "\n ]" - content.sub!(/ s\.#{field} = \[\n( .*\n)* \]/, updated) - end + fields.each do |field, values| + updated = " s.#{field} = [" + updated << values.map { |v| "\n %p" % v }.join(',') + updated << "\n ]" + content.sub!(/ s\.#{field} = \[\n( .*\n)* \]/, updated) + end - File.open('travis-api.gemspec', 'w') { |f| f << content } -end + File.open('travis-api.gemspec', 'w') { |f| f << content } + end -task default: 'travis-api.gemspec' + task default: 'travis-api.gemspec' -tasks_path = File.expand_path('../lib/tasks/*.rake', __FILE__) -Dir.glob(tasks_path).each { |r| import r } - -module ActiveRecord - class Migration - class << self - attr_accessor :disable_ddl_transaction - end - - # Disable DDL transactions for this migration. - def self.disable_ddl_transaction! - @disable_ddl_transaction = true - end - - def disable_ddl_transaction # :nodoc: - self.class.disable_ddl_transaction - end - end - - class Migrator - def use_transaction?(migration) - !migration.disable_ddl_transaction && Base.connection.supports_ddl_transactions? - end - - def ddl_transaction(migration, &block) - if use_transaction?(migration) - Base.transaction { block.call } - else - block.call - end - end - - def migrate(&block) - current = migrations.detect { |m| m.version == current_version } - target = migrations.detect { |m| m.version == @target_version } - - if target.nil? && @target_version && @target_version > 0 - raise UnknownMigrationVersionError.new(@target_version) - end - - start = up? ? 0 : (migrations.index(current) || 0) - finish = migrations.index(target) || migrations.size - 1 - runnable = migrations[start..finish] - - # skip the last migration if we're headed down, but not ALL the way down - runnable.pop if down? && target - - ran = [] - runnable.each do |migration| - if block && !block.call(migration) - next - end - - Base.logger.info "Migrating to #{migration.name} (#{migration.version})" if Base.logger - - seen = migrated.include?(migration.version.to_i) - - # On our way up, we skip migrating the ones we've already migrated - next if up? && seen - - # On our way down, we skip reverting the ones we've never migrated - if down? && !seen - migration.announce 'never migrated, skipping'; migration.write - next - end - - begin - ddl_transaction(migration) do - migration.migrate(@direction) - record_version_state_after_migrating(migration.version) - end - ran << migration - rescue => e - canceled_msg = Base.connection.supports_ddl_transactions? ? "this and " : "" - raise StandardError, "An error has occurred, #{canceled_msg}all later migrations canceled:\n\n#{e}", e.backtrace - end - end - ran - end - end - - class MigrationProxy - delegate :disable_ddl_transaction, to: :migration - end -end + tasks_path = File.expand_path('../lib/tasks/*.rake', __FILE__) + Dir.glob(tasks_path).each { |r| import r } diff --git a/config/database.yml b/config/database.yml index 26b09327..97ba5e01 100644 --- a/config/database.yml +++ b/config/database.yml @@ -20,4 +20,3 @@ development: test: <<: *defaults database: travis_test - diff --git a/lib/travis/api/app.rb b/lib/travis/api/app.rb index a2763fdd..6b72b8ce 100644 --- a/lib/travis/api/app.rb +++ b/lib/travis/api/app.rb @@ -122,7 +122,6 @@ module Travis::Api use Travis::Api::App::Middleware::Logging use Travis::Api::App::Middleware::ScopeCheck use Travis::Api::App::Middleware::UserAgentTracker - use Travis::Api::App::Middleware::Metriks # make sure this is below ScopeCheck so we have the token use Rack::Attack if Endpoint.production? @@ -133,6 +132,9 @@ module Travis::Api # rewrite should come after V3 hook use Travis::Api::App::Middleware::Rewrite + # v3 has its own metriks + use Travis::Api::App::Middleware::Metriks + SettingsEndpoint.subclass :env_vars if Travis.config.endpoints.ssh_key SingletonSettingsEndpoint.subclass :ssh_key @@ -197,8 +199,10 @@ module Travis::Api Travis::Database.connect if Travis.config.logs_database - Log.establish_connection 'logs_database' - Log::Part.establish_connection 'logs_database' + pool_size = ENV['DATABASE_POOL_SIZE'] + Travis.config.logs_database[:pool] = pool_size.to_i if pool_size + + Travis::LogsModel.establish_connection 'logs_database' end end diff --git a/lib/travis/api/attack.rb b/lib/travis/api/attack.rb index 207396f5..17fcd44a 100644 --- a/lib/travis/api/attack.rb +++ b/lib/travis/api/attack.rb @@ -61,7 +61,7 @@ class Rack::Attack # Ban after: 10 POST requests within 30 seconds blacklist('spamming with POST requests') do |request| Rack::Attack::Allow2Ban.filter(request.identifier, maxretry: 10, findtime: 30.seconds, bantime: bantime(1.hour)) do - request.post? and not POST_WHITELISTED.include? '/auth/github' + request.post? and not POST_WHITELISTED.include? request.path end end diff --git a/lib/travis/api/v2/http/build.rb b/lib/travis/api/v2/http/build.rb index 9d8203b5..394c4ac8 100644 --- a/lib/travis/api/v2/http/build.rb +++ b/lib/travis/api/v2/http/build.rb @@ -17,7 +17,7 @@ module Travis def data { 'build' => build_data(build), - 'commit' => commit_data(build.commit), + 'commit' => commit_data(build.commit, build.repository), 'jobs' => options[:include_jobs] ? build.matrix.map { |job| job_data(job) } : [], 'annotations' => options[:include_jobs] ? Annotations.new(annotations(build), @options).data["annotations"] : [], } @@ -44,11 +44,12 @@ module Travis } end - def commit_data(commit) + def commit_data(commit, repository) { 'id' => commit.id, 'sha' => commit.commit, 'branch' => commit.branch, + 'branch_is_default' => branch_is_default(commit, repository), 'message' => commit.message, 'committed_at' => format_date(commit.committed_at), 'author_name' => commit.author_name, @@ -78,6 +79,10 @@ module Travis } end + def branch_is_default(commit, repository) + repository.default_branch == commit.branch + end + def annotations(build) build.matrix.map(&:annotations).flatten end diff --git a/lib/travis/api/v2/http/job.rb b/lib/travis/api/v2/http/job.rb index 4b712b40..92366474 100644 --- a/lib/travis/api/v2/http/job.rb +++ b/lib/travis/api/v2/http/job.rb @@ -15,7 +15,7 @@ module Travis def data { 'job' => job_data(job), - 'commit' => commit_data(job.commit), + 'commit' => commit_data(job.commit, job.repository), 'annotations' => Annotations.new(job.annotations, @options).data["annotations"], } end @@ -42,11 +42,12 @@ module Travis } end - def commit_data(commit) + def commit_data(commit, repository) { 'id' => commit.id, 'sha' => commit.commit, 'branch' => commit.branch, + 'branch_is_default' => branch_is_default(commit, repository), 'message' => commit.message, 'committed_at' => format_date(commit.committed_at), 'author_name' => commit.author_name, @@ -56,6 +57,10 @@ module Travis 'compare_url' => commit.compare_url, } end + + def branch_is_default(commit, repository) + repository.default_branch == commit.branch + end end end end diff --git a/lib/travis/api/v3.rb b/lib/travis/api/v3.rb index 8c8be745..dd8c2af6 100644 --- a/lib/travis/api/v3.rb +++ b/lib/travis/api/v3.rb @@ -35,6 +35,7 @@ module Travis NotImplemented = ServerError .create('request not (yet) implemented', status: 501) RequestLimitReached = ClientError .create('request limit reached for resource', status: 429) AlreadySyncing = ClientError .create('sync already in progress', status: 409) + MethodNotAllowed = ClientError .create('method not allowed', status: 405) end end end diff --git a/lib/travis/api/v3/metrics.rb b/lib/travis/api/v3/metrics.rb new file mode 100644 index 00000000..6bf1bd3a --- /dev/null +++ b/lib/travis/api/v3/metrics.rb @@ -0,0 +1,103 @@ +require 'metriks' + +module Travis::API::V3 + class Metrics + class MetriksTracker + def initialize(prefix: "api.v3") + @prefx = prefix + end + + def time(name, duration) + ::Metriks.timer("#{@prefix}.#{name}").update(duration) + end + + def mark(name) + ::Metriks.meter("#{@prefix}.#{name}").mark + end + end + + class Processor + attr_reader :queue, :tracker + + def initialize(queue_size: 1000, tracker: MetriksTracker.new) + @tracker = tracker + @queue = queue_size ? ::SizedQueue.new(queue_size) : ::Queue.new + end + + def create(**options) + Metrics.new(self, **options) + end + + def start + Thread.new { loop { process(queue.pop) } } + end + + def process(metrics) + metrics.process(tracker) + rescue Exception => e + $stderr.puts e.message, e.backtrace + end + end + + def initialize(processor, time: Time.now) + @processor = processor + @start_time = time + @name_after = nil + @ticks = [] + @success = nil + @name = "unknown".freeze + end + + def tick(event, time: Time.now) + @ticks << [event, time] + self + end + + def success(**options) + finish(true, **options) + end + + def failure(**options) + finish(false, **options) + end + + def name_after(factory) + @name = nil + @name_after = factory + self + end + + def finish(success, time: Time.now, status: nil) + @success = !!success + @status = status + @status ||= success ? 200 : 500 + @end_time = time + @processor.queue << self + self + end + + def name + @name ||= @name_after.name[/[^:]+::[^:]+$/].underscore.tr(?/.freeze, ?..freeze) + end + + def process(tracker) + tracker.mark("status.#{@status}") + + if @success + process_ticks(tracker) + tracker.time("#{name}.overall", @end_time - @start_time) + tracker.mark("#{name}.success") + else + tracker.mark("#{name}.failure") + end + end + + def process_ticks(tracker) + start = @start_time + @ticks.each do |event, time| + tracker.time("#{name}.#{event}", time - start) + start = time + end + end + end +end diff --git a/lib/travis/api/v3/models/job.rb b/lib/travis/api/v3/models/job.rb index 852f515c..f8f9bfb4 100644 --- a/lib/travis/api/v3/models/job.rb +++ b/lib/travis/api/v3/models/job.rb @@ -2,12 +2,13 @@ module Travis::API::V3 class Models::Job < Model self.inheritance_column = :_type_disabled - + has_one :log, dependent: :destroy belongs_to :repository belongs_to :commit belongs_to :build, autosave: true, foreign_key: 'source_id' belongs_to :owner, polymorphic: true serialize :config + serialize :debug_options end end diff --git a/lib/travis/api/v3/permissions/job.rb b/lib/travis/api/v3/permissions/job.rb index 3055257e..b2193a50 100644 --- a/lib/travis/api/v3/permissions/job.rb +++ b/lib/travis/api/v3/permissions/job.rb @@ -9,5 +9,9 @@ module Travis::API::V3 def restart? write? end + + def debug? + write? + end end end diff --git a/lib/travis/api/v3/queries/repositories.rb b/lib/travis/api/v3/queries/repositories.rb index 6197a0c1..97d4cfc5 100644 --- a/lib/travis/api/v3/queries/repositories.rb +++ b/lib/travis/api/v3/queries/repositories.rb @@ -1,7 +1,7 @@ module Travis::API::V3 class Queries::Repositories < Query params :active, :private, :starred, prefix: :repository - sortable_by :id, :github_id, :owner_name, :name, active: sort_condition(:active) + sortable_by :id, :github_id, :owner_name, :name, active: sort_condition(:active), :'default_branch.last_build' => 'builds.started_at' def for_member(user, **options) all(user: user, **options).joins(:users).where(users: user_condition(user), invalidated_at: nil) diff --git a/lib/travis/api/v3/router.rb b/lib/travis/api/v3/router.rb index 8e39fc15..28085e81 100644 --- a/lib/travis/api/v3/router.rb +++ b/lib/travis/api/v3/router.rb @@ -1,30 +1,50 @@ module Travis::API::V3 class Router include Travis::API::V3 - attr_accessor :routes + attr_accessor :routes, :metrics_processor def initialize(routes = Routes) - @routes = routes + @routes = routes + @metrics_processor = Metrics::Processor.new + + metrics_processor.start routes.draw_routes end def call(env) return service_index(env) if env['PATH_INFO'.freeze] == ?/.freeze + metrics = @metrics_processor.create access_control = AccessControl.new(env) - factory, params = routes.factory_for(env['REQUEST_METHOD'.freeze], env['PATH_INFO'.freeze]) env_params = params(env) + factory, params = routes.factory_for(env['REQUEST_METHOD'.freeze], env['PATH_INFO'.freeze]) + raise NotFound unless factory + metrics.name_after(factory) - filtered = factory.filter_params(env_params) - service = factory.new(access_control, filtered.merge(params)) - result = service.run + filtered = factory.filter_params(env_params) + service = factory.new(access_control, filtered.merge(params)) + + metrics.tick(:prepare) + result = service.run + metrics.tick(:service) env_params.each_key { |key| result.ignored_param(key, reason: "not whitelisted".freeze) unless filtered.include?(key) } - render(result, env_params, env) + response = render(result, env_params, env) + + metrics.tick(:renderer) + metrics.success(status: response[0]) + response rescue Error => error - result = Result.new(access_control, :error, error) - V3.response(result.render(env_params, env), {}, status: error.status) + metrics.tick(:service) + + result = Result.new(access_control, :error, error) + response = V3.response(result.render(env_params, env), {}, status: error.status) + + metrics.tick(:rendered) + metrics.failure(status: error.status) + + response end def render(result, env_params, env) diff --git a/lib/travis/api/v3/routes.rb b/lib/travis/api/v3/routes.rb index db62dced..9d0f8883 100644 --- a/lib/travis/api/v3/routes.rb +++ b/lib/travis/api/v3/routes.rb @@ -42,6 +42,7 @@ module Travis::API::V3 post :cancel, '/cancel' post :restart, '/restart' + post :debug, '/debug' end resource :organization do diff --git a/lib/travis/api/v3/services/job/debug.rb b/lib/travis/api/v3/services/job/debug.rb new file mode 100644 index 00000000..63c1939c --- /dev/null +++ b/lib/travis/api/v3/services/job/debug.rb @@ -0,0 +1,29 @@ +module Travis::API::V3 + class Services::Job::Debug < Service + params "quiet" + + attr_reader :job + + def run + raise LoginRequired unless access_control.logged_in? or access_control.full_access? + raise NotFound unless @job = find(:job) + raise WrongCredentials unless Travis.config.debug_tools_enabled or Travis::Features.active?(:debug_tools, job.repository) + access_control.permissions(job).debug! + + job.debug_options = debug_data + job.save! + + query.restart(access_control.user) + accepted(job: job, state_change: :created) + end + + def debug_data + { + stage: 'before_install', + previous_state: job.state, + created_by: access_control.user.login, + quiet: params["quiet"] || false + } + end + end +end diff --git a/lib/travis/sidekiq.rb b/lib/travis/sidekiq.rb index ef5aa91c..077e6055 100644 --- a/lib/travis/sidekiq.rb +++ b/lib/travis/sidekiq.rb @@ -7,11 +7,13 @@ require 'travis/api/workers/job_cancellation' require 'travis/api/workers/job_restart' require 'travis/support/amqp' +pool_size = ENV['SIDEKIQ_DB_POOL_SIZE'] || 5 +Travis.config.database[:pool] = pool_size.to_i +Travis.config.logs_database[:pool] = pool_size.to_i Travis::Database.connect if Travis.config.logs_database - Log.establish_connection 'logs_database' - Log::Part.establish_connection 'logs_database' + Travis::LogsModel.establish_connection 'logs_database' end Travis::Async.enabled = true diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index ced5e7af..5161936e 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -3,6 +3,7 @@ ENV['RACK_ENV'] = ENV['RAILS_ENV'] = ENV['ENV'] = 'test' require 'support/coverage' require 'rspec' +require 'rspec/its' require 'database_cleaner' require 'sinatra/test_helpers' require 'logger' diff --git a/spec/unit/api/v2/http/build_spec.rb b/spec/unit/api/v2/http/build_spec.rb index 11a6dbea..f276b2b8 100644 --- a/spec/unit/api/v2/http/build_spec.rb +++ b/spec/unit/api/v2/http/build_spec.rb @@ -29,6 +29,7 @@ describe Travis::Api::V2::Http::Build do 'id' => 1, 'sha' => '62aae5f70ceee39123ef', 'branch' => 'master', + 'branch_is_default' => true, 'message' => 'the commit message', 'compare_url' => 'https://github.com/svenfuchs/minimal/compare/master...develop', 'committed_at' => json_format_time(Time.now.utc - 1.hour), diff --git a/spec/unit/api/v2/http/job_spec.rb b/spec/unit/api/v2/http/job_spec.rb index a9211b6f..22fda7b6 100644 --- a/spec/unit/api/v2/http/job_spec.rb +++ b/spec/unit/api/v2/http/job_spec.rb @@ -31,6 +31,7 @@ describe Travis::Api::V2::Http::Job do 'sha' => '62aae5f70ceee39123ef', 'message' => 'the commit message', 'branch' => 'master', + 'branch_is_default' => true, 'message' => 'the commit message', 'committed_at' => json_format_time(Time.now.utc - 1.hour), 'committer_name' => 'Sven Fuchs', diff --git a/spec/v3/error_handling_spec.rb b/spec/v3/error_handling_spec.rb new file mode 100644 index 00000000..b86bf917 --- /dev/null +++ b/spec/v3/error_handling_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe Travis::API::V3::ServiceIndex do + let(:headers) {{ }} + let(:path) { "/v3/repo/1/enable" } + let(:json) { JSON.load(response.body) } + let(:response) { get(path, {}, headers) } + let(:resources) { json.fetch('resources') } + + it "handles wrong HTTP method with 405 status" do + + response.status.should == 405 + end + +end diff --git a/spec/v3/metrics_spec.rb b/spec/v3/metrics_spec.rb new file mode 100644 index 00000000..a5afe054 --- /dev/null +++ b/spec/v3/metrics_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +describe Travis::API::V3::Metrics do + class TestProcessor + attr_reader :times, :marks, :queue + + def initialize + @queue = [] + @times = [] + @marks = [] + end + + def time(*args) + times << args + end + + def mark(name) + marks << name + end + end + + subject(:processor) { TestProcessor.new } + let(:metric) { described_class.new(processor, time: Time.at(0)) } + + before do + metric.name_after(Travis::API::V3::Services::Branch::Find) + metric.tick(:example, time: Time.at(10)) + metric.tick(:other_example, time: Time.at(15)) + metric.success(time: Time.at(25)) + metric.process(processor) + end + + its(:queue) { should be == [metric] } + + its(:times) { should be == [ + ["branch.find.example", 10.0], + ["branch.find.other_example", 5.0], + ["branch.find.overall", 25.0] + ] } + + its(:marks) { should be == ["status.200", "branch.find.success"] } +end diff --git a/spec/v3/services/job/debug_sepc.rb b/spec/v3/services/job/debug_sepc.rb new file mode 100644 index 00000000..03fe80fb --- /dev/null +++ b/spec/v3/services/job/debug_sepc.rb @@ -0,0 +1,70 @@ +require 'spec_helper' + +describe Travis::API::V3::Services::Job::Debug do + let(:repo) { Travis::API::V3::Models::Repository.where(owner_name: 'svenfuchs', name: 'minimal').first } + let(:owner_type) { repo.owner_type.constantize } + let(:owner) { owner_type.find(repo.owner_id)} + let(:build) { repo.builds.last } + let(:jobs) { Travis::API::V3::Models::Build.find(build.id).jobs } + let(:job) { jobs.last } + + before { repo.requests.each(&:delete) } + + before do + Travis::Features.stubs(:owner_active?).returns(true) + @original_sidekiq = Sidekiq::Client + Sidekiq.send(:remove_const, :Client) # to avoid a warning + Sidekiq::Client = [] + + Travis.config.stubs(:debug_tools_enabled).returns true + end + + after do + Sidekiq.send(:remove_const, :Client) # to avoid a warning + Sidekiq::Client = @original_sidekiq + end + + describe "#run" do + context "when unauthenticated" do + before { post("/v3/job/#{job.id}/debug") } + example { expect(last_response.status).to be == 403 } + example { expect(JSON.load(body)).to be == { + "@type" => "error", + "error_type" => "login_required", + "error_message" => "login required" + }} + end + + context "when authenticated" do + let(:token) { Travis::Api::App::AccessToken.create(user: repo.owner, app_id: 1) } + let(:headers) {{ 'HTTP_AUTHORIZATION' => "token #{token}" }} + + context "without sufficient authorization" do + before { post("/v3/job/#{job.id}/debug", {}, headers) } + + example { expect(last_response.status).to be == 403 } + example { expect(JSON.load(body)).to include( + "@type" => "error", + "error_type" => "insufficient_access", + "error_message" => "operation requires debug access to job", + "resource_type" => "job", + )} + end + + context "with sufficient authorization" do + let(:params) {{}} + + before { Travis::API::V3::Models::Permission.create(repository: repo, user: repo.owner, push: true) } + before { post("/v3/job/#{job.id}/debug", {}, headers) } + + example { expect(last_response.status).to be == 202 } + + example { expect(job.reload.debug_options).to include( + stage: "before_install", + created_by: owner.login, + quiet: false + ) } + end + end + end +end \ No newline at end of file diff --git a/spec/v3/services/job/find_spec.rb b/spec/v3/services/job/find_spec.rb index bf366386..cc2e6967 100644 --- a/spec/v3/services/job/find_spec.rb +++ b/spec/v3/services/job/find_spec.rb @@ -23,7 +23,8 @@ describe Travis::API::V3::Services::Job::Find do "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => job.id, "number" => job.number, "state" => job.state, @@ -93,7 +94,8 @@ describe Travis::API::V3::Services::Job::Find do "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => job.id, "number" => job.number, "state" => job.state, diff --git a/spec/v3/services/jobs/find_spec.rb b/spec/v3/services/jobs/find_spec.rb index f7b4c851..12ffa4fa 100644 --- a/spec/v3/services/jobs/find_spec.rb +++ b/spec/v3/services/jobs/find_spec.rb @@ -21,7 +21,8 @@ describe Travis::API::V3::Services::Jobs::Find do "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => jobs[0].id, "number" => "#{jobs[0].number}", "state" => "configured", @@ -30,45 +31,46 @@ describe Travis::API::V3::Services::Jobs::Find do "build" => { "@type" => "build", "@href" => "/v3/build/#{build.id}", - "@representation"=> "minimal", - "id" => build.id, - "number" => build.number, - "state" => "configured", - "duration" => nil, - "event_type" => "push", - "previous_state" => "passed", - "started_at" => "2010-11-12T13:00:00Z", - "finished_at" => nil}, - "queue" => "builds.linux", - "repository" =>{ - "@type" => "repository", - "@href" => "/v3/repo/1", - "@representation"=>"minimal", - "id" => repo.id, + "@representation"=> "minimal", + "id" => build.id, + "number" => build.number, + "state" => "configured", + "duration" => nil, + "event_type" => "push", + "previous_state" => "passed", + "started_at" => "2010-11-12T13:00:00Z", + "finished_at" => nil}, + "queue" => "builds.linux", + "repository" =>{ + "@type" => "repository", + "@href" => "/v3/repo/1", + "@representation"=>"minimal", + "id" => repo.id, "name" => "minimal", - "slug" => "svenfuchs/minimal"}, - "commit" =>{ - "@type" => "commit", - "@representation"=> "minimal", - "id" => commit.id, - "sha" => commit.commit, - "ref" => commit.ref, - "message" => commit.message, - "compare_url" => commit.compare_url, - "committed_at" =>"2010-11-12T12:55:00Z"}, - "owner" =>{ - "@type" => "user", - "@href" => "/v3/user/1", - "@representation"=> "minimal", - "id" => 1, - "login" => "svenfuchs"}}, + "slug" => "svenfuchs/minimal"}, + "commit" =>{ + "@type" => "commit", + "@representation"=> "minimal", + "id" => commit.id, + "sha" => commit.commit, + "ref" => commit.ref, + "message" => commit.message, + "compare_url" => commit.compare_url, + "committed_at" =>"2010-11-12T12:55:00Z"}, + "owner" =>{ + "@type" => "user", + "@href" => "/v3/user/1", + "@representation"=> "minimal", + "id" => 1, + "login" => "svenfuchs"}}, {"@type" => "job", "@href" => "/v3/job/#{jobs[1].id}", "@representation" => "standard", "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => jobs[1].id, "number" => "#{jobs[1].number}", "state" => "configured", @@ -77,45 +79,46 @@ describe Travis::API::V3::Services::Jobs::Find do "build" => { "@type" => "build", "@href" => "/v3/build/#{build.id}", - "@representation"=> "minimal", - "id" => build.id, - "number" => build.number, - "state" => "configured", - "duration" => nil, - "event_type" => "push", - "previous_state" => "passed", - "started_at" => "2010-11-12T13:00:00Z", - "finished_at" => nil}, - "queue" => "builds.linux", - "repository" =>{ - "@type" => "repository", - "@href" => "/v3/repo/1", - "@representation"=>"minimal", - "id" => repo.id, + "@representation"=> "minimal", + "id" => build.id, + "number" => build.number, + "state" => "configured", + "duration" => nil, + "event_type" => "push", + "previous_state" => "passed", + "started_at" => "2010-11-12T13:00:00Z", + "finished_at" => nil}, + "queue" => "builds.linux", + "repository" =>{ + "@type" => "repository", + "@href" => "/v3/repo/1", + "@representation"=>"minimal", + "id" => repo.id, "name" => "minimal", - "slug" => "svenfuchs/minimal"}, - "commit" =>{ - "@type" => "commit", - "@representation"=> "minimal", - "id" => commit.id, - "sha" => commit.commit, - "ref" => commit.ref, - "message" => commit.message, - "compare_url" => commit.compare_url, - "committed_at" =>"2010-11-12T12:55:00Z"}, - "owner" =>{ - "@type" => "user", - "@href" => "/v3/user/1", - "@representation"=> "minimal", - "id" => 1, - "login" => "svenfuchs"}}, + "slug" => "svenfuchs/minimal"}, + "commit" =>{ + "@type" => "commit", + "@representation"=> "minimal", + "id" => commit.id, + "sha" => commit.commit, + "ref" => commit.ref, + "message" => commit.message, + "compare_url" => commit.compare_url, + "committed_at" =>"2010-11-12T12:55:00Z"}, + "owner" =>{ + "@type" => "user", + "@href" => "/v3/user/1", + "@representation"=> "minimal", + "id" => 1, + "login" => "svenfuchs"}}, {"@type" => "job", "@href" => "/v3/job/#{jobs[2].id}", "@representation" => "standard", "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => jobs[2].id, "number" => "#{jobs[2].number}", "state" => "configured", @@ -124,45 +127,46 @@ describe Travis::API::V3::Services::Jobs::Find do "build" => { "@type" => "build", "@href" => "/v3/build/#{build.id}", - "@representation"=> "minimal", - "id" => build.id, - "number" => build.number, - "state" => "configured", - "duration" => nil, - "event_type" => "push", - "previous_state" => "passed", - "started_at" => "2010-11-12T13:00:00Z", - "finished_at" => nil}, - "queue" => "builds.linux", - "repository" =>{ - "@type" => "repository", - "@href" => "/v3/repo/1", - "@representation"=>"minimal", - "id" => repo.id, + "@representation"=> "minimal", + "id" => build.id, + "number" => build.number, + "state" => "configured", + "duration" => nil, + "event_type" => "push", + "previous_state" => "passed", + "started_at" => "2010-11-12T13:00:00Z", + "finished_at" => nil}, + "queue" => "builds.linux", + "repository" =>{ + "@type" => "repository", + "@href" => "/v3/repo/1", + "@representation"=>"minimal", + "id" => repo.id, "name" => "minimal", - "slug" => "svenfuchs/minimal"}, - "commit" =>{ - "@type" => "commit", - "@representation"=> "minimal", - "id" => commit.id, - "sha" => commit.commit, - "ref" => commit.ref, - "message" => commit.message, - "compare_url" => commit.compare_url, - "committed_at" =>"2010-11-12T12:55:00Z"}, - "owner" =>{ - "@type" => "user", - "@href" => "/v3/user/1", - "@representation"=> "minimal", - "id" => 1, - "login" => "svenfuchs"}}, + "slug" => "svenfuchs/minimal"}, + "commit" =>{ + "@type" => "commit", + "@representation"=> "minimal", + "id" => commit.id, + "sha" => commit.commit, + "ref" => commit.ref, + "message" => commit.message, + "compare_url" => commit.compare_url, + "committed_at" =>"2010-11-12T12:55:00Z"}, + "owner" =>{ + "@type" => "user", + "@href" => "/v3/user/1", + "@representation"=> "minimal", + "id" => 1, + "login" => "svenfuchs"}}, {"@type" => "job", "@href" => "/v3/job/#{jobs[3].id}", "@representation" => "standard", "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => jobs[3].id, "number" => "#{jobs[3].number}", "state" => "configured", @@ -171,38 +175,38 @@ describe Travis::API::V3::Services::Jobs::Find do "build" => { "@type" => "build", "@href" => "/v3/build/#{build.id}", - "@representation"=> "minimal", - "id" => build.id, - "number" => build.number, - "state" => "configured", - "duration" => nil, - "event_type" => "push", - "previous_state" => "passed", - "started_at" => "2010-11-12T13:00:00Z", - "finished_at" => nil}, - "queue" => "builds.linux", - "repository" =>{ - "@type" => "repository", - "@href" => "/v3/repo/1", - "@representation"=>"minimal", - "id" => repo.id, + "@representation"=> "minimal", + "id" => build.id, + "number" => build.number, + "state" => "configured", + "duration" => nil, + "event_type" => "push", + "previous_state" => "passed", + "started_at" => "2010-11-12T13:00:00Z", + "finished_at" => nil}, + "queue" => "builds.linux", + "repository" =>{ + "@type" => "repository", + "@href" => "/v3/repo/1", + "@representation"=>"minimal", + "id" => repo.id, "name" => "minimal", - "slug" => "svenfuchs/minimal"}, - "commit" =>{ - "@type" => "commit", - "@representation"=> "minimal", - "id" => commit.id, - "sha" => commit.commit, - "ref" => commit.ref, - "message" => commit.message, - "compare_url" => commit.compare_url, - "committed_at" =>"2010-11-12T12:55:00Z"}, - "owner" =>{ - "@type" => "user", - "@href" => "/v3/user/1", - "@representation"=> "minimal", - "id" => 1, - "login" => "svenfuchs"}} + "slug" => "svenfuchs/minimal"}, + "commit" =>{ + "@type" => "commit", + "@representation"=> "minimal", + "id" => commit.id, + "sha" => commit.commit, + "ref" => commit.ref, + "message" => commit.message, + "compare_url" => commit.compare_url, + "committed_at" =>"2010-11-12T12:55:00Z"}, + "owner" =>{ + "@type" => "user", + "@href" => "/v3/user/1", + "@representation"=> "minimal", + "id" => 1, + "login" => "svenfuchs"}} ] } } @@ -227,7 +231,8 @@ describe Travis::API::V3::Services::Jobs::Find do "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => jobs[0].id, "number" => "#{jobs[0].number}", "state" => "configured", @@ -236,45 +241,46 @@ describe Travis::API::V3::Services::Jobs::Find do "build" => { "@type" => "build", "@href" => "/v3/build/#{build.id}", - "@representation"=> "minimal", - "id" => build.id, - "number" => build.number, - "state" => "configured", - "duration" => nil, - "event_type" => "push", - "previous_state" => "passed", - "started_at" => "2010-11-12T13:00:00Z", - "finished_at" => nil}, - "queue" => "builds.linux", - "repository" =>{ - "@type" => "repository", - "@href" => "/v3/repo/1", - "@representation"=>"minimal", - "id" => repo.id, + "@representation"=> "minimal", + "id" => build.id, + "number" => build.number, + "state" => "configured", + "duration" => nil, + "event_type" => "push", + "previous_state" => "passed", + "started_at" => "2010-11-12T13:00:00Z", + "finished_at" => nil}, + "queue" => "builds.linux", + "repository" =>{ + "@type" => "repository", + "@href" => "/v3/repo/1", + "@representation"=>"minimal", + "id" => repo.id, "name" => "minimal", - "slug" => "svenfuchs/minimal"}, - "commit" =>{ - "@type" => "commit", - "@representation"=> "minimal", - "id" => commit.id, - "sha" => commit.commit, - "ref" => commit.ref, - "message" => commit.message, - "compare_url" => commit.compare_url, - "committed_at" =>"2010-11-12T12:55:00Z"}, - "owner" =>{ - "@type" => "user", - "@href" => "/v3/user/1", - "@representation"=> "minimal", - "id" => 1, - "login" => "svenfuchs"}}, + "slug" => "svenfuchs/minimal"}, + "commit" =>{ + "@type" => "commit", + "@representation"=> "minimal", + "id" => commit.id, + "sha" => commit.commit, + "ref" => commit.ref, + "message" => commit.message, + "compare_url" => commit.compare_url, + "committed_at" =>"2010-11-12T12:55:00Z"}, + "owner" =>{ + "@type" => "user", + "@href" => "/v3/user/1", + "@representation"=> "minimal", + "id" => 1, + "login" => "svenfuchs"}}, {"@type" => "job", "@href" => "/v3/job/#{jobs[1].id}", "@representation" => "standard", "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => jobs[1].id, "number" => "#{jobs[1].number}", "state" => "configured", @@ -283,45 +289,46 @@ describe Travis::API::V3::Services::Jobs::Find do "build" => { "@type" => "build", "@href" => "/v3/build/#{build.id}", - "@representation"=> "minimal", - "id" => build.id, - "number" => build.number, - "state" => "configured", - "duration" => nil, - "event_type" => "push", - "previous_state" => "passed", - "started_at" => "2010-11-12T13:00:00Z", - "finished_at" => nil}, - "queue" => "builds.linux", - "repository" =>{ - "@type" => "repository", - "@href" => "/v3/repo/1", - "@representation"=>"minimal", - "id" => repo.id, + "@representation"=> "minimal", + "id" => build.id, + "number" => build.number, + "state" => "configured", + "duration" => nil, + "event_type" => "push", + "previous_state" => "passed", + "started_at" => "2010-11-12T13:00:00Z", + "finished_at" => nil}, + "queue" => "builds.linux", + "repository" =>{ + "@type" => "repository", + "@href" => "/v3/repo/1", + "@representation"=>"minimal", + "id" => repo.id, "name" => "minimal", - "slug" => "svenfuchs/minimal"}, - "commit" =>{ - "@type" => "commit", - "@representation"=> "minimal", - "id" => commit.id, - "sha" => commit.commit, - "ref" => commit.ref, - "message" => commit.message, - "compare_url" => commit.compare_url, - "committed_at" =>"2010-11-12T12:55:00Z"}, - "owner" =>{ - "@type" => "user", - "@href" => "/v3/user/1", - "@representation"=> "minimal", - "id" => 1, - "login" => "svenfuchs"}}, + "slug" => "svenfuchs/minimal"}, + "commit" =>{ + "@type" => "commit", + "@representation"=> "minimal", + "id" => commit.id, + "sha" => commit.commit, + "ref" => commit.ref, + "message" => commit.message, + "compare_url" => commit.compare_url, + "committed_at" =>"2010-11-12T12:55:00Z"}, + "owner" =>{ + "@type" => "user", + "@href" => "/v3/user/1", + "@representation"=> "minimal", + "id" => 1, + "login" => "svenfuchs"}}, {"@type" => "job", "@href" => "/v3/job/#{jobs[2].id}", "@representation" => "standard", "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => jobs[2].id, "number" => "#{jobs[2].number}", "state" => "configured", @@ -330,45 +337,46 @@ describe Travis::API::V3::Services::Jobs::Find do "build" => { "@type" => "build", "@href" => "/v3/build/#{build.id}", - "@representation"=> "minimal", - "id" => build.id, - "number" => build.number, - "state" => "configured", - "duration" => nil, - "event_type" => "push", - "previous_state" => "passed", - "started_at" => "2010-11-12T13:00:00Z", - "finished_at" => nil}, - "queue" => "builds.linux", - "repository" =>{ - "@type" => "repository", - "@href" => "/v3/repo/1", - "@representation"=>"minimal", - "id" => repo.id, + "@representation"=> "minimal", + "id" => build.id, + "number" => build.number, + "state" => "configured", + "duration" => nil, + "event_type" => "push", + "previous_state" => "passed", + "started_at" => "2010-11-12T13:00:00Z", + "finished_at" => nil}, + "queue" => "builds.linux", + "repository" =>{ + "@type" => "repository", + "@href" => "/v3/repo/1", + "@representation"=>"minimal", + "id" => repo.id, "name" => "minimal", - "slug" => "svenfuchs/minimal"}, - "commit" =>{ - "@type" => "commit", - "@representation"=> "minimal", - "id" => commit.id, - "sha" => commit.commit, - "ref" => commit.ref, - "message" => commit.message, - "compare_url" => commit.compare_url, - "committed_at" =>"2010-11-12T12:55:00Z"}, - "owner" =>{ - "@type" => "user", - "@href" => "/v3/user/1", - "@representation"=> "minimal", - "id" => 1, - "login" => "svenfuchs"}}, + "slug" => "svenfuchs/minimal"}, + "commit" =>{ + "@type" => "commit", + "@representation"=> "minimal", + "id" => commit.id, + "sha" => commit.commit, + "ref" => commit.ref, + "message" => commit.message, + "compare_url" => commit.compare_url, + "committed_at" =>"2010-11-12T12:55:00Z"}, + "owner" =>{ + "@type" => "user", + "@href" => "/v3/user/1", + "@representation"=> "minimal", + "id" => 1, + "login" => "svenfuchs"}}, {"@type" => "job", "@href" => "/v3/job/#{jobs[3].id}", "@representation" => "standard", "@permissions" => { "read" => true, "cancel" => false, - "restart" => false }, + "restart" => false, + "debug" => false }, "id" => jobs[3].id, "number" => "#{jobs[3].number}", "state" => "configured", @@ -377,38 +385,38 @@ describe Travis::API::V3::Services::Jobs::Find do "build" => { "@type" => "build", "@href" => "/v3/build/#{build.id}", - "@representation"=> "minimal", - "id" => build.id, - "number" => build.number, - "state" => "configured", - "duration" => nil, - "event_type" => "push", - "previous_state" => "passed", - "started_at" => "2010-11-12T13:00:00Z", - "finished_at" => nil}, - "queue" => "builds.linux", - "repository" =>{ - "@type" => "repository", - "@href" => "/v3/repo/1", - "@representation"=>"minimal", - "id" => repo.id, + "@representation"=> "minimal", + "id" => build.id, + "number" => build.number, + "state" => "configured", + "duration" => nil, + "event_type" => "push", + "previous_state" => "passed", + "started_at" => "2010-11-12T13:00:00Z", + "finished_at" => nil}, + "queue" => "builds.linux", + "repository" =>{ + "@type" => "repository", + "@href" => "/v3/repo/1", + "@representation"=>"minimal", + "id" => repo.id, "name" => "minimal", - "slug" => "svenfuchs/minimal"}, - "commit" =>{ - "@type" => "commit", - "@representation"=> "minimal", - "id" => commit.id, - "sha" => commit.commit, - "ref" => commit.ref, - "message" => commit.message, - "compare_url" => commit.compare_url, - "committed_at" =>"2010-11-12T12:55:00Z"}, - "owner" =>{ - "@type" => "user", - "@href" => "/v3/user/1", - "@representation"=> "minimal", - "id" => 1, - "login" => "svenfuchs"}} + "slug" => "svenfuchs/minimal"}, + "commit" =>{ + "@type" => "commit", + "@representation"=> "minimal", + "id" => commit.id, + "sha" => commit.commit, + "ref" => commit.ref, + "message" => commit.message, + "compare_url" => commit.compare_url, + "committed_at" =>"2010-11-12T12:55:00Z"}, + "owner" =>{ + "@type" => "user", + "@href" => "/v3/user/1", + "@representation"=> "minimal", + "id" => 1, + "login" => "svenfuchs"}} ] } } diff --git a/spec/v3/services/repositories/for_owner_spec.rb b/spec/v3/services/repositories/for_owner_spec.rb index d2a8c784..f8300493 100644 --- a/spec/v3/services/repositories/for_owner_spec.rb +++ b/spec/v3/services/repositories/for_owner_spec.rb @@ -11,6 +11,7 @@ describe Travis::API::V3::Services::Repositories::ForOwner do before { repo.update_attribute(:private, true) } after { repo.update_attribute(:private, false) } + describe "private repository, private API, authenticated as user with access" do before { get("/v3/owner/svenfuchs/repos", {}, headers) } example { expect(last_response).to be_ok } @@ -104,4 +105,69 @@ describe Travis::API::V3::Services::Repositories::ForOwner do example { expect(JSON.load(body)['@href']) .to be == "/v3/repos?starred=false" } example { expect(JSON.load(body)['repositories']) .to be_empty } end + + describe "sorting by default_branch.last_build" do + let(:repo2) { Travis::API::V3::Models::Repository.create(owner_name: 'svenfuchs', name: 'maximal', owner_id: 1, owner_type: "User", last_build_state: "passed", active: true, last_build_id: 1788, next_build_number: 3) } + before { repo2.save! } + before { get("/v3/owner/svenfuchs/repos?sort_by=default_branch.last_build", {}, headers) } + example { expect(last_response).to be_ok } + example { expect(JSON.load(body)['@href']) .to be == "/v3/owner/svenfuchs/repos?sort_by=default_branch.last_build" } + example { expect(JSON.load(body)['repositories']) .to be == [{ + "@type" => "repository", + "@href" => "/v3/repo/1", + "@representation" => "standard", + "@permissions" => { + "read" => true, + "enable" => false, + "disable" => false, + "star" => false, + "unstar" => false, + "create_request"=> false }, + "id" => 1, + "name" => "minimal", + "slug" => "svenfuchs/minimal", + "description" => nil, + "github_language" => nil, + "active" => true, + "private" => true, + "owner" => { + "@type" => "user", + "id" => 1, + "login" => "svenfuchs", + "@href" => "/v3/user/1" }, + "default_branch" => { + "@type" => "branch", + "@href" => "/v3/repo/1/branch/master", + "@representation"=>"minimal", + "name" => "master" }, + "starred" => false }, { + "@type" => "repository", + "@href" => "/v3/repo/#{repo2.id}", + "@representation" => "standard", + "@permissions" => { + "read" => true, + "enable" => false, + "disable" => false, + "star" => false, + "unstar" => false, + "create_request"=> false }, + "id" => repo2.id, + "name" => "maximal", + "slug" => "svenfuchs/maximal", + "description" => nil, + "github_language" => nil, + "active" => true, + "private" => false, + "owner" => { + "@type" => "user", + "id" => 1, + "login" => "svenfuchs", + "@href" => "/v3/user/1" }, + "default_branch" => { + "@type" => "branch", + "@href" => "/v3/repo/#{repo2.id}/branch/master", + "@representation"=>"minimal", + "name" =>"master" }, + "starred"=>false}]} + end end