Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/models')
-rw-r--r--app/models/ci/build.rb7
-rw-r--r--app/models/ci/build_metadata.rb11
-rw-r--r--app/models/ci/catalog/resource.rb5
-rw-r--r--app/models/ci/catalog/resources/version.rb9
-rw-r--r--app/models/ci/pipeline.rb48
-rw-r--r--app/models/ci/stage.rb44
-rw-r--r--app/models/commit_status.rb7
-rw-r--r--app/models/concerns/ci/metadatable.rb2
-rw-r--r--app/models/concerns/ci/partitionable.rb4
-rw-r--r--app/models/release.rb7
10 files changed, 113 insertions, 31 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
diff --git a/app/models/commit_status.rb b/app/models/commit_status.rb
index 9f77bd8ebe2..a8e2615b327 100644
--- a/app/models/commit_status.rb
+++ b/app/models/commit_status.rb
@@ -25,11 +25,12 @@ class CommitStatus < Ci::ApplicationRecord
self.sequence_name = :ci_builds_id_seq
self.primary_key = :id
+ query_constraints :id, :partition_id
partitionable scope: :pipeline, partitioned: true
belongs_to :user
belongs_to :project
- belongs_to :pipeline, class_name: 'Ci::Pipeline', foreign_key: :commit_id, inverse_of: :statuses
+ belongs_to :pipeline, ->(build) { in_partition(build) }, class_name: 'Ci::Pipeline', foreign_key: :commit_id, inverse_of: :statuses, partition_foreign_key: :partition_id
belongs_to :auto_canceled_by, class_name: 'Ci::Pipeline', inverse_of: :auto_canceled_jobs
belongs_to :ci_stage, class_name: 'Ci::Stage', foreign_key: :stage_id
@@ -233,6 +234,10 @@ class CommitStatus < Ci::ApplicationRecord
false
end
+ def self.use_partition_id_filter?
+ Ci::Pipeline.use_partition_id_filter?
+ end
+
def locking_enabled?
will_save_change_to_status?
end
diff --git a/app/models/concerns/ci/metadatable.rb b/app/models/concerns/ci/metadatable.rb
index b785e39523d..5dcae7d594d 100644
--- a/app/models/concerns/ci/metadatable.rb
+++ b/app/models/concerns/ci/metadatable.rb
@@ -10,8 +10,10 @@ module Ci
included do
has_one :metadata,
+ ->(build) { where(partition_id: build.partition_id) },
class_name: 'Ci::BuildMetadata',
foreign_key: :build_id,
+ partition_foreign_key: :partition_id,
inverse_of: :build,
autosave: true
diff --git a/app/models/concerns/ci/partitionable.rb b/app/models/concerns/ci/partitionable.rb
index aaf07bfee3a..447603c1635 100644
--- a/app/models/concerns/ci/partitionable.rb
+++ b/app/models/concerns/ci/partitionable.rb
@@ -61,6 +61,10 @@ module Ci
before_validation :set_partition_id, on: :create
validates :partition_id, presence: true
+ scope :in_partition, ->(id) do
+ where(partition_id: (id.respond_to?(:partition_id) ? id.partition_id : id))
+ end
+
def set_partition_id
return if partition_id_changed? && partition_id.present?
return unless partition_scope_value
diff --git a/app/models/release.rb b/app/models/release.rb
index 6830f6e8480..f8a7973e451 100644
--- a/app/models/release.rb
+++ b/app/models/release.rb
@@ -25,6 +25,9 @@ class Release < ApplicationRecord
accepts_nested_attributes_for :links, allow_destroy: true
before_create :set_released_at
+ # TODO: Remove this callback after catalog_resource.released_at is denormalized. See https://gitlab.com/gitlab-org/gitlab/-/issues/430117.
+ after_update :update_catalog_resource, if: -> { project.catalog_resource && saved_change_to_released_at? }
+ after_destroy :update_catalog_resource, if: -> { project.catalog_resource }
validates :project, :tag, presence: true
validates :author_id, presence: true, on: :create
@@ -168,6 +171,10 @@ class Release < ApplicationRecord
order_created_desc
end
end
+
+ def update_catalog_resource
+ project.catalog_resource.update_latest_released_at!
+ end
end
Release.prepend_mod_with('Release')