Class: Ci::Bridge

Inherits:
Processable show all
Includes:
AfterCommitQueue, Contextable, Deployable, HasRef, Importable
Defined in:
app/models/ci/bridge.rb

Constant Summary collapse

InvalidBridgeTypeError =
Class.new(StandardError)
InvalidTransitionError =
Class.new(StandardError)
FORWARD_DEFAULTS =
{
  yaml_variables: true,
  pipeline_variables: false
}.freeze

Constants inherited from Processable

Processable::ACTIONABLE_WHEN

Constants included from TaggableQueries

TaggableQueries::MAX_TAGS_IDS, TaggableQueries::TooManyTagsError

Constants included from HasStatus

HasStatus::ACTIVE_STATUSES, HasStatus::ALIVE_STATUSES, HasStatus::AVAILABLE_STATUSES, HasStatus::BLOCKED_STATUS, HasStatus::CANCELABLE_STATUSES, HasStatus::COMPLETED_STATUSES, HasStatus::COMPLETED_WITH_MANUAL_STATUSES, HasStatus::DEFAULT_STATUS, HasStatus::EXECUTING_STATUSES, HasStatus::IGNORED_STATUSES, HasStatus::ORDERED_STATUSES, HasStatus::PASSED_WITH_WARNINGS_STATUSES, HasStatus::STARTED_STATUSES, HasStatus::STATUSES_ENUM, HasStatus::STOPPED_STATUSES, HasStatus::UnknownStatusError

Constants inherited from ApplicationRecord

ApplicationRecord::MAX_PLUCK

Constants included from HasCheckConstraints

HasCheckConstraints::NOT_NULL_CHECK_PATTERN

Constants included from ResetOnColumnErrors

ResetOnColumnErrors::MAX_RESET_PERIOD

Instance Attribute Summary

Attributes included from Importable

#importing, #user_contributions

Class Method Summary collapse

Instance Method Summary collapse

Methods included from HasRef

#branch?, #git_ref, #ref_slug

Methods included from AfterCommitQueue

#run_after_commit, #run_after_commit_or_now

Methods included from Deployable

#accesses_environment?, #actual_persisted_environment, #deployment_job?, #deployment_status, #environment_action, #environment_slug, #environment_status, #environment_tier, #environment_tier_from_options, #environment_url, #expanded_auto_stop_in, #expanded_environment_name, #expanded_kubernetes_namespace, #has_environment_keyword?, #has_outdated_deployment?, #on_stop, #persisted_environment, #persisted_environment=, #prepares_environment?, #stop_action_successful?, #stops_environment?, #successful_deployment_status, #verifies_environment?

Methods included from Contextable

#scoped_variables, #simple_variables, #simple_variables_without_dependencies, #track_duration, #unprotected_scoped_variables

Methods inherited from Processable

#aggregated_needs_names, #all_dependencies, #all_met_to_become_pending?, #assign_resource_from_resource_group, #clone, #dependency_variables, #ensure_scheduling_type!, #expanded_environment_name, #find_legacy_scheduling_type, #job_dependencies_with_accessible_artifacts, #manual_confirmation_message, #manual_job?, #needs_attributes, #other_manual_actions, #persisted_environment, populate_scheduling_type!, #scheduling_type_dag?, #scoped_user, select_with_aggregated_needs, #when, #with_resource_group?

Methods included from Gitlab::Utils::Override

#extended, extensions, #included, #method_added, #override, #prepended, #queue_verification, verify!

Methods included from Metadatable

#cancel_gracefully?, #degenerate!, #degenerated?, #enqueue_immediately?, #ensure_metadata, #has_exposed_artifacts?, #id_tokens=, #id_tokens?, #interruptible, #interruptible=, #options, #options=, #set_enqueue_immediately!, #yaml_variables, #yaml_variables=

Methods inherited from CommitStatus

#all_met_to_become_pending?, #archived?, #auto_canceled?, #cancelable?, #duration, #exit_code=, #expire_etag_cache!, #group_name, #has_trace?, #latest?, #locking_enabled?, locking_enabled?, names, #queued_duration, #recoverable?, #resource_parent, #sortable_name, #stage_name, #stuck?, #supports_canceling?, #to_ability_name, update_as_processed!, #update_older_statuses_retried!

Methods included from TaggableQueries

#tags_ids, #tags_ids_relation

Methods included from BulkInsertableAssociations

#bulk_insert_associations!, bulk_inserts_enabled?, with_bulk_insert

Methods included from Presentable

#present

Methods included from HasStatus

#active?, #blocked?, #complete?, #complete_or_manual?, #incomplete?, #started?

Methods included from Partitionable

registered_models

Methods inherited from ApplicationRecord

model_name, table_name_prefix

Methods inherited from ApplicationRecord

===, cached_column_list, #create_or_load_association, declarative_enum, default_select_columns, id_in, id_not_in, iid_in, nullable_column?, pluck_primary_key, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order

Methods included from ResetOnColumnErrors

#reset_on_union_error, #reset_on_unknown_attribute_error

Methods included from Gitlab::SensitiveSerializableHash

#serializable_hash

Class Method Details

.clone_accessorsObject



79
80
81
82
83
84
# File 'app/models/ci/bridge.rb', line 79

def self.clone_accessors
  %i[pipeline project ref tag options name
    allow_failure stage stage_idx
    yaml_variables when environment description needs_attributes
    scheduling_type ci_stage partition_id].freeze
end

.with_preloadsObject



70
71
72
73
74
75
76
77
# File 'app/models/ci/bridge.rb', line 70

def self.with_preloads
  preload(
    :metadata,
    user: [:followers, :followees],
    downstream_pipeline: [project: [:route, { namespace: :route }]],
    project: [:namespace]
  )
end

Instance Method Details

#action?Boolean

Returns:

  • (Boolean)


171
172
173
# File 'app/models/ci/bridge.rb', line 171

def action?
  %w[manual].include?(self.when)
end

#any_unmet_prerequisites?Boolean

Returns:

  • (Boolean)


209
210
211
# File 'app/models/ci/bridge.rb', line 209

def any_unmet_prerequisites?
  false
end

#artifacts?Boolean

Returns:

  • (Boolean)


201
202
203
# File 'app/models/ci/bridge.rb', line 201

def artifacts?
  false
end

#artifacts_expire_atObject



193
# File 'app/models/ci/bridge.rb', line 193

def artifacts_expire_at; end

#can_auto_cancel_pipeline_on_job_failure?Boolean

Returns:

  • (Boolean)


175
176
177
# File 'app/models/ci/bridge.rb', line 175

def can_auto_cancel_pipeline_on_job_failure?
  true
end

#dependent?Boolean

Returns:

  • (Boolean)


243
244
245
246
247
# File 'app/models/ci/bridge.rb', line 243

def dependent?
  strong_memoize(:dependent) do
    options&.dig(:trigger, :strategy) == 'depend'
  end
end

#detailed_status(current_user) ⇒ Object



157
158
159
160
161
# File 'app/models/ci/bridge.rb', line 157

def detailed_status(current_user)
  Gitlab::Ci::Status::Bridge::Factory
    .new(self, current_user)
    .fabricate!
end

#downstream_pipeline_paramsObject



103
104
105
106
107
108
# File 'app/models/ci/bridge.rb', line 103

def downstream_pipeline_params
  return child_params if triggers_child_pipeline?
  return cross_project_params if downstream_project.present?

  {}
end

#downstream_projectObject



110
111
112
113
114
115
116
117
118
# File 'app/models/ci/bridge.rb', line 110

def downstream_project
  strong_memoize(:downstream_project) do
    if downstream_project_path
      ::Project.find_by_full_path(downstream_project_path)
    elsif triggers_child_pipeline?
      project
    end
  end
end

#downstream_project_pathObject



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'app/models/ci/bridge.rb', line 120

def downstream_project_path
  strong_memoize(:downstream_project_path) do
    project = options&.dig(:trigger, :project)
    next unless project

    if ci_optimize_memory_for_variables_enabled?
      scoped_variables.to_hash_variables.then do |all_variables|
        ::ExpandVariables.expand(project, all_variables)
      end
    else
      scoped_variables.to_runner_variables.then do |all_variables|
        ::ExpandVariables.expand(project, all_variables)
      end
    end
  end
end

#downstream_variablesObject



253
254
255
# File 'app/models/ci/bridge.rb', line 253

def downstream_variables
  Gitlab::Ci::Variables::Downstream::Generator.new(self).calculate
end

#execute_hooksObject

Raises:

  • (NotImplementedError)


213
214
215
# File 'app/models/ci/bridge.rb', line 213

def execute_hooks
  raise NotImplementedError
end

#forward_pipeline_variables?Boolean

Returns:

  • (Boolean)


294
295
296
297
298
299
300
# File 'app/models/ci/bridge.rb', line 294

def forward_pipeline_variables?
  strong_memoize(:forward_pipeline_variables) do
    result = options&.dig(:trigger, :forward, :pipeline_variables)

    result.nil? ? FORWARD_DEFAULTS[:pipeline_variables] : result
  end
end

#forward_yaml_variables?Boolean

Returns:

  • (Boolean)


286
287
288
289
290
291
292
# File 'app/models/ci/bridge.rb', line 286

def forward_yaml_variables?
  strong_memoize(:forward_yaml_variables) do
    result = options&.dig(:trigger, :forward, :yaml_variables)

    result.nil? ? FORWARD_DEFAULTS[:yaml_variables] : result
  end
end

#has_downstream_pipeline?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'app/models/ci/bridge.rb', line 99

def has_downstream_pipeline?
  sourced_pipeline.present?
end

#inherit_status_from_downstream!(pipeline) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
# File 'app/models/ci/bridge.rb', line 86

def inherit_status_from_downstream!(pipeline)
  case pipeline.status
  when 'success'
    success!
  when 'canceled'
    finish_cancel!
  when 'failed', 'skipped'
    drop!
  else
    false
  end
end

#job_artifactsObject

rubocop: enable CodeReuse/ServiceClass



189
190
191
# File 'app/models/ci/bridge.rb', line 189

def job_artifacts
  Ci::JobArtifact.none
end

#parent_pipelineObject



137
138
139
# File 'app/models/ci/bridge.rb', line 137

def parent_pipeline
  pipeline if triggers_child_pipeline?
end

#pipeline_schedule_variablesObject



280
281
282
283
284
# File 'app/models/ci/bridge.rb', line 280

def pipeline_schedule_variables
  return [] unless pipeline.pipeline_schedule

  pipeline.pipeline_schedule.variables.to_a
end

#pipeline_variablesObject



276
277
278
# File 'app/models/ci/bridge.rb', line 276

def pipeline_variables
  pipeline.variables
end

#play(current_user, job_variables_attributes = nil) ⇒ Object

rubocop: disable CodeReuse/ServiceClass We don’t need it but we are taking ‘job_variables_attributes` parameter to make it consistent with `Ci::Build#play` method.



182
183
184
185
186
# File 'app/models/ci/bridge.rb', line 182

def play(current_user, job_variables_attributes = nil)
  Ci::PlayBridgeService
    .new(project, current_user)
    .execute(self)
end

#playable?Boolean

Returns:

  • (Boolean)


167
168
169
# File 'app/models/ci/bridge.rb', line 167

def playable?
  action? && !archived? && manual?
end

#retryable?Boolean

Returns:

  • (Boolean)


64
65
66
67
68
# File 'app/models/ci/bridge.rb', line 64

def retryable?
  return false if failed? && (pipeline_loop_detected? || reached_max_descendant_pipelines_depth?)

  super
end

#runnable?Boolean

Returns:

  • (Boolean)


205
206
207
# File 'app/models/ci/bridge.rb', line 205

def runnable?
  false
end

#runnerObject



195
# File 'app/models/ci/bridge.rb', line 195

def runner; end

#schedulable?Boolean

Returns:

  • (Boolean)


163
164
165
# File 'app/models/ci/bridge.rb', line 163

def schedulable?
  false
end

#tag_listObject



197
198
199
# File 'app/models/ci/bridge.rb', line 197

def tag_list
  Gitlab::Ci::Tags::TagList.new
end

#tagsObject



153
154
155
# File 'app/models/ci/bridge.rb', line 153

def tags
  [:bridge]
end

#target_refObject



228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'app/models/ci/bridge.rb', line 228

def target_ref
  branch = options&.dig(:trigger, :branch)
  return unless branch

  if ci_optimize_memory_for_variables_enabled?
    scoped_variables.to_hash_variables.then do |all_variables|
      ::ExpandVariables.expand(branch, all_variables)
    end
  else
    scoped_variables.to_runner_variables.then do |all_variables|
      ::ExpandVariables.expand(branch, all_variables)
    end
  end
end

#target_revision_refObject



249
250
251
# File 'app/models/ci/bridge.rb', line 249

def target_revision_ref
  downstream_pipeline_params.dig(:target_revision, :ref)
end

#to_partial_pathObject



217
218
219
# File 'app/models/ci/bridge.rb', line 217

def to_partial_path
  'projects/generic_commit_statuses/generic_commit_status'
end

#triggers_child_pipeline?Boolean

Returns:

  • (Boolean)


145
146
147
# File 'app/models/ci/bridge.rb', line 145

def triggers_child_pipeline?
  yaml_for_downstream.present?
end

#triggers_cross_project_pipeline?Boolean

Returns:

  • (Boolean)


149
150
151
# File 'app/models/ci/bridge.rb', line 149

def triggers_cross_project_pipeline?
  downstream_project_path.present?
end

#triggers_downstream_pipeline?Boolean

Returns:

  • (Boolean)


141
142
143
# File 'app/models/ci/bridge.rb', line 141

def triggers_downstream_pipeline?
  triggers_child_pipeline? || triggers_cross_project_pipeline?
end

#variablesObject



257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'app/models/ci/bridge.rb', line 257

def variables
  strong_memoize(:variables) do
    bridge_variables =
      if ::Feature.disabled?(:exclude_protected_variables_from_multi_project_pipeline_triggers, project) ||
          (expose_protected_project_variables? && expose_protected_group_variables?)
        scoped_variables
      else
        unprotected_scoped_variables(
          expose_project_variables: expose_protected_project_variables?,
          expose_group_variables: expose_protected_group_variables?
        )
      end

    Gitlab::Ci::Variables::Collection.new
     .concat(bridge_variables)
     .concat(pipeline.persisted_variables)
  end
end

#yaml_for_downstreamObject



221
222
223
224
225
226
# File 'app/models/ci/bridge.rb', line 221

def yaml_for_downstream
  strong_memoize(:yaml_for_downstream) do
    includes = options&.dig(:trigger, :include)
    YAML.dump('include' => includes) if includes
  end
end