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.rb98
1 files changed, 76 insertions, 22 deletions
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index 7762328d274..47eba685afe 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -19,6 +19,8 @@ module Ci
PROJECT_ROUTE_AND_NAMESPACE_ROUTE = {
project: [:project_feature, :route, { namespace: :route }]
}.freeze
+ CONFIG_EXTENSION = '.gitlab-ci.yml'
+ DEFAULT_CONFIG_PATH = CONFIG_EXTENSION
BridgeStatusError = Class.new(StandardError)
@@ -104,15 +106,15 @@ module Ci
after_create :keep_around_commits, unless: :importing?
- # We use `Ci::PipelineEnums.sources` here so that EE can more easily extend
+ # We use `Enums::Ci::Pipeline.sources` here so that EE can more easily extend
# this `Hash` with new values.
- enum_with_nil source: ::Ci::PipelineEnums.sources
+ enum_with_nil source: Enums::Ci::Pipeline.sources
- enum_with_nil config_source: ::Ci::PipelineEnums.config_sources
+ enum_with_nil config_source: Enums::Ci::Pipeline.config_sources
- # We use `Ci::PipelineEnums.failure_reasons` here so that EE can more easily
+ # We use `Enums::Ci::Pipeline.failure_reasons` here so that EE can more easily
# extend this `Hash` with new values.
- enum failure_reason: ::Ci::PipelineEnums.failure_reasons
+ enum failure_reason: Enums::Ci::Pipeline.failure_reasons
enum locked: { unlocked: 0, artifacts_locked: 1 }
@@ -229,7 +231,12 @@ module Ci
end
after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
- next unless pipeline.bridge_triggered?
+ pipeline.run_after_commit do
+ ::Ci::Pipelines::CreateArtifactWorker.perform_async(pipeline.id)
+ end
+ end
+
+ after_transition any => ::Ci::Pipeline.completed_statuses do |pipeline|
next unless pipeline.bridge_waiting?
pipeline.run_after_commit do
@@ -254,7 +261,7 @@ module Ci
scope :internal, -> { where(source: internal_sources) }
scope :no_child, -> { where.not(source: :parent_pipeline) }
- scope :ci_sources, -> { where(config_source: ::Ci::PipelineEnums.ci_config_sources_values) }
+ scope :ci_sources, -> { where(source: Enums::Ci::Pipeline.ci_sources.values) }
scope :for_user, -> (user) { where(user: user) }
scope :for_sha, -> (sha) { where(sha: sha) }
scope :for_source_sha, -> (source_sha) { where(source_sha: source_sha) }
@@ -483,6 +490,12 @@ module Ci
end
end
+ def git_commit_timestamp
+ strong_memoize(:git_commit_timestamp) do
+ commit.try(:timestamp)
+ end
+ end
+
def before_sha
super || Gitlab::Git::BLANK_SHA
end
@@ -539,12 +552,6 @@ module Ci
end
# rubocop: enable CodeReuse/ServiceClass
- def mark_as_processable_after_stage(stage_idx)
- builds.skipped.after_stage(stage_idx).find_each do |build|
- Gitlab::OptimisticLocking.retry_lock(build, &:process)
- end
- end
-
def lazy_ref_commit
return unless ::Gitlab::Ci::Features.pipeline_latest?
@@ -647,7 +654,7 @@ module Ci
def config_path
return unless repository_source? || unknown_source?
- project.ci_config_path.presence || '.gitlab-ci.yml'
+ project.ci_config_path_or_default
end
def has_yaml_errors?
@@ -669,8 +676,10 @@ module Ci
messages.select(&:error?)
end
- def warning_messages
- messages.select(&:warning?)
+ def warning_messages(limit: nil)
+ messages.select(&:warning?).tap do |warnings|
+ break warnings.take(limit) if limit
+ end
end
# Manually set the notes for a Ci::Pipeline
@@ -766,6 +775,7 @@ module Ci
variables.append(key: 'CI_COMMIT_TITLE', value: git_commit_full_title.to_s)
variables.append(key: 'CI_COMMIT_DESCRIPTION', value: git_commit_description.to_s)
variables.append(key: 'CI_COMMIT_REF_PROTECTED', value: (!!protected_ref?).to_s)
+ variables.append(key: 'CI_COMMIT_TIMESTAMP', value: git_commit_timestamp.to_s)
# legacy variables
variables.append(key: 'CI_BUILD_REF', value: sha)
@@ -810,11 +820,17 @@ module Ci
all_merge_requests.order(id: :desc)
end
- # If pipeline is a child of another pipeline, include the parent
- # and the siblings, otherwise return only itself and children.
def same_family_pipeline_ids
- parent = parent_pipeline || self
- [parent.id] + parent.child_pipelines.pluck(:id)
+ if ::Gitlab::Ci::Features.child_of_child_pipeline_enabled?(project)
+ ::Gitlab::Ci::PipelineObjectHierarchy.new(
+ base_and_ancestors(same_project: true), options: { same_project: true }
+ ).base_and_descendants.select(:id)
+ else
+ # If pipeline is a child of another pipeline, include the parent
+ # and the siblings, otherwise return only itself and children.
+ parent = parent_pipeline || self
+ [parent.id] + parent.child_pipelines.pluck(:id)
+ end
end
def bridge_triggered?
@@ -858,12 +874,26 @@ module Ci
builds.latest.with_reports(reports_scope)
end
+ def builds_with_coverage
+ builds.with_coverage
+ end
+
def has_reports?(reports_scope)
complete? && latest_report_builds(reports_scope).exists?
end
+ def has_coverage_reports?
+ pipeline_artifacts&.has_code_coverage?
+ end
+
+ def can_generate_coverage_reports?
+ has_reports?(Ci::JobArtifact.coverage_reports)
+ end
+
def test_report_summary
- Gitlab::Ci::Reports::TestReportSummary.new(latest_builds_report_results)
+ strong_memoize(:test_report_summary) do
+ Gitlab::Ci::Reports::TestReportSummary.new(latest_builds_report_results)
+ end
end
def test_reports
@@ -1008,7 +1038,11 @@ module Ci
end
def cacheable?
- Ci::PipelineEnums.ci_config_sources.key?(config_source.to_sym)
+ !dangling?
+ end
+
+ def dangling?
+ Enums::Ci::Pipeline.dangling_sources.key?(source.to_sym)
end
def source_ref_path
@@ -1029,6 +1063,26 @@ module Ci
self.ci_ref = Ci::Ref.ensure_for(self)
end
+ def base_and_ancestors(same_project: false)
+ # Without using `unscoped`, caller scope is also included into the query.
+ # Using `unscoped` here will be redundant after Rails 6.1
+ ::Gitlab::Ci::PipelineObjectHierarchy
+ .new(self.class.unscoped.where(id: id), options: { same_project: same_project })
+ .base_and_ancestors
+ end
+
+ # We need `base_and_ancestors` in a specific order to "break" when needed.
+ # If we use `find_each`, then the order is broken.
+ # rubocop:disable Rails/FindEach
+ def reset_ancestor_bridges!
+ base_and_ancestors.includes(:source_bridge).each do |pipeline|
+ break unless pipeline.bridge_waiting?
+
+ pipeline.source_bridge.pending!
+ end
+ end
+ # rubocop:enable Rails/FindEach
+
private
def add_message(severity, content)