From d0179d03b604e079718e7a07da01505c0a7165e5 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Wed, 5 Dec 2012 14:56:59 +0400 Subject: [PATCH 01/26] #751: add url to file-store into the application.yml --- app/views/platforms/product_build_lists/_results.html.haml | 3 +-- bin/file-store.rb | 2 +- lib/abf_worker/rpm_worker_observer.rb | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/app/views/platforms/product_build_lists/_results.html.haml b/app/views/platforms/product_build_lists/_results.html.haml index dae2dc053..228bfc64d 100644 --- a/app/views/platforms/product_build_lists/_results.html.haml +++ b/app/views/platforms/product_build_lists/_results.html.haml @@ -13,8 +13,7 @@ %tr - sha1 = item['sha1'] - filename = item['file_name'] - - url = 'http://file-store.rosalinux.ru/api/v1/file_stores/' - - url << sha1 + - url = "#{APP_CONFIG['file_store_url']}/#{sha1}" - url << '.log?show=true' if filename =~ /.*\.(log|txt)$/ %td= link_to filename, url %td= sha1 diff --git a/bin/file-store.rb b/bin/file-store.rb index 390121568..631b0067a 100755 --- a/bin/file-store.rb +++ b/bin/file-store.rb @@ -9,7 +9,7 @@ old_sources = if File.exist? abf_yml [] end #MAX_SIZE = 2 * 1024 * 1024 # 2.megabytes -url = 'http://file-store.rosalinux.ru/api/v1/file_stores.json' +url = "#{APP_CONFIG['file_store_url']}.json" #url = 'http://localhost:3001/api/v1/file_stores.json' rclient = RestClient::Resource.new(url, :user => ARGF.argv[0]) # user auth token diff --git a/lib/abf_worker/rpm_worker_observer.rb b/lib/abf_worker/rpm_worker_observer.rb index 811b85261..854d8acfa 100644 --- a/lib/abf_worker/rpm_worker_observer.rb +++ b/lib/abf_worker/rpm_worker_observer.rb @@ -49,7 +49,7 @@ module AbfWorker select{ |r| r['file_name'] !~ /.*\.log$/ }.first sha1 = container ? container['sha1'] : nil bl.results = options['results'] - bl.container_path = "http://file-store.rosalinux.ru/api/v1/file_stores/#{sha1}" if sha1 + bl.container_path = "#{APP_CONFIG['file_store_url']}/#{sha1}" if sha1 bl.save! end end From bdc2cd78fbffaa0fedbcec6ea6ea8264df7c9aed Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Thu, 6 Dec 2012 13:18:16 +0600 Subject: [PATCH 02/26] [refs #758] add default branch validation --- app/models/project.rb | 1 + config/locales/models/project.en.yml | 1 + config/locales/models/project.ru.yml | 1 + 3 files changed, 3 insertions(+) diff --git a/app/models/project.rb b/app/models/project.rb index ecc30a4f0..95063fc5b 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -30,6 +30,7 @@ class Project < ActiveRecord::Base validates :maintainer_id, :presence => true, :unless => :new_record? validates :visibility, :presence => true, :inclusion => {:in => VISIBILITIES} validate { errors.add(:base, :can_have_less_or_equal, :count => MAX_OWN_PROJECTS) if owner.projects.size >= MAX_OWN_PROJECTS } + validate { errors.add(:default_branch, I18n.t('activerecord.errors.project.default_branch')) unless self.repo.branches.map(&:name).include?(self.default_branch) } attr_accessible :name, :description, :visibility, :srpm, :is_package, :default_branch, :has_issues, :has_wiki, :maintainer_id attr_readonly :name, :owner_id, :owner_type diff --git a/config/locales/models/project.en.yml b/config/locales/models/project.en.yml index 19f76d2ae..3a617ba6b 100644 --- a/config/locales/models/project.en.yml +++ b/config/locales/models/project.en.yml @@ -99,3 +99,4 @@ en: errors: project: uname: The name can only use lower case Latin letters (a-z), numbers (0-9) and underscore (_) + default_branch: Wrong branch diff --git a/config/locales/models/project.ru.yml b/config/locales/models/project.ru.yml index 0a38bafb1..916052de3 100644 --- a/config/locales/models/project.ru.yml +++ b/config/locales/models/project.ru.yml @@ -99,3 +99,4 @@ ru: errors: project: uname: В имени можно использовать только строчные символы латинского алфавита (a-z), цифры (0-9) и символ нижнего подчеркивания (_) + default_branch: Указана несуществующая ветка From 18e53bd5b8c0ea41915ad41967fef2f3f253702c Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Thu, 6 Dec 2012 13:18:49 +0600 Subject: [PATCH 03/26] [refs #753] change git-repo HEAD --- app/models/project.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/models/project.rb b/app/models/project.rb index 95063fc5b..4050cd7a8 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -58,6 +58,7 @@ class Project < ActiveRecord::Base before_validation :truncate_name, :on => :create before_create :set_maintainer after_save :attach_to_personal_repository + after_update :set_new_git_head has_ancestry :orphan_strategy => :rootify #:adopt not available yet @@ -205,4 +206,7 @@ class Project < ActiveRecord::Base end end + def set_new_git_head + `cd #{path} && git symbolic-ref HEAD refs/heads/#{self.default_branch}` if self.default_branch_changed? && self.repo.branches.map(&:name).include?(self.default_branch) + end end From 76223ebff8180758b5f99c8e075bce5fc653ce31 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Thu, 6 Dec 2012 13:34:45 +0600 Subject: [PATCH 04/26] [refs #753] add rake --- lib/tasks/change_git_head.rake | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 lib/tasks/change_git_head.rake diff --git a/lib/tasks/change_git_head.rake b/lib/tasks/change_git_head.rake new file mode 100644 index 000000000..9ed2e5695 --- /dev/null +++ b/lib/tasks/change_git_head.rake @@ -0,0 +1,13 @@ +namespace :project do + + desc 'Change HEAD at projects where default branch is not master' + task :git_change_head => :environment do + projects = Project.where("default_branch <> 'master'") + say "Find #{projects.count} project(s) without master HEAD" + say "Start working..." + projects.each do |project| + `cd #{project.path} && git symbolic-ref HEAD refs/heads/#{project.default_branch}` if project.repo.branches.map(&:name).include?(project.default_branch) + end + say 'Done!' + end +end From 97196c5484accacac5c81410a6bc3bc3d368ce64 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Thu, 6 Dec 2012 18:35:05 +0600 Subject: [PATCH 05/26] [refs #758] fix error on fork --- app/models/project.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/models/project.rb b/app/models/project.rb index 4050cd7a8..9e2866d44 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -30,7 +30,7 @@ class Project < ActiveRecord::Base validates :maintainer_id, :presence => true, :unless => :new_record? validates :visibility, :presence => true, :inclusion => {:in => VISIBILITIES} validate { errors.add(:base, :can_have_less_or_equal, :count => MAX_OWN_PROJECTS) if owner.projects.size >= MAX_OWN_PROJECTS } - validate { errors.add(:default_branch, I18n.t('activerecord.errors.project.default_branch')) unless self.repo.branches.map(&:name).include?(self.default_branch) } + validate :check_default_branch attr_accessible :name, :description, :visibility, :srpm, :is_package, :default_branch, :has_issues, :has_wiki, :maintainer_id attr_readonly :name, :owner_id, :owner_type @@ -209,4 +209,10 @@ class Project < ActiveRecord::Base def set_new_git_head `cd #{path} && git symbolic-ref HEAD refs/heads/#{self.default_branch}` if self.default_branch_changed? && self.repo.branches.map(&:name).include?(self.default_branch) end + + def check_default_branch + if self.repo.branches.count > 0 && self.repo.branches.map(&:name).exclude?(self.default_branch) + errors.add :default_branch, I18n.t('activerecord.errors.project.default_branch') + end + end end From ff2ae7398586ff134f7e187ea0d2c83918509d47 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 18:41:24 +0400 Subject: [PATCH 06/26] #759: add action for cancel build, some refactoring --- .../product_build_lists_controller.rb | 10 +- .../projects/build_lists_controller.rb | 12 +- app/models/ability.rb | 2 +- app/models/build_list.rb | 109 +++++++++--------- app/models/product_build_list.rb | 33 ++---- .../product_build_lists/show.html.haml | 9 +- config/locales/models/build_list.en.yml | 2 + config/locales/models/build_list.ru.yml | 2 + .../locales/models/product_build_list.en.yml | 4 +- .../locales/models/product_build_list.ru.yml | 4 +- config/routes.rb | 2 +- lib/abf_worker/model_helper.rb | 68 +++++++++++ .../product_build_lists_controller_spec.rb | 8 +- 13 files changed, 163 insertions(+), 102 deletions(-) create mode 100644 lib/abf_worker/model_helper.rb diff --git a/app/controllers/platforms/product_build_lists_controller.rb b/app/controllers/platforms/product_build_lists_controller.rb index 1d8a9b814..2bc8e4bbd 100644 --- a/app/controllers/platforms/product_build_lists_controller.rb +++ b/app/controllers/platforms/product_build_lists_controller.rb @@ -5,7 +5,7 @@ class Platforms::ProductBuildListsController < Platforms::BaseController load_and_authorize_resource :platform, :except => [:index, :status_build] load_and_authorize_resource :product, :through => :platform, :except => [:index, :status_build] load_and_authorize_resource :product_build_list, :through => :product, :except => [:index, :status_build] - load_and_authorize_resource :only => [:index, :show, :log, :stop] + load_and_authorize_resource :only => [:index, :show, :log, :cancel] before_filter :authenticate_product_builder!, :only => [:status_build] before_filter :find_product_build_list, :only => [:status_build] @@ -25,15 +25,15 @@ class Platforms::ProductBuildListsController < Platforms::BaseController def show end - def stop - @product_build_list.stop - flash[:notice] = t('flash.product_build_list.will_be_stopped') + def cancel + @product_build_list.cancel_job + flash[:notice] = t('layout.build_lists.will_be_canceled') redirect_to platform_product_product_build_list_path(@platform, @product, @product_build_list) end def log render :json => { - :log => @product_build_list.log, + :log => @product_build_list.abf_worker_log, :building => @product_build_list.build_started? } end diff --git a/app/controllers/projects/build_lists_controller.rb b/app/controllers/projects/build_lists_controller.rb index b9131fe95..c9d6a75d7 100644 --- a/app/controllers/projects/build_lists_controller.rb +++ b/app/controllers/projects/build_lists_controller.rb @@ -100,11 +100,17 @@ class Projects::BuildListsController < Projects::BaseController end def cancel - if @build_list.cancel - redirect_to :back, :notice => t('layout.build_lists.cancel_success') + if @build_list.new_core? && @build_list.can_cancel? + @build_list.cancel_job + notice = t('layout.build_lists.will_be_canceled') else - redirect_to :back, :notice => t('layout.build_lists.cancel_fail') + if @build_list.cancel + notice = t('layout.build_lists.cancel_success') + else + notice = t('layout.build_lists.cancel_fail') + end end + redirect_to :back, :notice => notice end def log diff --git a/app/models/ability.rb b/app/models/ability.rb index edba06d89..7331773d6 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -114,7 +114,7 @@ class Ability can(:read, Product, read_relations_for('products', 'platforms')) {|product| product.platform.main?} can([:create, :update, :destroy, :clone], Product) {|product| local_admin? product.platform and product.platform.main?} - can([:create, :stop], ProductBuildList) {|pbl| can?(:update, pbl.product)} + can([:create, :cancel], ProductBuildList) {|pbl| can?(:update, pbl.product)} can(:destroy, ProductBuildList) {|pbl| can?(:destroy, pbl.product)} can [:read, :create], PrivateUser, :platform => {:owner_type => 'User', :owner_id => user.id} diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 6f9d6e69a..0120a86b2 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -1,6 +1,7 @@ # -*- encoding : utf-8 -*- class BuildList < ActiveRecord::Base include Modules::Models::CommitAndVersion + include AbfWorker::ModelHelper belongs_to :project belongs_to :arch @@ -49,11 +50,13 @@ class BuildList < ActiveRecord::Base BUILD_PUBLISH = 7000 FAILED_PUBLISH = 8000 REJECTED_PUBLISH = 9000 + BUILD_CANCELING = 10000 STATUSES = [ WAITING_FOR_RESPONSE, BUILD_CANCELED, BUILD_PENDING, BUILD_PUBLISHED, + BUILD_CANCELING, BUILD_PUBLISH, FAILED_PUBLISH, REJECTED_PUBLISH, @@ -70,6 +73,7 @@ class BuildList < ActiveRecord::Base HUMAN_STATUSES = { WAITING_FOR_RESPONSE => :waiting_for_response, BUILD_CANCELED => :build_canceled, + BUILD_CANCELING => :build_canceling, BUILD_PENDING => :build_pending, BUILD_PUBLISHED => :build_published, BUILD_PUBLISH => :build_publish, @@ -169,7 +173,7 @@ class BuildList < ActiveRecord::Base event :cancel do transition [:build_pending, :platform_pending] => :build_canceled, :if => lambda { |build_list| - build_list.can_cancel? && BuildServer.delete_build_list(build_list.bs_id) == BuildServer::SUCCESS + !build_list.new_core? && build_list.can_cancel? && BuildServer.delete_build_list(build_list.bs_id) == BuildServer::SUCCESS } end @@ -226,7 +230,11 @@ class BuildList < ActiveRecord::Base #TODO: Share this checking on product owner. def can_cancel? - [BUILD_PENDING, BuildServer::PLATFORM_PENDING].include?(status) && bs_id + if new_core? + build_started? || build_pending? + else + [BUILD_PENDING, BuildServer::PLATFORM_PENDING].include?(status) && bs_id + end end def can_publish? @@ -237,60 +245,10 @@ class BuildList < ActiveRecord::Base can_publish? and not save_to_repository.publish_without_qa end - def add_to_abf_worker_queue - include_repos_hash = {}.tap do |h| - include_repos.each do |r| - repo = Repository.find r - path = repo.platform.public_downloads_url(nil, arch.name, repo.name) - # path = path.gsub(/^http:\/\/0\.0\.0\.0\:3000/, 'https://abf.rosalinux.ru') - # Path looks like: - # http://abf.rosalinux.ru/downloads/rosa-server2012/repository/x86_64/base/ - # so, we should append: - # /release - # /updates - h["#{repo.name}_release"] = path + 'release' - h["#{repo.name}_updates"] = path + 'updates' - end - end - # mdv example: - # https://abf.rosalinux.ru/import/plasma-applet-stackfolder.git - # bfe6d68cc607238011a6108014bdcfe86c69456a - - # rhel example: - # https://abf.rosalinux.ru/server/gnome-settings-daemon.git - # fbb2549e44d97226fea6748a4f95d1d82ffb8726 - - options = { - :id => id, - :arch => arch.name, - :time_living => 2880, # 2 days - :distrib_type => build_for_platform.distrib_type, - # :git_project_address => 'https://abf.rosalinux.ru/server/gnome-settings-daemon.git', - :git_project_address => project.git_project_address, - # :commit_hash => 'fbb2549e44d97226fea6748a4f95d1d82ffb8726', - :commit_hash => commit_hash, - :build_requires => build_requires, - :include_repos => include_repos_hash, - :bplname => build_for_platform.name - # :project_version => project_version, - # :plname => save_to_platform.name, - # :bplname => (save_to_platform_id == build_for_platform_id ? '' : build_for_platform.name), - # :update_type => update_type, - # :priority => priority, - } - unless @status - Resque.push( - 'rpm_worker', - 'class' => 'AbfWorker::RpmWorker', - 'args' => [options] - ) - end - @status ||= BUILD_PENDING - end - def add_to_queue if new_core? - add_to_abf_worker_queue + add_job_to_abf_worker_queue unless @status + @status ||= BUILD_PENDING else # XML-RPC params: # - project_name @@ -390,16 +348,53 @@ class BuildList < ActiveRecord::Base def log(load_lines) if new_core? - log = Resque.redis.get("abfworker::rpm-worker-#{id}") + abf_worker_log else log = `tail -n #{load_lines.to_i} #{Rails.root + 'public' + fs_log_path}` - log = nil unless $?.success? + $?.success? ? log : I18n.t('layout.build_lists.log.not_available') end - log || I18n.t('layout.build_lists.log.not_available') end protected + def abf_worker_args + include_repos_hash = {}.tap do |h| + include_repos.each do |r| + repo = Repository.find r + path = repo.platform.public_downloads_url(nil, arch.name, repo.name) + # path = path.gsub(/^http:\/\/0\.0\.0\.0\:3000/, 'https://abf.rosalinux.ru') + # Path looks like: + # http://abf.rosalinux.ru/downloads/rosa-server2012/repository/x86_64/base/ + # so, we should append: + # /release + # /updates + h["#{repo.name}_release"] = path + 'release' + h["#{repo.name}_updates"] = path + 'updates' + end + end + # mdv example: + # https://abf.rosalinux.ru/import/plasma-applet-stackfolder.git + # bfe6d68cc607238011a6108014bdcfe86c69456a + + # rhel example: + # https://abf.rosalinux.ru/server/gnome-settings-daemon.git + # fbb2549e44d97226fea6748a4f95d1d82ffb8726 + + { + :id => id, + :arch => arch.name, + :time_living => 2880, # 2 days + :distrib_type => build_for_platform.distrib_type, + # :git_project_address => 'https://abf.rosalinux.ru/server/gnome-settings-daemon.git', + :git_project_address => project.git_project_address, + # :commit_hash => 'fbb2549e44d97226fea6748a4f95d1d82ffb8726', + :commit_hash => commit_hash, + :build_requires => build_requires, + :include_repos => include_repos_hash, + :bplname => build_for_platform.name + } + end + def notify_users unless mass_build_id users = [] diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index 5cfbed662..8548eb682 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -1,6 +1,7 @@ # -*- encoding : utf-8 -*- class ProductBuildList < ActiveRecord::Base include Modules::Models::CommitAndVersion + include AbfWorker::ModelHelper delegate :url_helpers, to: 'Rails.application.routes' BUILD_COMPLETED = 0 @@ -72,6 +73,10 @@ class ProductBuildList < ActiveRecord::Base status == BUILD_CANCELING end + def can_cancel? + [BUILD_STARTED, BUILD_PENDING].include? status + end + def container_path "/downloads/#{product.platform.name}/product/#{id}/" end @@ -92,22 +97,14 @@ class ProductBuildList < ActiveRecord::Base [BUILD_COMPLETED, BUILD_FAILED, BUILD_CANCELED].include? status end - def log - Resque.redis.get("abfworker::iso-worker-#{id}") || '' - end - - def stop - update_attributes({:status => BUILD_CANCELING}) - Resque.redis.setex( - "abfworker::iso-worker-#{id}::live-inspector", - 120, # Data will be removed from Redis after 120 sec. - 'USR1' # Immediately kill child but don't exit - ) - end - protected def xml_rpc_create + add_job_to_abf_worker_queue + return true + end + + def abf_worker_args file_name = "#{project.owner.uname}-#{project.name}-#{commit_hash}" srcpath = url_helpers.archive_url( project.owner, @@ -116,7 +113,7 @@ class ProductBuildList < ActiveRecord::Base 'tar.gz', :host => ActionMailer::Base.default_url_options[:host] ) - options = { + { :id => id, # TODO: remove comment # :srcpath => 'http://dl.dropbox.com/u/945501/avokhmin-test-iso-script-5d9b463d4e9c06ea8e7c89e1b7ff5cb37e99e27f.tar.gz', @@ -127,13 +124,7 @@ class ProductBuildList < ActiveRecord::Base :arch => arch.name, :distrib_type => product.platform.distrib_type } - Resque.push( - 'iso_worker', - 'class' => 'AbfWorker::IsoWorker', - 'args' => [options] - ) - return true - end + end def xml_delete_iso_container # TODO: write new worker for delete diff --git a/app/views/platforms/product_build_lists/show.html.haml b/app/views/platforms/product_build_lists/show.html.haml index 87aff3f1d..a39d22ecd 100644 --- a/app/views/platforms/product_build_lists/show.html.haml +++ b/app/views/platforms/product_build_lists/show.html.haml @@ -23,11 +23,12 @@ = render 'show_field', :key => :notified_at, :value => l(pbl.updated_at, :format => :long) +- if pbl.can_cancel? && can?(:cancel, pbl) + = link_to t("layout.build_lists.cancel"), cancel_platform_product_product_build_list_path(pbl.product.platform, pbl.product, pbl), + :method => :put, :confirm => t("layout.confirm"), :class => 'button' + .both + - if pbl.build_started? || pbl.build_canceling? - - if can? :stop, pbl - .leftlist= t("layout.product_build_lists.action") - .rightlist= link_to t("layout.product_build_lists.stop"), stop_platform_product_product_build_list_path(pbl.product.platform, pbl.product, pbl) - .both = render 'shared/log', { :build_started => true, :get_log_path => log_platform_product_product_build_list_path(pbl.product.platform, pbl.product, pbl) } = render 'results', :pbl => pbl diff --git a/config/locales/models/build_list.en.yml b/config/locales/models/build_list.en.yml index 8d381f75b..de90011ee 100644 --- a/config/locales/models/build_list.en.yml +++ b/config/locales/models/build_list.en.yml @@ -62,6 +62,7 @@ en: show: Show cancel: Cancel build cancel_success: 'Build canceled' + will_be_canceled: 'Build will be canceled...' publish_success: 'Build published' cancel_fail: 'Errors during build cancelation!' publish_fail: 'Errors during build publishing!' @@ -111,6 +112,7 @@ en: dependencies_fail: Dependences not found waiting_for_response: Waiting for response build_pending: Build pending + build_canceling: Build is canceling dependency_test_failed: Dependency test failed binary_test_failed: Binary test failed build_canceled: Build canceled diff --git a/config/locales/models/build_list.ru.yml b/config/locales/models/build_list.ru.yml index a04a52864..c7fb18275 100644 --- a/config/locales/models/build_list.ru.yml +++ b/config/locales/models/build_list.ru.yml @@ -60,6 +60,7 @@ ru: no_items_data: Данных нет show: Просмотр cancel: Отменить сборку + will_be_canceled: 'Сборка будет отменена...' cancel_success: 'Сборка отменена.' cancel_fail: 'При отмене сборки произошла ошибка!' publish_success: 'Сборка поставлена в очередь на публикацию.' @@ -111,6 +112,7 @@ ru: dependency_test_failed: тестирование зависимостей не пройдено binary_test_failed: тестирование бинарной совместимости не пройдено build_canceled: сборка отменена + build_canceling: сборка отменяется success: собран build_started: собирается platform_not_found: платформа не найдена diff --git a/config/locales/models/product_build_list.en.yml b/config/locales/models/product_build_list.en.yml index 9402287c2..945bdaaec 100644 --- a/config/locales/models/product_build_list.en.yml +++ b/config/locales/models/product_build_list.en.yml @@ -8,7 +8,6 @@ en: results_folder: all files from this folder will be uploaded into the file-store archives_folder: this folder will be archived and uploaded into the file-store delete: Delete - stop: Stop action: Action id_search: 'Id search' new: New build @@ -52,5 +51,4 @@ en: product_build_list: no_project: Project for build should be exist delete: Product build list deleted - delete_error: Unable to delete product build list - will_be_stopped: Build will be stopped \ No newline at end of file + delete_error: Unable to delete product build list \ No newline at end of file diff --git a/config/locales/models/product_build_list.ru.yml b/config/locales/models/product_build_list.ru.yml index 8411c9461..a6efbd419 100644 --- a/config/locales/models/product_build_list.ru.yml +++ b/config/locales/models/product_build_list.ru.yml @@ -8,7 +8,6 @@ ru: results_folder: все файлы из этой папки будут загружены на file-store archives_folder: эта папка будет заархивирована и загружена на file-store delete: Удалить - stop: Остановить action: Действие id_search: 'Поиск по Id' new: Новая сборка @@ -52,5 +51,4 @@ ru: product_build_list: no_project: Проект для сборки должен присутствовать delete: Сборочный лист продукта удален - delete_error: Не удалось удалить cборочный лист продукта - will_be_stopped: Сборка будет остановлена + delete_error: Не удалось удалить cборочный лист продукта \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 05d409a6d..2440bb70c 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -151,7 +151,7 @@ Rosa::Application.routes.draw do resources :product_build_lists, :only => [:create, :destroy, :new, :show] do member { get :log - get :stop + put :cancel } end collection { get :autocomplete_project } diff --git a/lib/abf_worker/model_helper.rb b/lib/abf_worker/model_helper.rb new file mode 100644 index 000000000..fd58c17e5 --- /dev/null +++ b/lib/abf_worker/model_helper.rb @@ -0,0 +1,68 @@ +module AbfWorker + module ModelHelper + # In model which contains this helper should be: + # - BUILD_CANCELING + # - BUILD_CANCELED + # - #abf_worker_args + + def abf_worker_log + q = 'abfworker::' + q << worker_queue + q << '-' + q << id.to_s + Resque.redis.get(q) || I18n.t('layout.build_lists.log.not_available') + end + + def add_job_to_abf_worker_queue + Resque.push( + worker_queue, + 'class' => worker_queue_class, + 'args' => [abf_worker_args] + ) + end + + def cancel_job + update_attributes({:status => self.class::BUILD_CANCELING}) + + deleted = Resque::Job.destroy( + worker_queue, + worker_queue_class, + abf_worker_args + ) + if deleted + update_attributes({:status => self.class::BUILD_CANCELED}) + else + send_stop_signal + end + true + end + + private + + def send_stop_signal + Resque.redis.setex( + live_inspector_queue, + 90, # Data will be removed from Redis after 90 sec. + 'USR1' # Immediately kill child but don't exit + ) + end + + def live_inspector_queue + q = 'abfworker::' + q << worker_queue + q << '-' + q << id.to_s + q << '::live-inspector' + q + end + + def worker_queue + is_a?(BuildList) ? 'rpm_worker' : 'iso_worker' + end + + def worker_queue_class + is_a?(BuildList) ? 'AbfWorker::RpmWorker' : 'AbfWorker::IsoWorker' + end + + end +end \ No newline at end of file diff --git a/spec/controllers/platforms/product_build_lists_controller_spec.rb b/spec/controllers/platforms/product_build_lists_controller_spec.rb index 75b833a93..a5be42f7e 100644 --- a/spec/controllers/platforms/product_build_lists_controller_spec.rb +++ b/spec/controllers/platforms/product_build_lists_controller_spec.rb @@ -23,8 +23,8 @@ shared_examples_for 'product build list admin' do response.should render_template(:index) end - it 'should be able to perform stop action' do - get :stop, valid_attributes_for_show + it 'should be able to perform cancel action' do + put :cancel, valid_attributes_for_show response.should redirect_to(platform_product_product_build_list_path(@product.platform, @product, @pbl)) end @@ -56,8 +56,8 @@ shared_examples_for 'product build list user without admin rights' do response.should_not be_success end - it 'should not be able to perform stop action' do - get :stop, valid_attributes_for_show + it 'should not be able to perform cancel action' do + put :cancel, valid_attributes_for_show response.should_not redirect_to(platform_product_product_build_list_path(@product.platform, @product, @pbl)) end end From da4eb1852e6a90af54a1548d595a30e34a0a7667 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 19:22:27 +0400 Subject: [PATCH 07/26] #759: update rpm_worker_observer --- lib/abf_worker/rpm_worker_observer.rb | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/lib/abf_worker/rpm_worker_observer.rb b/lib/abf_worker/rpm_worker_observer.rb index 811b85261..48a21726d 100644 --- a/lib/abf_worker/rpm_worker_observer.rb +++ b/lib/abf_worker/rpm_worker_observer.rb @@ -1,5 +1,11 @@ module AbfWorker class RpmWorkerObserver + BUILD_COMPLETED = 0 + BUILD_FAILED = 1 + BUILD_PENDING = 2 + BUILD_STARTED = 3 + BUILD_CANCELED = 4 + @queue = :rpm_worker_observer def self.perform(options) @@ -7,18 +13,20 @@ module AbfWorker status = options['status'].to_i item = find_or_create_item(bl) case status - when 0 + when BUILD_COMPLETED bl.build_success item.update_attributes({:status => BuildServer::SUCCESS}) - when 1 + when BUILD_FAILED bl.build_error item.update_attributes({:status => BuildServer::BUILD_ERROR}) - when 3 + when BUILD_STARTED bl.bs_id = bl.id bl.save! bl.start_build + when BUILD_CANCELED + bl.update_attributes({:status => BuildList::BUILD_CANCELED}) end - if status != 3 + if status != BUILD_STARTED fill_container_data bl, options end end @@ -55,4 +63,4 @@ module AbfWorker end end -end \ No newline at end of file +endх \ No newline at end of file From 60f2ab3d96118e0e90fe1ba16e5446aff6eed2b7 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 20:00:24 +0400 Subject: [PATCH 08/26] #759: some fixes --- app/models/build_list.rb | 4 +++- lib/abf_worker/model_helper.rb | 2 +- lib/abf_worker/rpm_worker_observer.rb | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 0120a86b2..accdb73f9 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -322,6 +322,7 @@ class BuildList < ActiveRecord::Base end def human_duration + duration ||= current_duration I18n.t("layout.build_lists.human_duration", {:hours => (duration/3600).to_i, :minutes => (duration%3600/60).to_i}) end @@ -391,7 +392,8 @@ class BuildList < ActiveRecord::Base :commit_hash => commit_hash, :build_requires => build_requires, :include_repos => include_repos_hash, - :bplname => build_for_platform.name + :bplname => build_for_platform.name, + :user => {:uname => user.uname, :email => user.email} } end diff --git a/lib/abf_worker/model_helper.rb b/lib/abf_worker/model_helper.rb index fd58c17e5..b9f6fc323 100644 --- a/lib/abf_worker/model_helper.rb +++ b/lib/abf_worker/model_helper.rb @@ -29,7 +29,7 @@ module AbfWorker worker_queue_class, abf_worker_args ) - if deleted + if deleted == 1 update_attributes({:status => self.class::BUILD_CANCELED}) else send_stop_signal diff --git a/lib/abf_worker/rpm_worker_observer.rb b/lib/abf_worker/rpm_worker_observer.rb index 48a21726d..10b4c1c7a 100644 --- a/lib/abf_worker/rpm_worker_observer.rb +++ b/lib/abf_worker/rpm_worker_observer.rb @@ -63,4 +63,4 @@ module AbfWorker end end -endх \ No newline at end of file +end \ No newline at end of file From ef8ece3e871fea6240d18119a54bb6c4fd25bd97 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 20:28:44 +0400 Subject: [PATCH 09/26] #759: update status for BuildList::Item, fix getting logs --- app/models/build_list.rb | 2 +- app/models/build_list/item.rb | 5 +++-- config/locales/models/build_list.en.yml | 1 + config/locales/models/build_list.ru.yml | 1 + lib/abf_worker/model_helper.rb | 11 +++++++---- lib/abf_worker/rpm_worker_observer.rb | 1 + 6 files changed, 14 insertions(+), 7 deletions(-) diff --git a/app/models/build_list.rb b/app/models/build_list.rb index accdb73f9..d2acc0ae9 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -201,7 +201,7 @@ class BuildList < ActiveRecord::Base end event :build_error do - transition [:build_started, :build_canceled] => :build_error + transition [:build_started, :build_canceled, :build_canceling] => :build_error end HUMAN_STATUSES.each do |code,name| diff --git a/app/models/build_list/item.rb b/app/models/build_list/item.rb index 36d7fab6c..540fa5a80 100644 --- a/app/models/build_list/item.rb +++ b/app/models/build_list/item.rb @@ -7,14 +7,15 @@ class BuildList::Item < ActiveRecord::Base GIT_ERROR = 5 - STATUSES = [BuildServer::SUCCESS, BuildServer::DEPENDENCIES_ERROR, BuildServer::BUILD_ERROR, BuildServer::BUILD_STARTED, GIT_ERROR] + STATUSES = [BuildServer::SUCCESS, BuildServer::DEPENDENCIES_ERROR, BuildServer::BUILD_ERROR, BuildServer::BUILD_STARTED, GIT_ERROR, BuildList::BUILD_CANCELED] HUMAN_STATUSES = { nil => :unknown, GIT_ERROR => :git_error, BuildServer::DEPENDENCIES_ERROR => :dependencies_error, BuildServer::SUCCESS => :success, BuildServer::BUILD_STARTED => :build_started, - BuildServer::BUILD_ERROR => :build_error + BuildServer::BUILD_ERROR => :build_error, + BuildList::BUILD_CANCELED => :build_canceled } scope :recent, order("level ASC, name ASC") diff --git a/config/locales/models/build_list.en.yml b/config/locales/models/build_list.en.yml index de90011ee..7b8be15ba 100644 --- a/config/locales/models/build_list.en.yml +++ b/config/locales/models/build_list.en.yml @@ -101,6 +101,7 @@ en: success: Build complete unknown: Build is waiting git_error: Git error + build_canceled: Build canceled statuses: build_lists: All diff --git a/config/locales/models/build_list.ru.yml b/config/locales/models/build_list.ru.yml index c7fb18275..d4d5a5b32 100644 --- a/config/locales/models/build_list.ru.yml +++ b/config/locales/models/build_list.ru.yml @@ -98,6 +98,7 @@ ru: success: собран unknown: ожидает сборки git_error: проблема с гит + build_canceled: сборка отменена statuses: build_lists: Всего diff --git a/lib/abf_worker/model_helper.rb b/lib/abf_worker/model_helper.rb index b9f6fc323..0803ead49 100644 --- a/lib/abf_worker/model_helper.rb +++ b/lib/abf_worker/model_helper.rb @@ -7,7 +7,7 @@ module AbfWorker def abf_worker_log q = 'abfworker::' - q << worker_queue + q << worker_queue('-') q << '-' q << id.to_s Resque.redis.get(q) || I18n.t('layout.build_lists.log.not_available') @@ -49,15 +49,18 @@ module AbfWorker def live_inspector_queue q = 'abfworker::' - q << worker_queue + q << worker_queue('-') q << '-' q << id.to_s q << '::live-inspector' q end - def worker_queue - is_a?(BuildList) ? 'rpm_worker' : 'iso_worker' + def worker_queue(delimiter = '_') + a = [] + a << (is_a?(BuildList) ? 'rpm' : 'iso') + a << 'worker' + a.join(delimiter) end def worker_queue_class diff --git a/lib/abf_worker/rpm_worker_observer.rb b/lib/abf_worker/rpm_worker_observer.rb index 10b4c1c7a..618114462 100644 --- a/lib/abf_worker/rpm_worker_observer.rb +++ b/lib/abf_worker/rpm_worker_observer.rb @@ -25,6 +25,7 @@ module AbfWorker bl.start_build when BUILD_CANCELED bl.update_attributes({:status => BuildList::BUILD_CANCELED}) + item.update_attributes({:status => BuildList::BUILD_CANCELED}) end if status != BUILD_STARTED fill_container_data bl, options From c3e8d189255ffeb9a332e246351b5894a2b4cc6a Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 21:10:23 +0400 Subject: [PATCH 10/26] #759: remove #xml_rpc_create method --- app/models/product_build_list.rb | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index 8548eb682..501e058a3 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -61,7 +61,7 @@ class ProductBuildList < ActiveRecord::Base scope :scoped_to_product_name, lambda {|product_name| joins(:product).where('products.name LIKE ?', "%#{product_name}%")} scope :recent, order("#{table_name}.updated_at DESC") - after_create :xml_rpc_create + after_create :add_job_to_abf_worker_queue before_destroy :can_destroy? after_destroy :xml_delete_iso_container @@ -99,11 +99,6 @@ class ProductBuildList < ActiveRecord::Base protected - def xml_rpc_create - add_job_to_abf_worker_queue - return true - end - def abf_worker_args file_name = "#{project.owner.uname}-#{project.name}-#{commit_hash}" srcpath = url_helpers.archive_url( From ab8c4016b5786dc6567c36355af978534677bf84 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 21:34:09 +0400 Subject: [PATCH 11/26] #759: refactoring according to Vladimir's comments --- app/controllers/projects/build_lists_controller.rb | 13 +++++-------- app/models/build_list.rb | 11 +++++++++++ lib/abf_worker/rpm_worker_observer.rb | 2 +- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/app/controllers/projects/build_lists_controller.rb b/app/controllers/projects/build_lists_controller.rb index c9d6a75d7..07bd95353 100644 --- a/app/controllers/projects/build_lists_controller.rb +++ b/app/controllers/projects/build_lists_controller.rb @@ -100,15 +100,12 @@ class Projects::BuildListsController < Projects::BaseController end def cancel - if @build_list.new_core? && @build_list.can_cancel? - @build_list.cancel_job - notice = t('layout.build_lists.will_be_canceled') + if @build_list.cancel + notice = @build_list.new_core? ? + t('layout.build_lists.will_be_canceled') : + t('layout.build_lists.cancel_success') else - if @build_list.cancel - notice = t('layout.build_lists.cancel_success') - else - notice = t('layout.build_lists.cancel_fail') - end + notice = t('layout.build_lists.cancel_fail') end redirect_to :back, :notice => notice end diff --git a/app/models/build_list.rb b/app/models/build_list.rb index d2acc0ae9..2050781c4 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -141,6 +141,8 @@ class BuildList < ActiveRecord::Base end after_transition :on => :published, :do => [:set_version_and_tag, :actualize_packages] + after_transition :on => :cancel, :do => [:cancel_job], + :if => lambda { |build_list| build_list.build_canceling? } after_transition :on => [:published, :fail_publish, :build_error], :do => :notify_users after_transition :on => :build_success, :do => :notify_users, @@ -175,6 +177,15 @@ class BuildList < ActiveRecord::Base transition [:build_pending, :platform_pending] => :build_canceled, :if => lambda { |build_list| !build_list.new_core? && build_list.can_cancel? && BuildServer.delete_build_list(build_list.bs_id) == BuildServer::SUCCESS } + transition [:build_pending, :build_started] => :build_canceling, :if => lambda { |build_list| + build_list.new_core? && build_list.can_cancel? + } + end + + event :build_canceled do + transition [:build_canceling] => :build_canceled, :if => lambda { |build_list| + build_list.new_core? + } end event :published do diff --git a/lib/abf_worker/rpm_worker_observer.rb b/lib/abf_worker/rpm_worker_observer.rb index 618114462..212f043ce 100644 --- a/lib/abf_worker/rpm_worker_observer.rb +++ b/lib/abf_worker/rpm_worker_observer.rb @@ -24,7 +24,7 @@ module AbfWorker bl.save! bl.start_build when BUILD_CANCELED - bl.update_attributes({:status => BuildList::BUILD_CANCELED}) + bl.build_canceled item.update_attributes({:status => BuildList::BUILD_CANCELED}) end if status != BUILD_STARTED From dc1525b85e72e079582483379336c19546f9da17 Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Thu, 6 Dec 2012 23:59:17 +0600 Subject: [PATCH 12/26] [refs #762] add mass build from list --- .../platforms/mass_builds_controller.rb | 12 ++++++--- app/helpers/mass_build_helper.rb | 8 ++++++ app/models/ability.rb | 4 +-- app/models/mass_build.rb | 24 ++++++++++------- app/models/platform.rb | 26 +++++++++++++++++++ .../platforms/mass_builds/index.html.haml | 12 ++++++++- config/locales/models/mass_build.en.yml | 2 ++ config/locales/models/mass_build.ru.yml | 2 ++ config/routes.rb | 2 +- .../20121206143724_add_list_to_mass_build.rb | 7 +++++ db/schema.rb | 5 +++- 11 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 app/helpers/mass_build_helper.rb create mode 100644 db/migrate/20121206143724_add_list_to_mass_build.rb diff --git a/app/controllers/platforms/mass_builds_controller.rb b/app/controllers/platforms/mass_builds_controller.rb index ecea50458..41a911137 100644 --- a/app/controllers/platforms/mass_builds_controller.rb +++ b/app/controllers/platforms/mass_builds_controller.rb @@ -12,7 +12,8 @@ class Platforms::MassBuildsController < Platforms::BaseController def create mass_build = @platform.mass_builds.new(:repositories => params[:repositories], :arches => params[:arches], - :auto_publish => params[:auto_publish] || false) + :auto_publish => params[:auto_publish] || false, + :projects_list => params[:projects_list]) mass_build.user = current_user authorize! :create, mass_build @@ -40,7 +41,12 @@ class Platforms::MassBuildsController < Platforms::BaseController redirect_to platform_mass_builds_path(@mass_build.platform) end - def failed_builds_list - render :text => @mass_build.generate_failed_builds_list + def get_list + text = if params[:kind] == 'failed_builds_list' + @mass_build.generate_failed_builds_list + elsif ['projects_list', 'missed_projects_list'].include? params[:kind] + @mass_build.send params[:kind] + end + render :text => text end end diff --git a/app/helpers/mass_build_helper.rb b/app/helpers/mass_build_helper.rb new file mode 100644 index 000000000..037f0a2d8 --- /dev/null +++ b/app/helpers/mass_build_helper.rb @@ -0,0 +1,8 @@ +# -*- encoding : utf-8 -*- +module MassBuildHelper + def link_to_list platform, mass_build, which + link_to t("layout.mass_builds.#{which}"), + get_list_platform_mass_build_path(@platform, mass_build, :kind => which, :format => :txt), + :target => "_blank" if can?(:get_list, mass_build) + end +end diff --git a/app/models/ability.rb b/app/models/ability.rb index edba06d89..b4f4c9f92 100644 --- a/app/models/ability.rb +++ b/app/models/ability.rb @@ -95,7 +95,7 @@ class Ability can([:update, :members], Platform) {|platform| local_admin? platform} can([:destroy, :members, :add_member, :remove_member, :remove_members] , Platform) {|platform| owner?(platform) || local_admin?(platform) } - can([:failed_builds_list, :create], MassBuild) {|mass_build| (owner?(mass_build.platform) || local_admin?(mass_build.platform)) && mass_build.platform.main? } + can([:get_list, :create], 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} @@ -151,7 +151,7 @@ class Ability cannot [:create, :update, :destroy, :clone], Product, :platform => {:platform_type => 'personal'} cannot [:clone], Platform, :platform_type => 'personal' - cannot([:failed_builds_list, :create], MassBuild) {|mass_build| mass_build.platform.personal?} + cannot([:get_list, :create], MassBuild) {|mass_build| mass_build.platform.personal?} cannot(:cancel, MassBuild) {|mass_build| mass_build.platform.personal? || mass_build.stop_build} can :create, Subscribe do |subscribe| diff --git a/app/models/mass_build.rb b/app/models/mass_build.rb index 8383151f7..da46a2f70 100644 --- a/app/models/mass_build.rb +++ b/app/models/mass_build.rb @@ -7,9 +7,10 @@ class MassBuild < ActiveRecord::Base scope :outdated, where('created_at < ?', Time.now + 1.day - BuildList::MAX_LIVE_TIME) attr_accessor :repositories, :arches - attr_accessible :repositories, :arches, :auto_publish + attr_accessible :repositories, :arches, :auto_publish, :projects_list - validates :platform_id, :arch_names, :name, :user_id, :repositories, :rep_names, :presence => true + validates :platform_id, :arch_names, :name, :user_id, :presence => true + validate :rep_names, :repositories, :presence => true, :if => Proc.new {|mb| mb.projects_list.blank?} validates_inclusion_of :auto_publish, :in => [true, false] after_create :build_all @@ -26,13 +27,18 @@ class MassBuild < ActiveRecord::Base # ATTENTION: repositories and arches must be set before calling this method! def build_all - platform.build_all( - :mass_build_id => self.id, - :user => self.user, - :repositories => self.repositories, - :arches => self.arches, - :auto_publish => self.auto_publish - ) # later with resque + # later with resque + if projects_list.present? + platform.build_from_list :mass_build_id => self.id + else + platform.build_all( + :mass_build_id => self.id, + :user => self.user, + :repositories => self.repositories, + :arches => self.arches, + :auto_publish => self.auto_publish + ) + end end def generate_failed_builds_list diff --git a/app/models/platform.rb b/app/models/platform.rb index ca0d08ba2..3617319fd 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -205,6 +205,32 @@ class Platform < ActiveRecord::Base end later :build_all, :loner => true, :queue => :clone_build + def build_from_list(opts={}) + mass_build = MassBuild.find opts[:mass_build_id] + arches = mass_build.arches ? Arch.where(:id => mass_build.arches) : Arch.all + auto_publish = opts[:auto_publish] || false + user = opts[:user] + + mass_build.projects_list.lines.each do |name| + name.chomp!; name.strip! + if p = Project.joins(:repositories).where('repositories.id IN (?)', repositories).find_by_name(name) + begin + return if mass_build.reload.stop_build + p.build_for(self, rep.id, user, arch, auto_publish, mass_build_id) + rescue RuntimeError, Exception + end + else + MassBuild.increment_counter :missed_projects_count, mass_build.id + #mass_build.missed_projects_list = '' if mass_build.missed_projects_list.nil? + #mass_build.missed_projects_list << "#{name}\n" + list = (mass_build.missed_projects_list || '') << "#{name}\n" + mass_build.update_column :missed_projects_list, list + end + sleep 0.2 + end + end + later :build_from_list, :loner => true, :queue => :clone_build + def destroy with_skip {super} # avoid cascade XML RPC requests end diff --git a/app/views/platforms/mass_builds/index.html.haml b/app/views/platforms/mass_builds/index.html.haml index e1115e0fa..ece1e54a3 100644 --- a/app/views/platforms/mass_builds/index.html.haml +++ b/app/views/platforms/mass_builds/index.html.haml @@ -8,6 +8,8 @@ .both = check_box_tag "repositories[]", rep.id, (params[:repositories]||[]).include?(rep.id.to_s), :id => "repositories_#{rep.id}" = label_tag "repositories_#{rep.id}", rep.name + %h3= t("layout.mass_builds.projects_list") + = text_area_tag :projects_list, nil %br = f.submit t("layout.projects.build_button") %section.right @@ -43,11 +45,19 @@ = link_to t("layout.build_lists.statuses.#{status}") + ": ", build_lists_path(:filter => {:mass_build_id => mass_build.id, :ownership => 'everything'}.merge(status != :build_lists ? {:status => BuildList.status_by_human(status)} : {})) = mass_build.read_attribute "#{status}_count" .both - %td= link_to t("layout.mass_builds.failed_builds_list"), failed_builds_list_platform_mass_build_path(@platform, mass_build.id, :format => :txt), :target => "_blank" if can?(:failed_builds_list, mass_build) + %td + =link_to_list @platform, mass_build, 'failed_builds_list' + -if mass_build.projects_list.present? + %br + =link_to_list @platform, mass_build, 'missed_projects_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 %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 }"} + -if mass_build.projects_list.present? + = t('activerecord.attributes.mass_build.projects_list') + ": " + = link_to_list @platform, mass_build, 'projects_list' + .both = t('activerecord.attributes.mass_build.arch_names') + ": " = mass_build.arch_names .both diff --git a/config/locales/models/mass_build.en.yml b/config/locales/models/mass_build.en.yml index 734172bcc..f160515f5 100644 --- a/config/locales/models/mass_build.en.yml +++ b/config/locales/models/mass_build.en.yml @@ -7,6 +7,8 @@ en: statuses: Statuses cancel_mass_build: Cancel cancel_confirm: Are you sure you want to cancel mass build? + projects_list: Projects list + missed_projects_list: Missed projects list activerecord: models: mass_build: Mass Build diff --git a/config/locales/models/mass_build.ru.yml b/config/locales/models/mass_build.ru.yml index 5e7cc7c38..923c128dc 100644 --- a/config/locales/models/mass_build.ru.yml +++ b/config/locales/models/mass_build.ru.yml @@ -7,6 +7,8 @@ ru: statuses: Статусы cancel_mass_build: Отмена cancel_confirm: Вы уверены, что хотите отменить массовую сборку? + projects_list: Список проектов + missed_projects_list: Список несуществующих проектов activerecord: models: mass_build: Массовая Сборка diff --git a/config/routes.rb b/config/routes.rb index 05d409a6d..99a383488 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -131,8 +131,8 @@ Rosa::Application.routes.draw do resources :mass_builds, :only => [:create, :index] do member do - get :failed_builds_list post :cancel + get '/:kind.:format' => "mass_builds#get_list", :as => :get_list, :kind => /failed_builds_list|missed_projects_list|projects_list/ end end diff --git a/db/migrate/20121206143724_add_list_to_mass_build.rb b/db/migrate/20121206143724_add_list_to_mass_build.rb new file mode 100644 index 000000000..3bca325e6 --- /dev/null +++ b/db/migrate/20121206143724_add_list_to_mass_build.rb @@ -0,0 +1,7 @@ +class AddListToMassBuild < ActiveRecord::Migration + def change + add_column :mass_builds, :projects_list, :text + add_column :mass_builds, :missed_projects_count, :integer, :default => 0, :null => false + add_column :mass_builds, :missed_projects_list, :text + end +end diff --git a/db/schema.rb b/db/schema.rb index 235411879..05c811032 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20121203142727) do +ActiveRecord::Schema.define(:version => 20121206143724) do create_table "activity_feeds", :force => true do |t| t.integer "user_id", :null => false @@ -252,6 +252,9 @@ ActiveRecord::Schema.define(:version => 20121203142727) do t.integer "build_error_count", :default => 0, :null => false t.string "rep_names" t.boolean "stop_build", :default => false, :null => false + t.text "projects_list" + t.integer "missed_projects_count", :default => 0, :null => false + t.text "missed_projects_list" end create_table "platforms", :force => true do |t| From e3e228de333abbb00fa4d60945ba4e1e5bdc38ec Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 22:04:39 +0400 Subject: [PATCH 13/26] #759: add tester role for user --- app/controllers/admin/users_controller.rb | 2 +- app/controllers/projects/build_lists_controller.rb | 2 +- app/models/build_list.rb | 4 ++++ app/models/user.rb | 7 ++++++- app/views/projects/build_lists/new.html.haml | 2 +- config/locales/users.en.yml | 1 + config/locales/users.ru.yml | 1 + 7 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb index 498d11926..7c34b13ac 100644 --- a/app/controllers/admin/users_controller.rb +++ b/app/controllers/admin/users_controller.rb @@ -57,7 +57,7 @@ class Admin::UsersController < Admin::BaseController @users = @users.where('users.name ILIKE ? or users.uname ILIKE ? or users.email ILIKE ?', search, search, search) end @filter = params[:filter] || 'all' - @users = @users.send(@filter) if ['real', 'admin', 'banned'].include? @filter + @users = @users.send(@filter) if ['real', 'admin', 'banned', 'tester'].include? @filter @users = @users.order(order) render :partial => 'users_ajax', :layout => false diff --git a/app/controllers/projects/build_lists_controller.rb b/app/controllers/projects/build_lists_controller.rb index 07bd95353..c13d5c254 100644 --- a/app/controllers/projects/build_lists_controller.rb +++ b/app/controllers/projects/build_lists_controller.rb @@ -55,7 +55,7 @@ class Projects::BuildListsController < Projects::BaseController build_for_platforms = Repository.select(:platform_id). where(:id => params[:build_list][:include_repos]).group(:platform_id).map(&:platform_id) - new_core = current_user.admin? && params[:build_list][:new_core] == '1' + new_core = BuildList.has_access_to_new_core?(current_user) && params[:build_list][:new_core] == '1' params[:build_list][:auto_publish] = false if new_core Arch.where(:id => params[:arches]).each do |arch| Platform.main.where(:id => build_for_platforms).each do |build_for_platform| diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 2050781c4..d381a5894 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -290,6 +290,10 @@ class BuildList < ActiveRecord::Base @status end + def self.has_access_to_new_core?(user) + user && (user.admin? || user.tester?) + end + def self.human_status(status) I18n.t("layout.build_lists.statuses.#{HUMAN_STATUSES[status]}") end diff --git a/app/models/user.rb b/app/models/user.rb index 1159a2a77..b640134ed 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,6 @@ # -*- encoding : utf-8 -*- class User < Avatar - ROLES = ['', 'admin', 'banned'] + ROLES = ['', 'admin', 'banned', 'tester'] LANGUAGES_FOR_SELECT = [['Russian', 'ru'], ['English', 'en']] LANGUAGES = LANGUAGES_FOR_SELECT.map(&:last) @@ -42,6 +42,7 @@ class User < Avatar scope :opened, where('1=1') scope :banned, where(:role => 'banned') scope :admin, where(:role => 'admin') + scope :tester, where(:role => 'tester') scope :real, where(:role => ['', nil]) scope :member_of_project, lambda {|item| @@ -66,6 +67,10 @@ class User < Avatar new_record? end + def tester? + role == 'tester' + end + def access_locked? role == 'banned' end diff --git a/app/views/projects/build_lists/new.html.haml b/app/views/projects/build_lists/new.html.haml index 26c7425bc..86e077fa9 100644 --- a/app/views/projects/build_lists/new.html.haml +++ b/app/views/projects/build_lists/new.html.haml @@ -29,7 +29,7 @@ .both = f.check_box :build_requires = f.label :build_requires - - if current_user.admin? + - if BuildList.has_access_to_new_core?(current_user) .both = f.check_box :new_core = f.label :new_core diff --git a/config/locales/users.en.yml b/config/locales/users.en.yml index 4dc842606..b910b21f6 100644 --- a/config/locales/users.en.yml +++ b/config/locales/users.en.yml @@ -26,6 +26,7 @@ en: admin: Admins real: Real banned: Banned + tester: Testers register_request: list_header: Register requests diff --git a/config/locales/users.ru.yml b/config/locales/users.ru.yml index f85f57523..bd30181e5 100644 --- a/config/locales/users.ru.yml +++ b/config/locales/users.ru.yml @@ -26,6 +26,7 @@ ru: admin: Админы real: Обычные banned: Забаненные + tester: Тестеры register_request: list_header: Заявки на регистрацию From 26f7cd31fbe3e53238518edddbfc29af618edcca Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Fri, 7 Dec 2012 00:46:56 +0600 Subject: [PATCH 14/26] [refs #762] remove label --- app/views/platforms/mass_builds/index.html.haml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/views/platforms/mass_builds/index.html.haml b/app/views/platforms/mass_builds/index.html.haml index ece1e54a3..4967c095d 100644 --- a/app/views/platforms/mass_builds/index.html.haml +++ b/app/views/platforms/mass_builds/index.html.haml @@ -55,7 +55,6 @@ %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 }"} -if mass_build.projects_list.present? - = t('activerecord.attributes.mass_build.projects_list') + ": " = link_to_list @platform, mass_build, 'projects_list' .both = t('activerecord.attributes.mass_build.arch_names') + ": " From eae2b2ce02ea6d54baceb2571c56e1fd4ba4cbc3 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 23:18:28 +0400 Subject: [PATCH 15/26] #759: add state_machine into the ProductBuildList --- .../product_build_lists_controller.rb | 9 ++- app/models/build_list.rb | 6 +- app/models/product_build_list.rb | 55 ++++++++++++++++--- lib/abf_worker/iso_worker_observer.rb | 22 +++++++- lib/abf_worker/model_helper.rb | 7 +-- 5 files changed, 76 insertions(+), 23 deletions(-) diff --git a/app/controllers/platforms/product_build_lists_controller.rb b/app/controllers/platforms/product_build_lists_controller.rb index 2bc8e4bbd..c41dce55d 100644 --- a/app/controllers/platforms/product_build_lists_controller.rb +++ b/app/controllers/platforms/product_build_lists_controller.rb @@ -26,9 +26,12 @@ class Platforms::ProductBuildListsController < Platforms::BaseController end def cancel - @product_build_list.cancel_job - flash[:notice] = t('layout.build_lists.will_be_canceled') - redirect_to platform_product_product_build_list_path(@platform, @product, @product_build_list) + if @product_build_list.cancel + notice = t('layout.build_lists.will_be_canceled') + else + notice = t('layout.build_lists.cancel_fail') + end + redirect_to :back, :notice => notice end def log diff --git a/app/models/build_list.rb b/app/models/build_list.rb index d381a5894..de5fcff6e 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -142,7 +142,7 @@ class BuildList < ActiveRecord::Base after_transition :on => :published, :do => [:set_version_and_tag, :actualize_packages] after_transition :on => :cancel, :do => [:cancel_job], - :if => lambda { |build_list| build_list.build_canceling? } + :if => lambda { |build_list| build_list.new_core? } after_transition :on => [:published, :fail_publish, :build_error], :do => :notify_users after_transition :on => :build_success, :do => :notify_users, @@ -178,12 +178,12 @@ class BuildList < ActiveRecord::Base !build_list.new_core? && build_list.can_cancel? && BuildServer.delete_build_list(build_list.bs_id) == BuildServer::SUCCESS } transition [:build_pending, :build_started] => :build_canceling, :if => lambda { |build_list| - build_list.new_core? && build_list.can_cancel? + build_list.new_core? } end event :build_canceled do - transition [:build_canceling] => :build_canceled, :if => lambda { |build_list| + transition :build_canceling => :build_canceled, :if => lambda { |build_list| build_list.new_core? } end diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index 501e058a3..d7a1777f3 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -4,19 +4,21 @@ class ProductBuildList < ActiveRecord::Base include AbfWorker::ModelHelper delegate :url_helpers, to: 'Rails.application.routes' - BUILD_COMPLETED = 0 - BUILD_FAILED = 1 - BUILD_PENDING = 2 - BUILD_STARTED = 3 - BUILD_CANCELED = 4 - BUILD_CANCELING = 5 + BUILD_COMPLETED = 0 + BUILD_FAILED = 1 + BUILD_PENDING = 2 + BUILD_STARTED = 3 + BUILD_CANCELED = 4 + BUILD_CANCELING = 5 + WAITING_FOR_RESPONSE = 4000 STATUSES = [ BUILD_STARTED, BUILD_COMPLETED, BUILD_FAILED, BUILD_PENDING, BUILD_CANCELED, - BUILD_CANCELING + BUILD_CANCELING, + WAITING_FOR_RESPONSE ] HUMAN_STATUSES = { BUILD_STARTED => :build_started, @@ -24,7 +26,8 @@ class ProductBuildList < ActiveRecord::Base BUILD_FAILED => :build_failed, BUILD_PENDING => :build_pending, BUILD_CANCELED => :build_canceled, - BUILD_CANCELING => :build_canceling + BUILD_CANCELING => :build_canceling, + WAITING_FOR_RESPONSE => :waiting_for_response } belongs_to :product @@ -61,10 +64,44 @@ class ProductBuildList < ActiveRecord::Base scope :scoped_to_product_name, lambda {|product_name| joins(:product).where('products.name LIKE ?', "%#{product_name}%")} scope :recent, order("#{table_name}.updated_at DESC") - after_create :add_job_to_abf_worker_queue + after_create :place_build before_destroy :can_destroy? after_destroy :xml_delete_iso_container + state_machine :status, :initial => :waiting_for_response do + + event :place_build do + transition :waiting_for_response => :build_pending, :if => lambda { |pbl| + pbl.add_job_to_abf_worker_queue + } + end + + event :start_build do + transition :build_pending => :build_started + end + + event :cancel do + transition [:build_pending, :build_started] => :build_canceling + end + after_transition :on => :cancel, :do => [:cancel_job] + + event :build_canceled do + transition :build_canceling => :build_canceled + end + + event :build_success do + transition :build_started => :build_completed + end + + event :build_error do + transition [:build_started, :build_canceled, :build_canceling] => :build_failed + end + + HUMAN_STATUSES.each do |code,name| + state name, :value => code + end + end + def build_started? status == BUILD_STARTED end diff --git a/lib/abf_worker/iso_worker_observer.rb b/lib/abf_worker/iso_worker_observer.rb index 026874368..4bac9f6d7 100644 --- a/lib/abf_worker/iso_worker_observer.rb +++ b/lib/abf_worker/iso_worker_observer.rb @@ -1,13 +1,29 @@ module AbfWorker class IsoWorkerObserver + BUILD_COMPLETED = 0 + BUILD_FAILED = 1 + BUILD_PENDING = 2 + BUILD_STARTED = 3 + BUILD_CANCELED = 4 @queue = :iso_worker_observer def self.perform(options) status = options['status'].to_i pbl = ProductBuildList.find options['id'] - pbl.status = status - pbl.results = options['results'] if status != ProductBuildList::BUILD_STARTED - pbl.save! + case status + when BUILD_COMPLETED + pbl.build_success + when BUILD_FAILED + pbl.build_error + when BUILD_STARTED + pbl.start_build + when BUILD_CANCELED + pbl.build_canceled + end + if status != BUILD_STARTED + pbl.results = options['results'] + pbl.save! + end end end diff --git a/lib/abf_worker/model_helper.rb b/lib/abf_worker/model_helper.rb index 0803ead49..b9a921ff6 100644 --- a/lib/abf_worker/model_helper.rb +++ b/lib/abf_worker/model_helper.rb @@ -1,9 +1,8 @@ module AbfWorker module ModelHelper # In model which contains this helper should be: - # - BUILD_CANCELING - # - BUILD_CANCELED # - #abf_worker_args + # - #build_canceled def abf_worker_log q = 'abfworker::' @@ -22,15 +21,13 @@ module AbfWorker end def cancel_job - update_attributes({:status => self.class::BUILD_CANCELING}) - deleted = Resque::Job.destroy( worker_queue, worker_queue_class, abf_worker_args ) if deleted == 1 - update_attributes({:status => self.class::BUILD_CANCELED}) + build_canceled else send_stop_signal end From 8eabfc975ae863d18bc7486ab10b8e1e6df4a449 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 23:45:35 +0400 Subject: [PATCH 16/26] #759: add comment --- app/models/build_list.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/build_list.rb b/app/models/build_list.rb index de5fcff6e..a27ef35b8 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -258,6 +258,7 @@ class BuildList < ActiveRecord::Base def add_to_queue if new_core? + # TODO: Investigate: why 2 tasks will be created without checking @state add_job_to_abf_worker_queue unless @status @status ||= BUILD_PENDING else From 4d3fe773cd4055b0a05e34ffa04652aa8dc57e1b Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Thu, 6 Dec 2012 23:57:20 +0400 Subject: [PATCH 17/26] #759: update time_living for tasks --- app/models/build_list.rb | 2 +- app/models/product_build_list.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/build_list.rb b/app/models/build_list.rb index a27ef35b8..4a3465f19 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -400,7 +400,7 @@ class BuildList < ActiveRecord::Base { :id => id, :arch => arch.name, - :time_living => 2880, # 2 days + :time_living => 43200, # 12 hours :distrib_type => build_for_platform.distrib_type, # :git_project_address => 'https://abf.rosalinux.ru/server/gnome-settings-daemon.git', :git_project_address => project.git_project_address, diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index d7a1777f3..6c8ca3e3b 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -151,7 +151,7 @@ class ProductBuildList < ActiveRecord::Base # :srcpath => 'http://dl.dropbox.com/u/945501/avokhmin-test-iso-script-5d9b463d4e9c06ea8e7c89e1b7ff5cb37e99e27f.tar.gz', :srcpath => srcpath, :params => params, - :time_living => time_living, + :time_living => (time_living * 60), :main_script => main_script, :arch => arch.name, :distrib_type => product.platform.distrib_type From b91489c886b467d069f8574220b3610591d1956c Mon Sep 17 00:00:00 2001 From: Alexander Machehin Date: Fri, 7 Dec 2012 01:34:32 +0600 Subject: [PATCH 18/26] [refs #762] fix many errors --- app/models/platform.rb | 6 ++++-- app/models/project.rb | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/models/platform.rb b/app/models/platform.rb index 3617319fd..4ba1042ed 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -210,13 +210,15 @@ class Platform < ActiveRecord::Base arches = mass_build.arches ? Arch.where(:id => mass_build.arches) : Arch.all auto_publish = opts[:auto_publish] || false user = opts[:user] - mass_build.projects_list.lines.each do |name| name.chomp!; name.strip! if p = Project.joins(:repositories).where('repositories.id IN (?)', repositories).find_by_name(name) begin return if mass_build.reload.stop_build - p.build_for(self, rep.id, user, arch, auto_publish, mass_build_id) + arches.map(&:name).each do |arch| + rep = (p.repositories | repositories).first + p.build_for(self, rep.id, user, arch, auto_publish, mass_build.id) + end rescue RuntimeError, Exception end else diff --git a/app/models/project.rb b/app/models/project.rb index 9e2866d44..64ffbe309 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -128,7 +128,7 @@ class Project < ActiveRecord::Base # Select main and project platform repository(contrib, non-free and etc) # If main does not exist, will connect only project platform repository # If project platform repository is main, only main will be connect - main_rep_id = platform.repositories.find_by_name('main').id + main_rep_id = platform.repositories.find_by_name('main').try(:id) build_reps_ids = [main_rep_id, repository_id].compact.uniq arch = Arch.find_by_name(arch) if arch.acts_like?(:string) From 632a007e2d77b9be138dc5c24ffea9a763ee8575 Mon Sep 17 00:00:00 2001 From: Vladimir Sharshov Date: Fri, 7 Dec 2012 01:21:05 +0400 Subject: [PATCH 19/26] Add missing params for build_from_list operations --- app/models/mass_build.rb | 7 ++++++- app/models/platform.rb | 4 +--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/models/mass_build.rb b/app/models/mass_build.rb index da46a2f70..befd88c93 100644 --- a/app/models/mass_build.rb +++ b/app/models/mass_build.rb @@ -29,7 +29,12 @@ class MassBuild < ActiveRecord::Base def build_all # later with resque if projects_list.present? - platform.build_from_list :mass_build_id => self.id + platform.build_from_list( + :mass_build_id => self.id, + :user => self.user, + :arches => self.arches, + :auto_publish => self.auto_publish + ) else platform.build_all( :mass_build_id => self.id, diff --git a/app/models/platform.rb b/app/models/platform.rb index 4ba1042ed..465328a17 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -223,12 +223,10 @@ class Platform < ActiveRecord::Base end else MassBuild.increment_counter :missed_projects_count, mass_build.id - #mass_build.missed_projects_list = '' if mass_build.missed_projects_list.nil? - #mass_build.missed_projects_list << "#{name}\n" list = (mass_build.missed_projects_list || '') << "#{name}\n" mass_build.update_column :missed_projects_list, list end - sleep 0.2 + sleep 1 end end later :build_from_list, :loner => true, :queue => :clone_build From 31461eeadf32db6d9c726dc30e440b374c5f2061 Mon Sep 17 00:00:00 2001 From: Vladimir Sharshov Date: Fri, 7 Dec 2012 02:28:51 +0400 Subject: [PATCH 20/26] [refs #762] Fix searching platform package, fix repository selecting. --- app/models/platform.rb | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/app/models/platform.rb b/app/models/platform.rb index 465328a17..80c8a1afd 100644 --- a/app/models/platform.rb +++ b/app/models/platform.rb @@ -207,17 +207,24 @@ class Platform < ActiveRecord::Base def build_from_list(opts={}) mass_build = MassBuild.find opts[:mass_build_id] - arches = mass_build.arches ? Arch.where(:id => mass_build.arches) : Arch.all + arches = opts[:arches] ? Arch.where(:id => opts[:arches]) : Arch.all auto_publish = opts[:auto_publish] || false user = opts[:user] + mass_build.projects_list.lines.each do |name| name.chomp!; name.strip! - if p = Project.joins(:repositories).where('repositories.id IN (?)', repositories).find_by_name(name) + + project = "" + Project.where(:name => name).each do |pr| + project = pr if (pr.repository_ids & self.repository_ids).present? + end + + if project begin return if mass_build.reload.stop_build arches.map(&:name).each do |arch| - rep = (p.repositories | repositories).first - p.build_for(self, rep.id, user, arch, auto_publish, mass_build.id) + rep = (project.repositories & self.repositories).first + project.build_for(self, rep.id, user, arch, auto_publish, mass_build.id) end rescue RuntimeError, Exception end From f8cbae424e2b0248f9f4d94c7b78004c98943750 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Fri, 7 Dec 2012 13:10:38 +0400 Subject: [PATCH 21/26] #759: update #build_canceled event --- app/models/build_list.rb | 2 +- app/models/product_build_list.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 4a3465f19..99a7a7cae 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -183,7 +183,7 @@ class BuildList < ActiveRecord::Base end event :build_canceled do - transition :build_canceling => :build_canceled, :if => lambda { |build_list| + transition [:build_canceling, :build_started] => :build_canceled, :if => lambda { |build_list| build_list.new_core? } end diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index 6c8ca3e3b..6f2a71153 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -86,7 +86,7 @@ class ProductBuildList < ActiveRecord::Base after_transition :on => :cancel, :do => [:cancel_job] event :build_canceled do - transition :build_canceling => :build_canceled + transition [:build_canceling, :build_started] => :build_canceled end event :build_success do From a8e1cea0575285af2df374867c5affe5aa48830f Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Fri, 7 Dec 2012 15:11:12 +0400 Subject: [PATCH 22/26] #759: save sec of time_living instead of minut, some fixes of state_machine --- app/models/product.rb | 5 +-- app/models/product_build_list.rb | 22 ++++--------- .../product_build_lists/show.html.haml | 4 ++- .../platforms/products/_def_fields.html.haml | 8 +++-- config/locales/models/product.en.yml | 3 +- config/locales/models/product.ru.yml | 3 +- config/locales/models/time_living.en.yml | 4 +++ config/locales/models/time_living.ru.yml | 4 +++ lib/modules/models/time_living.rb | 32 +++++++++++++++++++ 9 files changed, 62 insertions(+), 23 deletions(-) create mode 100644 config/locales/models/time_living.en.yml create mode 100644 config/locales/models/time_living.ru.yml create mode 100644 lib/modules/models/time_living.rb diff --git a/app/models/product.rb b/app/models/product.rb index 7526dbb2c..8d77f6c66 100644 --- a/app/models/product.rb +++ b/app/models/product.rb @@ -1,5 +1,7 @@ # -*- encoding : utf-8 -*- class Product < ActiveRecord::Base + include Modules::Models::TimeLiving + belongs_to :platform belongs_to :project has_many :product_build_lists, :dependent => :destroy @@ -13,8 +15,7 @@ class Product < ActiveRecord::Base :description, :project_id, :main_script, - :params, - :time_living + :params attr_readonly :platform_id def full_clone(attrs = {}) diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index 6f2a71153..5edcccaef 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -1,6 +1,7 @@ # -*- encoding : utf-8 -*- class ProductBuildList < ActiveRecord::Base include Modules::Models::CommitAndVersion + include Modules::Models::TimeLiving include AbfWorker::ModelHelper delegate :url_helpers, to: 'Rails.application.routes' @@ -10,15 +11,13 @@ class ProductBuildList < ActiveRecord::Base BUILD_STARTED = 3 BUILD_CANCELED = 4 BUILD_CANCELING = 5 - WAITING_FOR_RESPONSE = 4000 STATUSES = [ BUILD_STARTED, BUILD_COMPLETED, BUILD_FAILED, BUILD_PENDING, BUILD_CANCELED, - BUILD_CANCELING, - WAITING_FOR_RESPONSE + BUILD_CANCELING ] HUMAN_STATUSES = { BUILD_STARTED => :build_started, @@ -26,8 +25,7 @@ class ProductBuildList < ActiveRecord::Base BUILD_FAILED => :build_failed, BUILD_PENDING => :build_pending, BUILD_CANCELED => :build_canceled, - BUILD_CANCELING => :build_canceling, - WAITING_FOR_RESPONSE => :waiting_for_response + BUILD_CANCELING => :build_canceling } belongs_to :product @@ -39,7 +37,6 @@ class ProductBuildList < ActiveRecord::Base :status, :project_id, :main_script, - :time_living, :arch_id, :presence => true validates :status, :inclusion => { :in => STATUSES } @@ -52,7 +49,6 @@ class ProductBuildList < ActiveRecord::Base :params, :project_version, :commit_hash, - :time_living, :arch_id attr_readonly :product_id serialize :results, Array @@ -64,17 +60,11 @@ class ProductBuildList < ActiveRecord::Base scope :scoped_to_product_name, lambda {|product_name| joins(:product).where('products.name LIKE ?', "%#{product_name}%")} scope :recent, order("#{table_name}.updated_at DESC") - after_create :place_build + after_create :add_job_to_abf_worker_queue before_destroy :can_destroy? after_destroy :xml_delete_iso_container - state_machine :status, :initial => :waiting_for_response do - - event :place_build do - transition :waiting_for_response => :build_pending, :if => lambda { |pbl| - pbl.add_job_to_abf_worker_queue - } - end + state_machine :status, :initial => :build_pending do event :start_build do transition :build_pending => :build_started @@ -151,7 +141,7 @@ class ProductBuildList < ActiveRecord::Base # :srcpath => 'http://dl.dropbox.com/u/945501/avokhmin-test-iso-script-5d9b463d4e9c06ea8e7c89e1b7ff5cb37e99e27f.tar.gz', :srcpath => srcpath, :params => params, - :time_living => (time_living * 60), + :time_living => time_living, :main_script => main_script, :arch => arch.name, :distrib_type => product.platform.distrib_type diff --git a/app/views/platforms/product_build_lists/show.html.haml b/app/views/platforms/product_build_lists/show.html.haml index a39d22ecd..d3f52459c 100644 --- a/app/views/platforms/product_build_lists/show.html.haml +++ b/app/views/platforms/product_build_lists/show.html.haml @@ -18,9 +18,11 @@ = 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, :time_living].each do |el| +- [:main_script, :params].each do |el| = render 'show_field', :key => el, :value => pbl.send(el) += render 'show_field', :key => :time_living, :value => (pbl.time_living / 60) + = render 'show_field', :key => :notified_at, :value => l(pbl.updated_at, :format => :long) - if pbl.can_cancel? && can?(:cancel, pbl) diff --git a/app/views/platforms/products/_def_fields.html.haml b/app/views/platforms/products/_def_fields.html.haml index 1f404747e..97a842e04 100644 --- a/app/views/platforms/products/_def_fields.html.haml +++ b/app/views/platforms/products/_def_fields.html.haml @@ -1,4 +1,8 @@ -- [:main_script, :params, :time_living].each do |el| +- [:main_script, :params].each do |el| .leftlist= f.label el, t("activerecord.attributes.product_build_list.#{el}"), :class => :label .rightlist= f.text_field el - .both \ No newline at end of file + .both + +.leftlist= f.label :time_living, t("activerecord.attributes.product_build_list.time_living"), :class => :label +.rightlist= f.text_field :time_living, :value => (@product.time_living / 60) +.both \ No newline at end of file diff --git a/config/locales/models/product.en.yml b/config/locales/models/product.en.yml index 4df44ef73..df7e20768 100644 --- a/config/locales/models/product.en.yml +++ b/config/locales/models/product.en.yml @@ -31,4 +31,5 @@ en: build_status: Build status created_at: Created updated_at: Updated - project: Project \ No newline at end of file + project: Project + time_living: Max time for building (in minutes) \ No newline at end of file diff --git a/config/locales/models/product.ru.yml b/config/locales/models/product.ru.yml index cc9486144..f1cbf6fc1 100644 --- a/config/locales/models/product.ru.yml +++ b/config/locales/models/product.ru.yml @@ -31,4 +31,5 @@ ru: build_status: Статус последней сборки created_at: Создан updated_at: Обновлен - project: Проект \ No newline at end of file + project: Проект + time_living: Максимальное время сборки (в минутах) \ No newline at end of file diff --git a/config/locales/models/time_living.en.yml b/config/locales/models/time_living.en.yml new file mode 100644 index 000000000..cc1837181 --- /dev/null +++ b/config/locales/models/time_living.en.yml @@ -0,0 +1,4 @@ +en: + flash: + time_living: + numericality_error: must be 2 to 720 minut \ No newline at end of file diff --git a/config/locales/models/time_living.ru.yml b/config/locales/models/time_living.ru.yml new file mode 100644 index 000000000..ea0ef50b2 --- /dev/null +++ b/config/locales/models/time_living.ru.yml @@ -0,0 +1,4 @@ +ru: + flash: + time_living: + numericality_error: должно быть от 2 до 720 минут \ No newline at end of file diff --git a/lib/modules/models/time_living.rb b/lib/modules/models/time_living.rb new file mode 100644 index 000000000..68742b75f --- /dev/null +++ b/lib/modules/models/time_living.rb @@ -0,0 +1,32 @@ +# -*- encoding : utf-8 -*- +module Modules + module Models + module TimeLiving + extend ActiveSupport::Concern + + included do + + validates :time_living, :numericality => { + :only_integer => true + }, :presence => true + + validate lambda { + # 2 min <= time_living <= 12 hours + if 120 > time_living || time_living > 43200 + errors.add(:time_living, I18n.t('flash.time_living.numericality_error')) + end + } + + before_validation :convert_time_living + + attr_accessible :time_living + end + + protected + + def convert_time_living + self.time_living = time_living.to_i * 60 if time_living_was.to_i != time_living.to_i + end + end + end +end From ba147718426b7855b01c3c2a81c5379844caea01 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Fri, 7 Dec 2012 15:22:41 +0400 Subject: [PATCH 23/26] #759: increase time --- lib/abf_worker/model_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/abf_worker/model_helper.rb b/lib/abf_worker/model_helper.rb index b9a921ff6..543a84d0f 100644 --- a/lib/abf_worker/model_helper.rb +++ b/lib/abf_worker/model_helper.rb @@ -39,7 +39,7 @@ module AbfWorker def send_stop_signal Resque.redis.setex( live_inspector_queue, - 90, # Data will be removed from Redis after 90 sec. + 240, # Data will be removed from Redis after 240 sec. 'USR1' # Immediately kill child but don't exit ) end From 4039a92bfa8d0b6256f354966b450342760cd16a Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Fri, 7 Dec 2012 15:23:41 +0400 Subject: [PATCH 24/26] #759: update error message --- config/locales/models/time_living.en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/models/time_living.en.yml b/config/locales/models/time_living.en.yml index cc1837181..c7c4cd11f 100644 --- a/config/locales/models/time_living.en.yml +++ b/config/locales/models/time_living.en.yml @@ -1,4 +1,4 @@ en: flash: time_living: - numericality_error: must be 2 to 720 minut \ No newline at end of file + numericality_error: must be 2 to 720 minutes \ No newline at end of file From 6a99d56489fafc44a1782cd4fad6e5f2e3fdc950 Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Fri, 7 Dec 2012 15:47:42 +0400 Subject: [PATCH 25/26] #759: add comments, some refactoring according to Vladimir's comments --- app/models/build_list.rb | 3 ++- app/models/build_list_observer.rb | 7 +++++-- app/models/product_build_list.rb | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 99a7a7cae..853fede2c 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -182,6 +182,8 @@ class BuildList < ActiveRecord::Base } end + # :build_canceling => :build_canceled - canceling from UI + # :build_started => :build_canceled - canceling from worker by time-out (time_living has been expired) event :build_canceled do transition [:build_canceling, :build_started] => :build_canceled, :if => lambda { |build_list| build_list.new_core? @@ -338,7 +340,6 @@ class BuildList < ActiveRecord::Base end def human_duration - duration ||= current_duration I18n.t("layout.build_lists.human_duration", {:hours => (duration/3600).to_i, :minutes => (duration%3600/60).to_i}) end diff --git a/app/models/build_list_observer.rb b/app/models/build_list_observer.rb index 2d12b85d0..251fcf301 100644 --- a/app/models/build_list_observer.rb +++ b/app/models/build_list_observer.rb @@ -4,9 +4,12 @@ class BuildListObserver < ActiveRecord::Observer def before_update(record) if record.status_changed? record.started_at = Time.now if record.status == BuildServer::BUILD_STARTED - if [BuildServer::BUILD_ERROR, BuildServer::SUCCESS].include? record.status + if [BuildServer::BUILD_ERROR, + BuildServer::SUCCESS, + BuildList::BUILD_CANCELING, + BuildList::BUILD_CANCELED].include? record.status # stores time interval beetwin build start and finish in seconds - record.duration = record.current_duration + record.duration = record.current_duration if record.started_at if record.status == BuildServer::SUCCESS # Update project average build time diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index 5edcccaef..c89b57786 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -75,6 +75,8 @@ class ProductBuildList < ActiveRecord::Base end after_transition :on => :cancel, :do => [:cancel_job] + # :build_canceling => :build_canceled - canceling from UI + # :build_started => :build_canceled - canceling from worker by time-out (time_living has been expired) event :build_canceled do transition [:build_canceling, :build_started] => :build_canceled end From 62a761a7c9f9437ec4b174762f5f30d0f2ffcfba Mon Sep 17 00:00:00 2001 From: Vokhmin Alexey V Date: Mon, 10 Dec 2012 16:15:22 +0400 Subject: [PATCH 26/26] #766: add filter to /build_lists page --- app/helpers/build_lists_helper.rb | 7 +++++++ app/models/build_list.rb | 1 + app/models/build_list/filter.rb | 5 ++++- app/views/projects/build_lists/_filter.html.haml | 2 ++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/app/helpers/build_lists_helper.rb b/app/helpers/build_lists_helper.rb index 3be58d7e7..b6d0237b7 100644 --- a/app/helpers/build_lists_helper.rb +++ b/app/helpers/build_lists_helper.rb @@ -13,6 +13,13 @@ module BuildListsHelper 'nocolor' end + def build_list_options_for_new_core + [ + [I18n.t("layout.true_"), 1], + [I18n.t("layout.false_"), 0] + ] + end + def build_list_item_status_color(status) if BuildServer::SUCCESS == status return 'success' diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 853fede2c..7876487b7 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -112,6 +112,7 @@ class BuildList < ActiveRecord::Base s } scope :scoped_to_project_name, lambda {|project_name| joins(:project).where('projects.name LIKE ?', "%#{project_name}%")} + scope :scoped_to_new_core, lambda {|new_core| where(:new_core => new_core)} scope :outdated, where('created_at < ? AND status <> ? OR created_at < ?', Time.now - LIVE_TIME, BUILD_PUBLISHED, Time.now - MAX_LIVE_TIME) serialize :additional_repos diff --git a/app/models/build_list/filter.rb b/app/models/build_list/filter.rb index f3a4f78f2..bae506cf3 100644 --- a/app/models/build_list/filter.rb +++ b/app/models/build_list/filter.rb @@ -13,6 +13,7 @@ class BuildList::Filter build_lists = build_lists.where(:bs_id => @options[:bs_id]) else build_lists = build_lists.accessible_by(::Ability.new(@user), @options[:ownership].to_sym) if @options[:ownership] + build_lists = build_lists.scoped_to_new_core(@options[:new_core] == '0' ? nil : true) if @options[:new_core].present? build_lists = build_lists.for_status(@options[:status]) if @options[:status] build_lists = build_lists.scoped_to_arch(@options[:arch_id]) if @options[:arch_id] build_lists = build_lists.scoped_to_save_platform(@options[:platform_id]) if @options[:platform_id] @@ -49,7 +50,8 @@ class BuildList::Filter :project_version => nil, :bs_id => nil, :project_name => nil, - :mass_build_id => nil + :mass_build_id => nil, + :new_core => nil })) @options[:ownership] = @options[:ownership].presence || (@project || !@user ? 'everything' : 'owned') @@ -65,6 +67,7 @@ class BuildList::Filter @options[:bs_id] = @options[:bs_id].presence @options[:project_name] = @options[:project_name].presence @options[:mass_build_id] = @options[:mass_build_id].presence + @options[:new_core] = @options[:new_core].presence end def build_date_from_params(field_name, params) diff --git a/app/views/projects/build_lists/_filter.html.haml b/app/views/projects/build_lists/_filter.html.haml index a9ca14988..939d76789 100644 --- a/app/views/projects/build_lists/_filter.html.haml +++ b/app/views/projects/build_lists/_filter.html.haml @@ -37,6 +37,8 @@ %br = f.submit t("layout.search.header") .block + %h3.small= t("activerecord.attributes.build_list.new_core") + .lineForm.aside= f.select :new_core, build_list_options_for_new_core, {:include_blank => true, :selected => @filter.new_core}, {:class => 'sel80 aside', :id => 'new_core', :tabindex => 2} %h3.small= t("activerecord.attributes.build_list.status") .lineForm.aside= f.select :status, BuildList::STATUSES.collect{|status| [BuildList.human_status(status), status]}, {:include_blank => true, :selected => @filter.status}, {:class => 'sel80 aside', :id => 'status', :tabindex => 2} %h3.small= t("activerecord.models.platform")