debian-mirror-gitlab/app/models/ci/processable.rb

208 lines
5.7 KiB
Ruby
Raw Normal View History

2020-03-13 15:44:24 +05:30
# frozen_string_literal: true
module Ci
class Processable < ::CommitStatus
include Gitlab::Utils::StrongMemoize
2021-03-11 19:13:27 +05:30
extend ::Gitlab::Utils::Override
has_one :resource, class_name: 'Ci::Resource', foreign_key: 'build_id', inverse_of: :processable
belongs_to :resource_group, class_name: 'Ci::ResourceGroup', inverse_of: :processables
2020-03-13 15:44:24 +05:30
accepts_nested_attributes_for :needs
scope :preload_needs, -> { preload(:needs) }
scope :with_needs, -> (names = nil) do
needs = Ci::BuildNeed.scoped_build.select(1)
needs = needs.where(name: names) if names
2022-05-07 20:08:51 +05:30
where('EXISTS (?)', needs)
2020-03-13 15:44:24 +05:30
end
scope :without_needs, -> (names = nil) do
needs = Ci::BuildNeed.scoped_build.select(1)
needs = needs.where(name: names) if names
where('NOT EXISTS (?)', needs)
end
2021-03-11 19:13:27 +05:30
state_machine :status do
event :enqueue do
transition [:created, :skipped, :manual, :scheduled] => :waiting_for_resource, if: :with_resource_group?
end
event :enqueue_scheduled do
transition scheduled: :waiting_for_resource, if: :with_resource_group?
end
event :enqueue_waiting_for_resource do
transition waiting_for_resource: :preparing, if: :any_unmet_prerequisites?
transition waiting_for_resource: :pending
end
before_transition any => :waiting_for_resource do |processable|
processable.waiting_for_resource_at = Time.current
end
before_transition on: :enqueue_waiting_for_resource do |processable|
next unless processable.with_resource_group?
processable.resource_group.assign_resource_to(processable)
end
after_transition any => :waiting_for_resource do |processable|
processable.run_after_commit do
Ci::ResourceGroups::AssignResourceFromResourceGroupWorker
.perform_async(processable.resource_group_id)
end
end
after_transition any => ::Ci::Processable.completed_statuses do |processable|
next unless processable.with_resource_group?
2021-11-18 22:05:49 +05:30
processable.resource_group.release_resource_from(processable)
2021-03-11 19:13:27 +05:30
processable.run_after_commit do
Ci::ResourceGroups::AssignResourceFromResourceGroupWorker
.perform_async(processable.resource_group_id)
end
end
end
2020-03-13 15:44:24 +05:30
def self.select_with_aggregated_needs(project)
aggregated_needs_names = Ci::BuildNeed
.scoped_build
.select("ARRAY_AGG(name)")
.to_sql
all.select(
'*',
"(#{aggregated_needs_names}) as aggregated_needs_names"
)
end
# Old processables may have scheduling_type as nil,
# so we need to ensure the data exists before using it.
def self.populate_scheduling_type!
needs = Ci::BuildNeed.scoped_build.select(1)
where(scheduling_type: nil).update_all(
"scheduling_type = CASE WHEN (EXISTS (#{needs.to_sql}))
THEN #{scheduling_types[:dag]}
ELSE #{scheduling_types[:stage]}
END"
)
end
validates :type, presence: true
2020-05-24 23:13:21 +05:30
validates :scheduling_type, presence: true, on: :create, unless: :importing?
2020-03-13 15:44:24 +05:30
2020-04-22 19:07:51 +05:30
delegate :merge_request?,
:merge_request_ref?,
:legacy_detached_merge_request_pipeline?,
:merge_train_pipeline?,
to: :pipeline
2022-07-16 23:28:13 +05:30
def clone(current_user:)
new_attributes = self.class.clone_accessors.to_h do |attribute|
[attribute, public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend
end
if persisted_environment.present?
new_attributes[:metadata_attributes] ||= {}
new_attributes[:metadata_attributes][:expanded_environment_name] = expanded_environment_name
end
new_attributes[:user] = current_user
self.class.new(new_attributes)
end
2022-06-21 17:19:12 +05:30
def retryable?
return false if retried? || archived? || deployment_rejected?
success? || failed? || canceled?
end
2020-03-13 15:44:24 +05:30
def aggregated_needs_names
read_attribute(:aggregated_needs_names)
end
def schedulable?
raise NotImplementedError
end
def action?
raise NotImplementedError
end
def when
read_attribute(:when) || 'on_success'
end
def expanded_environment_name
raise NotImplementedError
end
2021-09-04 01:27:46 +05:30
def persisted_environment
2021-06-08 01:23:25 +05:30
raise NotImplementedError
end
2021-03-11 19:13:27 +05:30
override :all_met_to_become_pending?
def all_met_to_become_pending?
super && !with_resource_group?
end
def with_resource_group?
self.resource_group_id.present?
end
2020-03-13 15:44:24 +05:30
# Overriding scheduling_type enum's method for nil `scheduling_type`s
def scheduling_type_dag?
2020-05-24 23:13:21 +05:30
scheduling_type.nil? ? find_legacy_scheduling_type == :dag : super
2020-03-13 15:44:24 +05:30
end
# scheduling_type column of previous builds/bridges have not been populated,
# so we calculate this value on runtime when we need it.
def find_legacy_scheduling_type
strong_memoize(:find_legacy_scheduling_type) do
needs.exists? ? :dag : :stage
end
end
2020-04-08 14:13:33 +05:30
def needs_attributes
strong_memoize(:needs_attributes) do
needs.map { |need| need.attributes.except('id', 'build_id') }
end
end
2020-05-24 23:13:21 +05:30
def ensure_scheduling_type!
# If this has a scheduling_type, it means all processables in the pipeline already have.
return if scheduling_type
2020-03-13 15:44:24 +05:30
2020-05-24 23:13:21 +05:30
pipeline.ensure_scheduling_type!
reset
2020-03-13 15:44:24 +05:30
end
2021-01-29 00:20:46 +05:30
def dependency_variables
return [] if all_dependencies.empty?
Gitlab::Ci::Variables::Collection.new.concat(
Ci::JobVariable.where(job: all_dependencies).dotenv_source
)
end
def all_dependencies
2021-10-27 15:23:28 +05:30
strong_memoize(:all_dependencies) do
2021-04-29 21:17:54 +05:30
dependencies.all
end
2021-01-29 00:20:46 +05:30
end
private
def dependencies
strong_memoize(:dependencies) do
Ci::BuildDependencies.new(self)
end
end
2020-03-13 15:44:24 +05:30
end
end