diff --git a/app/assets/stylesheets/design/custom.scss b/app/assets/stylesheets/design/custom.scss index d6fbed8e5..6e57d4df0 100644 --- a/app/assets/stylesheets/design/custom.scss +++ b/app/assets/stylesheets/design/custom.scss @@ -982,6 +982,10 @@ table.diff { } /* Mass build forms */ +.mass-build-actions a.button { + margin-bottom: 5px; +} + form.mass_build input[type="checkbox"] { width: 10px; height: 11px; @@ -1537,6 +1541,10 @@ table.tablesorter.platform-maintainers.static-search thead tr.search th input[ty width: 430px; } +.tablesorter .right { + text-align: right; +} + .all_platforms { > .both { margin: 0 0 5px; } .build_for_pl { font-weight: bold; } diff --git a/app/controllers/platforms/mass_builds_controller.rb b/app/controllers/platforms/mass_builds_controller.rb index f35127f1d..ff90c71b2 100644 --- a/app/controllers/platforms/mass_builds_controller.rb +++ b/app/controllers/platforms/mass_builds_controller.rb @@ -6,8 +6,8 @@ class Platforms::MassBuildsController < Platforms::BaseController load_and_authorize_resource skip_load_and_authorize_resource :only => [:index, :create] - skip_load_and_authorize_resource :platform, :only => [:cancel, :failed_builds_list] - skip_authorize_resource :platform, :only => [:create, :index] + skip_load_and_authorize_resource :platform, :only => [:cancel, :failed_builds_list, :publish] + skip_authorize_resource :platform, :only => [:index, :create] def create mass_build = @platform.mass_builds.new(:arches => params[:arches], @@ -27,6 +27,15 @@ class Platforms::MassBuildsController < Platforms::BaseController end end + def publish + if params[:status] == 'test_failed' + @mass_build.publish_test_faild_builds + else + @mass_build.publish_success_builds + end + redirect_to(platform_mass_builds_path(@mass_build.platform), :notice => t("flash.platform.publish_success")) + end + def index authorize! :local_admin_manage, @platform diff --git a/app/models/ability.rb b/app/models/ability.rb index f7d26c011..98a4939dc 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -98,7 +98,7 @@ class Ability can([:update, :destroy], Platform) {|platform| owner?(platform) } can([:local_admin_manage, :members, :add_member, :remove_member, :remove_members] , Platform) {|platform| owner?(platform) || local_admin?(platform) } - can([:get_list, :create], MassBuild) {|mass_build| (owner?(mass_build.platform) || local_admin?(mass_build.platform)) && mass_build.platform.main?} + can([:get_list, :create, :publish], MassBuild) {|mass_build| (owner?(mass_build.platform) || local_admin?(mass_build.platform)) && mass_build.platform.main?} can(:cancel, MassBuild) {|mass_build| (owner?(mass_build.platform) || local_admin?(mass_build.platform)) && !mass_build.stop_build && mass_build.platform.main?} can [:read, :projects_list, :projects], Repository, :platform => {:owner_type => 'User', :owner_id => user.id} @@ -158,7 +158,7 @@ class Ability cannot :create_container, BuildList, :new_core => false cannot(:publish, BuildList) {|build_list| !build_list.can_publish? } - cannot([:get_list, :create], MassBuild) {|mass_build| mass_build.platform.personal?} + cannot([:get_list, :create, :publish], MassBuild) {|mass_build| mass_build.platform.personal?} cannot(:cancel, MassBuild) {|mass_build| mass_build.platform.personal? || mass_build.stop_build} cannot(:regenerate_metadata, Repository) {|repository| !repository.platform.main?} diff --git a/app/models/mass_build.rb b/app/models/mass_build.rb index ffa14c480..14c2a84d1 100644 --- a/app/models/mass_build.rb +++ b/app/models/mass_build.rb @@ -28,7 +28,7 @@ class MassBuild < ActiveRecord::Base def build_all # later with resque - arches_list = arches ? Arch.where(:id => arches) : Arch.all + arches_list = arch_names ? Arch.where(:name => arch_names.split(', ')) : Arch.all auto_publish ||= false projects_list.lines.each do |name| @@ -70,8 +70,24 @@ class MassBuild < ActiveRecord::Base end later :cancel_all, :queue => :clone_build + def publish_success_builds + publish BuildList::SUCCESS, BuildList::FAILED_PUBLISH + end + later :publish_success_builds, :queue => :clone_build + + def publish_test_faild_builds + publish BuildList::TESTS_FAILED + end + later :publish_test_faild_builds, :queue => :clone_build + private + def publish(*statuses) + build_lists.where(:status => statuses).order(:id).find_in_batches(:batch_size => 50) do |bls| + bls.each{ |bl| bl.can_publish? && bl.now_publish } + end + end + def set_data if new_record? self.name = "#{Time.now.utc.to_date.strftime("%d.%b")}-#{platform.name}" diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index 98d0b68e6..a5ec9e656 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -34,7 +34,8 @@ class ProductBuildList < ActiveRecord::Base belongs_to :arch belongs_to :user - + # see: Issue #6 + before_validation lambda { self.arch_id = Arch.find_by_name('x86_64').id } validates :product_id, :status, :project_id, @@ -52,7 +53,6 @@ class ProductBuildList < ActiveRecord::Base :params, :project_version, :commit_hash, - :arch_id, :product_id attr_readonly :product_id serialize :results, Array diff --git a/app/models/pull_request.rb b/app/models/pull_request.rb index 77a769dce..47a2ff04d 100644 --- a/app/models/pull_request.rb +++ b/app/models/pull_request.rb @@ -78,12 +78,17 @@ class PullRequest < ActiveRecord::Base def merge!(who) return false unless can_merging? Dir.chdir(path) do + old_commit = to_project.repo.commits(to_ref).first commit = repo.commits(to_ref).first system "git config user.name \"#{who.uname}\" && git config user.email \"#{who.email}\"" res = merge if commit.id != repo.commits(to_ref).first.id - system("export GL_ID=user-#{who.id} && git push origin HEAD") + res2 = %x(export GL_ID=user-#{who.id} && git push origin HEAD) system("git reset --hard HEAD^") # for diff maybe FIXME + + if old_commit.id == to_project.repo.commits(to_ref).first.id + raise "merge result pull_request #{id}: #{$?.exitstatus}; #{res2}; #{res}" + end set_user_and_time who merging else # Try to catch no merge errors diff --git a/app/views/api/v1/product_build_lists/show.json.jbuilder b/app/views/api/v1/product_build_lists/show.json.jbuilder index 04362cf4a..d735eecf8 100644 --- a/app/views/api/v1/product_build_lists/show.json.jbuilder +++ b/app/views/api/v1/product_build_lists/show.json.jbuilder @@ -12,10 +12,6 @@ json.product_build_list do |json| :project => @product_build_list.project, :json => json_project end - json.arch do |json_arch| - json_arch.(@product_build_list.arch, :id, :name) - end - json.created_at @product_build_list.created_at.to_i json.updated_at @product_build_list.updated_at.to_i diff --git a/app/views/platforms/mass_builds/index.html.haml b/app/views/platforms/mass_builds/index.html.haml index 77b52a940..a5276ea0e 100644 --- a/app/views/platforms/mass_builds/index.html.haml +++ b/app/views/platforms/mass_builds/index.html.haml @@ -27,7 +27,7 @@ %th.lpadding16= t('activerecord.attributes.mass_build.name') %th.lpadding16= t("layout.mass_builds.statuses") %th.lpadding16= t("layout.mass_builds.failed_builds_list") - %th.lpadding16= t("layout.mass_builds.cancel_mass_build") + %th.lpadding16= t("layout.mass_builds.actions") %th.lpadding16= t("layout.mass_builds.extended_data") - @mass_builds.each do |mass_build| %tr @@ -43,7 +43,20 @@ = mass_build.read_attribute 'missed_projects_count' %td =link_to_list @platform, mass_build, 'failed_builds_list' - %td= link_to image_tag('x.png'), cancel_platform_mass_build_path(@platform, mass_build.id), :method => :post, :confirm => t("layout.mass_builds.cancel_confirm") if can?(:cancel, mass_build) + %td.right.mass-build-actions + - if can?(:publish, mass_build) + - unless mass_build.auto_publish? + = link_to t('layout.mass_builds.publish_success'), + publish_platform_mass_build_path(@platform, mass_build.id), + :method => :post, :confirm => t("layout.confirm"), :class => 'button' + = link_to t('layout.mass_builds.publish_test_failed'), + publish_platform_mass_build_path(@platform, mass_build.id, :status => 'test_failed'), + :method => :post, :confirm => t("layout.confirm"), :class => 'button' + - if can?(:cancel, mass_build) + = link_to t('layout.cancel'), + cancel_platform_mass_build_path(@platform, mass_build.id), + :method => :post, :class => 'button', + :confirm => t('layout.mass_builds.cancel_confirm') %td %a.toggle_btn{:href => "#toggle_#{ mass_build.id }", :'data-target' => "#toggle_#{ mass_build.id }"}= t("layout.mass_builds.extended_data") .toggle{:id => "toggle_#{ mass_build.id }"} diff --git a/app/views/platforms/product_build_lists/new.html.haml b/app/views/platforms/product_build_lists/new.html.haml index d1fbd0c82..6f03eb78a 100644 --- a/app/views/platforms/product_build_lists/new.html.haml +++ b/app/views/platforms/product_build_lists/new.html.haml @@ -12,10 +12,6 @@ .rightlist= f.select :project_version, versions_for_group_select(pbl.project), :selected => params[:product_build_lists].try(:fetch, :project_version) || pbl.project.default_branch .both - .leftlist= f.label :arch, t("activerecord.attributes.product_build_list.arch"), :class => :label - .rightlist= f.select :arch_id, Arch.recent.map{ |a| [a.name, a.id]} - .both - = render 'platforms/products/def_fields', :f => f = f.submit t("layout.projects.build_button") diff --git a/app/views/platforms/product_build_lists/show.html.haml b/app/views/platforms/product_build_lists/show.html.haml index 6af23ac72..a46024bbd 100644 --- a/app/views/platforms/product_build_lists/show.html.haml +++ b/app/views/platforms/product_build_lists/show.html.haml @@ -19,7 +19,6 @@ = render 'show_field', :key => :project_version, :value => product_build_list_version_link(pbl, true) -= render 'show_field', :key => :arch, :value => pbl.arch.name - [:main_script, :params].each do |el| = render 'show_field', :key => el, :value => pbl.send(el) diff --git a/config/locales/models/mass_build.en.yml b/config/locales/models/mass_build.en.yml index b8adf2f1f..bafb62b01 100644 --- a/config/locales/models/mass_build.en.yml +++ b/config/locales/models/mass_build.en.yml @@ -1,11 +1,13 @@ en: layout: mass_builds: + publish_success: Publish success builds + publish_test_failed: Publish test failed builds repositories: Repositories extended_data: Extended data failed_builds_list: Failed Builds List statuses: Statuses - cancel_mass_build: Cancel + actions: Actions cancel_confirm: Are you sure you want to cancel mass build? projects_list: Projects list missed_projects_list: 'Missed projects: ' diff --git a/config/locales/models/mass_build.ru.yml b/config/locales/models/mass_build.ru.yml index f202ba420..974e7f09d 100644 --- a/config/locales/models/mass_build.ru.yml +++ b/config/locales/models/mass_build.ru.yml @@ -1,11 +1,13 @@ ru: layout: mass_builds: + publish_success: Опубликовать успешные сборки + publish_test_failed: Опубликовать сборки с проваленными тестами repositories: Репозитории extended_data: Параметры задания failed_builds_list: Список ошибок сборок statuses: Статусы - cancel_mass_build: Отмена + actions: Действия cancel_confirm: Вы уверены, что хотите отменить массовую сборку? projects_list: Список проектов missed_projects_list: 'Несуществующие проекты: ' diff --git a/config/locales/models/platform.en.yml b/config/locales/models/platform.en.yml index afb83a510..b834312d1 100644 --- a/config/locales/models/platform.en.yml +++ b/config/locales/models/platform.en.yml @@ -62,6 +62,7 @@ en: build_all_success: All project build in progress build_all_error: Mass build failed cancel_mass_build: Mass build canceled + publish_success: Builds have been sent to queue for publishing successfully clone_success: Cloned successfully members: successfully_added: "%{name} successfully added to the platform" diff --git a/config/locales/models/platform.ru.yml b/config/locales/models/platform.ru.yml index a379f293b..a59233458 100644 --- a/config/locales/models/platform.ru.yml +++ b/config/locales/models/platform.ru.yml @@ -62,6 +62,7 @@ ru: build_all_success: Все проекты успешно отправлены на сборку build_all_error: Сборка не удалась! cancel_mass_build: Массовая сборка отменена + publish_success: Сборки успешно отправлены в очередь на публикацию clone_success: Клонирование успешно members: successfully_added: "Участник %{name} успешно добавлен к платформе" diff --git a/config/routes.rb b/config/routes.rb index 4d5e5c11c..6d0e10947 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -145,6 +145,7 @@ Rosa::Application.routes.draw do resources :mass_builds, :only => [:create, :index] do member do post :cancel + post :publish get '/:kind.:format' => "mass_builds#get_list", :as => :get_list, :kind => /failed_builds_list|missed_projects_list|projects_list/ end end diff --git a/lib/abf_worker/base_observer.rb b/lib/abf_worker/base_observer.rb index 45151da79..cc217648f 100644 --- a/lib/abf_worker/base_observer.rb +++ b/lib/abf_worker/base_observer.rb @@ -32,7 +32,7 @@ module AbfWorker def sort_results_and_save(results, item = subject) item.results = results.sort_by{ |r| r['file_name'] } - item.save! + item.save(:validate => false) end end diff --git a/lib/abf_worker/build_lists_publish_task_manager.rb b/lib/abf_worker/build_lists_publish_task_manager.rb index dc731f2dc..e8a9e88c7 100644 --- a/lib/abf_worker/build_lists_publish_task_manager.rb +++ b/lib/abf_worker/build_lists_publish_task_manager.rb @@ -228,6 +228,17 @@ module AbfWorker end def create_rpm_build_task(save_to_repository_id, build_for_platform_id) + projects_for_cleanup = @redis.lrange(PROJECTS_FOR_CLEANUP, 0, -1). + select{ |k| k =~ /#{save_to_repository_id}\-#{build_for_platform_id}$/ } + + # We should not to publish new builds into repository + # if project of builds has been removed from repository. + BuildList.where( + :project_id => projects_for_cleanup.map{ |k| k.split('-')[0] }.uniq, + :save_to_repository_id => save_to_repository_id, + :status => BuildList::BUILD_PUBLISH + ).update_all(:status => BuildList::FAILED_PUBLISH) + build_lists = BuildList. where(:new_core => true, :status => BuildList::BUILD_PUBLISH). where(:save_to_repository_id => save_to_repository_id). @@ -237,9 +248,6 @@ module AbfWorker build_lists = build_lists.where('build_lists.id NOT IN (?)', locked_ids) unless locked_ids.empty? build_lists = build_lists.limit(50) - projects_for_cleanup = @redis.lrange(PROJECTS_FOR_CLEANUP, 0, -1). - select{ |k| k =~ /#{save_to_repository_id}\-#{build_for_platform_id}$/ } - old_packages = {:sources => [], :binaries => {:x86_64 => [], :i586 => []}} projects_for_cleanup.each do |key| diff --git a/lib/abf_worker/publish_observer.rb b/lib/abf_worker/publish_observer.rb index a3958510f..a6166535a 100644 --- a/lib/abf_worker/publish_observer.rb +++ b/lib/abf_worker/publish_observer.rb @@ -36,9 +36,10 @@ module AbfWorker update_results build_list case status when COMPLETED - build_list.published + # 'update_column' - when project of build_list has been removed from repository + build_list.published || build_list.update_column(:status, BuildList::BUILD_PUBLISHED) when FAILED, CANCELED - build_list.fail_publish + build_list.fail_publish || build_list.update_column(:status, BuildList::FAILED_PUBLISH) end AbfWorker::BuildListsPublishTaskManager.unlock_build_list build_list end diff --git a/lib/ext/git/grit.rb b/lib/ext/git/grit.rb index 6200a079f..596d2a4fd 100644 --- a/lib/ext/git/grit.rb +++ b/lib/ext/git/grit.rb @@ -1,5 +1,14 @@ # -*- encoding : utf-8 -*- module Grit + class Commit + + # Fix: NoMethodError: undefined method 'touch' for Grit::Commit + # see: model Comment belongs_to :commentable + def touch + true + end + end + class Blob include Linguist::BlobHelper diff --git a/spec/controllers/platforms/mass_builds_controller_spec.rb b/spec/controllers/platforms/mass_builds_controller_spec.rb index e7a449a2c..b459124fd 100644 --- a/spec/controllers/platforms/mass_builds_controller_spec.rb +++ b/spec/controllers/platforms/mass_builds_controller_spec.rb @@ -22,6 +22,16 @@ shared_examples_for 'mass_build platform owner' do @mass_build.reload.stop_build.should == true end + it 'should be able to perform publish action' do + post :publish, :platform_id => @platform, :id => @mass_build + response.should redirect_to(platform_mass_builds_path(@platform)) + end + + it 'should change build_publish on publish' do + post :publish, :platform_id => @platform, :id => @mass_build + @mass_build.reload.build_publish_count.should == 1 + end + it 'should not be able to perform cancel action if stop_build is true' do @mass_build.stop_build = true; @mass_build.save post :cancel, :platform_id => @platform, :id => @mass_build @@ -34,10 +44,10 @@ shared_examples_for 'mass_build platform owner' do context 'for personal platform' do before(:each) do - Platform.update_all("platform_type = 'personal'") + Platform.update_all(:platform_type => 'personal') end - [:cancel, :get_list, :create].each do |action| + [:cancel, :get_list, :create, :publish].each do |action| it "should not be able to perform #{ action } action" do get action, :platform_id => @platform, :id => @mass_build.id response.should redirect_to(forbidden_path) @@ -54,7 +64,7 @@ shared_examples_for 'mass_build platform reader' do end end - [:cancel, :get_list].each do |action| + [:cancel, :get_list, :publish].each do |action| it "should not be able to perform #{ action } action" do get action, :platform_id => @platform, :id => @mass_build.id response.should redirect_to(forbidden_path) @@ -69,6 +79,11 @@ shared_examples_for 'mass_build platform reader' do post :cancel, :platform_id => @platform, :id => @mass_build @mass_build.reload.stop_build.should == false end + + it 'should not change build_publish on publish' do + post :publish, :platform_id => @platform, :id => @mass_build + @mass_build.reload.build_publish_count.should == 0 + end end @@ -92,6 +107,7 @@ describe Platforms::MassBuildsController do } @mass_build = FactoryGirl.create(:mass_build, :platform => @platform, :user => @user, :projects_list => project.name) + FactoryGirl.create(:build_list_core, :mass_build => @mass_build, :status => BuildList::SUCCESS) end context 'for guest' do @@ -107,9 +123,11 @@ describe Platforms::MassBuildsController do response.should redirect_to(new_user_session_path) end - it "should not be able to perform cancel action" do - post :cancel, :platform_id => @platform, :id => @mass_build - response.should redirect_to(new_user_session_path) + [:cancel, :publish].each do |action| + it "should not be able to perform #{action} action" do + post action, :platform_id => @platform, :id => @mass_build + response.should redirect_to(new_user_session_path) + end end it 'should not change objects count on create success' do @@ -120,6 +138,12 @@ describe Platforms::MassBuildsController do post :cancel, :platform_id => @platform, :id => @mass_build @mass_build.reload.stop_build.should == false end + + it 'should not change build_publish_count on publish' do + post :publish, :platform_id => @platform, :id => @mass_build + @mass_build.reload.build_publish_count.should == 0 + end + end context 'for global admin' do diff --git a/spec/factories/product_build_lists.rb b/spec/factories/product_build_lists.rb index 4c2a12e2b..978851e86 100644 --- a/spec/factories/product_build_lists.rb +++ b/spec/factories/product_build_lists.rb @@ -9,5 +9,8 @@ FactoryGirl.define do params 'ENV=i586' time_living 150 project_version 'master' + + # see: before_validation in ProductBuildList model + before(:create) { Arch.find_or_create_by_name('x86_64') } end end diff --git a/spec/lib/abf-worker/build_lists_publish_task_manager_spec.rb b/spec/lib/abf-worker/build_lists_publish_task_manager_spec.rb index d33481f48..dc95cea49 100644 --- a/spec/lib/abf-worker/build_lists_publish_task_manager_spec.rb +++ b/spec/lib/abf-worker/build_lists_publish_task_manager_spec.rb @@ -186,11 +186,18 @@ describe AbfWorker::BuildListsPublishTaskManager do :save_to_repository => build_list.save_to_repository, :build_for_platform => build_list.build_for_platform ) } + let(:build_list3) { FactoryGirl.create(:build_list_core, + :new_core => true, + :save_to_platform => build_list.save_to_platform, + :save_to_repository => build_list.save_to_repository, + :build_for_platform => build_list.build_for_platform + ) } before do stub_redis build_list.update_column(:status, BuildList::BUILD_PUBLISH) build_list2.update_column(:status, BuildList::BUILD_PUBLISHED) - ProjectToRepository.where(:project_id => build_list.project_id, :repository_id => build_list.save_to_repository_id).destroy_all + build_list3.update_column(:status, BuildList::BUILD_PUBLISHED) + ProjectToRepository.where(:project_id => build_list3.project_id, :repository_id => build_list3.save_to_repository_id).destroy_all 2.times{ subject.new.run } end @@ -212,7 +219,7 @@ describe AbfWorker::BuildListsPublishTaskManager do it "ensure that 'locked projects for cleanup' has only one item" do queue = @redis_instance.lrange(subject::LOCKED_PROJECTS_FOR_CLEANUP, 0, -1) queue.should have(1).item - queue.should include("#{build_list.project_id}-#{build_list.save_to_repository_id}-#{build_list.build_for_platform_id}") + queue.should include("#{build_list3.project_id}-#{build_list3.save_to_repository_id}-#{build_list3.build_for_platform_id}") end it "ensure that new task for publishing has been created" do