diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 19:05:49 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-17 19:05:49 +0300 |
commit | 43a25d93ebdabea52f99b05e15b06250cd8f07d7 (patch) | |
tree | dceebdc68925362117480a5d672bcff122fb625b /app/models/ci/pipeline.rb | |
parent | 20c84b99005abd1c82101dfeff264ac50d2df211 (diff) |
Add latest changes from gitlab-org/gitlab@16-0-stable-eev16.0.0-rc42
Diffstat (limited to 'app/models/ci/pipeline.rb')
-rw-r--r-- | app/models/ci/pipeline.rb | 119 |
1 files changed, 85 insertions, 34 deletions
diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index bd426e02b9c..babea831d85 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -11,7 +11,6 @@ module Ci include Gitlab::OptimisticLocking include Gitlab::Utils::StrongMemoize include AtomicInternalId - include EnumWithNil include Ci::HasRef include ShaAttribute include FromUnion @@ -19,6 +18,9 @@ module Ci include EachBatch include FastDestroyAll::Helpers + include IgnorableColumns + ignore_column :id_convert_to_bigint, remove_with: '16.3', remove_after: '2023-08-22' + MAX_OPEN_MERGE_REQUESTS_REFS = 4 PROJECT_ROUTE_AND_NAMESPACE_ROUTE = { @@ -46,39 +48,53 @@ module Ci belongs_to :project, inverse_of: :all_pipelines belongs_to :user - belongs_to :auto_canceled_by, class_name: 'Ci::Pipeline' + belongs_to :auto_canceled_by, class_name: 'Ci::Pipeline', inverse_of: :auto_canceled_pipelines belongs_to :pipeline_schedule, class_name: 'Ci::PipelineSchedule' belongs_to :merge_request, class_name: 'MergeRequest' belongs_to :external_pull_request belongs_to :ci_ref, class_name: 'Ci::Ref', foreign_key: :ci_ref_id, inverse_of: :pipelines has_internal_id :iid, scope: :project, presence: false, - track_if: -> { !importing? }, - ensure_if: -> { !importing? }, - init: ->(pipeline, scope) do - if pipeline - pipeline.project&.all_pipelines&.maximum(:iid) || pipeline.project&.all_pipelines&.count - elsif scope - ::Ci::Pipeline.where(**scope).maximum(:iid) - end - end + track_if: -> { !importing? }, + ensure_if: -> { !importing? }, + init: ->(pipeline, scope) do + if pipeline + pipeline.project&.all_pipelines&.maximum(:iid) || pipeline.project&.all_pipelines&.count + elsif scope + ::Ci::Pipeline.where(**scope).maximum(:iid) + end + end has_many :stages, -> { order(position: :asc) }, inverse_of: :pipeline + + # + # In https://gitlab.com/groups/gitlab-org/-/epics/9991, we aim to convert all CommitStatus related models to + # Ci:Job models. With that epic, we aim to replace `statuses` with `jobs`. + # + # DEPRECATED: has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline + has_many :processables, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline has_many :latest_statuses_ordered_by_stage, -> { latest.order(:stage_idx, :stage) }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline has_many :latest_statuses, -> { latest }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline - has_many :statuses_order_id_desc, -> { order_id_desc }, class_name: 'CommitStatus', foreign_key: :commit_id - has_many :processables, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline + has_many :statuses_order_id_desc, -> { order_id_desc }, class_name: 'CommitStatus', foreign_key: :commit_id, + inverse_of: :pipeline has_many :bridges, class_name: 'Ci::Bridge', foreign_key: :commit_id, inverse_of: :pipeline has_many :builds, foreign_key: :commit_id, inverse_of: :pipeline has_many :generic_commit_statuses, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'GenericCommitStatus' + # + # NEW: + has_many :all_jobs, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline + has_many :current_jobs, -> { latest }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline + has_many :all_processable_jobs, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline + has_many :current_processable_jobs, -> { latest }, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline + has_many :job_artifacts, through: :builds has_many :build_trace_chunks, class_name: 'Ci::BuildTraceChunk', through: :builds, source: :trace_chunks - has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id # rubocop:disable Cop/ActiveRecordDependent + has_many :trigger_requests, dependent: :destroy, foreign_key: :commit_id, inverse_of: :pipeline # rubocop:disable Cop/ActiveRecordDependent has_many :variables, class_name: 'Ci::PipelineVariable' has_many :latest_builds, -> { latest.with_project_and_metadata }, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'Ci::Build' has_many :downloadable_artifacts, -> do - not_expired.or(where_exists(::Ci::Pipeline.artifacts_locked.where('ci_pipelines.id = ci_builds.commit_id'))).downloadable.with_job + not_expired.or(where_exists(Ci::Pipeline.artifacts_locked.where("#{Ci::Pipeline.quoted_table_name}.id = #{Ci::Build.quoted_table_name}.commit_id"))).downloadable.with_job end, through: :latest_builds, source: :job_artifacts has_many :latest_successful_builds, -> { latest.success.with_project_and_metadata }, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'Ci::Build' @@ -86,17 +102,24 @@ module Ci # Merge requests for which the current pipeline is running against # the merge request's latest commit. - has_many :merge_requests_as_head_pipeline, foreign_key: "head_pipeline_id", class_name: 'MergeRequest' + has_many :merge_requests_as_head_pipeline, foreign_key: :head_pipeline_id, class_name: 'MergeRequest', + inverse_of: :head_pipeline + has_many :pending_builds, -> { pending }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :pipeline - has_many :failed_builds, -> { latest.failed }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :pipeline + has_many :failed_builds, -> { latest.failed }, foreign_key: :commit_id, class_name: 'Ci::Build', + inverse_of: :pipeline has_many :retryable_builds, -> { latest.failed_or_canceled.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :pipeline - has_many :cancelable_statuses, -> { cancelable }, foreign_key: :commit_id, class_name: 'CommitStatus' + has_many :cancelable_statuses, -> { cancelable }, foreign_key: :commit_id, class_name: 'CommitStatus', + inverse_of: :pipeline has_many :manual_actions, -> { latest.manual_actions.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :pipeline has_many :scheduled_actions, -> { latest.scheduled_actions.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :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 :sourced_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :source_pipeline_id + has_many :auto_canceled_pipelines, class_name: 'Ci::Pipeline', foreign_key: :auto_canceled_by_id, + inverse_of: :auto_canceled_by + has_many :auto_canceled_jobs, class_name: 'CommitStatus', foreign_key: :auto_canceled_by_id, + inverse_of: :auto_canceled_by + has_many :sourced_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :source_pipeline_id, + inverse_of: :source_pipeline has_one :source_pipeline, class_name: 'Ci::Sources::Pipeline', inverse_of: :pipeline @@ -114,7 +137,9 @@ module Ci has_one :pipeline_metadata, class_name: 'Ci::PipelineMetadata', inverse_of: :pipeline - has_many :daily_build_group_report_results, class_name: 'Ci::DailyBuildGroupReportResult', foreign_key: :last_pipeline_id + has_many :daily_build_group_report_results, class_name: 'Ci::DailyBuildGroupReportResult', + foreign_key: :last_pipeline_id, inverse_of: :last_pipeline + has_many :latest_builds_report_results, through: :latest_builds, source: :report_results has_many :pipeline_artifacts, class_name: 'Ci::PipelineArtifact', inverse_of: :pipeline, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent @@ -143,9 +168,9 @@ module Ci # We use `Enums::Ci::Pipeline.sources` here so that EE can more easily extend # this `Hash` with new values. - enum_with_nil source: Enums::Ci::Pipeline.sources + enum source: Enums::Ci::Pipeline.sources - enum_with_nil config_source: Enums::Ci::Pipeline.config_sources + enum config_source: Enums::Ci::Pipeline.config_sources # We use `Enums::Ci::Pipeline.failure_reasons` here so that EE can more easily # extend this `Hash` with new values. @@ -336,6 +361,22 @@ module Ci AutoDevops::DisableWorker.perform_async(pipeline.id) if pipeline.auto_devops_source? end end + + after_transition any => [:running, *::Ci::Pipeline.completed_statuses] do |pipeline| + project = pipeline&.project + + next unless project + next unless Feature.enabled?(:pipeline_trigger_merge_status, project) + + pipeline.run_after_commit do + next if pipeline.child? + next unless project.only_allow_merge_if_pipeline_succeeds?(inherit_group_setting: true) + + pipeline.all_merge_requests.opened.each do |merge_request| + GraphqlTriggers.merge_request_merge_status_updated(merge_request) + end + end + end end scope :internal, -> { where(source: internal_sources) } @@ -361,18 +402,25 @@ module Ci scope :created_before_id, -> (id) { where(arel_table[:id].lt(id)) } scope :before_pipeline, -> (pipeline) { created_before_id(pipeline.id).outside_pipeline_family(pipeline) } scope :with_pipeline_source, -> (source) { where(source: source) } + scope :preload_pipeline_metadata, -> { preload(:pipeline_metadata) } scope :outside_pipeline_family, ->(pipeline) do where.not(id: pipeline.same_family_pipeline_ids) end scope :with_reports, -> (reports_scope) do - where('EXISTS (?)', ::Ci::Build.latest.with_artifacts(reports_scope).where('ci_pipelines.id=ci_builds.commit_id').select(1)) + where('EXISTS (?)', + ::Ci::Build + .latest + .with_artifacts(reports_scope) + .where("#{quoted_table_name}.id = #{Ci::Build.quoted_table_name}.commit_id") + .select(1) + ) end scope :with_only_interruptible_builds, -> do where('NOT EXISTS (?)', - Ci::Build.where('ci_builds.commit_id = ci_pipelines.id') + Ci::Build.where("#{Ci::Build.quoted_table_name}.commit_id = #{quoted_table_name}.id") .with_status(STARTED_STATUSES) .not_interruptible ) @@ -382,11 +430,15 @@ module Ci # In general, please use `Ci::PipelinesForMergeRequestFinder` instead, # for checking permission of the actor. scope :triggered_by_merge_request, -> (merge_request) do - where(source: :merge_request_event, - merge_request: merge_request, - project: [merge_request.source_project, merge_request.target_project]) + where( + source: :merge_request_event, + merge_request: merge_request, + project: [merge_request.source_project, merge_request.target_project] + ) end + scope :order_id_desc, -> { order(id: :desc) } + # Returns the pipelines in descending order (= newest first), optionally # limited to a number of references. # @@ -657,7 +709,7 @@ module Ci # rubocop: enable CodeReuse/ServiceClass def lazy_ref_commit - BatchLoader.for(ref).batch do |refs, loader| + BatchLoader.for(ref).batch(key: project.id) do |refs, loader| next unless project.repository_exists? project.repository.list_commits_by_ref_name(refs).then do |commits| @@ -818,8 +870,7 @@ module Ci when 'manual' then block when 'scheduled' then delay else - raise Ci::HasStatus::UnknownStatusError, - "Unknown status `#{new_status}`" + raise Ci::HasStatus::UnknownStatusError, "Unknown status `#{new_status}`" end end end @@ -1282,7 +1333,7 @@ module Ci types_to_collect = report_types.empty? ? ::Ci::JobArtifact::SECURITY_REPORT_FILE_TYPES : report_types ::Gitlab::Ci::Reports::Security::Reports.new(self).tap do |security_reports| - latest_report_builds(reports_scope).each do |build| + latest_report_builds_in_self_and_project_descendants(reports_scope).includes(pipeline: { project: :route }).each do |build| # rubocop:disable Rails/FindEach build.collect_security_reports!(security_reports, report_types: types_to_collect) end end @@ -1294,7 +1345,7 @@ module Ci def cluster_agent_authorizations strong_memoize(:cluster_agent_authorizations) do - ::Clusters::AgentAuthorizationsFinder.new(project).execute + ::Clusters::Agents::Authorizations::CiAccess::Finder.new(project).execute end end |