gitlab-org--gitlab-foss/app/models/concerns/has_status.rb
Rydkin Maxim c81ef3041e add auto-cancel for pending pipelines on branch, if they are not HEAD
fix changelog MR reference

add non-HEAD builds finder and add `created` pipelines to scope

add spec for auto-cancel non-HEAD pipelines and refactor create_pipeline_service_spec

more refactoring for spec

adds option for auto-cancel into CI/CD settings

fix spec to new configuration

fix rubocop

fix schema.rb

fix schema.rb

replace Gitlab 9.0 with 9.1 in doc

change wording on pipeline settings

added auto_canceled_by field as identifier of autocancel subject

remove unnecessary index

replace service with retry_lock

replace auto_cancel_pending_pipelines boolean setting with integer (and enum in model)

fix schema.rb

fix schema.rb

remove projekt attribute and clean up spec

clean up spec withcouple of shared examples

added spec for "It does not cancel current pipeline" scenario

add some specs to auto-cancel

add spec for another branch pipelines
2017-04-04 21:11:24 +03:00

114 lines
3.6 KiB
Ruby

module HasStatus
extend ActiveSupport::Concern
DEFAULT_STATUS = 'created'.freeze
BLOCKED_STATUS = 'manual'.freeze
AVAILABLE_STATUSES = %w[created pending running success failed canceled skipped manual].freeze
STARTED_STATUSES = %w[running success failed skipped manual].freeze
ACTIVE_STATUSES = %w[pending running].freeze
COMPLETED_STATUSES = %w[success failed canceled skipped].freeze
ORDERED_STATUSES = %w[failed pending running manual canceled success skipped created].freeze
class_methods do
def status_sql
scope = respond_to?(:exclude_ignored) ? exclude_ignored : all
builds = scope.select('count(*)').to_sql
created = scope.created.select('count(*)').to_sql
success = scope.success.select('count(*)').to_sql
manual = scope.manual.select('count(*)').to_sql
pending = scope.pending.select('count(*)').to_sql
running = scope.running.select('count(*)').to_sql
skipped = scope.skipped.select('count(*)').to_sql
canceled = scope.canceled.select('count(*)').to_sql
"(CASE
WHEN (#{builds})=(#{skipped}) THEN 'skipped'
WHEN (#{builds})=(#{success}) THEN 'success'
WHEN (#{builds})=(#{created}) THEN 'created'
WHEN (#{builds})=(#{success})+(#{skipped}) THEN 'success'
WHEN (#{builds})=(#{success})+(#{skipped})+(#{canceled}) THEN 'canceled'
WHEN (#{builds})=(#{created})+(#{skipped})+(#{pending}) THEN 'pending'
WHEN (#{running})+(#{pending})>0 THEN 'running'
WHEN (#{manual})>0 THEN 'manual'
WHEN (#{created})>0 THEN 'running'
ELSE 'failed'
END)"
end
def status
all.pluck(status_sql).first
end
def started_at
all.minimum(:started_at)
end
def finished_at
all.maximum(:finished_at)
end
def all_state_names
state_machines.values.flat_map(&:states).flat_map { |s| s.map(&:name) }
end
end
included do
validates :status, inclusion: { in: AVAILABLE_STATUSES }
state_machine :status, initial: :created do
state :created, value: 'created'
state :pending, value: 'pending'
state :running, value: 'running'
state :failed, value: 'failed'
state :success, value: 'success'
state :canceled, value: 'canceled'
state :skipped, value: 'skipped'
state :manual, value: 'manual'
end
scope :created, -> { where(status: 'created') }
scope :relevant, -> { where.not(status: 'created') }
scope :running, -> { where(status: 'running') }
scope :pending, -> { where(status: 'pending') }
scope :success, -> { where(status: 'success') }
scope :failed, -> { where(status: 'failed') }
scope :canceled, -> { where(status: 'canceled') }
scope :skipped, -> { where(status: 'skipped') }
scope :manual, -> { where(status: 'manual') }
scope :created_or_pending, -> { where(status: [:created, :pending]) }
scope :running_or_pending, -> { where(status: [:running, :pending]) }
scope :finished, -> { where(status: [:success, :failed, :canceled]) }
scope :failed_or_canceled, -> { where(status: [:failed, :canceled]) }
scope :cancelable, -> do
where(status: [:running, :pending, :created, :manual])
end
end
def started?
STARTED_STATUSES.include?(status) && started_at
end
def active?
ACTIVE_STATUSES.include?(status)
end
def complete?
COMPLETED_STATUSES.include?(status)
end
def blocked?
BLOCKED_STATUS == status
end
private
def calculate_duration
if started_at && finished_at
finished_at - started_at
elsif started_at
Time.now - started_at
end
end
end