Merge branch 'master' into 369-bootstrap

Conflicts:
	app/models/build_list.rb
	app/models/build_list/package.rb
	app/models/build_script.rb
	app/models/product_build_list.rb
	app/models/project_tag.rb
	app/views/projects/build_lists/_filter.html.haml
This commit is contained in:
Alexander Machehin 2014-12-18 15:07:27 +05:00
commit ab0a57d6b2
21 changed files with 147 additions and 96 deletions

View File

@ -194,15 +194,15 @@ RosaABF.controller('BuildListsController',
page: params.page || 1, page: params.page || 1,
per_page: params.per_page || 25, per_page: params.per_page || 25,
filter: { filter: {
ownership: params['filter[ownership]'] || 'owned', ownership: params['filter[ownership]'] || 'owned',
status: params['filter[status]'], status: params['filter[status]'],
platform_id: params['filter[platform_id]'], save_to_platform_id: params['filter[save_to_platform_id]'],
arch_id: params['filter[arch_id]'], arch_id: params['filter[arch_id]'],
mass_build_id: params['filter[mass_build_id]'], mass_build_id: params['filter[mass_build_id]'],
updated_at_start: params['filter[updated_at_start]'], updated_at_start: params['filter[updated_at_start]'],
updated_at_end: params['filter[updated_at_end]'], updated_at_end: params['filter[updated_at_end]'],
project_name: params['filter[project_name]'], project_name: params['filter[project_name]'],
id: params['filter[id]'] id: params['filter[id]']
} }
} }
} }

View File

@ -2,7 +2,6 @@ class Api::V1::BuildListsController < Api::V1::BaseController
before_filter :authenticate_user! before_filter :authenticate_user!
skip_before_filter :authenticate_user!, only: [:show, :index] if APP_CONFIG['anonymous_access'] skip_before_filter :authenticate_user!, only: [:show, :index] if APP_CONFIG['anonymous_access']
load_resource :project, only: :index, parent: false
load_and_authorize_resource :build_list, only: [:show, :create, :cancel, :publish, :reject_publish, :create_container, :publish_into_testing, :rerun_tests] load_and_authorize_resource :build_list, only: [:show, :create, :cancel, :publish, :reject_publish, :create_container, :publish_into_testing, :rerun_tests]
def show def show
@ -10,9 +9,16 @@ class Api::V1::BuildListsController < Api::V1::BaseController
end end
def index def index
@project = Project.find(params[:project_id]) if params[:project_id].present?
authorize!(:show, @project) if @project authorize!(:show, @project) if @project
filter = BuildList::Filter.new(@project, current_user, current_ability, params[:filter] || {}) filter = BuildList::Filter.new(@project, current_user, current_ability, params[:filter] || {})
@build_lists = filter.find.includes(:save_to_platform, :project, :user, :arch) @build_lists = filter.find.includes(:build_for_platform,
:save_to_repository,
:save_to_platform,
:project,
:user,
:arch)
@build_lists = @build_lists.recent.paginate(paginate_params) @build_lists = @build_lists.recent.paginate(paginate_params)
respond_to :json respond_to :json
end end

View File

@ -22,7 +22,7 @@ class Api::V1::JobsController < Api::V1::BaseController
else else
@build_list = build_lists.external_nodes(:owned).for_user(current_user).first @build_list = build_lists.external_nodes(:owned).for_user(current_user).first
@build_list ||= build_lists.external_nodes(:everything). @build_list ||= build_lists.external_nodes(:everything).
accessible_by(current_ability, :everything).readonly(false).first accessible_by(current_ability, :related).readonly(false).first
end end
set_builder set_builder
end end

View File

@ -23,6 +23,13 @@ module AbfWorker
item = find_or_create_item item = find_or_create_item
fill_container_data if status != STARTED fill_container_data if status != STARTED
unless subject.valid?
item.update_attributes({status: BuildList::BUILD_ERROR})
subject.build_error(false)
subject.save(validate: false)
return
end
rerunning_tests = subject.rerunning_tests? rerunning_tests = subject.rerunning_tests?
case status case status

View File

@ -40,14 +40,15 @@ class BuildList < ActiveRecord::Base
AUTO_PUBLISH_STATUS_TESTING = 'testing' AUTO_PUBLISH_STATUS_TESTING = 'testing'
] ]
validates :project, validates :project, :project_id,
:project_version, :project_version,
:arch, :arch, :arch_id,
:include_repos, :include_repos,
:build_for_platform, :build_for_platform, :build_for_platform_id,
:save_to_platform, :save_to_platform, :save_to_platform_id,
:save_to_repository, :save_to_repository, :save_to_repository_id,
presence: true presence: true
validates_numericality_of :priority, greater_than_or_equal_to: 0 validates_numericality_of :priority, greater_than_or_equal_to: 0
validates :external_nodes, inclusion: { in: EXTERNAL_NODES }, allow_blank: true validates :external_nodes, inclusion: { in: EXTERNAL_NODES }, allow_blank: true
validates :auto_publish_status, inclusion: { in: AUTO_PUBLISH_STATUSES } validates :auto_publish_status, inclusion: { in: AUTO_PUBLISH_STATUSES }
@ -133,10 +134,12 @@ class BuildList < ActiveRecord::Base
scope :for_platform, ->(platform) { where(build_for_platform_id: platform) if platform.present? } scope :for_platform, ->(platform) { where(build_for_platform_id: platform) if platform.present? }
scope :by_mass_build, ->(mass_build) { where(mass_build_id: mass_build) } scope :by_mass_build, ->(mass_build) { where(mass_build_id: mass_build) }
scope :scoped_to_arch, ->(arch) { where(arch_id: arch) if arch.present? } scope :scoped_to_arch, ->(arch) { where(arch_id: arch) if arch.present? }
scope :scoped_to_save_platform, ->(pl_id) { where(save_to_platform_id: pl_id) if pl_id.present? } scope :scoped_to_save_platform, ->(pl_id) { where(save_to_platform_id: pl_id) if pl_id.present? }
scope :scoped_to_project_version, ->(pr_version) { where(project_version: pr_version) if pr_version.present? } scope :scoped_to_build_for_platform, ->(pl_id) { where(build_for_platform_id: pl_id) if pl_id.present? }
scope :scoped_to_is_circle, ->(is_circle) { where(is_circle: is_circle) } scope :scoped_to_save_to_repository, ->(repo_id) { where(save_to_repository_id: repo_id) if repo_id.present? }
scope :for_creation_date_period, ->(start_date, end_date) { scope :scoped_to_project_version, ->(pr_version) { where(project_version: pr_version) if pr_version.present? }
scope :scoped_to_is_circle, ->(is_circle) { where(is_circle: is_circle) }
scope :for_creation_date_period, ->(start_date, end_date) {
s = all s = all
s = s.where(["#{table_name}.created_at >= ?", start_date]) if start_date s = s.where(["#{table_name}.created_at >= ?", start_date]) if start_date
s = s.where(["#{table_name}.created_at <= ?", end_date]) if end_date s = s.where(["#{table_name}.created_at <= ?", end_date]) if end_date
@ -598,35 +601,41 @@ class BuildList < ActiveRecord::Base
end end
def self.next_build(arch_ids, platform_ids) def self.next_build(arch_ids, platform_ids)
kind_id = Redis.current.spop(USER_BUILDS_SET) build_list = next_build_from_queue(USER_BUILDS_SET, arch_ids, platform_ids)
key = "user_build_#{kind_id}_rpm_worker_default" if kind_id build_list ||= next_build_from_queue(MASS_BUILDS_SET, arch_ids, platform_ids)
build_list = next_build_from_queue(kind_id, key, arch_ids, platform_ids) if key
Redis.current.sadd(USER_BUILDS_SET, kind_id) if build_list
kind_id ||= Redis.current.spop(MASS_BUILDS_SET) build_list.delayed_add_job_to_abf_worker_queue if build_list
key ||= "mass_build_#{kind_id}_rpm_worker" if kind_id
build_list ||= next_build_from_queue(kind_id, key, arch_ids, platform_ids, true) if key
Redis.current.sadd(MASS_BUILDS_SET, kind_id) if build_list && key =~ /^mass_build/
build_list.delayed_add_job_to_abf_worker_queue if build_list.present?
build_list build_list
end end
def self.next_build_from_queue(kind_id, key, arch_ids, platform_ids, mass_build = false) def self.next_build_from_queue(set, arch_ids, platform_ids)
if kind_id && (arch_ids.present? || platform_ids.present?) kind_id = Redis.current.spop(set)
build_list = BuildList.where(user_id: kind_id). key =
scoped_to_arch(arch_ids). case set
for_status([BuildList::BUILD_PENDING, BuildList::RERUN_TESTS]). when USER_BUILDS_SET
for_platform(platform_ids) "user_build_#{kind_id}_rpm_worker_default"
build_list = build_list.where.not(mass_build_id: nil) if mass_build when MASS_BUILDS_SET
build_list = build_list.oldest.order(:created_at).first "mass_build_#{kind_id}_rpm_worker"
end if kind_id
build_list = nil if build_list && build_list.destroy_from_resque_queue != 1 task = Resque.pop(key) if key
elsif key
task = Resque.pop(key) if task || Redis.current.llen("resque:queue:#{key}") > 0
Redis.current.sadd(set, kind_id)
end
build_list = BuildList.where(id: task['args'][0]['id']).first if task
return unless build_list
if platform_ids.present? && platform_ids.exclude?(build_list.build_for_platform_id)
build_list.restart_job
return
end
if arch_ids.present? && arch_ids.exclude?(build_list.arch_id)
build_list.restart_job
return
end end
build_list ||= BuildList.where(id: task['args'][0]['id']).first if task
build_list build_list
end end

View File

@ -22,7 +22,9 @@ class BuildList::Filter
build_lists = build_lists.for_status(@options[:status]) build_lists = build_lists.for_status(@options[:status])
.scoped_to_arch(@options[:arch_id]) .scoped_to_arch(@options[:arch_id])
.scoped_to_save_platform(@options[:platform_id]) .scoped_to_save_platform(@options[:save_to_platform_id])
.scoped_to_build_for_platform(@options[:build_for_platform_id])
.scoped_to_save_to_repository(@options[:save_to_repository_id])
.scoped_to_project_version(@options[:project_version]) .scoped_to_project_version(@options[:project_version])
.scoped_to_project_name(@options[:project_name]) .scoped_to_project_name(@options[:project_name])
.for_notified_date_period(@options[:updated_at_start], @options[:updated_at_end]) .for_notified_date_period(@options[:updated_at_start], @options[:updated_at_end])
@ -44,34 +46,38 @@ class BuildList::Filter
def set_options(options) def set_options(options)
@options = HashWithIndifferentAccess.new(options.reverse_merge({ @options = HashWithIndifferentAccess.new(options.reverse_merge({
ownership: nil, ownership: nil,
status: nil, status: nil,
updated_at_start: nil, updated_at_start: nil,
updated_at_end: nil, updated_at_end: nil,
arch_id: nil, arch_id: nil,
platform_id: nil, save_to_platform_id: nil,
is_circle: nil, build_for_platform_id: nil,
project_version: nil, save_to_repository_id: nil,
id: nil, is_circle: nil,
project_name: nil, project_version: nil,
mass_build_id: nil, id: nil,
new_core: nil project_name: nil,
mass_build_id: nil,
new_core: nil
})) }))
@options[:ownership] = @options[:ownership].presence || (@project || !@user ? 'everything' : 'owned') @options[:ownership] = @options[:ownership].presence || (@project || !@user ? 'everything' : 'owned')
@options[:status] = @options[:status].present? ? @options[:status].to_i : nil @options[:status] = @options[:status].present? ? @options[:status].to_i : nil
@options[:created_at_start] = build_date_from_params(:created_at_start, @options) @options[:created_at_start] = build_date_from_params(:created_at_start, @options)
@options[:created_at_end] = build_date_from_params(:created_at_end, @options) @options[:created_at_end] = build_date_from_params(:created_at_end, @options)
@options[:updated_at_start] = build_date_from_params(:updated_at_start, @options) @options[:updated_at_start] = build_date_from_params(:updated_at_start, @options)
@options[:updated_at_end] = build_date_from_params(:updated_at_end, @options) @options[:updated_at_end] = build_date_from_params(:updated_at_end, @options)
@options[:project_version] = @options[:project_version].presence @options[:project_version] = @options[:project_version].presence
@options[:arch_id] = @options[:arch_id].try(:to_i) @options[:arch_id] = @options[:arch_id].try(:to_i)
@options[:platform_id] = @options[:platform_id].try(:to_i) @options[:save_to_platform_id] = @options[:save_to_platform_id].try(:to_i)
@options[:is_circle] = @options[:is_circle].present? ? @options[:is_circle] == "1" : nil @options[:build_for_platform_id] = @options[:build_for_platform_id].try(:to_i)
@options[:id] = @options[:id].presence @options[:save_to_repository_id] = @options[:save_to_repository_id].try(:to_i)
@options[:project_name] = @options[:project_name].presence @options[:is_circle] = @options[:is_circle].present? ? @options[:is_circle] == "1" : nil
@options[:mass_build_id] = @options[:mass_build_id].presence @options[:id] = @options[:id].presence
@options[:new_core] = @options[:new_core].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 end
def build_date_from_params(field_name, params) def build_date_from_params(field_name, params)

View File

@ -9,7 +9,8 @@ class BuildList::Package < ActiveRecord::Base
attr_accessible :fullname, :name, :release, :version, :sha1, :epoch, :dependent_packages attr_accessible :fullname, :name, :release, :version, :sha1, :epoch, :dependent_packages
validates :build_list, :project, :platform, :fullname, validates :build_list, :build_list_id, :project, :project_id,
:platform, :platform_id, :fullname,
:package_type, :name, :release, :version, :package_type, :name, :release, :version,
presence: true presence: true
validates :package_type, inclusion: PACKAGE_TYPES validates :package_type, inclusion: PACKAGE_TYPES

View File

@ -10,7 +10,8 @@ class BuildScript < ActiveRecord::Base
belongs_to :project belongs_to :project
validates :treeish, presence: true validates :treeish, presence: true
validates :project, presence: true, uniqueness: { scope: :treeish } validates :project, presence: true
validates :project_id, uniqueness: { scope: :treeish }
scope :by_active, -> { where(status: ACTIVE) } scope :by_active, -> { where(status: ACTIVE) }
scope :by_treeish, -> treeish { where(treeish: treeish) } scope :by_treeish, -> treeish { where(treeish: treeish) }

View File

@ -94,7 +94,8 @@ class MassBuild < ActiveRecord::Base
def build_all def build_all
return unless start return unless start
# later with resque # later with resque
arches_list = arch_names ? Arch.where(name: arch_names.split(', ')) : Arch.all arches_list = arch_names ? Arch.where(name: arch_names.split(', ')) : Arch.all
current_ability = Ability.new(user)
projects_list.lines.each do |name| projects_list.lines.each do |name|
next if name.blank? next if name.blank?
@ -103,6 +104,8 @@ class MassBuild < ActiveRecord::Base
if project = Project.joins(:repositories).where('repositories.id in (?)', save_to_platform.repository_ids).find_by(name: name) if project = Project.joins(:repositories).where('repositories.id in (?)', save_to_platform.repository_ids).find_by(name: name)
begin begin
return if self.reload.stop_build return if self.reload.stop_build
# Ensures that user has rights to create a build_list
next unless current_ability.can?(:write, project)
increase_rt = increase_release_tag? increase_rt = increase_release_tag?
arches_list.each do |arch| arches_list.each do |arch|
rep_id = (project.repository_ids & save_to_platform.repository_ids).first rep_id = (project.repository_ids & save_to_platform.repository_ids).first

View File

@ -45,12 +45,13 @@ class ProductBuildList < ActiveRecord::Base
before_validation -> { self.arch_id = Arch.find_by(name: 'x86_64').id }, on: :create before_validation -> { self.arch_id = Arch.find_by(name: 'x86_64').id }, on: :create
# field "not_delete" can be changed only if build has been completed # field "not_delete" can be changed only if build has been completed
before_validation -> { self.not_delete = false unless build_completed?; true } before_validation -> { self.not_delete = false unless build_completed?; true }
validates :product,
validates :product, :product_id,
:status, :status,
:project, :project, :project_id,
:main_script, :main_script,
:project_version, :arch, :arch_id,
:arch, presence: true presence: true
validates :status, inclusion: { in: STATUSES } validates :status, inclusion: { in: STATUSES }
validates :main_script, :params, length: { maximum: 255 } validates :main_script, :params, length: { maximum: 255 }

View File

@ -8,7 +8,7 @@ class ProjectTag < ActiveRecord::Base
belongs_to :project belongs_to :project
validates :project, :commit, :sha1, :tag_name, :format_id, presence: true validates :project, :commit_id, :sha1, :tag_name, :format_id, presence: true
validates :project_id, uniqueness: { scope: [:tag_name, :format_id] } validates :project_id, uniqueness: { scope: [:tag_name, :format_id] }
attr_accessible :project_id, :commit_id, :sha1, :tag_name, :format_id attr_accessible :project_id, :commit_id, :sha1, :tag_name, :format_id

View File

@ -1,5 +1,5 @@
json.build_lists @build_lists do |build_list| json.build_lists @build_lists do |build_list|
json.(build_list, :id, :status) json.(build_list, :id, :status, :project_id)
json.url api_v1_build_list_path(build_list, format: :json) json.url api_v1_build_list_path(build_list, format: :json)
end end

View File

@ -2,3 +2,8 @@ json.(project, :id, :name)
json.fullname project.name_with_owner json.fullname project.name_with_owner
json.url api_v1_project_path(project.id, format: :json) json.url api_v1_project_path(project.id, format: :json)
json.git_url git_repo_url(project.name_with_owner) json.git_url git_repo_url(project.name_with_owner)
json.maintainer do
if project.maintainer
json.partial! 'api/v1/maintainers/maintainer', maintainer: project.maintainer
end
end

View File

@ -5,7 +5,9 @@ json.project do
json.updated_at @project.updated_at.to_i json.updated_at @project.updated_at.to_i
json.partial! 'api/v1/shared/owner', owner: @project.owner json.partial! 'api/v1/shared/owner', owner: @project.owner
json.maintainer do json.maintainer do
json.partial! 'api/v1/shared/member', member: @project.maintainer if @project.maintainer
json.partial! 'api/v1/maintainers/maintainer', maintainer: @project.maintainer
end
end end
json.project_statistics @project.project_statistics do |statistic| json.project_statistics @project.project_statistics do |statistic|

View File

@ -24,9 +24,9 @@
= t "layout.build_lists.ownership.#{ownership}" = t "layout.build_lists.ownership.#{ownership}"
.col-md-4.col-sm-6 .col-md-4.col-sm-6
%h4= t 'activerecord.models.platform' %h4= t 'activerecord.models.platform'
= f.select :platform_id, availables_main_platforms.collect{ |pl| [pl.name, pl.id] }, = f.select :save_to_platform_id, availables_main_platforms.collect{ |pl| [pl.name, pl.id] },
{ include_blank: true }, { include_blank: true },
html_options.merge(id: 'platform', 'ng-model' => 'params.filter.platform_id') html_options.merge(id: 'platform', 'ng-model' => 'params.filter.save_to_platform_id')
-[:updated_at_start, :updated_at_end].each do |attr| -[:updated_at_start, :updated_at_end].each do |attr|
.col-md-2.col-sm-4 .col-md-2.col-sm-4
%h4= t attr == :updated_at_start ? '_on' : 'until' %h4= t attr == :updated_at_start ? '_on' : 'until'

View File

@ -9,7 +9,7 @@ class ApiDefender < Rack::Throttle::Hourly
options = { options = {
cache: Redis.new(thread_safe: true), cache: Redis.new(thread_safe: true),
key_prefix: :throttle, key_prefix: :throttle,
max: 2000 # only 2000 request per hour max: 3000 # only 3000 request per hour
} }
@app, @options = app, options @app, @options = app, options
end end

View File

@ -51,6 +51,20 @@ shared_examples_for 'create build list via api' do
it 'should not create without existing commit hash in project' do it 'should not create without existing commit hash in project' do
lambda{ post :create, @create_params.deep_merge(build_list: {commit_hash: 'wrong'})}.should change{@project.build_lists.count}.by(0) lambda{ post :create, @create_params.deep_merge(build_list: {commit_hash: 'wrong'})}.should change{@project.build_lists.count}.by(0)
end end
it 'should not create without existing arch' do
lambda{ post :create, @create_params.deep_merge(build_list: {arch_id: -1})}.should change{@project.build_lists.count}.by(0)
end
it 'should not create without existing save_to_platform' do
lambda{
post :create, @create_params.deep_merge(build_list: {save_to_platform_id: -1, save_to_repository_id: -1})
}.should change{@project.build_lists.count}.by(0)
end
it 'should not create without existing save_to_repository' do
lambda{ post :create, @create_params.deep_merge(build_list: {save_to_repository_id: -1})}.should change{@project.build_lists.count}.by(0)
end
end end
shared_examples_for 'not create build list via api' do shared_examples_for 'not create build list via api' do

View File

@ -120,6 +120,10 @@ shared_examples_for 'api projects user with admin rights' do
get :members, id: @project.id, format: :json get :members, id: @project.id, format: :json
response.should be_success response.should be_success
end end
it 'should not set a wrong maintainer_id' do
put :update, project: { maintainer_id: -1 }, id: @project.id, format: :json
response.should_not be_success
end
context 'api project user with update rights' do context 'api project user with update rights' do
before do before do
@ -129,7 +133,7 @@ shared_examples_for 'api projects user with admin rights' do
it 'should be able to perform update action' do it 'should be able to perform update action' do
response.should be_success response.should be_success
end end
it 'ensures that group has been updated' do it 'ensures that description has been updated' do
@project.reload @project.reload
@project.description.should == 'new description' @project.description.should == 'new description'
end end

View File

@ -29,12 +29,8 @@ describe BuildList do
expect(BuildList.next_build([], [build_list.build_for_platform_id])).to eq build_list expect(BuildList.next_build([], [build_list.build_for_platform_id])).to eq build_list
end end
it 'returns nothing if build list does not in queue' do
expect_any_instance_of(BuildList).to receive(:destroy_from_resque_queue).and_return(0)
expect(BuildList.next_build([], [build_list.build_for_platform_id])).to be_nil
end
it 'returns nothing for wrong platform' do it 'returns nothing for wrong platform' do
expect_any_instance_of(BuildList).to receive(:restart_job)
expect(BuildList.next_build([], [-1])).to be_nil expect(BuildList.next_build([], [-1])).to be_nil
end end
end end
@ -45,12 +41,8 @@ describe BuildList do
expect(BuildList.next_build([build_list.arch_id], [])).to eq build_list expect(BuildList.next_build([build_list.arch_id], [])).to eq build_list
end end
it 'returns nothing if build list does not in queue' do
expect_any_instance_of(BuildList).to receive(:destroy_from_resque_queue).and_return(0)
expect(BuildList.next_build([build_list.arch_id], [])).to be_nil
end
it 'returns nothing for wrong arch' do it 'returns nothing for wrong arch' do
expect_any_instance_of(BuildList).to receive(:restart_job)
expect(BuildList.next_build([-1], [])).to be_nil expect(BuildList.next_build([-1], [])).to be_nil
end end
end end

View File

@ -12,7 +12,7 @@ describe BuildScript do
context 'ensures that validations and associations exist' do context 'ensures that validations and associations exist' do
it { should belong_to(:project) } it { should belong_to(:project) }
it { should validate_presence_of(:project_id) } it { should validate_presence_of(:project) }
it { should validate_presence_of(:treeish) } it { should validate_presence_of(:treeish) }
context 'uniqueness' do context 'uniqueness' do

View File

@ -6,8 +6,8 @@ describe ProjectStatistic do
it { should belong_to(:project) } it { should belong_to(:project) }
it { should belong_to(:arch) } it { should belong_to(:arch) }
it { should validate_presence_of(:project_id) } it { should validate_presence_of(:project) }
it { should validate_presence_of(:arch_id) } it { should validate_presence_of(:arch) }
it { should validate_presence_of(:average_build_time) } it { should validate_presence_of(:average_build_time) }
it { should validate_presence_of(:build_count) } it { should validate_presence_of(:build_count) }