diff --git a/app/assets/javascripts/angular-new/build_lists/build_lists_controller.js.erb b/app/assets/javascripts/angular-new/build_lists/build_lists_controller.js.erb index 9c9e55670..8c15bebaa 100644 --- a/app/assets/javascripts/angular-new/build_lists/build_lists_controller.js.erb +++ b/app/assets/javascripts/angular-new/build_lists/build_lists_controller.js.erb @@ -194,15 +194,15 @@ RosaABF.controller('BuildListsController', page: params.page || 1, per_page: params.per_page || 25, filter: { - ownership: params['filter[ownership]'] || 'owned', - status: params['filter[status]'], - platform_id: params['filter[platform_id]'], - arch_id: params['filter[arch_id]'], - mass_build_id: params['filter[mass_build_id]'], - updated_at_start: params['filter[updated_at_start]'], - updated_at_end: params['filter[updated_at_end]'], - project_name: params['filter[project_name]'], - id: params['filter[id]'] + ownership: params['filter[ownership]'] || 'owned', + status: params['filter[status]'], + save_to_platform_id: params['filter[save_to_platform_id]'], + arch_id: params['filter[arch_id]'], + mass_build_id: params['filter[mass_build_id]'], + updated_at_start: params['filter[updated_at_start]'], + updated_at_end: params['filter[updated_at_end]'], + project_name: params['filter[project_name]'], + id: params['filter[id]'] } } } diff --git a/app/controllers/api/v1/build_lists_controller.rb b/app/controllers/api/v1/build_lists_controller.rb index f1b69b9a1..a87a7c717 100644 --- a/app/controllers/api/v1/build_lists_controller.rb +++ b/app/controllers/api/v1/build_lists_controller.rb @@ -2,7 +2,6 @@ class Api::V1::BuildListsController < Api::V1::BaseController before_filter :authenticate_user! 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] def show @@ -10,9 +9,16 @@ class Api::V1::BuildListsController < Api::V1::BaseController end def index + @project = Project.find(params[:project_id]) if params[:project_id].present? authorize!(:show, @project) if @project 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) respond_to :json end diff --git a/app/controllers/api/v1/jobs_controller.rb b/app/controllers/api/v1/jobs_controller.rb index 2af2eedbf..bbb663609 100644 --- a/app/controllers/api/v1/jobs_controller.rb +++ b/app/controllers/api/v1/jobs_controller.rb @@ -22,7 +22,7 @@ class Api::V1::JobsController < Api::V1::BaseController else @build_list = build_lists.external_nodes(:owned).for_user(current_user).first @build_list ||= build_lists.external_nodes(:everything). - accessible_by(current_ability, :everything).readonly(false).first + accessible_by(current_ability, :related).readonly(false).first end set_builder end diff --git a/app/jobs/abf_worker/rpm_worker_observer.rb b/app/jobs/abf_worker/rpm_worker_observer.rb index 75a38f9bd..f888bc89d 100644 --- a/app/jobs/abf_worker/rpm_worker_observer.rb +++ b/app/jobs/abf_worker/rpm_worker_observer.rb @@ -23,6 +23,13 @@ module AbfWorker item = find_or_create_item 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? case status diff --git a/app/models/build_list.rb b/app/models/build_list.rb index 3b9238b62..90463a9be 100644 --- a/app/models/build_list.rb +++ b/app/models/build_list.rb @@ -40,14 +40,15 @@ class BuildList < ActiveRecord::Base AUTO_PUBLISH_STATUS_TESTING = 'testing' ] - validates :project, + validates :project, :project_id, :project_version, - :arch, + :arch, :arch_id, :include_repos, - :build_for_platform, - :save_to_platform, - :save_to_repository, + :build_for_platform, :build_for_platform_id, + :save_to_platform, :save_to_platform_id, + :save_to_repository, :save_to_repository_id, presence: true + validates_numericality_of :priority, greater_than_or_equal_to: 0 validates :external_nodes, inclusion: { in: EXTERNAL_NODES }, allow_blank: true 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 :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_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_is_circle, ->(is_circle) { where(is_circle: is_circle) } - scope :for_creation_date_period, ->(start_date, end_date) { + scope :scoped_to_save_platform, ->(pl_id) { where(save_to_platform_id: pl_id) if pl_id.present? } + scope :scoped_to_build_for_platform, ->(pl_id) { where(build_for_platform_id: pl_id) if pl_id.present? } + scope :scoped_to_save_to_repository, ->(repo_id) { where(save_to_repository_id: repo_id) if repo_id.present? } + 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 = s.where(["#{table_name}.created_at >= ?", start_date]) if start_date s = s.where(["#{table_name}.created_at <= ?", end_date]) if end_date @@ -598,35 +601,41 @@ class BuildList < ActiveRecord::Base end def self.next_build(arch_ids, platform_ids) - kind_id = Redis.current.spop(USER_BUILDS_SET) - key = "user_build_#{kind_id}_rpm_worker_default" if kind_id - 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 + build_list = next_build_from_queue(USER_BUILDS_SET, arch_ids, platform_ids) + build_list ||= next_build_from_queue(MASS_BUILDS_SET, arch_ids, platform_ids) - kind_id ||= Redis.current.spop(MASS_BUILDS_SET) - 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.delayed_add_job_to_abf_worker_queue if build_list build_list end - def self.next_build_from_queue(kind_id, key, arch_ids, platform_ids, mass_build = false) - if kind_id && (arch_ids.present? || platform_ids.present?) - build_list = BuildList.where(user_id: kind_id). - scoped_to_arch(arch_ids). - for_status([BuildList::BUILD_PENDING, BuildList::RERUN_TESTS]). - for_platform(platform_ids) - build_list = build_list.where.not(mass_build_id: nil) if mass_build - build_list = build_list.oldest.order(:created_at).first + def self.next_build_from_queue(set, arch_ids, platform_ids) + kind_id = Redis.current.spop(set) + key = + case set + when USER_BUILDS_SET + "user_build_#{kind_id}_rpm_worker_default" + when MASS_BUILDS_SET + "mass_build_#{kind_id}_rpm_worker" + end if kind_id - build_list = nil if build_list && build_list.destroy_from_resque_queue != 1 - elsif key - task = Resque.pop(key) + task = Resque.pop(key) if 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 - build_list ||= BuildList.where(id: task['args'][0]['id']).first if task build_list end diff --git a/app/models/build_list/filter.rb b/app/models/build_list/filter.rb index 200d83961..c35d672b1 100644 --- a/app/models/build_list/filter.rb +++ b/app/models/build_list/filter.rb @@ -22,7 +22,9 @@ class BuildList::Filter build_lists = build_lists.for_status(@options[:status]) .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_name(@options[:project_name]) .for_notified_date_period(@options[:updated_at_start], @options[:updated_at_end]) @@ -44,34 +46,38 @@ class BuildList::Filter def set_options(options) @options = HashWithIndifferentAccess.new(options.reverse_merge({ - ownership: nil, - status: nil, - updated_at_start: nil, - updated_at_end: nil, - arch_id: nil, - platform_id: nil, - is_circle: nil, - project_version: nil, - id: nil, - project_name: nil, - mass_build_id: nil, - new_core: nil + ownership: nil, + status: nil, + updated_at_start: nil, + updated_at_end: nil, + arch_id: nil, + save_to_platform_id: nil, + build_for_platform_id: nil, + save_to_repository_id: nil, + is_circle: nil, + project_version: nil, + id: nil, + project_name: nil, + mass_build_id: nil, + new_core: nil })) @options[:ownership] = @options[:ownership].presence || (@project || !@user ? 'everything' : 'owned') - @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_end] = build_date_from_params(:created_at_end, @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[:project_version] = @options[:project_version].presence - @options[:arch_id] = @options[:arch_id].try(:to_i) - @options[:platform_id] = @options[:platform_id].try(:to_i) - @options[:is_circle] = @options[:is_circle].present? ? @options[:is_circle] == "1" : nil - @options[:id] = @options[: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 + @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_end] = build_date_from_params(:created_at_end, @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[:project_version] = @options[:project_version].presence + @options[:arch_id] = @options[:arch_id].try(:to_i) + @options[:save_to_platform_id] = @options[:save_to_platform_id].try(:to_i) + @options[:build_for_platform_id] = @options[:build_for_platform_id].try(:to_i) + @options[:save_to_repository_id] = @options[:save_to_repository_id].try(:to_i) + @options[:is_circle] = @options[:is_circle].present? ? @options[:is_circle] == "1" : nil + @options[:id] = @options[: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/models/build_list/package.rb b/app/models/build_list/package.rb index 873c1227b..73120be63 100644 --- a/app/models/build_list/package.rb +++ b/app/models/build_list/package.rb @@ -9,7 +9,8 @@ class BuildList::Package < ActiveRecord::Base 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, presence: true validates :package_type, inclusion: PACKAGE_TYPES diff --git a/app/models/build_script.rb b/app/models/build_script.rb index 30ebbb5b2..1c5a395d3 100644 --- a/app/models/build_script.rb +++ b/app/models/build_script.rb @@ -10,7 +10,8 @@ class BuildScript < ActiveRecord::Base belongs_to :project 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_treeish, -> treeish { where(treeish: treeish) } diff --git a/app/models/mass_build.rb b/app/models/mass_build.rb index f1a00511a..270154dc5 100644 --- a/app/models/mass_build.rb +++ b/app/models/mass_build.rb @@ -94,7 +94,8 @@ class MassBuild < ActiveRecord::Base def build_all return unless start # 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| 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) begin 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? arches_list.each do |arch| rep_id = (project.repository_ids & save_to_platform.repository_ids).first diff --git a/app/models/product_build_list.rb b/app/models/product_build_list.rb index d8050f77d..130f4248c 100644 --- a/app/models/product_build_list.rb +++ b/app/models/product_build_list.rb @@ -45,12 +45,13 @@ class ProductBuildList < ActiveRecord::Base 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 before_validation -> { self.not_delete = false unless build_completed?; true } - validates :product, + + validates :product, :product_id, :status, - :project, + :project, :project_id, :main_script, - :project_version, - :arch, presence: true + :arch, :arch_id, + presence: true validates :status, inclusion: { in: STATUSES } validates :main_script, :params, length: { maximum: 255 } diff --git a/app/models/project_tag.rb b/app/models/project_tag.rb index 634fdffbb..3886e86a8 100644 --- a/app/models/project_tag.rb +++ b/app/models/project_tag.rb @@ -8,7 +8,7 @@ class ProjectTag < ActiveRecord::Base 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] } attr_accessible :project_id, :commit_id, :sha1, :tag_name, :format_id diff --git a/app/views/api/v1/build_lists/index.json.jbuilder b/app/views/api/v1/build_lists/index.json.jbuilder index 6bc5eba1a..aaf19e8a5 100644 --- a/app/views/api/v1/build_lists/index.json.jbuilder +++ b/app/views/api/v1/build_lists/index.json.jbuilder @@ -1,5 +1,5 @@ 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) end diff --git a/app/views/api/v1/projects/_project.json.jbuilder b/app/views/api/v1/projects/_project.json.jbuilder index 3a336cfe9..caddb99ec 100644 --- a/app/views/api/v1/projects/_project.json.jbuilder +++ b/app/views/api/v1/projects/_project.json.jbuilder @@ -2,3 +2,8 @@ json.(project, :id, :name) json.fullname project.name_with_owner json.url api_v1_project_path(project.id, format: :json) 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 \ No newline at end of file diff --git a/app/views/api/v1/projects/show.json.jbuilder b/app/views/api/v1/projects/show.json.jbuilder index dfd1c3689..ecd9d382c 100644 --- a/app/views/api/v1/projects/show.json.jbuilder +++ b/app/views/api/v1/projects/show.json.jbuilder @@ -5,7 +5,9 @@ json.project do json.updated_at @project.updated_at.to_i json.partial! 'api/v1/shared/owner', owner: @project.owner 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 json.project_statistics @project.project_statistics do |statistic| diff --git a/app/views/projects/build_lists/_filter.html.haml b/app/views/projects/build_lists/_filter.html.haml index e51a29eac..55eea66cf 100644 --- a/app/views/projects/build_lists/_filter.html.haml +++ b/app/views/projects/build_lists/_filter.html.haml @@ -24,9 +24,9 @@ = t "layout.build_lists.ownership.#{ownership}" .col-md-4.col-sm-6 %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 }, - 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| .col-md-2.col-sm-4 %h4= t attr == :updated_at_start ? '_on' : 'until' diff --git a/lib/api_defender.rb b/lib/api_defender.rb index 053dd6c23..f23221c34 100644 --- a/lib/api_defender.rb +++ b/lib/api_defender.rb @@ -9,7 +9,7 @@ class ApiDefender < Rack::Throttle::Hourly options = { cache: Redis.new(thread_safe: true), key_prefix: :throttle, - max: 2000 # only 2000 request per hour + max: 3000 # only 3000 request per hour } @app, @options = app, options end diff --git a/spec/controllers/api/v1/build_lists_controller_spec.rb b/spec/controllers/api/v1/build_lists_controller_spec.rb index df5c5d01c..4b71c764e 100644 --- a/spec/controllers/api/v1/build_lists_controller_spec.rb +++ b/spec/controllers/api/v1/build_lists_controller_spec.rb @@ -51,6 +51,20 @@ shared_examples_for 'create build list via api' 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) 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 shared_examples_for 'not create build list via api' do diff --git a/spec/controllers/api/v1/projects_controller_spec.rb b/spec/controllers/api/v1/projects_controller_spec.rb index 06dcaa8ec..1fe487702 100644 --- a/spec/controllers/api/v1/projects_controller_spec.rb +++ b/spec/controllers/api/v1/projects_controller_spec.rb @@ -120,6 +120,10 @@ shared_examples_for 'api projects user with admin rights' do get :members, id: @project.id, format: :json response.should be_success 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 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 response.should be_success end - it 'ensures that group has been updated' do + it 'ensures that description has been updated' do @project.reload @project.description.should == 'new description' end diff --git a/spec/models/build_list_spec.rb b/spec/models/build_list_spec.rb index 48a156bda..db67e1520 100644 --- a/spec/models/build_list_spec.rb +++ b/spec/models/build_list_spec.rb @@ -29,12 +29,8 @@ describe BuildList do expect(BuildList.next_build([], [build_list.build_for_platform_id])).to eq build_list 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 + expect_any_instance_of(BuildList).to receive(:restart_job) expect(BuildList.next_build([], [-1])).to be_nil end end @@ -45,12 +41,8 @@ describe BuildList do expect(BuildList.next_build([build_list.arch_id], [])).to eq build_list 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 + expect_any_instance_of(BuildList).to receive(:restart_job) expect(BuildList.next_build([-1], [])).to be_nil end end diff --git a/spec/models/build_script_spec.rb b/spec/models/build_script_spec.rb index c7fff54f5..30a8308db 100644 --- a/spec/models/build_script_spec.rb +++ b/spec/models/build_script_spec.rb @@ -12,7 +12,7 @@ describe BuildScript do context 'ensures that validations and associations exist' do it { should belong_to(:project) } - it { should validate_presence_of(:project_id) } + it { should validate_presence_of(:project) } it { should validate_presence_of(:treeish) } context 'uniqueness' do diff --git a/spec/models/project_statistic_spec.rb b/spec/models/project_statistic_spec.rb index e13a0ec20..fca55d974 100644 --- a/spec/models/project_statistic_spec.rb +++ b/spec/models/project_statistic_spec.rb @@ -6,8 +6,8 @@ describe ProjectStatistic do it { should belong_to(:project) } it { should belong_to(:arch) } - it { should validate_presence_of(:project_id) } - it { should validate_presence_of(:arch_id) } + it { should validate_presence_of(:project) } + it { should validate_presence_of(:arch) } it { should validate_presence_of(:average_build_time) } it { should validate_presence_of(:build_count) }