Class: Ci::CancelPipelineService

Inherits:
Object
  • Object
show all
Includes:
Gitlab::Allowable, Gitlab::OptimisticLocking
Defined in:
app/services/ci/cancel_pipeline_service.rb

Overview

Cancel a pipelines cancelable jobs and optionally it’s child pipelines cancelable jobs

Constant Summary

Constants included from Gitlab::OptimisticLocking

Gitlab::OptimisticLocking::MAX_RETRIES

Instance Method Summary collapse

Methods included from Gitlab::Allowable

#can?

Methods included from Gitlab::OptimisticLocking

log_optimistic_lock_retries, retry_lock, retry_lock_histogram, retry_lock_logger

Constructor Details

#initialize(pipeline:, current_user:, cascade_to_children: true, auto_canceled_by_pipeline_id: nil, execute_async: true) ⇒ CancelPipelineService

Returns a new instance of CancelPipelineService.



13
14
15
16
17
18
19
20
21
22
23
24
# File 'app/services/ci/cancel_pipeline_service.rb', line 13

def initialize(
  pipeline:,
  current_user:,
  cascade_to_children: true,
  auto_canceled_by_pipeline_id: nil,
  execute_async: true)
  @pipeline = pipeline
  @current_user = current_user
  @cascade_to_children = cascade_to_children
  @auto_canceled_by_pipeline_id = auto_canceled_by_pipeline_id
  @execute_async = execute_async
end

Instance Method Details

#executeObject



26
27
28
29
30
31
32
33
34
# File 'app/services/ci/cancel_pipeline_service.rb', line 26

def execute
  unless can?(current_user, :update_pipeline, pipeline)
    return ServiceResponse.error(
      message: 'Insufficient permissions to cancel the pipeline',
      reason: :insufficient_permissions)
  end

  force_execute
end

#force_executeObject

This method should be used only when we want to always cancel the pipeline without checking whether the current_user has permissions to do so, or when we don’t have a current_user available in the context.



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'app/services/ci/cancel_pipeline_service.rb', line 39

def force_execute
  return ServiceResponse.error(message: 'No pipeline provided', reason: :no_pipeline) unless pipeline

  unless pipeline.cancelable?
    return ServiceResponse.error(message: 'Pipeline is not cancelable', reason: :pipeline_not_cancelable)
  end

  log_pipeline_being_canceled

  pipeline.update_column(:auto_canceled_by_id, @auto_canceled_by_pipeline_id) if @auto_canceled_by_pipeline_id
  cancel_jobs(pipeline.cancelable_statuses)

  return ServiceResponse.success unless cascade_to_children?

  # cancel any bridges that could spin up new child pipelines
  cancel_jobs(pipeline.bridges_in_self_and_project_descendants.cancelable)
  cancel_children

  ServiceResponse.success
end