diff options
Diffstat (limited to 'app/models/ci')
-rw-r--r-- | app/models/ci/build.rb | 34 | ||||
-rw-r--r-- | app/models/ci/build_metadata.rb | 35 | ||||
-rw-r--r-- | app/models/ci/group_variable.rb | 2 | ||||
-rw-r--r-- | app/models/ci/job_artifact.rb | 10 | ||||
-rw-r--r-- | app/models/ci/pipeline.rb | 26 | ||||
-rw-r--r-- | app/models/ci/pipeline_schedule_variable.rb | 2 | ||||
-rw-r--r-- | app/models/ci/runner.rb | 9 | ||||
-rw-r--r-- | app/models/ci/variable.rb | 2 |
8 files changed, 103 insertions, 17 deletions
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb index 1e066b69c6e..ed02af05e3d 100644 --- a/app/models/ci/build.rb +++ b/app/models/ci/build.rb @@ -3,6 +3,7 @@ module Ci prepend ArtifactMigratable include TokenAuthenticatable include AfterCommitQueue + include ObjectStorage::BackgroundMove include Presentable include Importable @@ -23,6 +24,10 @@ module Ci has_one :job_artifacts_metadata, -> { where(file_type: Ci::JobArtifact.file_types[:metadata]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id has_one :job_artifacts_trace, -> { where(file_type: Ci::JobArtifact.file_types[:trace]) }, class_name: 'Ci::JobArtifact', inverse_of: :job, foreign_key: :job_id + has_one :metadata, class_name: 'Ci::BuildMetadata' + + delegate :timeout, to: :metadata, prefix: true, allow_nil: true + # The "environment" field for builds is a String, and is the unexpanded name def persisted_environment @persisted_environment ||= Environment.find_by( @@ -45,6 +50,7 @@ module Ci where('(artifacts_file IS NOT NULL AND artifacts_file <> ?) OR EXISTS (?)', '', Ci::JobArtifact.select(1).where('ci_builds.id = ci_job_artifacts.job_id').archive) end + scope :with_artifacts_stored_locally, -> { with_artifacts_archive.where(artifacts_file_store: [nil, LegacyArtifactUploader::Store::LOCAL]) } scope :with_artifacts_not_expired, ->() { with_artifacts_archive.where('artifacts_expire_at IS NULL OR artifacts_expire_at > ?', Time.now) } scope :with_expired_artifacts, ->() { with_artifacts_archive.where('artifacts_expire_at < ?', Time.now) } scope :last_month, ->() { where('created_at > ?', Date.today - 1.month) } @@ -151,6 +157,14 @@ module Ci before_transition any => [:running] do |build| build.validates_dependencies! unless Feature.enabled?('ci_disable_validates_dependencies') end + + before_transition pending: :running do |build| + build.ensure_metadata.update_timeout_state + end + end + + def ensure_metadata + metadata || build_metadata(project: project) end def detailed_status(current_user) @@ -229,10 +243,6 @@ module Ci latest_builds.where('stage_idx < ?', stage_idx) end - def timeout - project.build_timeout - end - def triggered_by?(current_user) user == current_user end @@ -365,13 +375,19 @@ module Ci project.running_or_pending_build_count(force: true) end + def browsable_artifacts? + artifacts_metadata? + end + def artifacts_metadata_entry(path, **options) - metadata = Gitlab::Ci::Build::Artifacts::Metadata.new( - artifacts_metadata.path, - path, - **options) + artifacts_metadata.use_file do |metadata_path| + metadata = Gitlab::Ci::Build::Artifacts::Metadata.new( + metadata_path, + path, + **options) - metadata.to_entry + metadata.to_entry + end end def erase_artifacts! diff --git a/app/models/ci/build_metadata.rb b/app/models/ci/build_metadata.rb new file mode 100644 index 00000000000..96762f8845c --- /dev/null +++ b/app/models/ci/build_metadata.rb @@ -0,0 +1,35 @@ +module Ci + # The purpose of this class is to store Build related data that can be disposed. + # Data that should be persisted forever, should be stored with Ci::Build model. + class BuildMetadata < ActiveRecord::Base + extend Gitlab::Ci::Model + include Presentable + include ChronicDurationAttribute + + self.table_name = 'ci_builds_metadata' + + belongs_to :build, class_name: 'Ci::Build' + belongs_to :project + + validates :build, presence: true + validates :project, presence: true + + chronic_duration_attr_reader :timeout_human_readable, :timeout + + enum timeout_source: { + unknown_timeout_source: 1, + project_timeout_source: 2, + runner_timeout_source: 3 + } + + def update_timeout_state + return unless build.runner.present? + + project_timeout = project&.build_timeout + timeout = [project_timeout, build.runner.maximum_timeout].compact.min + timeout_source = timeout < project_timeout ? :runner_timeout_source : :project_timeout_source + + update(timeout: timeout, timeout_source: timeout_source) + end + end +end diff --git a/app/models/ci/group_variable.rb b/app/models/ci/group_variable.rb index 1dd0e050ba9..62d768cc6cf 100644 --- a/app/models/ci/group_variable.rb +++ b/app/models/ci/group_variable.rb @@ -6,6 +6,8 @@ module Ci belongs_to :group + alias_attribute :secret_value, :value + validates :key, uniqueness: { scope: :group_id, message: "(%{value}) has already been taken" diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index 0a599f72bc7..df57b4f65e3 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -1,5 +1,7 @@ module Ci class JobArtifact < ActiveRecord::Base + include AfterCommitQueue + include ObjectStorage::BackgroundMove extend Gitlab::Ci::Model belongs_to :project @@ -7,9 +9,11 @@ module Ci before_save :set_size, if: :file_changed? + scope :with_files_stored_locally, -> { where(file_store: [nil, ::JobArtifactUploader::Store::LOCAL]) } + mount_uploader :file, JobArtifactUploader - delegate :open, :exists?, to: :file + delegate :exists?, :open, to: :file enum file_type: { archive: 1, @@ -21,6 +25,10 @@ module Ci self.where(project: project).sum(:size) end + def local_store? + [nil, ::JobArtifactUploader::Store::LOCAL].include?(self.file_store) + end + def set_size self.size = file.size end diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb index 44f9bdf111e..434b9b64c65 100644 --- a/app/models/ci/pipeline.rb +++ b/app/models/ci/pipeline.rb @@ -6,6 +6,7 @@ module Ci include AfterCommitQueue include Presentable include Gitlab::OptimisticLocking + include Gitlab::Utils::StrongMemoize belongs_to :project, inverse_of: :pipelines belongs_to :user @@ -361,21 +362,23 @@ module Ci def stage_seeds return [] unless config_processor - @stage_seeds ||= config_processor.stage_seeds(self) + strong_memoize(:stage_seeds) do + seeds = config_processor.stages_attributes.map do |attributes| + Gitlab::Ci::Pipeline::Seed::Stage.new(self, attributes) + end + + seeds.select(&:included?) + end end def seeds_size - @seeds_size ||= stage_seeds.sum(&:size) + stage_seeds.sum(&:size) end def has_kubernetes_active? project.deployment_platform&.active? end - def has_stage_seeds? - stage_seeds.any? - end - def has_warnings? builds.latest.failed_but_allowed.any? end @@ -388,6 +391,9 @@ module Ci end end + ## + # TODO, setting yaml_errors should be moved to the pipeline creation chain. + # def config_processor return unless ci_yaml_file return @config_processor if defined?(@config_processor) @@ -472,6 +478,14 @@ module Ci end end + def protected_ref? + strong_memoize(:protected_ref) { project.protected_for?(ref) } + end + + def legacy_trigger + strong_memoize(:legacy_trigger) { trigger_requests.first } + end + def predefined_variables Gitlab::Ci::Variables::Collection.new .append(key: 'CI_PIPELINE_ID', value: id.to_s) diff --git a/app/models/ci/pipeline_schedule_variable.rb b/app/models/ci/pipeline_schedule_variable.rb index af989fb14b4..03df4e3e638 100644 --- a/app/models/ci/pipeline_schedule_variable.rb +++ b/app/models/ci/pipeline_schedule_variable.rb @@ -5,6 +5,8 @@ module Ci belongs_to :pipeline_schedule + alias_attribute :secret_value, :value + validates :key, uniqueness: { scope: :pipeline_schedule_id } end end diff --git a/app/models/ci/runner.rb b/app/models/ci/runner.rb index 7173f88f1c7..5a4c56ec0dc 100644 --- a/app/models/ci/runner.rb +++ b/app/models/ci/runner.rb @@ -3,12 +3,13 @@ module Ci extend Gitlab::Ci::Model include Gitlab::SQL::Pattern include RedisCacheable + include ChronicDurationAttribute RUNNER_QUEUE_EXPIRY_TIME = 60.minutes ONLINE_CONTACT_TIMEOUT = 1.hour UPDATE_DB_RUNNER_INFO_EVERY = 40.minutes AVAILABLE_SCOPES = %w[specific shared active paused online].freeze - FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level].freeze + FORM_EDITABLE = %i[description tag_list active run_untagged locked access_level maximum_timeout_human_readable].freeze has_many :builds has_many :runner_projects, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent @@ -51,6 +52,12 @@ module Ci cached_attr_reader :version, :revision, :platform, :architecture, :contacted_at, :ip_address + chronic_duration_attr :maximum_timeout_human_readable, :maximum_timeout + + validates :maximum_timeout, allow_nil: true, + numericality: { greater_than_or_equal_to: 600, + message: 'needs to be at least 10 minutes' } + # Searches for runners matching the given query. # # This method uses ILIKE on PostgreSQL and LIKE on MySQL. diff --git a/app/models/ci/variable.rb b/app/models/ci/variable.rb index 7c71291de84..452cb910bca 100644 --- a/app/models/ci/variable.rb +++ b/app/models/ci/variable.rb @@ -6,6 +6,8 @@ module Ci belongs_to :project + alias_attribute :secret_value, :value + validates :key, uniqueness: { scope: [:project_id, :environment_scope], message: "(%{value}) has already been taken" |