diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-07-06 18:08:42 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-07-06 18:08:42 +0300 |
commit | ce06ce825b9ef5204a84aaa37d0dfc7742da5037 (patch) | |
tree | 2568846a1101580dd1b1f522526378bce7d1357f /app/services | |
parent | 9fc7cdf0b7a3c8c3528ec930f59fde110683d8fd (diff) |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/services')
-rw-r--r-- | app/services/ci/authorize_job_artifact_service.rb | 53 | ||||
-rw-r--r-- | app/services/ci/create_job_artifacts_service.rb | 116 |
2 files changed, 87 insertions, 82 deletions
diff --git a/app/services/ci/authorize_job_artifact_service.rb b/app/services/ci/authorize_job_artifact_service.rb deleted file mode 100644 index 893e92d427c..00000000000 --- a/app/services/ci/authorize_job_artifact_service.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: true - -module Ci - class AuthorizeJobArtifactService - include Gitlab::Utils::StrongMemoize - - # Max size of the zipped LSIF artifact - LSIF_ARTIFACT_MAX_SIZE = 20.megabytes - LSIF_ARTIFACT_TYPE = 'lsif' - - def initialize(job, params, max_size:) - @job = job - @max_size = max_size - @size = params[:filesize] - @type = params[:artifact_type].to_s - end - - def forbidden? - lsif? && !code_navigation_enabled? - end - - def too_large? - size && max_size <= size.to_i - end - - def headers - default_headers = JobArtifactUploader.workhorse_authorize(has_length: false, maximum_size: max_size) - default_headers.tap do |h| - h[:ProcessLsif] = true if lsif? && code_navigation_enabled? - end - end - - private - - attr_reader :job, :size, :type - - def code_navigation_enabled? - strong_memoize(:code_navigation_enabled) do - Feature.enabled?(:code_navigation, job.project, default_enabled: true) - end - end - - def lsif? - strong_memoize(:lsif) do - type == LSIF_ARTIFACT_TYPE - end - end - - def max_size - lsif? ? LSIF_ARTIFACT_MAX_SIZE : @max_size.to_i - end - end -end diff --git a/app/services/ci/create_job_artifacts_service.rb b/app/services/ci/create_job_artifacts_service.rb index f0ffe67510b..a8b504e42bc 100644 --- a/app/services/ci/create_job_artifacts_service.rb +++ b/app/services/ci/create_job_artifacts_service.rb @@ -3,42 +3,100 @@ module Ci class CreateJobArtifactsService < ::BaseService ArtifactsExistError = Class.new(StandardError) + + LSIF_ARTIFACT_TYPE = 'lsif' + OBJECT_STORAGE_ERRORS = [ Errno::EIO, Google::Apis::ServerError, Signet::RemoteServerError ].freeze - def execute(job, artifacts_file, params, metadata_file: nil) - return success if sha256_matches_existing_artifact?(job, params['artifact_type'], artifacts_file) + def initialize(job) + @job = job + @project = job.project + end + + def authorize(artifact_type:, filesize: nil) + result = validate_requirements(artifact_type: artifact_type, filesize: filesize) + return result unless result[:status] == :success + + headers = JobArtifactUploader.workhorse_authorize(has_length: false, maximum_size: max_size(artifact_type)) + headers[:ProcessLsif] = true if lsif?(artifact_type) - artifact, artifact_metadata = build_artifact(job, artifacts_file, params, metadata_file) - result = parse_artifact(job, artifact) + success(headers: headers) + end + def execute(artifacts_file, params, metadata_file: nil) + result = validate_requirements(artifact_type: params[:artifact_type], filesize: artifacts_file.size) return result unless result[:status] == :success - persist_artifact(job, artifact, artifact_metadata) + return success if sha256_matches_existing_artifact?(params[:artifact_type], artifacts_file) + + artifact, artifact_metadata = build_artifact(artifacts_file, params, metadata_file) + result = parse_artifact(artifact) + + return result unless result[:status] == :success + + persist_artifact(artifact, artifact_metadata, params) end private - def build_artifact(job, artifacts_file, params, metadata_file) + attr_reader :job, :project + + def validate_requirements(artifact_type:, filesize:) + return forbidden_type_error(artifact_type) if forbidden_type?(artifact_type) + return too_large_error if too_large?(artifact_type, filesize) + + success + end + + def forbidden_type?(type) + lsif?(type) && !code_navigation_enabled? + end + + def too_large?(type, size) + size > max_size(type) if size + end + + def code_navigation_enabled? + Feature.enabled?(:code_navigation, project, default_enabled: true) + end + + def lsif?(type) + type == LSIF_ARTIFACT_TYPE + end + + def max_size(type) + Ci::JobArtifact.max_artifact_size(type: type, project: project) + end + + def forbidden_type_error(type) + error("#{type} artifacts are forbidden", :forbidden) + end + + def too_large_error + error('file size has reached maximum size limit', :payload_too_large) + end + + def build_artifact(artifacts_file, params, metadata_file) expire_in = params['expire_in'] || Gitlab::CurrentSettings.current_application_settings.default_artifacts_expire_in artifact = Ci::JobArtifact.new( job_id: job.id, - project: job.project, + project: project, file: artifacts_file, - file_type: params['artifact_type'], - file_format: params['artifact_format'], + file_type: params[:artifact_type], + file_format: params[:artifact_format], file_sha256: artifacts_file.sha256, expire_in: expire_in) artifact_metadata = if metadata_file Ci::JobArtifact.new( job_id: job.id, - project: job.project, + project: project, file: metadata_file, file_type: :metadata, file_format: :gzip, @@ -46,7 +104,7 @@ module Ci expire_in: expire_in) end - if Feature.enabled?(:keep_latest_artifact_for_ref, job.project) + if Feature.enabled?(:keep_latest_artifact_for_ref, project) artifact.locked = true artifact_metadata&.locked = true end @@ -54,23 +112,23 @@ module Ci [artifact, artifact_metadata] end - def parse_artifact(job, artifact) - unless Feature.enabled?(:ci_synchronous_artifact_parsing, job.project, default_enabled: true) + def parse_artifact(artifact) + unless Feature.enabled?(:ci_synchronous_artifact_parsing, project, default_enabled: true) return success end case artifact.file_type - when 'dotenv' then parse_dotenv_artifact(job, artifact) - when 'cluster_applications' then parse_cluster_applications_artifact(job, artifact) + when 'dotenv' then parse_dotenv_artifact(artifact) + when 'cluster_applications' then parse_cluster_applications_artifact(artifact) else success end end - def persist_artifact(job, artifact, artifact_metadata) + def persist_artifact(artifact, artifact_metadata, params) Ci::JobArtifact.transaction do artifact.save! artifact_metadata&.save! - unlock_previous_artifacts!(artifact) + unlock_previous_artifacts! # NOTE: The `artifacts_expire_at` column is already deprecated and to be removed in the near future. job.update_column(:artifacts_expire_at, artifact.expire_at) @@ -78,42 +136,42 @@ module Ci success rescue ActiveRecord::RecordNotUnique => error - track_exception(error, job, params) + track_exception(error, params) error('another artifact of the same type already exists', :bad_request) rescue *OBJECT_STORAGE_ERRORS => error - track_exception(error, job, params) + track_exception(error, params) error(error.message, :service_unavailable) rescue => error - track_exception(error, job, params) + track_exception(error, params) error(error.message, :bad_request) end - def unlock_previous_artifacts!(artifact) - return unless Feature.enabled?(:keep_latest_artifact_for_ref, artifact.job.project) + def unlock_previous_artifacts! + return unless Feature.enabled?(:keep_latest_artifact_for_ref, project) - Ci::JobArtifact.for_ref(artifact.job.ref, artifact.project_id).locked.update_all(locked: false) + Ci::JobArtifact.for_ref(job.ref, project.id).locked.update_all(locked: false) end - def sha256_matches_existing_artifact?(job, artifact_type, artifacts_file) + def sha256_matches_existing_artifact?(artifact_type, artifacts_file) existing_artifact = job.job_artifacts.find_by_file_type(artifact_type) return false unless existing_artifact existing_artifact.file_sha256 == artifacts_file.sha256 end - def track_exception(error, job, params) + def track_exception(error, params) Gitlab::ErrorTracking.track_exception(error, job_id: job.id, project_id: job.project_id, - uploading_type: params['artifact_type'] + uploading_type: params[:artifact_type] ) end - def parse_dotenv_artifact(job, artifact) - Ci::ParseDotenvArtifactService.new(job.project, current_user).execute(artifact) + def parse_dotenv_artifact(artifact) + Ci::ParseDotenvArtifactService.new(project, current_user).execute(artifact) end - def parse_cluster_applications_artifact(job, artifact) + def parse_cluster_applications_artifact(artifact) Clusters::ParseClusterApplicationsArtifactService.new(job, job.user).execute(artifact) end end |