diff options
Diffstat (limited to 'app/models/ci')
-rw-r--r-- | app/models/ci/build.rb | 26 | ||||
-rw-r--r-- | app/models/ci/build_need.rb | 1 | ||||
-rw-r--r-- | app/models/ci/build_report_result.rb | 4 | ||||
-rw-r--r-- | app/models/ci/daily_build_group_report_result.rb | 14 | ||||
-rw-r--r-- | app/models/ci/deleted_object.rb | 4 | ||||
-rw-r--r-- | app/models/ci/group.rb | 2 | ||||
-rw-r--r-- | app/models/ci/group_variable.rb | 4 | ||||
-rw-r--r-- | app/models/ci/job_artifact.rb | 10 | ||||
-rw-r--r-- | app/models/ci/legacy_stage.rb | 2 | ||||
-rw-r--r-- | app/models/ci/pipeline.rb | 33 | ||||
-rw-r--r-- | app/models/ci/processable.rb | 4 | ||||
-rw-r--r-- | app/models/ci/ref.rb | 2 | ||||
-rw-r--r-- | app/models/ci/runner.rb | 40 | ||||
-rw-r--r-- | app/models/ci/runner_namespace.rb | 9 | ||||
-rw-r--r-- | app/models/ci/stage.rb | 4 | ||||
-rw-r--r-- | app/models/ci/variable.rb | 1 |
16 files changed, 92 insertions, 68 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index db151126caf..824e35a6480 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -486,6 +486,10 @@ module Ci self.options.fetch(:environment, {}).fetch(:action, 'start') if self.options end + def environment_deployment_tier + self.options.dig(:environment, :deployment_tier) if self.options + end + def outdated_deployment? success? && !deployment.try(:last?) end @@ -510,7 +514,6 @@ module Ci .concat(scoped_variables) .concat(job_variables) .concat(persisted_environment_variables) - .to_runner_variables end end @@ -523,6 +526,7 @@ module Ci .append(key: 'CI_JOB_ID', value: id.to_s) .append(key: 'CI_JOB_URL', value: Gitlab::Routing.url_helpers.project_job_url(project, self)) .append(key: 'CI_JOB_TOKEN', value: token.to_s, public: false, masked: true) + .append(key: 'CI_JOB_STARTED_AT', value: started_at&.iso8601) .append(key: 'CI_BUILD_ID', value: id.to_s) .append(key: 'CI_BUILD_TOKEN', value: token.to_s, public: false, masked: true) .append(key: 'CI_REGISTRY_USER', value: ::Gitlab::Auth::CI_JOB_USER) @@ -564,7 +568,10 @@ module Ci end def features - { trace_sections: true } + { + trace_sections: true, + failure_reasons: self.class.failure_reasons.keys + } end def merge_request @@ -691,7 +698,7 @@ module Ci end def any_runners_online? - project.any_runners? { |runner| runner.active? && runner.online? && runner.can_pick?(self) } + project.any_active_runners? { |runner| runner.match_build_if_online?(self) } end def stuck? @@ -810,14 +817,15 @@ module Ci end def cache - cache = options[:cache] + cache = Array.wrap(options[:cache]) - if cache && project.jobs_cache_index - cache = cache.merge( - key: "#{cache[:key]}-#{project.jobs_cache_index}") + if project.jobs_cache_index + cache = cache.map do |single_cache| + single_cache.merge(key: "#{single_cache[:key]}-#{project.jobs_cache_index}") + end end - [cache] + cache end def credentials @@ -983,7 +991,7 @@ module Ci # TODO: Have `debug_mode?` check against data on sent back from runner # to capture all the ways that variables can be set. # See (https://gitlab.com/gitlab-org/gitlab/-/issues/290955) - variables.any? { |variable| variable[:key] == 'CI_DEBUG_TRACE' && variable[:value].casecmp('true') == 0 } + variables['CI_DEBUG_TRACE']&.value&.casecmp('true') == 0 end def drop_with_exit_code!(failure_reason, exit_code) diff --git a/app/models/ci/build_need.rb b/app/models/ci/build_need.rb index fac615f97b9..7bc70f9f1e1 100644 --- a/app/models/ci/build_need.rb +++ b/app/models/ci/build_need.rb @@ -10,6 +10,7 @@ module Ci validates :build, presence: true validates :name, presence: true, length: { maximum: 128 } + validates :optional, inclusion: { in: [true, false] } scope :scoped_build, -> { where('ci_builds.id=ci_build_needs.build_id') } scope :artifacts, -> { where(artifacts: true) } diff --git a/app/models/ci/build_report_result.rb b/app/models/ci/build_report_result.rb index 530233ad5c0..eb6a0700006 100644 --- a/app/models/ci/build_report_result.rb +++ b/app/models/ci/build_report_result.rb @@ -38,6 +38,10 @@ module Ci tests.dig("skipped").to_i end + def suite_error + tests.dig("suite_error") + end + def tests_total [tests_success, tests_failed, tests_errored, tests_skipped].sum end diff --git a/app/models/ci/daily_build_group_report_result.rb b/app/models/ci/daily_build_group_report_result.rb index 23c96e63724..5dcf575abd7 100644 --- a/app/models/ci/daily_build_group_report_result.rb +++ b/app/models/ci/daily_build_group_report_result.rb @@ -4,7 +4,6 @@ module Ci class DailyBuildGroupReportResult < ApplicationRecord extend Gitlab::Ci::Model - REPORT_WINDOW = 90.days PARAM_TYPES = %w[coverage].freeze belongs_to :last_pipeline, class_name: 'Ci::Pipeline', foreign_key: :last_pipeline_id @@ -13,13 +12,11 @@ module Ci validates :data, json_schema: { filename: "daily_build_group_report_result_data" } - scope :with_included_projects, -> { includes(:project) } scope :by_ref_path, -> (ref_path) { where(ref_path: ref_path) } scope :by_projects, -> (ids) { where(project_id: ids) } scope :by_group, -> (group_id) { where(group_id: group_id) } scope :with_coverage, -> { where("(data->'coverage') IS NOT NULL") } scope :with_default_branch, -> { where(default_branch: true) } - scope :by_date, -> (start_date) { where(date: report_window(start_date)..Date.current) } scope :by_dates, -> (start_date, end_date) { where(date: start_date..end_date) } scope :ordered_by_date_and_group_name, -> { order(date: :desc, group_name: :asc) } @@ -29,17 +26,6 @@ module Ci def upsert_reports(data) upsert_all(data, unique_by: :index_daily_build_group_report_results_unique_columns) if data.any? end - - def recent_results(attrs, limit: nil) - where(attrs).order(date: :desc, group_name: :asc).limit(limit) - end - - def report_window(start_date) - default_date = REPORT_WINDOW.ago.to_date - date = Date.parse(start_date) rescue default_date - - [date, default_date].max - end end end end diff --git a/app/models/ci/deleted_object.rb b/app/models/ci/deleted_object.rb index e74946eda16..2942a153e05 100644 --- a/app/models/ci/deleted_object.rb +++ b/app/models/ci/deleted_object.rb @@ -17,9 +17,9 @@ module Ci .lock('FOR UPDATE SKIP LOCKED') end - def self.bulk_import(artifacts) + def self.bulk_import(artifacts, pick_up_at = nil) attributes = artifacts.each.with_object([]) do |artifact, accumulator| - record = artifact.to_deleted_object_attrs + record = artifact.to_deleted_object_attrs(pick_up_at) accumulator << record if record[:store_dir] && record[:file] end diff --git a/app/models/ci/group.rb b/app/models/ci/group.rb index c7c0ec61e62..4ba09fd8152 100644 --- a/app/models/ci/group.rb +++ b/app/models/ci/group.rb @@ -39,7 +39,7 @@ module Ci def status_struct strong_memoize(:status_struct) do Gitlab::Ci::Status::Composite - .new(@jobs) + .new(@jobs, project: project) end end diff --git a/app/models/ci/group_variable.rb b/app/models/ci/group_variable.rb index 1e1dd68ee6c..2928ce801ad 100644 --- a/app/models/ci/group_variable.rb +++ b/app/models/ci/group_variable.rb @@ -6,16 +6,18 @@ module Ci include Ci::HasVariable include Presentable include Ci::Maskable + prepend HasEnvironmentScope belongs_to :group, class_name: "::Group" alias_attribute :secret_value, :value validates :key, uniqueness: { - scope: :group_id, + scope: [:group_id, :environment_scope], message: "(%{value}) has already been taken" } scope :unprotected, -> { where(protected: false) } + scope :by_environment_scope, -> (environment_scope) { where(environment_scope: environment_scope) } end end diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index f927111758a..d5e88f2be5b 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -136,11 +136,7 @@ module Ci scope :for_sha, ->(sha, project_id) { joins(job: :pipeline).where(ci_pipelines: { sha: sha, project_id: project_id }) } scope :for_job_name, ->(name) { joins(:job).where(ci_builds: { name: name }) } - scope :with_job, -> do - if Feature.enabled?(:non_public_artifacts, type: :development) - joins(:job).includes(:job) - end - end + scope :with_job, -> { joins(:job).includes(:job) } scope :with_file_types, -> (file_types) do types = self.file_types.select { |file_type| file_types.include?(file_type) }.values @@ -311,12 +307,12 @@ module Ci max_size&.megabytes.to_i end - def to_deleted_object_attrs + def to_deleted_object_attrs(pick_up_at = nil) { file_store: file_store, store_dir: file.store_dir.to_s, file: file_identifier, - pick_up_at: expire_at || Time.current + pick_up_at: pick_up_at || expire_at || Time.current } end diff --git a/app/models/ci/legacy_stage.rb b/app/models/ci/legacy_stage.rb index df4368eccd5..ffd3d3fcd88 100644 --- a/app/models/ci/legacy_stage.rb +++ b/app/models/ci/legacy_stage.rb @@ -32,7 +32,7 @@ module Ci end def status - @status ||= statuses.latest.composite_status + @status ||= statuses.latest.composite_status(project: project) end def detailed_status(current_user) diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 3be107ea2e1..b63ec0c8a97 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -228,7 +228,7 @@ module Ci pipeline.run_after_commit do PipelineHooksWorker.perform_async(pipeline.id) - ExpirePipelineCacheWorker.perform_async(pipeline.id) if pipeline.cacheable? + ExpirePipelineCacheWorker.perform_async(pipeline.id) end end @@ -573,7 +573,7 @@ module Ci end def cancel_running(retries: nil) - retry_optimistic_lock(cancelable_statuses, retries) do |cancelable| + retry_optimistic_lock(cancelable_statuses, retries, name: 'ci_pipeline_cancel_running') do |cancelable| cancelable.find_each do |job| yield(job) if block_given? job.cancel @@ -693,14 +693,6 @@ module Ci .exists? end - # TODO: this logic is duplicate with Pipeline::Chain::Config::Content - # we should persist this is `ci_pipelines.config_path` - def config_path - return unless repository_source? || unknown_source? - - project.ci_config_path_or_default - end - def has_yaml_errors? yaml_errors.present? end @@ -744,7 +736,7 @@ module Ci end def set_status(new_status) - retry_optimistic_lock(self) do + retry_optimistic_lock(self, name: 'ci_pipeline_set_status') do case new_status when 'created' then nil when 'waiting_for_resource' then request_resource @@ -785,8 +777,7 @@ module Ci Gitlab::Ci::Variables::Collection.new.tap do |variables| variables.append(key: 'CI_PIPELINE_IID', value: iid.to_s) variables.append(key: 'CI_PIPELINE_SOURCE', value: source.to_s) - - variables.append(key: 'CI_CONFIG_PATH', value: config_path) + variables.append(key: 'CI_PIPELINE_CREATED_AT', value: created_at&.iso8601) variables.concat(predefined_commit_variables) @@ -938,6 +929,12 @@ module Ci .first end + def self_with_ancestors_and_descendants(same_project: false) + ::Gitlab::Ci::PipelineObjectHierarchy + .new(self.class.unscoped.where(id: id), options: { same_project: same_project }) + .all_objects + end + def bridge_triggered? source_bridge.present? end @@ -1117,7 +1114,7 @@ module Ci detached_merge_request_pipeline? && !merge_request_ref? end - def merge_request_pipeline? + def merged_result_pipeline? merge_request? && target_sha.present? end @@ -1157,7 +1154,7 @@ module Ci return unless merge_request? strong_memoize(:merge_request_event_type) do - if merge_request_pipeline? + if merged_result_pipeline? :merged_result elsif detached_merge_request_pipeline? :detached @@ -1169,10 +1166,6 @@ module Ci @persistent_ref ||= PersistentRef.new(pipeline: self) end - def cacheable? - !dangling? - end - def dangling? Enums::Ci::Pipeline.dangling_sources.key?(source.to_sym) end @@ -1247,7 +1240,7 @@ module Ci def merge_request_diff_sha return unless merge_request? - if merge_request_pipeline? + if merged_result_pipeline? source_sha else sha diff --git a/app/models/ci/processable.rb b/app/models/ci/processable.rb index fae65ed0632..0ad1ed2fce8 100644 --- a/app/models/ci/processable.rb +++ b/app/models/ci/processable.rb @@ -120,10 +120,6 @@ module Ci raise NotImplementedError end - def scoped_variables_hash - raise NotImplementedError - end - override :all_met_to_become_pending? def all_met_to_become_pending? super && !with_resource_group? diff --git a/app/models/ci/ref.rb b/app/models/ci/ref.rb index 713a0bf9c45..3d71a5f2c96 100644 --- a/app/models/ci/ref.rb +++ b/app/models/ci/ref.rb @@ -62,7 +62,7 @@ module Ci end def update_status_by!(pipeline) - retry_lock(self) do + retry_lock(self, name: 'ci_ref_update_status_by') do next unless last_finished_pipeline_id == pipeline.id case pipeline.status diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 44a00e36bcc..d1a20bc93c3 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -9,6 +9,7 @@ module Ci include FromUnion include TokenAuthenticatable include IgnorableColumns + include FeatureGate add_authentication_token_field :token, encrypted: -> { Feature.enabled?(:ci_runners_tokens_optional_encryption, default_enabled: true) ? :optional : :required } @@ -251,10 +252,21 @@ module Ci runner_projects.any? end + # TODO: remove this method in favor of `matches_build?` once feature flag is removed + # https://gitlab.com/gitlab-org/gitlab/-/issues/323317 def can_pick?(build) - return false if self.ref_protected? && !build.protected? + if Feature.enabled?(:ci_runners_short_circuit_assignable_for, self, default_enabled: :yaml) + matches_build?(build) + else + # Run `matches_build?` checks before, since they are cheaper than + # `assignable_for?`. + # + matches_build?(build) && assignable_for?(build.project_id) + end + end - assignable_for?(build.project_id) && accepting_tags?(build) + def match_build_if_online?(build) + active? && online? && can_pick?(build) end def only_for?(project) @@ -265,6 +277,16 @@ module Ci token[0...8] if token end + def tag_list + return super unless Feature.enabled?(:ci_preload_runner_tags, default_enabled: :yaml) + + if tags.loaded? + tags.map(&:name) + else + super + end + end + def has_tags? tag_list.any? end @@ -304,8 +326,10 @@ module Ci end def pick_build!(build) - if can_pick?(build) - tick_runner_queue + if Feature.enabled?(:ci_reduce_queries_when_ticking_runner_queue, self, default_enabled: :yaml) + tick_runner_queue if matches_build?(build) + else + tick_runner_queue if can_pick?(build) end end @@ -341,6 +365,8 @@ module Ci end end + # TODO: remove this method once feature flag ci_runners_short_circuit_assignable_for + # is removed. https://gitlab.com/gitlab-org/gitlab/-/issues/323317 def assignable_for?(project_id) self.class.owned_or_instance_wide(project_id).where(id: self.id).any? end @@ -369,6 +395,12 @@ module Ci end end + def matches_build?(build) + return false if self.ref_protected? && !build.protected? + + accepting_tags?(build) + end + def accepting_tags?(build) (run_untagged? || build.has_tags?) && (build.tag_list - tag_list).empty? end diff --git a/app/models/ci/runner_namespace.rb b/app/models/ci/runner_namespace.rb index 6903e8a21a1..e6c1899c89d 100644 --- a/app/models/ci/runner_namespace.rb +++ b/app/models/ci/runner_namespace.rb @@ -4,10 +4,17 @@ module Ci class RunnerNamespace < ApplicationRecord extend Gitlab::Ci::Model - belongs_to :runner, inverse_of: :runner_namespaces, validate: true + belongs_to :runner, inverse_of: :runner_namespaces belongs_to :namespace, inverse_of: :runner_namespaces, class_name: '::Namespace' belongs_to :group, class_name: '::Group', foreign_key: :namespace_id validates :runner_id, uniqueness: { scope: :namespace_id } + validate :group_runner_type + + private + + def group_runner_type + errors.add(:runner, 'is not a group runner') unless runner&.group_type? + end end end diff --git a/app/models/ci/stage.rb b/app/models/ci/stage.rb index ae80692d598..03a97355574 100644 --- a/app/models/ci/stage.rb +++ b/app/models/ci/stage.rb @@ -84,7 +84,7 @@ module Ci end def set_status(new_status) - retry_optimistic_lock(self) do + retry_optimistic_lock(self, name: 'ci_stage_set_status') do case new_status when 'created' then nil when 'waiting_for_resource' then request_resource @@ -138,7 +138,7 @@ module Ci end def latest_stage_status - statuses.latest.composite_status || 'skipped' + statuses.latest.composite_status(project: project) || 'skipped' end end end diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb index 13358b95a47..84505befc5c 100644 --- a/app/models/ci/variable.rb +++ b/app/models/ci/variable.rb @@ -18,7 +18,6 @@ module Ci } scope :unprotected, -> { where(protected: false) } - scope :by_key, -> (key) { where(key: key) } scope :by_environment_scope, -> (environment_scope) { where(environment_scope: environment_scope) } end end |