diff options
Diffstat (limited to 'app/models/ci')
-rw-r--r-- | app/models/ci/build.rb | 7 | ||||
-rw-r--r-- | app/models/ci/build_metadata.rb | 11 | ||||
-rw-r--r-- | app/models/ci/catalog/resource.rb | 5 | ||||
-rw-r--r-- | app/models/ci/catalog/resources/version.rb | 9 | ||||
-rw-r--r-- | app/models/ci/pipeline.rb | 48 | ||||
-rw-r--r-- | app/models/ci/stage.rb | 44 |
6 files changed, 94 insertions, 30 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 0bb93a68470..284495a1d97 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -19,7 +19,12 @@ module Ci belongs_to :runner belongs_to :trigger_request belongs_to :erased_by, class_name: 'User' - belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id, inverse_of: :builds + belongs_to :pipeline, + ->(build) { in_partition(build) }, + class_name: 'Ci::Pipeline', + foreign_key: :commit_id, + partition_foreign_key: :partition_id, + inverse_of: :builds RUNNER_FEATURES = { upload_multiple_artifacts: -> (build) { build.publishes_artifacts_reports? }, diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb index 555565ff621..4194be7c0af 100644 --- a/app/models/ci/build_metadata.rb +++ b/app/models/ci/build_metadata.rb @@ -14,9 +14,14 @@ module Ci self.table_name = 'p_ci_builds_metadata' self.primary_key = 'id' + query_constraints :id, :partition_id partitionable scope: :build, partitioned: true - belongs_to :build, class_name: 'CommitStatus' + belongs_to :build, # rubocop: disable Rails/InverseOf -- this relation is not present on CommitStatus + ->(metadata) { in_partition(metadata) }, + partition_foreign_key: :partition_id, + class_name: 'CommitStatus' + belongs_to :project before_create :set_build_project @@ -42,6 +47,10 @@ module Ci job_timeout_source: 4 } + def self.use_partition_id_filter? + Ci::Pipeline.use_partition_id_filter? + end + def update_timeout_state timeout = timeout_with_highest_precedence diff --git a/app/models/ci/catalog/resource.rb b/app/models/ci/catalog/resource.rb index 3ead852e834..8bfef225e05 100644 --- a/app/models/ci/catalog/resource.rb +++ b/app/models/ci/catalog/resource.rb @@ -50,6 +50,11 @@ module Ci save! end + # Triggered in Ci::Catalog::Resources::Version and Release model callbacks. + def update_latest_released_at! + update!(latest_released_at: versions.latest&.released_at) + end + private # These columns are denormalized from the `projects` table. We first sync these diff --git a/app/models/ci/catalog/resources/version.rb b/app/models/ci/catalog/resources/version.rb index bd0ebc77a6d..ab4d5c52526 100644 --- a/app/models/ci/catalog/resources/version.rb +++ b/app/models/ci/catalog/resources/version.rb @@ -28,6 +28,9 @@ module Ci delegate :name, :description, :tag, :sha, :released_at, :author_id, to: :release + after_destroy :update_catalog_resource + after_save :update_catalog_resource + class << self # In the future, we should support semantic versioning. # See https://gitlab.com/gitlab-org/gitlab/-/issues/427286 @@ -110,6 +113,12 @@ module Ci end end end + + private + + def update_catalog_resource + catalog_resource.update_latest_released_at! + end end end end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 54aa3d78cf3..faa79f8f49c 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -80,31 +80,31 @@ module Ci # 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, - 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' + has_many :statuses, ->(pipeline) { in_partition(pipeline) }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :processables, ->(pipeline) { in_partition(pipeline) }, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :latest_statuses_ordered_by_stage, -> (pipeline) { latest.in_partition(pipeline).order(:stage_idx, :stage) }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :latest_statuses, ->(pipeline) { latest.in_partition(pipeline) }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :statuses_order_id_desc, ->(pipeline) { in_partition(pipeline).order_id_desc }, class_name: 'CommitStatus', foreign_key: :commit_id, + inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :bridges, ->(pipeline) { in_partition(pipeline) }, class_name: 'Ci::Bridge', foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :builds, ->(pipeline) { in_partition(pipeline) }, foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :generic_commit_statuses, ->(pipeline) { in_partition(pipeline) }, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'GenericCommitStatus', partition_foreign_key: :partition_id # # 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 :all_jobs, ->(pipeline) { in_partition(pipeline) }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :current_jobs, ->(pipeline) { latest.in_partition(pipeline) }, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :all_processable_jobs, ->(pipeline) { in_partition(pipeline) }, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id + has_many :current_processable_jobs, ->(pipeline) { latest.in_partition(pipeline) }, class_name: 'Ci::Processable', foreign_key: :commit_id, inverse_of: :pipeline, partition_foreign_key: :partition_id 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, 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 :latest_builds, ->(pipeline) { in_partition(pipeline).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::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_jobs, -> { latest.success.with_project_and_metadata }, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'Ci::Processable' + has_many :latest_successful_jobs, ->(pipeline) { in_partition(pipeline).latest.success.with_project_and_metadata }, foreign_key: :commit_id, inverse_of: :pipeline, class_name: 'Ci::Processable' has_many :messages, class_name: 'Ci::PipelineMessage', inverse_of: :pipeline @@ -113,14 +113,14 @@ module Ci 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', + has_many :pending_builds, ->(pipeline) { in_partition(pipeline).pending }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :pipeline + has_many :failed_builds, ->(pipeline) { in_partition(pipeline).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 :retryable_builds, ->(pipeline) { in_partition(pipeline).latest.failed_or_canceled.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Build', inverse_of: :pipeline + has_many :cancelable_statuses, ->(pipeline) { in_partition(pipeline).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::Processable', 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 :manual_actions, ->(pipeline) { in_partition(pipeline).latest.manual_actions.includes(:project) }, foreign_key: :commit_id, class_name: 'Ci::Processable', inverse_of: :pipeline + has_many :scheduled_actions, ->(pipeline) { in_partition(pipeline).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, inverse_of: :auto_canceled_by @@ -605,6 +605,12 @@ module Ci ::Gitlab::Ci::PipelineObjectHierarchy.new(relation, options: options) end + def self.use_partition_id_filter? + ::Gitlab::SafeRequestStore.fetch(:ci_builds_partition_id_query_filter) do + ::Feature.enabled?(:ci_builds_partition_id_query_filter) + end + end + def uses_needs? processables.where(scheduling_type: :dag).any? end diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb index 3d2df9a45ef..e413ed8a668 100644 --- a/app/models/ci/stage.rb +++ b/app/models/ci/stage.rb @@ -21,19 +21,45 @@ module Ci belongs_to :project belongs_to :pipeline - has_many :statuses, class_name: 'CommitStatus', foreign_key: :stage_id, inverse_of: :ci_stage - has_many :latest_statuses, -> { ordered.latest }, + has_many :statuses, + ->(stage) { in_partition(stage) }, class_name: 'CommitStatus', foreign_key: :stage_id, + partition_foreign_key: :partition_id, inverse_of: :ci_stage - has_many :retried_statuses, -> { ordered.retried }, + has_many :latest_statuses, + ->(stage) { in_partition(stage).ordered.latest }, class_name: 'CommitStatus', foreign_key: :stage_id, + partition_foreign_key: :partition_id, + inverse_of: :ci_stage + has_many :retried_statuses, + ->(stage) { in_partition(stage).ordered.retried }, + class_name: 'CommitStatus', + foreign_key: :stage_id, + partition_foreign_key: :partition_id, + inverse_of: :ci_stage + has_many :processables, + ->(stage) { in_partition(stage) }, + class_name: 'Ci::Processable', + foreign_key: :stage_id, + partition_foreign_key: :partition_id, + inverse_of: :ci_stage + has_many :builds, + ->(stage) { in_partition(stage) }, + foreign_key: :stage_id, + partition_foreign_key: :partition_id, + inverse_of: :ci_stage + has_many :bridges, + ->(stage) { in_partition(stage) }, + foreign_key: :stage_id, + partition_foreign_key: :partition_id, + inverse_of: :ci_stage + has_many :generic_commit_statuses, + ->(stage) { in_partition(stage) }, + foreign_key: :stage_id, + partition_foreign_key: :partition_id, inverse_of: :ci_stage - has_many :processables, class_name: 'Ci::Processable', foreign_key: :stage_id, inverse_of: :ci_stage - has_many :builds, foreign_key: :stage_id, inverse_of: :ci_stage - has_many :bridges, foreign_key: :stage_id, inverse_of: :ci_stage - has_many :generic_commit_statuses, foreign_key: :stage_id, inverse_of: :ci_stage scope :ordered, -> { order(position: :asc) } scope :in_pipelines, ->(pipelines) { where(pipeline: pipelines) } @@ -107,6 +133,10 @@ module Ci end end + def self.use_partition_id_filter? + Ci::Pipeline.use_partition_id_filter? + end + def set_status(new_status) retry_optimistic_lock(self, name: 'ci_stage_set_status') do case new_status |