diff options
Diffstat (limited to 'app/models/ci')
-rw-r--r-- | app/models/ci/bridge.rb | 9 | ||||
-rw-r--r-- | app/models/ci/build.rb | 90 | ||||
-rw-r--r-- | app/models/ci/build_metadata.rb | 1 | ||||
-rw-r--r-- | app/models/ci/build_trace_metadata.rb | 4 | ||||
-rw-r--r-- | app/models/ci/deleted_object.rb | 4 | ||||
-rw-r--r-- | app/models/ci/job_artifact.rb | 67 | ||||
-rw-r--r-- | app/models/ci/pipeline.rb | 104 | ||||
-rw-r--r-- | app/models/ci/processable.rb | 2 | ||||
-rw-r--r-- | app/models/ci/runner.rb | 17 | ||||
-rw-r--r-- | app/models/ci/runner_version.rb | 4 | ||||
-rw-r--r-- | app/models/ci/secure_file.rb | 6 |
11 files changed, 204 insertions, 104 deletions
diff --git a/app/models/ci/bridge.rb b/app/models/ci/bridge.rb index 13af5b1f8d1..3fda8693a58 100644 --- a/app/models/ci/bridge.rb +++ b/app/models/ci/bridge.rb @@ -19,7 +19,7 @@ module Ci belongs_to :project belongs_to :trigger_request has_many :sourced_pipelines, class_name: "::Ci::Sources::Pipeline", - foreign_key: :source_job_id + foreign_key: :source_job_id has_one :sourced_pipeline, class_name: "::Ci::Sources::Pipeline", foreign_key: :source_job_id has_one :downstream_pipeline, through: :sourced_pipeline, source: :pipeline @@ -114,7 +114,12 @@ module Ci def downstream_project_path strong_memoize(:downstream_project_path) do - options&.dig(:trigger, :project) + project = options&.dig(:trigger, :project) + next unless project + + scoped_variables.to_runner_variables.yield_self do |all_variables| + ::ExpandVariables.expand(project, all_variables) + end end end diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 7f9697d0424..bf8817e6e78 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -194,7 +194,7 @@ module Ci after_save :stick_build_if_status_changed after_create unless: :importing? do |build| - run_after_commit { BuildHooksWorker.perform_async(build) } + run_after_commit { build.feature_flagged_execute_hooks } end class << self @@ -285,7 +285,7 @@ module Ci build.run_after_commit do BuildQueueWorker.perform_async(id) - BuildHooksWorker.perform_async(build) + build.feature_flagged_execute_hooks end end @@ -313,7 +313,7 @@ module Ci build.run_after_commit do build.ensure_persistent_ref - BuildHooksWorker.perform_async(build) + build.feature_flagged_execute_hooks end end @@ -322,6 +322,8 @@ module Ci build.run_status_commit_hooks! Ci::BuildFinishedWorker.perform_async(id) + + observe_report_types end end @@ -340,8 +342,8 @@ module Ci # rubocop: disable CodeReuse/ServiceClass Ci::RetryJobService.new(build.project, build.user).execute(build) # rubocop: enable CodeReuse/ServiceClass - rescue Gitlab::Access::AccessDeniedError => ex - Gitlab::AppLogger.error "Unable to auto-retry job #{build.id}: #{ex}" + rescue Gitlab::Access::AccessDeniedError => e + Gitlab::AppLogger.error "Unable to auto-retry job #{build.id}: #{e}" end end end @@ -490,11 +492,7 @@ module Ci if metadata&.expanded_environment_name.present? metadata.expanded_environment_name else - if ::Feature.enabled?(:ci_expand_environment_name_and_url, project) - ExpandVariables.expand(environment, -> { simple_variables.sort_and_expand_all }) - else - ExpandVariables.expand(environment, -> { simple_variables }) - end + ExpandVariables.expand(environment, -> { simple_variables.sort_and_expand_all }) end end end @@ -527,10 +525,14 @@ module Ci self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options end - def environment_deployment_tier + def environment_tier_from_options self.options.dig(:environment, :deployment_tier) if self.options end + def environment_tier + environment_tier_from_options || persisted_environment.try(:tier) + end + def triggered_by?(current_user) user == current_user end @@ -585,6 +587,7 @@ module Ci variables.concat(persisted_environment.predefined_variables) variables.append(key: 'CI_ENVIRONMENT_ACTION', value: environment_action) + variables.append(key: 'CI_ENVIRONMENT_TIER', value: environment_tier) # Here we're passing unexpanded environment_url for runner to expand, # and we need to make sure that CI_ENVIRONMENT_NAME and @@ -777,10 +780,20 @@ module Ci pending? && !any_runners_online? end + def feature_flagged_execute_hooks + if Feature.enabled?(:execute_build_hooks_inline, project) + execute_hooks + else + BuildHooksWorker.perform_async(self) + end + end + def execute_hooks return unless project return if user&.blocked? + ActiveRecord::Associations::Preloader.new.preload([self], { runner: :tags }) + project.execute_hooks(build_data.dup, :job_hooks) if project.has_active_hooks?(:job_hooks) project.execute_integrations(build_data.dup, :job_hooks) if project.has_active_integrations?(:job_hooks) end @@ -818,7 +831,11 @@ module Ci ) end - job_artifacts.erasable.destroy_all # rubocop: disable Cop/DestroyAll + destroyed_artifacts = job_artifacts.erasable.destroy_all # rubocop: disable Cop/DestroyAll + + Gitlab::Ci::Artifacts::Logger.log_deleted(destroyed_artifacts, 'Ci::Build#erase_erasable_artifacts!') + + destroyed_artifacts end def erase(opts = {}) @@ -831,7 +848,12 @@ module Ci ) end - job_artifacts.destroy_all # rubocop: disable Cop/DestroyAll + # TODO: We should use DestroyBatchService here + # See https://gitlab.com/gitlab-org/gitlab/-/issues/369132 + destroyed_artifacts = job_artifacts.destroy_all # rubocop: disable Cop/DestroyAll + + Gitlab::Ci::Artifacts::Logger.log_deleted(destroyed_artifacts, 'Ci::Build#erase') + erase_trace! update_erased!(opts[:erased_by]) end @@ -983,7 +1005,7 @@ module Ci def collect_test_reports!(test_reports) test_reports.get_suite(test_suite_name).tap do |test_suite| - each_report(Ci::JobArtifact::TEST_REPORT_FILE_TYPES) do |file_type, blob| + each_report(Ci::JobArtifact.file_types_for_report(:test)) do |file_type, blob| Gitlab::Ci::Parsers.fabricate!(file_type).parse!( blob, test_suite, @@ -994,7 +1016,7 @@ module Ci end def collect_accessibility_reports!(accessibility_report) - each_report(Ci::JobArtifact::ACCESSIBILITY_REPORT_FILE_TYPES) do |file_type, blob| + each_report(Ci::JobArtifact.file_types_for_report(:accessibility)) do |file_type, blob| Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, accessibility_report) end @@ -1002,7 +1024,7 @@ module Ci end def collect_codequality_reports!(codequality_report) - each_report(Ci::JobArtifact::CODEQUALITY_REPORT_FILE_TYPES) do |file_type, blob| + each_report(Ci::JobArtifact.file_types_for_report(:codequality)) do |file_type, blob| Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, codequality_report) end @@ -1010,7 +1032,7 @@ module Ci end def collect_terraform_reports!(terraform_reports) - each_report(::Ci::JobArtifact::TERRAFORM_REPORT_FILE_TYPES) do |file_type, blob, report_artifact| + each_report(::Ci::JobArtifact.file_types_for_report(:terraform)) do |file_type, blob, report_artifact| ::Gitlab::Ci::Parsers.fabricate!(file_type).parse!(blob, terraform_reports, artifact: report_artifact) end @@ -1079,7 +1101,10 @@ module Ci end def drop_with_exit_code!(failure_reason, exit_code) - drop!(::Gitlab::Ci::Build::Status::Reason.new(self, failure_reason, exit_code)) + failure_reason ||= :unknown_failure + result = drop!(::Gitlab::Ci::Build::Status::Reason.new(self, failure_reason, exit_code)) + ::Ci::TrackFailedBuildWorker.perform_async(id, exit_code, failure_reason) + result end def exit_codes_defined? @@ -1149,6 +1174,21 @@ module Ci end end + def clone(current_user:, new_job_variables_attributes: []) + new_build = super + + if action? && new_job_variables_attributes.any? + new_build.job_variables = [] + new_build.job_variables_attributes = new_job_variables_attributes + end + + new_build + end + + def job_artifact_types + job_artifacts.map(&:file_type) + end + protected def run_status_commit_hooks! @@ -1256,6 +1296,20 @@ module Ci expires_in: RUNNERS_STATUS_CACHE_EXPIRATION ) { yield } end + + def observe_report_types + return unless ::Gitlab.com? && Feature.enabled?(:report_artifact_build_completed_metrics_on_build_completion) + + report_types = options&.dig(:artifacts, :reports)&.keys || [] + + report_types.each do |report_type| + next unless Ci::JobArtifact::REPORT_TYPES.include?(report_type) + + ::Gitlab::Ci::Artifacts::Metrics + .build_completed_report_type_counter(report_type) + .increment(status: status) + end + end end end diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb index 4ee661d89f4..5fc21ba3f28 100644 --- a/app/models/ci/build_metadata.rb +++ b/app/models/ci/build_metadata.rb @@ -19,6 +19,7 @@ module Ci before_create :set_build_project validates :build, presence: true + validates :id_tokens, json_schema: { filename: 'build_metadata_id_tokens' } validates :secrets, json_schema: { filename: 'build_metadata_secrets' } serialize :config_options, Serializers::SymbolizedJson # rubocop:disable Cop/ActiveRecordSerialize diff --git a/app/models/ci/build_trace_metadata.rb b/app/models/ci/build_trace_metadata.rb index 1ffa0e31f99..86de90983ff 100644 --- a/app/models/ci/build_trace_metadata.rb +++ b/app/models/ci/build_trace_metadata.rb @@ -39,8 +39,8 @@ module Ci def track_archival!(trace_artifact_id, checksum) update!(trace_artifact_id: trace_artifact_id, - checksum: checksum, - archived_at: Time.current) + checksum: checksum, + archived_at: Time.current) end def archival_attempts_message diff --git a/app/models/ci/deleted_object.rb b/app/models/ci/deleted_object.rb index aba7b73aba9..d36646aba66 100644 --- a/app/models/ci/deleted_object.rb +++ b/app/models/ci/deleted_object.rb @@ -27,8 +27,8 @@ module Ci def delete_file_from_storage file.remove! true - rescue StandardError => exception - Gitlab::ErrorTracking.track_exception(exception) + rescue StandardError => e + Gitlab::ErrorTracking.track_exception(e) false end end diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index ee7175a4f69..71d33f0bb63 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -13,14 +13,19 @@ module Ci include EachBatch include Gitlab::Utils::StrongMemoize - TEST_REPORT_FILE_TYPES = %w[junit].freeze - COVERAGE_REPORT_FILE_TYPES = %w[cobertura].freeze - CODEQUALITY_REPORT_FILE_TYPES = %w[codequality].freeze - ACCESSIBILITY_REPORT_FILE_TYPES = %w[accessibility].freeze NON_ERASABLE_FILE_TYPES = %w[trace].freeze - TERRAFORM_REPORT_FILE_TYPES = %w[terraform].freeze - SAST_REPORT_TYPES = %w[sast].freeze - SECRET_DETECTION_REPORT_TYPES = %w[secret_detection].freeze + + REPORT_FILE_TYPES = { + sast: %w[sast], + secret_detection: %w[secret_detection], + test: %w[junit], + accessibility: %w[accessibility], + coverage: %w[cobertura], + codequality: %w[codequality], + terraform: %w[terraform], + sbom: %w[cyclonedx] + }.freeze + DEFAULT_FILE_NAMES = { archive: nil, metadata: nil, @@ -48,7 +53,8 @@ module Ci cluster_applications: 'gl-cluster-applications.json', # DEPRECATED: https://gitlab.com/gitlab-org/gitlab/-/issues/361094 requirements: 'requirements.json', coverage_fuzzing: 'gl-coverage-fuzzing.json', - api_fuzzing: 'gl-api-fuzzing-report.json' + api_fuzzing: 'gl-api-fuzzing-report.json', + cyclonedx: 'gl-sbom.cdx.zip' }.freeze INTERNAL_TYPES = { @@ -88,7 +94,8 @@ module Ci terraform: :raw, requirements: :raw, coverage_fuzzing: :raw, - api_fuzzing: :raw + api_fuzzing: :raw, + cyclonedx: :zip }.freeze DOWNLOADABLE_TYPES = %w[ @@ -112,6 +119,7 @@ module Ci secret_detection requirements cluster_image_scanning + cyclonedx ].freeze TYPE_AND_FORMAT_PAIRS = INTERNAL_TYPES.merge(REPORT_TYPES).freeze @@ -152,36 +160,14 @@ module Ci where(file_type: types) end - scope :all_reports, -> do - with_file_types(REPORT_TYPES.keys.map(&:to_s)) - end - - scope :sast_reports, -> do - with_file_types(SAST_REPORT_TYPES) - end - - scope :secret_detection_reports, -> do - with_file_types(SECRET_DETECTION_REPORT_TYPES) - end - - scope :test_reports, -> do - with_file_types(TEST_REPORT_FILE_TYPES) - end - - scope :accessibility_reports, -> do - with_file_types(ACCESSIBILITY_REPORT_FILE_TYPES) - end - - scope :coverage_reports, -> do - with_file_types(COVERAGE_REPORT_FILE_TYPES) - end - - scope :codequality_reports, -> do - with_file_types(CODEQUALITY_REPORT_FILE_TYPES) + REPORT_FILE_TYPES.each do |report_type, file_types| + scope "#{report_type}_reports", -> do + with_file_types(file_types) + end end - scope :terraform_reports, -> do - with_file_types(TERRAFORM_REPORT_FILE_TYPES) + scope :all_reports, -> do + with_file_types(REPORT_TYPES.keys.map(&:to_s)) end scope :erasable, -> do @@ -225,7 +211,8 @@ module Ci browser_performance: 24, ## EE-specific load_performance: 25, ## EE-specific api_fuzzing: 26, ## EE-specific - cluster_image_scanning: 27 ## EE-specific + cluster_image_scanning: 27, ## EE-specific + cyclonedx: 28 ## EE-specific } # `file_location` indicates where actual files are stored. @@ -259,6 +246,10 @@ module Ci end end + def self.file_types_for_report(report_type) + REPORT_FILE_TYPES.fetch(report_type) + end + def self.associated_file_types_for(file_type) return unless file_types.include?(file_type) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 95c6da4a7af..a94330270e2 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -52,15 +52,15 @@ module Ci 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 has_many :statuses, class_name: 'CommitStatus', foreign_key: :commit_id, inverse_of: :pipeline @@ -102,6 +102,7 @@ module Ci has_one :chat_data, class_name: 'Ci::PipelineChatData' has_many :triggered_pipelines, through: :sourced_pipelines, source: :pipeline + # Only includes direct and not nested children has_many :child_pipelines, -> { merge(Ci::Sources::Pipeline.same_project) }, through: :sourced_pipelines, source: :pipeline has_one :triggered_by_pipeline, through: :source_pipeline, source: :source_pipeline has_one :parent_pipeline, -> { merge(Ci::Sources::Pipeline.same_project) }, through: :source_pipeline, source: :source_pipeline @@ -389,7 +390,7 @@ module Ci end def self.latest_status(ref = nil) - newest_first(ref: ref).pluck(:status).first + newest_first(ref: ref).pick(:status) end def self.latest_successful_for_ref(ref) @@ -592,26 +593,20 @@ module Ci canceled? && auto_canceled_by_id? end - def cancel_running(retries: 1) - preloaded_relations = [:project, :pipeline, :deployment, :taggings] - - retry_lock(cancelable_statuses, retries, name: 'ci_pipeline_cancel_running') do |cancelables| - cancelables.find_in_batches do |batch| - Preloaders::CommitStatusPreloader.new(batch).execute(preloaded_relations) - - batch.each do |job| - yield(job) if block_given? - job.cancel - end - end - end - end + # Cancel a pipelines cancelable jobs and optionally it's child pipelines cancelable jobs + # retries - # of times to retry if errors + # cascade_to_children - if true cancels all related child pipelines for parent child pipelines + # auto_canceled_by_pipeline_id - store the pipeline_id of the pipeline that triggered cancellation + # execute_async - if true cancel the children asyncronously + def cancel_running(retries: 1, cascade_to_children: true, auto_canceled_by_pipeline_id: nil, execute_async: true) + update(auto_canceled_by_id: auto_canceled_by_pipeline_id) if auto_canceled_by_pipeline_id - def auto_cancel_running(pipeline, retries: 1) - update(auto_canceled_by: pipeline) + cancel_jobs(cancelable_statuses, retries: retries, auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id) - cancel_running(retries: retries) do |job| - job.auto_canceled_by = pipeline + if cascade_to_children + # cancel any bridges that could spin up new child pipelines + cancel_jobs(bridges_in_self_and_descendants.cancelable, retries: retries, auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id) + cancel_children(auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id, execute_async: execute_async) end end @@ -953,6 +948,10 @@ module Ci Ci::Build.latest.where(pipeline: self_and_descendants) end + def bridges_in_self_and_descendants + Ci::Bridge.latest.where(pipeline: self_and_descendants) + end + def environments_in_self_and_descendants(deployment_status: nil) # We limit to 100 unique environments for application safety. # See: https://gitlab.com/gitlab-org/gitlab/-/issues/340781#note_699114700 @@ -986,6 +985,11 @@ module Ci object_hierarchy(project_condition: :same).base_and_descendants end + # With only parent-child pipelines + def all_child_pipelines + object_hierarchy(project_condition: :same).descendants + end + def self_and_descendants_complete? self_and_descendants.all?(&:complete?) end @@ -1152,6 +1156,10 @@ module Ci end end + def modified_paths_since(compare_to_sha) + project.repository.diff_stats(project.repository.merge_base(compare_to_sha, sha), sha).paths + end + def all_worktree_paths strong_memoize(:all_worktree_paths) do project.repository.ls_files(sha) @@ -1216,10 +1224,6 @@ module Ci stages.find_by(name: name) end - def find_stage_by_name!(name) - stages.find_by!(name: name) - end - def full_error_messages errors ? errors.full_messages.to_sentence : "" end @@ -1321,6 +1325,42 @@ module Ci private + def cancel_jobs(jobs, retries: 1, auto_canceled_by_pipeline_id: nil) + retry_lock(jobs, retries, name: 'ci_pipeline_cancel_running') do |statuses| + preloaded_relations = [:project, :pipeline, :deployment, :taggings] + + statuses.find_in_batches do |status_batch| + relation = CommitStatus.where(id: status_batch) + Preloaders::CommitStatusPreloader.new(relation).execute(preloaded_relations) + + relation.each do |job| + job.auto_canceled_by_id = auto_canceled_by_pipeline_id if auto_canceled_by_pipeline_id + job.cancel + end + end + end + end + + # For parent child-pipelines only (not multi-project) + def cancel_children(auto_canceled_by_pipeline_id: nil, execute_async: true) + all_child_pipelines.each do |child_pipeline| + if execute_async + ::Ci::CancelPipelineWorker.perform_async( + child_pipeline.id, + auto_canceled_by_pipeline_id + ) + else + child_pipeline.cancel_running( + # cascade_to_children is false because we iterate through children + # we also cancel bridges prior to prevent more children + cascade_to_children: false, + execute_async: execute_async, + auto_canceled_by_pipeline_id: auto_canceled_by_pipeline_id + ) + end + end + end + def add_message(severity, content) messages.build(severity: severity, content: content) end diff --git a/app/models/ci/processable.rb b/app/models/ci/processable.rb index f666629c8fd..a2ff49077be 100644 --- a/app/models/ci/processable.rb +++ b/app/models/ci/processable.rb @@ -101,7 +101,7 @@ module Ci :merge_train_pipeline?, to: :pipeline - def clone(current_user:) + def clone(current_user:, new_job_variables_attributes: []) new_attributes = self.class.clone_accessors.to_h do |attribute| [attribute, public_send(attribute)] # rubocop:disable GitlabSecurity/PublicSend end diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index f41ad890184..6c3754d84d0 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -15,7 +15,7 @@ module Ci include Presentable include EachBatch - ignore_column :semver, remove_with: '15.3', remove_after: '2022-07-22' + ignore_column :semver, remove_with: '15.4', remove_after: '2022-08-22' add_authentication_token_field :token, encrypted: :optional, expires_at: :compute_token_expiration, expiration_enforced?: :token_expiration_enforced? @@ -437,7 +437,12 @@ module Ci cache_attributes(values) # We save data without validation, it will always change due to `contacted_at` - self.update_columns(values) if persist_cached_data? + if persist_cached_data? + version_updated = values.include?(:version) && values[:version] != version + + update_columns(values) + schedule_runner_version_update if version_updated + end end end @@ -477,7 +482,7 @@ module Ci private scope :with_upgrade_status, ->(upgrade_status) do - Ci::Runner.joins(:runner_version).where(runner_version: { status: upgrade_status }) + joins(:runner_version).where(runner_version: { status: upgrade_status }) end EXECUTOR_NAME_TO_TYPES = { @@ -565,6 +570,12 @@ module Ci errors.add(:runner, 'needs to be assigned to exactly one group') end end + + def schedule_runner_version_update + return unless version + + Ci::Runners::ProcessRunnerVersionUpdateWorker.perform_async(version) + end end end diff --git a/app/models/ci/runner_version.rb b/app/models/ci/runner_version.rb index 6b2d0060c9b..bbde98ee591 100644 --- a/app/models/ci/runner_version.rb +++ b/app/models/ci/runner_version.rb @@ -8,7 +8,6 @@ module Ci enum_with_nil status: { not_processed: nil, invalid_version: -1, - unknown: 0, not_available: 1, available: 2, recommended: 3 @@ -16,7 +15,6 @@ module Ci STATUS_DESCRIPTIONS = { invalid_version: 'Runner version is not valid.', - unknown: 'Upgrade status is unknown.', not_available: 'Upgrade is not available for the runner.', available: 'Upgrade is available for the runner.', recommended: 'Upgrade is available and recommended for the runner.' @@ -27,7 +25,7 @@ module Ci # This scope returns all versions that might need recalculating. For instance, once a version is considered # :recommended, it normally doesn't change status even if the instance is upgraded - scope :potentially_outdated, -> { where(status: [nil, :not_available, :available, :unknown]) } + scope :potentially_outdated, -> { where(status: [nil, :not_available, :available]) } validates :version, length: { maximum: 2048 } end diff --git a/app/models/ci/secure_file.rb b/app/models/ci/secure_file.rb index 078b05ff779..9a35f1876c9 100644 --- a/app/models/ci/secure_file.rb +++ b/app/models/ci/secure_file.rb @@ -3,11 +3,8 @@ module Ci class SecureFile < Ci::ApplicationRecord include FileStoreMounter - include IgnorableColumns include Limitable - ignore_column :permissions, remove_with: '15.2', remove_after: '2022-06-22' - FILE_SIZE_LIMIT = 5.megabytes.freeze CHECKSUM_ALGORITHM = 'sha256' @@ -24,6 +21,7 @@ module Ci before_validation :assign_checksum scope :order_by_created_at, -> { order(created_at: :desc) } + scope :project_id_in, ->(ids) { where(project_id: ids) } default_value_for(:file_store) { Ci::SecureFileUploader.default_store } @@ -46,3 +44,5 @@ module Ci end end end + +Ci::SecureFile.prepend_mod |