Merge pull request #896 from warpc/756-new-packages-should-be-tested

[refs #756]: Packages testing with new status and refactoring.
This commit is contained in:
Vladimir Sharshov 2013-02-07 03:16:09 -08:00
commit c869718dda
14 changed files with 186 additions and 163 deletions

View File

@ -496,29 +496,22 @@ span.delete {
#fork-and-edit {display:block;}
.notify.blue div.success {
border: 1px solid #bad099;
background: #d7e599;
float: left;
}
div.notify.blue div.error {
float: left;
border: 1px solid #ddd;
background-color: #FBE3E4;
border-color: #FBC2C4;
}
div.notify.blue div.nocolor {
float: left;
border: 1px solid #a9c6dd;
}
div.notify.blue div.red {
float: left;
border: 1px solid #ddd;
background-color: #FBE3E4;
border-color: #FBC2C4;
.notify.blue {
.error, .red, .nocolor, .warning, .success { float: left; }
.error, .red {
border: 1px solid #ddd;
background-color: #FBE3E4;
border-color: #FBC2C4;
}
.success {
border: 1px solid #bad099;
background: #d7e599;
}
.nocolor { border: 1px solid #a9c6dd; }
.warning {
border: 1px solid #FBEED5;
background-color: #FCF8E3;
}
}
a.button.left_floated {

View File

@ -1990,13 +1990,10 @@ div.right.slim {
img.delete-row {
cursor: pointer;
}
table tbody tr.error td {
background: #fedede;
}
table tbody tr.success td {
background: #e3edb7;
table tbody {
.error td { background: #fedede; }
.success td { background: #e3edb7; }
.warning td { background: #FCF8E3; }
}
/* Create group */

View File

@ -1,15 +1,16 @@
# -*- encoding : utf-8 -*-
module BuildListsHelper
def build_list_status_color(status)
if [BuildList::BUILD_PUBLISHED, BuildList::SUCCESS].include? status
return 'success'
case status
when BuildList::BUILD_PUBLISHED, BuildList::SUCCESS
'success'
when BuildList::BUILD_ERROR, BuildList::PROJECT_VERSION_NOT_FOUND, BuildList::FAILED_PUBLISH, BuildList::REJECTED_PUBLISH
'error'
when BuildList::TESTS_FAILED
'warning'
else
'nocolor'
end
if [BuildList::BUILD_ERROR, BuildList::PROJECT_VERSION_NOT_FOUND,
BuildList::FAILED_PUBLISH, BuildList::REJECTED_PUBLISH].include? status
return 'error'
end
'nocolor'
end
def build_list_options_for_new_core
@ -20,14 +21,14 @@ module BuildListsHelper
end
def build_list_item_status_color(status)
if BuildList::SUCCESS == status
return 'success'
case status
when BuildList::SUCCESS
'success'
when BuildList::DEPENDENCIES_ERROR, BuildList::BUILD_ERROR, BuildList::Item::GIT_ERROR
'error'
else
''
end
if [BuildList::DEPENDENCIES_ERROR, BuildList::BUILD_ERROR, BuildList::Item::GIT_ERROR].include? status
return 'error'
end
''
end
def build_list_classified_update_types

View File

@ -154,6 +154,7 @@ class Ability
cannot [:clone], Platform, :platform_type => 'personal'
cannot :publish, BuildList, :new_core => false
cannot :create_container, BuildList, :new_core => false
cannot([:get_list, :create], MassBuild) {|mass_build| mass_build.platform.personal?}
cannot(:cancel, MassBuild) {|mass_build| mass_build.platform.personal? || mass_build.stop_build}

View File

@ -130,8 +130,13 @@ class ActivityFeedObserver < ActiveRecord::Observer
end
when 'BuildList'
if [BuildList::BUILD_PUBLISHED, BuildList::SUCCESS, BuildList::BUILD_ERROR,
BuildList::PROJECT_VERSION_NOT_FOUND, BuildList::FAILED_PUBLISH].include? record.status or
if [BuildList::BUILD_PUBLISHED,
BuildList::SUCCESS,
BuildList::BUILD_ERROR,
BuildList::PROJECT_VERSION_NOT_FOUND,
BuildList::FAILED_PUBLISH,
BuildList::TESTS_FAILED
].include? record.status or
(record.status == BuildList::BUILD_PENDING && record.bs_id_changed?)
record.project.admins.each do |recipient|
ActivityFeed.create(

View File

@ -67,6 +67,7 @@ class BuildList < ActiveRecord::Base
FAILED_PUBLISH = 8000
REJECTED_PUBLISH = 9000
BUILD_CANCELING = 10000
TESTS_FAILED = 11000
STATUSES = [ WAITING_FOR_RESPONSE,
BUILD_CANCELED,
@ -79,7 +80,8 @@ class BuildList < ActiveRecord::Base
SUCCESS,
BUILD_STARTED,
BUILD_ERROR,
PROJECT_VERSION_NOT_FOUND
PROJECT_VERSION_NOT_FOUND,
TESTS_FAILED
]
HUMAN_STATUSES = { WAITING_FOR_RESPONSE => :waiting_for_response,
@ -94,6 +96,7 @@ class BuildList < ActiveRecord::Base
BUILD_STARTED => :build_started,
SUCCESS => :success,
PROJECT_VERSION_NOT_FOUND => :project_version_not_found,
TESTS_FAILED => :tests_failed
}
scope :recent, order("#{table_name}.updated_at DESC")
@ -188,7 +191,7 @@ class BuildList < ActiveRecord::Base
end
event :publish do
transition [:success, :failed_publish, :build_published] => :build_publish
transition [:success, :failed_publish, :build_published, :tests_failed] => :build_publish
transition [:success, :failed_publish] => :failed_publish
end
@ -200,8 +203,10 @@ class BuildList < ActiveRecord::Base
transition [:build_started, :build_canceled] => :success
end
event :build_error do
transition [:build_started, :build_canceled, :build_canceling] => :build_error
[:build_error, :tests_failed].each do |kind|
event kind do
transition [:build_started, :build_canceling] => kind
end
end
HUMAN_STATUSES.each do |code,name|
@ -225,7 +230,8 @@ class BuildList < ActiveRecord::Base
:do => :remove_container
event :publish_container do
transition [:waiting_for_publish, :container_failed_publish] => :container_publish, :if => :success?
transition [:waiting_for_publish, :container_failed_publish] => :container_publish,
:if => :can_create_container?
end
event :published_container do
@ -263,7 +269,7 @@ class BuildList < ActiveRecord::Base
end
def can_create_container?
success? && [WAITING_FOR_RESPONSE, FAILED_PUBLISH].include?(container_status)
(success? || tests_failed?) && [WAITING_FOR_RESPONSE, FAILED_PUBLISH].include?(container_status)
end
#TODO: Share this checking on product owner.
@ -272,7 +278,7 @@ class BuildList < ActiveRecord::Base
end
def can_publish?
[SUCCESS, FAILED_PUBLISH, BUILD_PUBLISHED].include? status
[SUCCESS, FAILED_PUBLISH, BUILD_PUBLISHED, TESTS_FAILED].include? status
end
def can_reject_publish?
@ -387,7 +393,7 @@ class BuildList < ActiveRecord::Base
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.gsub!(/^http:\/\/(0\.0\.0\.0|localhost)\:[\d]+/, 'https://abf.rosalinux.ru') unless Rails.env.production?
# Path looks like:
# http://abf.rosalinux.ru/downloads/rosa-server2012/repository/x86_64/base/
# so, we should append:
@ -401,26 +407,19 @@ class BuildList < ActiveRecord::Base
include_repos_hash["#{save_to_platform.name}_release"] = save_to_platform.
urpmi_list(nil, nil, false, save_to_repository.name)["#{build_for_platform.name}"]["#{arch.name}"]
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
git_project_address = project.git_project_address(user)
# git_project_address.gsub!(/^http:\/\/(0\.0\.0\.0|localhost)\:[\d]+/, 'https://abf.rosalinux.ru') unless Rails.env.production?
{
:id => id,
:arch => arch.name,
: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(user),
# :commit_hash => 'fbb2549e44d97226fea6748a4f95d1d82ffb8726',
:commit_hash => commit_hash,
:include_repos => include_repos_hash,
:bplname => build_for_platform.name,
:user => {:uname => user.uname, :email => user.email}
:id => id,
:arch => arch.name,
:time_living => 43200, # 12 hours
:distrib_type => build_for_platform.distrib_type,
:git_project_address => git_project_address,
:commit_hash => commit_hash,
:include_repos => include_repos_hash,
:bplname => build_for_platform.name,
:user => {:uname => user.uname, :email => user.email}
}
end

View File

@ -7,6 +7,7 @@ class BuildListObserver < ActiveRecord::Observer
if [BuildList::BUILD_ERROR,
BuildList::SUCCESS,
BuildList::BUILD_CANCELING,
BuildList::TESTS_FAILED,
BuildList::BUILD_CANCELED].include? record.status
# stores time interval beetwin build start and finish in seconds
record.duration = record.current_duration if record.started_at

View File

@ -140,7 +140,8 @@
- if @build_list.build_published?
= submit_tag t("layout.publish_again"), :confirm => t("layout.publish_again_warning"), :name => 'publish'
- elsif @build_list.can_publish?
= submit_tag t("layout.publish"), :confirm => t("layout.confirm"), :name => 'publish'
- confirm = @build_list.tests_failed? ? t('layout.build_lists.tests_failed') : t('layout.confirm')
= submit_tag t("layout.publish"), :confirm => confirm, :name => 'publish'
- if @build_list.can_reject_publish? && can?(:reject_publish, @build_list)
= submit_tag t("layout.reject_publish"), :confirm => t("layout.confirm"), :name => 'reject_publish'
- if @build_list.can_create_container? && can?(:create_container, @build_list)

View File

@ -78,6 +78,7 @@ en:
action: Action
new_header: New build
main_data: Main data
tests_failed: Some tests failed. Be careful!
human_current_duration: Build currently takes %{hours} h. %{minutes} min.
human_duration: Built in %{hours} h. %{minutes} min.
@ -114,6 +115,7 @@ en:
build_lists: All
build_error: Build error
build_published: Build has been published
tests_failed: Tests failed
rejected_publish: Publishing rejected
build_publish: Build is being published
failed_publish: Publishing error

View File

@ -77,6 +77,7 @@ ru:
action: Действие
new_header: Новая сборка
main_data: Основные данные
tests_failed: Некоторые тесты провалились. Будьте осторожны!
human_current_duration: Сборка длится уже %{hours} ч. %{minutes} мин.
human_duration: Собрано за %{hours} ч. %{minutes} мин.
@ -113,6 +114,7 @@ ru:
build_lists: Всего
build_error: ошибка сборки
build_published: опубликован
tests_failed: тесты не прошли
rejected_publish: публикация отклонена
build_publish: публикуется
failed_publish: ошибка публикации

View File

@ -1,19 +1,38 @@
module AbfWorker
class BaseObserver
COMPLETED = 0
FAILED = 1
PENDING = 2
STARTED = 3
CANCELED = 4
COMPLETED = 0
FAILED = 1
PENDING = 2
STARTED = 3
CANCELED = 4
TESTS_FAILED = 5
def self.update_results(subject, options)
results = (subject.results || []) + options['results']
sort_results_and_save(subject, results)
attr_accessor :status, :options
def initialize(options, subject_class)
@status = options['status'].to_i
@options = options
@subject_class = subject_class
end
def self.sort_results_and_save(subject, results)
subject.results = results.sort_by{ |r| r['file_name'] }
subject.save!
def perform
raise NotImplementedError, "You should implement this method"
end
protected
def subject
@subject ||= @subject_class.find options['id']
end
def update_results
results = (subject.results || []) + options['results']
sort_results_and_save results
end
def sort_results_and_save(results, item = subject)
item.results = results.sort_by{ |r| r['file_name'] }
item.save!
end
end

View File

@ -3,21 +3,21 @@ module AbfWorker
@queue = :iso_worker_observer
def self.perform(options)
status = options['status'].to_i
pbl = ProductBuildList.find options['id']
new(options, ProductBuildList).perform
end
def perform
case status
when COMPLETED
pbl.build_success
subject.build_success
when FAILED
pbl.build_error
subject.build_error
when STARTED
pbl.start_build
subject.start_build
when CANCELED
pbl.build_canceled
end
if status != STARTED
update_results(pbl, options)
subject.build_canceled
end
update_results if status != STARTED
end
end

View File

@ -4,53 +4,53 @@ module AbfWorker
def self.perform(options)
status = options['status'].to_i
new(options, BuildList).perform
end
def perform
return if status == STARTED # do nothing when publication started
if options['type'] == 'resign'
AbfWorker::BuildListsPublishTaskManager.unlock_repository options['id']
else
if options['extra']['create_container'] # Container has been created
bl = BuildList.find(options['id'])
case status
when COMPLETED
bl.published_container
subject.published_container
when FAILED, CANCELED
bl.fail_publish_container
subject.fail_publish_container
end
update_results(bl, options)
update_results
else
update_rpm_builds options, status
update_rpm_builds
end
end
end
def self.update_rpm_builds(options, status)
protected
def update_rpm_builds
build_lists = BuildList.where(:id => options['build_list_ids'])
build_lists.each do |bl|
update_results(bl, options)
build_lists.each do |build_list|
update_results build_list
case status
when COMPLETED
bl.published
build_list.published
AbfWorker::BuildListsPublishTaskManager.cleanup_completed options['projects_for_cleanup']
when FAILED, CANCELED
bl.fail_publish
build_list.fail_publish
AbfWorker::BuildListsPublishTaskManager.cleanup_failed options['projects_for_cleanup']
end
AbfWorker::BuildListsPublishTaskManager.unlock_build_list bl
AbfWorker::BuildListsPublishTaskManager.unlock_build_list build_list
end
bl = build_lists.first || BuildList.find(options['id'])
AbfWorker::BuildListsPublishTaskManager.unlock_rep_and_platform bl
build_list = build_lists.first || subject
AbfWorker::BuildListsPublishTaskManager.unlock_rep_and_platform build_list
end
class << self
protected
def update_results(subject, options)
results = (subject.results || []).
select{ |r| r['file_name'] !~ /^abfworker\:\:publish\-worker.*\.log$/ }
results |= options['results']
sort_results_and_save(subject, results)
end
def update_results(build_list)
results = (build_list.results || []).
select{ |r| r['file_name'] !~ /^abfworker\:\:publish\-worker.*\.log$/ }
results |= options['results']
sort_results_and_save results, build_list
end
end
end

View File

@ -1,68 +1,70 @@
module AbfWorker
class RpmWorkerObserver < AbfWorker::BaseObserver
RESTARTED_BUILD_LISTS = 'abf-worker::rpm-worker-observer::restarted-build-lists'
@queue = :rpm_worker_observer
def self.perform(options)
bl = BuildList.find options['id']
status = options['status'].to_i
new(options, BuildList).perform
end
return if restart_task(bl, status, options)
item = find_or_create_item(bl)
fill_container_data(bl, options) if status != STARTED
def perform
return if restart_task
item = find_or_create_item
fill_container_data if status != STARTED
case status
when COMPLETED
bl.build_success
item.update_attributes({:status => BuildList::SUCCESS})
bl.now_publish if bl.auto_publish?
subject.build_success
subject.now_publish if subject.auto_publish?
when FAILED
bl.build_error
subject.build_error
item.update_attributes({:status => BuildList::BUILD_ERROR})
when STARTED
bl.start_build
subject.start_build
when CANCELED
bl.build_canceled
subject.build_canceled
item.update_attributes({:status => BuildList::BUILD_CANCELED})
when TESTS_FAILED
subject.tests_failed
end
item.update_attributes({:status => BuildList::SUCCESS}) if [TESTS_FAILED, COMPLETED].include?(status)
end
protected
def find_or_create_item
subject.items.first || subject.items.create({
:version => subject.commit_hash,
:name => subject.project.name,
:status => BuildList::BUILD_STARTED,
:level => 0
})
end
def restart_task
redis = Resque.redis
if redis.lrem(RESTARTED_BUILD_LISTS, 0, subject.id) > 0 || status != FAILED || (options['results'] || []).size > 1
return false
else
redis.lpush RESTARTED_BUILD_LISTS, subject.id
subject.update_column(:status, BuildList::BUILD_PENDING)
subject.add_job_to_abf_worker_queue
return true
end
end
class << self
protected
def restart_task(bl, status, options)
redis = Resque.redis
if redis.lrem(RESTARTED_BUILD_LISTS, 0, bl.id) > 0 || status != FAILED || (options['results'] || []).size > 1
return false
else
redis.lpush RESTARTED_BUILD_LISTS, bl.id
bl.update_column(:status, BuildList::BUILD_PENDING)
bl.add_job_to_abf_worker_queue
return true
end
end
def find_or_create_item(bl)
bl.items.first || bl.items.create({
:version => bl.commit_hash,
:name => bl.project.name,
:status => BuildList::BUILD_STARTED,
:level => 0
})
end
def fill_container_data(bl, options)
packages = options['packages'] || []
packages.each do |package|
package = bl.packages.build(package)
package.package_type = package['fullname'] =~ /.*\.src\.rpm$/ ? 'source' : 'binary'
package.project_id = bl.project_id
package.platform_id = bl.save_to_platform_id
package.save!
end
update_results(bl, options)
def fill_container_data
(options['packages'] || []).each do |package|
package = subject.packages.build(package)
package.package_type = package['fullname'] =~ /.*\.src\.rpm$/ ? 'source' : 'binary'
package.project_id = subject.project_id
package.platform_id = subject.save_to_platform_id
package.save!
end
update_results
end
end