From 517a3b04f79f808afad3c03ba6849ca94adc807a Mon Sep 17 00:00:00 2001 From: carlad Date: Tue, 27 Jan 2015 16:22:30 +0100 Subject: [PATCH] Revert "Revert "Merge branch 'master' of github.com:travis-ci/travis-api"" This reverts commit 171b9c57c79b74e46a285e102e47a69a49719d77. --- .gitignore | 1 - Gemfile | 2 +- Gemfile.lock | 43 ++++----------- Procfile | 1 + lib/travis/api/app/endpoint/builds.rb | 16 +++++- lib/travis/api/app/endpoint/jobs.rb | 16 +++++- lib/travis/api/workers/build_cancellation.rb | 19 +++++++ lib/travis/api/workers/build_restart.rb | 19 +++++++ lib/travis/api/workers/job_cancellation.rb | 19 +++++++ lib/travis/api/workers/job_restart.rb | 19 +++++++ lib/travis/sidekiq.rb | 22 ++++++++ spec/integration/v2/builds_spec.rb | 55 +++++++++++++++++--- spec/integration/v2/jobs_spec.rb | 52 +++++++++++++++--- 13 files changed, 234 insertions(+), 50 deletions(-) create mode 100644 lib/travis/api/workers/build_cancellation.rb create mode 100644 lib/travis/api/workers/build_restart.rb create mode 100644 lib/travis/api/workers/job_cancellation.rb create mode 100644 lib/travis/api/workers/job_restart.rb create mode 100644 lib/travis/sidekiq.rb diff --git a/.gitignore b/.gitignore index ec837dcd..e5dd18e6 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,3 @@ log/ vendor config/skylight.yml .coverage -.coverage/ diff --git a/Gemfile b/Gemfile index 4c6c11ca..8aa43451 100644 --- a/Gemfile +++ b/Gemfile @@ -8,7 +8,7 @@ gem 's3', github: 'travis-ci/s3' gem 'travis-core', github: 'travis-ci/travis-core' gem 'travis-support', github: 'travis-ci/travis-support' gem 'travis-config', '~> 0.1.0' -gem 'travis-sidekiqs', github: 'travis-ci/travis-sidekiqs', require: nil, ref: 'cde9741' +gem 'travis-sidekiqs', github: 'travis-ci/travis-sidekiqs', require: nil gem 'travis-yaml', github: 'travis-ci/travis-yaml' gem 'mustermann', github: 'rkh/mustermann' gem 'sinatra' diff --git a/Gemfile.lock b/Gemfile.lock index 80283b3f..c846a17e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -74,11 +74,10 @@ GIT GIT remote: git://github.com/travis-ci/travis-sidekiqs.git - revision: cde9741f8e6811fe3929bdd0dd653b87289c5eef - ref: cde9741 + revision: 21a2fee158e25252dd78f5fa31e81b4f6583be23 specs: travis-sidekiqs (0.0.1) - sidekiq (~> 2.5.0) + sidekiq GIT remote: git://github.com/travis-ci/travis-support.git @@ -149,26 +148,13 @@ GEM backports (3.6.4) builder (3.0.4) bunny (0.8.0) - celluloid (0.12.0) - timers (>= 1.0.0) - chunky_png (1.3.3) + celluloid (0.16.0) + timers (~> 4.0.0) coder (0.4.0) coderay (1.1.0) coercible (1.0.0) descendants_tracker (~> 0.0.1) - compass (1.0.1) - chunky_png (~> 1.2) - compass-core (~> 1.0.1) - compass-import-once (~> 1.0.5) - rb-fsevent (>= 0.9.3) - rb-inotify (>= 0.9) - sass (>= 3.3.13, < 3.5) - compass-core (1.0.1) - multi_json (~> 1.0) - sass (>= 3.3.0, < 3.5) - compass-import-once (1.0.5) - sass (>= 3.2, < 3.5) - connection_pool (0.9.3) + connection_pool (2.1.1) daemons (1.1.9) dalli (2.7.2) data_migrations (0.0.1) @@ -282,16 +268,12 @@ GEM rspec-expectations (2.99.2) diff-lcs (>= 1.1.3, < 2.0) rspec-mocks (2.99.2) - sass (3.4.6) - sidekiq (2.5.0) - celluloid (~> 0.12.0) - compass - connection_pool (~> 0.9.2) - multi_json (~> 1) - redis (~> 3) - redis-namespace - sass - sprockets-sass + sidekiq (3.3.0) + celluloid (>= 0.16.0) + connection_pool (>= 2.0.0) + json + redis (>= 3.0.6) + redis-namespace (>= 1.3.1) signature (0.1.7) simple_states (1.0.1) activesupport @@ -320,9 +302,6 @@ GEM multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - sprockets-sass (1.2.0) - sprockets (~> 2.0) - tilt (~> 1.1) thin (1.6.3) daemons (~> 1.0, >= 1.0.9) eventmachine (~> 1.0) diff --git a/Procfile b/Procfile index bbb53736..6d6d6353 100644 --- a/Procfile +++ b/Procfile @@ -1,2 +1,3 @@ web: bundle exec ./script/server console: bundle exec ./script/console +sidekiq: bundle exec sidekiq -c 5 -r ./lib/travis/sidekiq.rb -q build_cancellations, -q build_restarts, -q job_cancellations, -q job_restarts diff --git a/lib/travis/api/app/endpoint/builds.rb b/lib/travis/api/app/endpoint/builds.rb index 2f1e5837..91d375dc 100644 --- a/lib/travis/api/app/endpoint/builds.rb +++ b/lib/travis/api/app/endpoint/builds.rb @@ -1,4 +1,6 @@ require 'travis/api/app' +require 'travis/api/workers/build_cancellation' +require 'travis/api/workers/build_restart' class Travis::Api::App class Endpoint @@ -37,7 +39,7 @@ class Travis::Api::App status 422 respond_with json else - service.run + Travis::Sidekiq::BuildCancellation.perform_async(id: params[:id], user_id: current_user.id, source: 'api') Metriks.meter("api.request.cancel_build.success").mark status 204 @@ -46,7 +48,17 @@ class Travis::Api::App post '/:id/restart' do Metriks.meter("api.request.restart_build").mark - respond_with service(:reset_model, build_id: params[:id]) + + service = self.service(:reset_model, build_id: params[:id]) + if !service.accept? + status 400 + result = false + else + Travis::Sidekiq::BuildRestart.perform_async(id: params[:id], user_id: current_user.id) + status 202 + result = true + end + respond_with(result: result, flash: service.messages) end end end diff --git a/lib/travis/api/app/endpoint/jobs.rb b/lib/travis/api/app/endpoint/jobs.rb index 0d65e78e..9bb2fbc9 100644 --- a/lib/travis/api/app/endpoint/jobs.rb +++ b/lib/travis/api/app/endpoint/jobs.rb @@ -1,4 +1,6 @@ require 'travis/api/app' +require 'travis/api/workers/job_cancellation' +require 'travis/api/workers/job_restart' class Travis::Api::App class Endpoint @@ -44,7 +46,7 @@ class Travis::Api::App status 422 respond_with json else - service.run + Travis::Sidekiq::JobCancellation.perform_async(id: params[:id], user_id: current_user.id, source: 'api') Metriks.meter("api.request.cancel_job.success").mark status 204 @@ -53,7 +55,17 @@ class Travis::Api::App post '/:id/restart' do Metriks.meter("api.request.restart_job").mark - respond_with service(:reset_model, job_id: params[:id]) + + service = self.service(:reset_model, job_id: params[:id]) + if !service.accept? + status 400 + result = false + else + Travis::Sidekiq::JobRestart.perform_async(id: params[:id], user_id: current_user.id) + status 202 + result = true + end + respond_with(result: result, flash: service.messages) end get '/:job_id/log' do diff --git a/lib/travis/api/workers/build_cancellation.rb b/lib/travis/api/workers/build_cancellation.rb new file mode 100644 index 00000000..bf1eca76 --- /dev/null +++ b/lib/travis/api/workers/build_cancellation.rb @@ -0,0 +1,19 @@ +require 'sidekiq/worker' +require 'multi_json' + +module Travis + module Sidekiq + class BuildCancellation + class ProcessingError < StandardError; end + + include ::Sidekiq::Worker + sidekiq_options queue: :build_cancellations + + def perform(data) + user = User.find(data['user_id']) + Travis.service(:cancel_build, user, { id: data['id'], source: data['source'] }).run + end + + end + end +end diff --git a/lib/travis/api/workers/build_restart.rb b/lib/travis/api/workers/build_restart.rb new file mode 100644 index 00000000..427bc24b --- /dev/null +++ b/lib/travis/api/workers/build_restart.rb @@ -0,0 +1,19 @@ +require 'sidekiq/worker' +require 'multi_json' + +module Travis + module Sidekiq + class BuildRestart + class ProcessingError < StandardError; end + + include ::Sidekiq::Worker + sidekiq_options queue: :build_restarts + + def perform(data) + user = User.find(data['user_id']) + Travis.service(:reset_model, user, build_id: data['id']).run + end + + end + end +end diff --git a/lib/travis/api/workers/job_cancellation.rb b/lib/travis/api/workers/job_cancellation.rb new file mode 100644 index 00000000..dadf60d0 --- /dev/null +++ b/lib/travis/api/workers/job_cancellation.rb @@ -0,0 +1,19 @@ +require 'sidekiq/worker' +require 'multi_json' + +module Travis + module Sidekiq + class JobCancellation + class ProcessingError < StandardError; end + + include ::Sidekiq::Worker + sidekiq_options queue: :job_cancellations + + def perform(data) + user = User.find(data['user_id']) + Travis.service(:cancel_job, user, { id: data['id'], source: data['source'] }).run + end + + end + end +end diff --git a/lib/travis/api/workers/job_restart.rb b/lib/travis/api/workers/job_restart.rb new file mode 100644 index 00000000..12ab6b33 --- /dev/null +++ b/lib/travis/api/workers/job_restart.rb @@ -0,0 +1,19 @@ +require 'sidekiq/worker' +require 'multi_json' + +module Travis + module Sidekiq + class JobRestart + class ProcessingError < StandardError; end + + include ::Sidekiq::Worker + sidekiq_options queue: :job_restarts + + def perform(data) + user = User.find(data['user_id']) + Travis.service(:reset_model, user, job_id: data['id']).run + end + + end + end +end diff --git a/lib/travis/sidekiq.rb b/lib/travis/sidekiq.rb new file mode 100644 index 00000000..6822f930 --- /dev/null +++ b/lib/travis/sidekiq.rb @@ -0,0 +1,22 @@ +#$: << './lib' +require 'sidekiq' +require 'travis' +require 'travis/api/workers/build_cancellation' +require 'travis/api/workers/build_restart' +require 'travis/api/workers/job_cancellation' +require 'travis/api/workers/job_restart' +require 'travis/support/amqp' + +Travis::Database.connect +Travis::Async.enabled = true +Travis::Amqp.config = Travis.config.amqp +Travis::Metrics.setup +Travis::Notification.setup + +Sidekiq.configure_server do |config| + config.redis = Travis.config.redis.merge(namespace: Travis.config.sidekiq.namespace) +end + +Sidekiq.configure_client do |config| + config.redis = Travis.config.redis.merge(size: 1, namespace: Travis.config.sidekiq.namespace) +end diff --git a/spec/integration/v2/builds_spec.rb b/spec/integration/v2/builds_spec.rb index 4c528c53..e36aeeb2 100644 --- a/spec/integration/v2/builds_spec.rb +++ b/spec/integration/v2/builds_spec.rb @@ -75,17 +75,60 @@ describe 'Builds' do end context 'when build can be canceled' do - it 'cancels the build and responds with 204' do + before do + Travis::Sidekiq::BuildCancellation.stubs(:perform_async) build.matrix.each { |j| j.update_attribute(:state, 'created') } build.update_attribute(:state, 'created') + end - response = nil - expect { - response = post "/builds/#{build.id}/cancel", {}, headers - }.to change { build.reload.state } + it 'cancels the build' do + Travis::Sidekiq::BuildCancellation.expects(:perform_async).with( id: build.id.to_s, user_id: user.id, source: 'api') + post "/builds/#{build.id}/cancel", {}, headers + end + + it 'responds with 204' do + response = post "/builds/#{build.id}/cancel", {}, headers response.status.should == 204 + end + end + end - build.state.should == 'canceled' + describe 'POST /builds/:id/restart' 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 restart is not acceptable' do + before { user.permissions.destroy_all } + + it 'responds with 400' do + response = post "/builds/#{build.id}/restart", {}, headers + response.status.should == 400 + end + end + + context 'when build passed' do + before do + Travis::Sidekiq::BuildCancellation.stubs(:perform_async) + build.matrix.each { |j| j.update_attribute(:state, 'passed') } + build.update_attribute(:state, 'passed') + end + + it 'restarts the build' do + Travis::Sidekiq::BuildRestart.expects(:perform_async).with(id: build.id.to_s, user_id: user.id) + response = post "/builds/#{build.id}/restart", {}, headers + response.status.should == 202 + end + + it 'sends the correct response body' do + Travis::Sidekiq::BuildRestart.expects(:perform_async).with(id: build.id.to_s, user_id: user.id) + response = post "/builds/#{build.id}/restart", {}, headers + body = JSON.parse(response.body) + body.should == {"result"=>true, "flash"=>[{"notice"=>"The build was successfully restarted."}]} end end end diff --git a/spec/integration/v2/jobs_spec.rb b/spec/integration/v2/jobs_spec.rb index a17a4b17..81486845 100644 --- a/spec/integration/v2/jobs_spec.rb +++ b/spec/integration/v2/jobs_spec.rb @@ -242,16 +242,56 @@ describe 'Jobs' do end context 'when job can be canceled' do - it 'cancels the job and responds with 204' do + before do job.update_attribute(:state, 'created') + end - response = nil - expect { - response = post "/jobs/#{job.id}/cancel", {}, headers - }.to change { job.reload.state } + it 'cancels the job' do + Travis::Sidekiq::JobCancellation.expects(:perform_async).with( id: job.id.to_s, user_id: user.id, source: 'api') + post "/jobs/#{job.id}/cancel", {}, headers + end + + it 'responds with 204' do + response = post "/jobs/#{job.id}/cancel", {}, headers response.status.should == 204 + end + end + end - job.state.should == 'canceled' + describe 'POST /jobs/:id/restart' 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, :pull => true, :push => true) + } + + context 'when restart is not acceptable' do + before { user.permissions.destroy_all } + + it 'responds with 400' do + response = post "/jobs/#{job.id}/restart", {}, headers + response.status.should == 400 + end + end + + context 'when job passed' do + before do + Travis::Sidekiq::JobCancellation.stubs(:perform_async) + job.update_attribute(:state, 'passed') + end + + it 'restarts the job' do + Travis::Sidekiq::JobRestart.expects(:perform_async).with(id: job.id.to_s, user_id: user.id) + response = post "/jobs/#{job.id}/restart", {}, headers + response.status.should == 202 + end + it 'sends the correct response body' do + Travis::Sidekiq::JobRestart.expects(:perform_async).with(id: job.id.to_s, user_id: user.id) + response = post "/jobs/#{job.id}/restart", {}, headers + body = JSON.parse(response.body) + body.should == {"result"=>true, "flash"=>[{"notice"=>"The job was successfully restarted."}]} end end end