summaryrefslogtreecommitdiff
path: root/app/models/ci/pipeline.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/models/ci/pipeline.rb')
-rw-r--r--app/models/ci/pipeline.rb51
1 files changed, 37 insertions, 14 deletions
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 49dec770096..37a81fa7781 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -4,14 +4,25 @@ module Ci
include HasStatus
include Importable
include AfterCommitQueue
+ include Presentable
belongs_to :project
belongs_to :user
+ belongs_to :auto_canceled_by, class_name: 'Ci::Pipeline'
+
+ has_many :auto_canceled_pipelines, class_name: 'Ci::Pipeline', foreign_key: 'auto_canceled_by_id'
+ has_many :auto_canceled_jobs, class_name: 'CommitStatus', foreign_key: 'auto_canceled_by_id'
has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id
has_many :builds, foreign_key: :commit_id
has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id
+ has_many :pending_builds, -> { pending }, foreign_key: :commit_id, class_name: 'Ci::Build'
+ has_many :retryable_builds, -> { latest.failed_or_canceled }, foreign_key: :commit_id, class_name: 'Ci::Build'
+ has_many :cancelable_statuses, -> { cancelable }, foreign_key: :commit_id, class_name: 'CommitStatus'
+ has_many :manual_actions, -> { latest.manual_actions }, foreign_key: :commit_id, class_name: 'Ci::Build'
+ has_many :artifacts, -> { latest.with_artifacts_not_expired }, foreign_key: :commit_id, class_name: 'Ci::Build'
+
delegate :id, to: :project, prefix: true
validates :sha, presence: { unless: :importing? }
@@ -65,6 +76,10 @@ module Ci
pipeline.update_duration
end
+ before_transition canceled: any - [:canceled] do |pipeline|
+ pipeline.auto_canceled_by = nil
+ end
+
after_transition [:created, :pending] => :running do |pipeline|
pipeline.run_after_commit { PipelineMetricsWorker.perform_async(id) }
end
@@ -82,6 +97,8 @@ module Ci
pipeline.run_after_commit do
PipelineHooksWorker.perform_async(id)
+ Ci::ExpirePipelineCacheService.new(project, nil)
+ .execute(pipeline)
end
end
@@ -160,10 +177,6 @@ module Ci
end
end
- def artifacts
- builds.latest.with_artifacts_not_expired.includes(project: [:namespace])
- end
-
def valid_commit_sha
if self.sha == Gitlab::Git::BLANK_SHA
self.errors.add(:sha, " cant be 00000000 (branch removal)")
@@ -200,27 +213,37 @@ module Ci
!tag?
end
- def manual_actions
- builds.latest.manual_actions.includes(project: [:namespace])
- end
-
def stuck?
- builds.pending.includes(:project).any?(&:stuck?)
+ pending_builds.any?(&:stuck?)
end
def retryable?
- builds.latest.failed_or_canceled.any?(&:retryable?)
+ retryable_builds.any?
end
def cancelable?
- statuses.cancelable.any?
+ cancelable_statuses.any?
+ end
+
+ def auto_canceled?
+ canceled? && auto_canceled_by_id?
end
def cancel_running
- Gitlab::OptimisticLocking.retry_lock(
- statuses.cancelable) do |cancelable|
- cancelable.find_each(&:cancel)
+ Gitlab::OptimisticLocking.retry_lock(cancelable_statuses) do |cancelable|
+ cancelable.find_each do |job|
+ yield(job) if block_given?
+ job.cancel
end
+ end
+ end
+
+ def auto_cancel_running(pipeline)
+ update(auto_canceled_by: pipeline)
+
+ cancel_running do |job|
+ job.auto_canceled_by = pipeline
+ end
end
def retry_failed(current_user)