Class: Ci::JobArtifact
- Inherits:
-
ApplicationRecord
show all
- Includes:
- AfterCommitQueue, Artifactable, Lockable, Partitionable, EachBatch, FileStoreMounter, Gitlab::Utils::StrongMemoize, IgnorableColumns, SafelyChangeColumnDefault, Sortable, UpdateProjectStatistics, UsageStatistics
- Defined in:
- app/models/ci/job_artifact.rb
Constant Summary
collapse
- NON_ERASABLE_FILE_TYPES =
%w[trace].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]
}.freeze
- DEFAULT_FILE_NAMES =
{
archive: nil,
metadata: nil,
trace: nil,
metrics_referee: nil,
network_referee: nil,
junit: 'junit.xml',
accessibility: 'gl-accessibility.json',
codequality: 'gl-code-quality-report.json',
sast: 'gl-sast-report.json',
secret_detection: 'gl-secret-detection-report.json',
dependency_scanning: 'gl-dependency-scanning-report.json',
container_scanning: 'gl-container-scanning-report.json',
cluster_image_scanning: 'gl-cluster-image-scanning-report.json',
dast: 'gl-dast-report.json',
license_scanning: 'gl-license-scanning-report.json',
performance: 'performance.json',
browser_performance: 'browser-performance.json',
load_performance: 'load-performance.json',
metrics: 'metrics.txt',
lsif: 'lsif.json',
dotenv: '.env',
cobertura: 'cobertura-coverage.xml',
terraform: 'tfplan.json',
cluster_applications: 'gl-cluster-applications.json', requirements: 'requirements.json', requirements_v2: 'requirements_v2.json',
coverage_fuzzing: 'gl-coverage-fuzzing.json',
api_fuzzing: 'gl-api-fuzzing-report.json',
cyclonedx: 'gl-sbom.cdx.json',
annotations: 'gl-annotations.json'
}.freeze
- INTERNAL_TYPES =
{
archive: :zip,
metadata: :gzip,
trace: :raw
}.freeze
- REPORT_TYPES =
{
junit: :gzip,
metrics: :gzip,
metrics_referee: :gzip,
network_referee: :gzip,
dotenv: :gzip,
cobertura: :gzip,
cluster_applications: :gzip, lsif: :zip,
cyclonedx: :gzip,
annotations: :gzip,
sast: :raw,
secret_detection: :raw,
dependency_scanning: :raw,
container_scanning: :raw,
cluster_image_scanning: :raw,
dast: :raw,
license_scanning: :raw,
accessibility: :raw,
codequality: :raw,
performance: :raw,
browser_performance: :raw,
load_performance: :raw,
terraform: :raw,
requirements: :raw,
requirements_v2: :raw,
coverage_fuzzing: :raw,
api_fuzzing: :raw
}.freeze
- DOWNLOADABLE_TYPES =
%w[
accessibility
api_fuzzing
archive
cobertura
codequality
container_scanning
dast
dependency_scanning
dotenv
junit
license_scanning
lsif
metrics
performance
browser_performance
load_performance
sast
secret_detection
requirements
requirements_v2
cluster_image_scanning
cyclonedx
].freeze
- TYPE_AND_FORMAT_PAIRS =
INTERNAL_TYPES.merge(REPORT_TYPES).freeze
- PLAN_LIMIT_PREFIX =
'ci_max_artifact_size_'
FileStoreMounter::ALLOWED_FILE_FIELDS
Artifactable::FILE_FORMAT_ADAPTERS, Artifactable::NotSupportedAdapterError, Artifactable::STORE_COLUMN
Partitionable::MUTEX
ApplicationRecord::MAX_PLUCK
ResetOnUnionError::MAX_RESET_PERIOD
Class Method Summary
collapse
Instance Method Summary
collapse
#each_blob
#log_artifacts_context, #log_artifacts_filesize, #log_build_dependencies, log_created, log_deleted
#run_after_commit, #run_after_commit_or_now
model_name, table_name_prefix
cached_column_list, #create_or_load_association, declarative_enum, default_select_columns, id_in, id_not_in, iid_in, pluck_primary_key, primary_key_in, #readable_by?, safe_ensure_unique, safe_find_or_create_by, safe_find_or_create_by!, #to_ability_name, underscore, where_exists, where_not_exists, with_fast_read_statement_timeout, without_order
#serializable_hash
Class Method Details
.archived_trace_exists_for?(job_id) ⇒ Boolean
331
332
333
|
# File 'app/models/ci/job_artifact.rb', line 331
def self.archived_trace_exists_for?(job_id)
where(job_id: job_id).trace.take&.stored?
end
|
.artifacts_size_for(project) ⇒ Object
274
275
276
|
# File 'app/models/ci/job_artifact.rb', line 274
def self.artifacts_size_for(project)
self.where(project: project).sum(:size)
end
|
.associated_file_types_for(file_type) ⇒ Object
260
261
262
263
264
|
# File 'app/models/ci/job_artifact.rb', line 260
def self.associated_file_types_for(file_type)
return unless file_types.include?(file_type)
[file_type]
end
|
.begin_fast_destroy ⇒ Object
FastDestroyAll concerns rubocop: disable CodeReuse/ServiceClass
.erasable_file_types ⇒ Object
266
267
268
|
# File 'app/models/ci/job_artifact.rb', line 266
def self.erasable_file_types
self.file_types.keys - NON_ERASABLE_FILE_TYPES
end
|
.file_types_for_report(report_type) ⇒ Object
256
257
258
|
# File 'app/models/ci/job_artifact.rb', line 256
def self.file_types_for_report(report_type)
REPORT_FILE_TYPES.fetch(report_type) { raise ArgumentError, "Unrecognized report type: #{report_type}" }
end
|
.finalize_fast_destroy(service) ⇒ Object
294
295
296
|
# File 'app/models/ci/job_artifact.rb', line 294
def self.finalize_fast_destroy(service)
service.update_statistics
end
|
.max_artifact_size(type:, project:) ⇒ Object
335
336
337
338
339
340
341
342
343
344
|
# File 'app/models/ci/job_artifact.rb', line 335
def self.max_artifact_size(type:, project:)
limit_name = "#{PLAN_LIMIT_PREFIX}#{type}"
max_size = project.actual_limits.limit_for(
limit_name,
alternate_limit: -> { project.closest_setting(:max_artifacts_size) }
)
max_size&.megabytes.to_i
end
|
.of_report_type(report_type) ⇒ Object
250
251
252
253
254
|
# File 'app/models/ci/job_artifact.rb', line 250
def self.of_report_type(report_type)
file_types = file_types_for_report(report_type)
with_file_types(file_types)
end
|
.pluck_job_id ⇒ Object
278
279
280
|
# File 'app/models/ci/job_artifact.rb', line 278
def self.pluck_job_id
pluck(:job_id)
end
|
.total_size ⇒ Object
270
271
272
|
# File 'app/models/ci/job_artifact.rb', line 270
def self.total_size
self.sum(:size)
end
|
Instance Method Details
#expire_in ⇒ Object
316
317
318
|
# File 'app/models/ci/job_artifact.rb', line 316
def expire_in
expire_at - Time.current if expire_at
end
|
#expire_in=(value) ⇒ Object
#expired? ⇒ Boolean
308
309
310
|
# File 'app/models/ci/job_artifact.rb', line 308
def expired?
expire_at.present? && expire_at < Time.current
end
|
#expiring? ⇒ Boolean
312
313
314
|
# File 'app/models/ci/job_artifact.rb', line 312
def expiring?
expire_at.present? && expire_at > Time.current
end
|
#hashed_path? ⇒ Boolean
302
303
304
305
306
|
# File 'app/models/ci/job_artifact.rb', line 302
def hashed_path?
return true if trace?
super || self.file_location.nil?
end
|
#local_store? ⇒ Boolean
298
299
300
|
# File 'app/models/ci/job_artifact.rb', line 298
def local_store?
[nil, ::JobArtifactUploader::Store::LOCAL].include?(self.file_store)
end
|
#public_access? ⇒ Boolean
367
368
369
370
371
|
# File 'app/models/ci/job_artifact.rb', line 367
def public_access?
return true unless Feature.enabled?(:non_public_artifacts, type: :development)
public_accessibility?
end
|
#store_after_commit? ⇒ Boolean
361
362
363
364
365
|
# File 'app/models/ci/job_artifact.rb', line 361
def store_after_commit?
strong_memoize(:store_after_commit) do
trace? && JobArtifactUploader.direct_upload_enabled?
end
end
|
#stored? ⇒ Boolean
327
328
329
|
# File 'app/models/ci/job_artifact.rb', line 327
def stored?
file&.file&.exists?
end
|
#to_deleted_object_attrs(pick_up_at = nil) ⇒ Object
346
347
348
349
350
351
352
353
354
355
356
357
358
359
|
# File 'app/models/ci/job_artifact.rb', line 346
def to_deleted_object_attrs(pick_up_at = nil)
final_path_store_dir, final_path_filename = nil
if file_final_path.present?
final_path_store_dir = File.dirname(file_final_path)
final_path_filename = File.basename(file_final_path)
end
{
file_store: file_store,
store_dir: final_path_store_dir || file.store_dir.to_s,
file: final_path_filename || file_identifier,
pick_up_at: pick_up_at || expire_at || Time.current
}
end
|
244
245
246
247
248
|
# File 'app/models/ci/job_artifact.rb', line 244
def validate_file_format!
unless TYPE_AND_FORMAT_PAIRS[self.file_type&.to_sym] == self.file_format&.to_sym
errors.add(:base, _('Invalid file format with specified file type'))
end
end
|