rosa-build/app/models/product_build_list.rb

198 lines
5.6 KiB
Ruby

class ProductBuildList < ActiveRecord::Base
include CommitAndVersion
include TimeLiving
include FileStoreClean
include UrlHelper
include AbfWorker::ModelHelper
include EventLoggable
delegate :url_helpers, to: 'Rails.application.routes'
LIVE_TIME = 2.week # for autostart
MAX_LIVE_TIME = 3.month # for manual start;
BUILD_COMPLETED = 0
BUILD_FAILED = 1
BUILD_PENDING = 2
BUILD_STARTED = 3
BUILD_CANCELED = 4
BUILD_CANCELING = 5
STATUSES = [ BUILD_STARTED,
BUILD_COMPLETED,
BUILD_FAILED,
BUILD_PENDING,
BUILD_CANCELED,
BUILD_CANCELING
].freeze
HUMAN_STATUSES = { BUILD_STARTED => :build_started,
BUILD_COMPLETED => :build_completed,
BUILD_FAILED => :build_failed,
BUILD_PENDING => :build_pending,
BUILD_CANCELED => :build_canceled,
BUILD_CANCELING => :build_canceling
}.freeze
CACHED_CHROOT_TOKEN_DESCRIPTION = 'cached-chroot'
belongs_to :product
belongs_to :project
belongs_to :arch
belongs_to :user
# see: Issue #6
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_id,
:status,
:project_id,
:main_script,
:arch_id, presence: true
validates :status, inclusion: { in: STATUSES }
validates :main_script, :params, length: { maximum: 255 }
attr_accessor :base_url
attr_accessible :status,
:base_url,
:branch,
:project_id,
:main_script,
:params,
:project_version,
:commit_hash,
:product_id,
:not_delete
attr_readonly :product_id
serialize :results, Array
scope :default_order, -> { order(updated_at: :desc) }
scope :for_status, ->(status) { where(status: status) }
scope :for_user, ->(user) { where(user_id: user.id) }
scope :scoped_to_product_name, ->(product_name) { joins(:product).where('products.name LIKE ?', "%#{product_name}%") }
scope :recent, -> { order(updated_at: :desc) }
scope :outdated, -> {
where(not_delete: false).
where("(#{table_name}.created_at < ? AND #{table_name}.autostarted is TRUE) OR #{table_name}.created_at < ?",
Time.now - LIVE_TIME, Time.now - MAX_LIVE_TIME)
}
after_create :add_job_to_abf_worker_queue
before_destroy :can_destroy?
state_machine :status, initial: :build_pending do
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
# 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
# build_canceling: :build_completed - Worker hasn't time to cancel building because build had been already completed
event :build_success do
transition [:build_started, :build_canceling] => :build_completed
end
# build_canceling: :build_failed - Worker hasn't time to cancel building because build had been already failed
event :build_error do
transition [:build_started, :build_canceling] => :build_failed
end
HUMAN_STATUSES.each do |code,name|
state name, value: code
end
end
def build_started?
status == BUILD_STARTED
end
def build_canceling?
status == BUILD_CANCELING
end
def can_destroy?
![BUILD_STARTED, BUILD_PENDING, BUILD_CANCELING].include?(status)
end
def can_cancel?
[BUILD_STARTED, BUILD_PENDING].include?(status)
end
def event_log_message
{product: product.name}.inspect
end
def self.human_status(status)
I18n.t("layout.product_build_lists.statuses.#{HUMAN_STATUSES[status]}")
end
def human_status
self.class.human_status(status)
end
def can_destroy?
[BUILD_COMPLETED, BUILD_FAILED, BUILD_CANCELED].include? status
end
def sha1_of_file_store_files
(results || []).map{ |r| r['sha1'] }.compact
end
protected
def abf_worker_priority
''
end
def abf_worker_base_queue
'iso_worker'
end
def abf_worker_args
file_name = "#{project.name}-#{commit_hash}"
opts = default_url_options
opts.merge!({user: user.authentication_token, password: ''}) if user.present?
srcpath = url_helpers.archive_url(
project.name_with_owner,
file_name,
'tar.gz',
opts
)
cmd_params = "BUILD_ID=#{id} "
if product.platform.hidden?
token = product.platform.tokens.by_active.where(description: CACHED_CHROOT_TOKEN_DESCRIPTION).first
cmd_params << "TOKEN=#{token.authentication_token} " if token
end
cmd_params << params.to_s
{
id: id,
# TODO: remove comment
# srcpath: 'http://dl.dropbox.com/u/945501/avokhmin-test-iso-script-5d9b463d4e9c06ea8e7c89e1b7ff5cb37e99e27f.tar.gz',
srcpath: srcpath,
params: cmd_params,
time_living: time_living,
main_script: main_script,
platform: {
type: product.platform.distrib_type,
name: product.platform.name,
arch: arch.name
},
user: {uname: user.try(:uname), email: user.try(:email)}
}
end
end