diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-18 11:18:50 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2020-06-18 11:18:50 +0000 |
commit | 8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781 (patch) | |
tree | a77e7fe7a93de11213032ed4ab1f33a3db51b738 /app/services/ci | |
parent | 00b35af3db1abfe813a778f643dad221aad51fca (diff) | |
download | gitlab-ce-8c7f4e9d5f36cff46365a7f8c4b9c21578c1e781.tar.gz |
Add latest changes from gitlab-org/gitlab@13-1-stable-ee
Diffstat (limited to 'app/services/ci')
-rw-r--r-- | app/services/ci/authorize_job_artifact_service.rb | 53 | ||||
-rw-r--r-- | app/services/ci/build_report_result_service.rb | 36 | ||||
-rw-r--r-- | app/services/ci/create_cross_project_pipeline_service.rb | 1 | ||||
-rw-r--r-- | app/services/ci/create_web_ide_terminal_service.rb | 123 | ||||
-rw-r--r-- | app/services/ci/extract_sections_from_build_trace_service.rb | 2 | ||||
-rw-r--r-- | app/services/ci/process_pipeline_service.rb | 2 | ||||
-rw-r--r-- | app/services/ci/update_ci_ref_status_service.rb | 1 | ||||
-rw-r--r-- | app/services/ci/web_ide_config_service.rb | 59 |
8 files changed, 275 insertions, 2 deletions
diff --git a/app/services/ci/authorize_job_artifact_service.rb b/app/services/ci/authorize_job_artifact_service.rb new file mode 100644 index 00000000000..893e92d427c --- /dev/null +++ b/app/services/ci/authorize_job_artifact_service.rb @@ -0,0 +1,53 @@ +# 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/build_report_result_service.rb b/app/services/ci/build_report_result_service.rb new file mode 100644 index 00000000000..758ba1c73bf --- /dev/null +++ b/app/services/ci/build_report_result_service.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Ci + class BuildReportResultService + def execute(build) + return unless Feature.enabled?(:build_report_summary, build.project) + return unless build.has_test_reports? + + build.report_results.create!( + project_id: build.project_id, + data: tests_params(build) + ) + end + + private + + def generate_test_suite_report(build) + build.collect_test_reports!(Gitlab::Ci::Reports::TestReports.new) + end + + def tests_params(build) + test_suite = generate_test_suite_report(build) + + { + tests: { + name: test_suite.name, + duration: test_suite.total_time, + failed: test_suite.failed_count, + errored: test_suite.error_count, + skipped: test_suite.skipped_count, + success: test_suite.success_count + } + } + end + end +end diff --git a/app/services/ci/create_cross_project_pipeline_service.rb b/app/services/ci/create_cross_project_pipeline_service.rb index a73a2e2b471..1700312b941 100644 --- a/app/services/ci/create_cross_project_pipeline_service.rb +++ b/app/services/ci/create_cross_project_pipeline_service.rb @@ -47,6 +47,7 @@ module Ci # and update the status when the downstream pipeline completes. subject.success! unless subject.dependent? else + subject.options[:downstream_errors] = pipeline.errors.full_messages subject.drop!(:downstream_pipeline_creation_failed) end end diff --git a/app/services/ci/create_web_ide_terminal_service.rb b/app/services/ci/create_web_ide_terminal_service.rb new file mode 100644 index 00000000000..29d40756ab4 --- /dev/null +++ b/app/services/ci/create_web_ide_terminal_service.rb @@ -0,0 +1,123 @@ +# frozen_string_literal: true + +module Ci + class CreateWebIdeTerminalService < ::BaseService + include ::Gitlab::Utils::StrongMemoize + + TerminalCreationError = Class.new(StandardError) + + TERMINAL_NAME = 'terminal'.freeze + + attr_reader :terminal + + def execute + check_access! + validate_params! + load_terminal_config! + + pipeline = create_pipeline! + success(pipeline: pipeline) + rescue TerminalCreationError => e + error(e.message) + rescue ActiveRecord::RecordInvalid => e + error("Failed to persist the pipeline: #{e.message}") + end + + private + + def create_pipeline! + build_pipeline.tap do |pipeline| + pipeline.stages << terminal_stage_seed(pipeline).to_resource + pipeline.save! + + Ci::ProcessPipelineService + .new(pipeline) + .execute(nil, initial_process: true) + + pipeline_created_counter.increment(source: :webide) + end + end + + def build_pipeline + Ci::Pipeline.new( + project: project, + user: current_user, + source: :webide, + config_source: :webide_source, + ref: ref, + sha: sha, + tag: false, + before_sha: Gitlab::Git::BLANK_SHA + ) + end + + def terminal_stage_seed(pipeline) + attributes = { + name: TERMINAL_NAME, + index: 0, + builds: [terminal_build_seed] + } + + Gitlab::Ci::Pipeline::Seed::Stage.new(pipeline, attributes, []) + end + + def terminal_build_seed + terminal.merge( + name: TERMINAL_NAME, + stage: TERMINAL_NAME, + user: current_user, + scheduling_type: :stage) + end + + def load_terminal_config! + result = ::Ci::WebIdeConfigService.new(project, current_user, sha: sha).execute + raise TerminalCreationError, result[:message] if result[:status] != :success + + @terminal = result[:terminal] + raise TerminalCreationError, 'Terminal is not configured' unless terminal + end + + def validate_params! + unless sha + raise TerminalCreationError, 'Ref does not exist' + end + + unless branch_exists? + raise TerminalCreationError, 'Ref needs to be a branch' + end + end + + def check_access! + unless can?(current_user, :create_web_ide_terminal, project) + raise TerminalCreationError, 'Insufficient permissions to create a terminal' + end + + if terminal_active? + raise TerminalCreationError, 'There is already a terminal running' + end + end + + def pipeline_created_counter + @pipeline_created_counter ||= Gitlab::Metrics + .counter(:pipelines_created_total, "Counter of pipelines created") + end + + def terminal_active? + project.active_webide_pipelines(user: current_user).exists? + end + + def ref + strong_memoize(:ref) do + Gitlab::Git.ref_name(params[:ref]) + end + end + + def branch_exists? + project.repository.branch_exists?(ref) + end + + def sha + project.commit(params[:ref]).try(:id) + end + end +end diff --git a/app/services/ci/extract_sections_from_build_trace_service.rb b/app/services/ci/extract_sections_from_build_trace_service.rb index 97f9918fdb7..c756e376901 100644 --- a/app/services/ci/extract_sections_from_build_trace_service.rb +++ b/app/services/ci/extract_sections_from_build_trace_service.rb @@ -5,7 +5,7 @@ module Ci def execute(build) return false unless build.trace_sections.empty? - Gitlab::Database.bulk_insert(BuildTraceSection.table_name, extract_sections(build)) + Gitlab::Database.bulk_insert(BuildTraceSection.table_name, extract_sections(build)) # rubocop:disable Gitlab/BulkInsert true end diff --git a/app/services/ci/process_pipeline_service.rb b/app/services/ci/process_pipeline_service.rb index 3f23e81dcdd..80ebe5f5eb6 100644 --- a/app/services/ci/process_pipeline_service.rb +++ b/app/services/ci/process_pipeline_service.rb @@ -11,7 +11,7 @@ module Ci def execute(trigger_build_ids = nil, initial_process: false) update_retried - if Feature.enabled?(:ci_atomic_processing, pipeline.project) + if ::Gitlab::Ci::Features.atomic_processing?(pipeline.project) Ci::PipelineProcessing::AtomicProcessingService .new(pipeline) .execute diff --git a/app/services/ci/update_ci_ref_status_service.rb b/app/services/ci/update_ci_ref_status_service.rb index 4f7ac4d11b0..22cc43232cc 100644 --- a/app/services/ci/update_ci_ref_status_service.rb +++ b/app/services/ci/update_ci_ref_status_service.rb @@ -1,5 +1,6 @@ # frozen_string_literal: true +# NOTE: This class is unused and to be removed in 13.1~ module Ci class UpdateCiRefStatusService include Gitlab::OptimisticLocking diff --git a/app/services/ci/web_ide_config_service.rb b/app/services/ci/web_ide_config_service.rb new file mode 100644 index 00000000000..ade9132f419 --- /dev/null +++ b/app/services/ci/web_ide_config_service.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +module Ci + class WebIdeConfigService < ::BaseService + include ::Gitlab::Utils::StrongMemoize + + ValidationError = Class.new(StandardError) + + WEBIDE_CONFIG_FILE = '.gitlab/.gitlab-webide.yml'.freeze + + attr_reader :config, :config_content + + def execute + check_access! + load_config_content! + load_config! + + success(terminal: config.terminal_value) + rescue ValidationError => e + error(e.message) + end + + private + + def check_access! + unless can?(current_user, :download_code, project) + raise ValidationError, 'Insufficient permissions to read configuration' + end + end + + def load_config_content! + @config_content = webide_yaml_from_repo + + unless config_content + raise ValidationError, "Failed to load Web IDE config file '#{WEBIDE_CONFIG_FILE}' for #{params[:sha]}" + end + end + + def load_config! + @config = Gitlab::WebIde::Config.new(config_content) + + unless @config.valid? + raise ValidationError, @config.errors.first + end + rescue Gitlab::WebIde::Config::ConfigError => e + raise ValidationError, e.message + end + + def webide_yaml_from_repo + gitlab_webide_yml_for(params[:sha]) + rescue GRPC::NotFound, GRPC::Internal + nil + end + + def gitlab_webide_yml_for(sha) + project.repository.blob_data_at(sha, WEBIDE_CONFIG_FILE) + end + end +end |