summaryrefslogtreecommitdiff
path: root/app/services/ci/create_web_ide_terminal_service.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/services/ci/create_web_ide_terminal_service.rb')
-rw-r--r--app/services/ci/create_web_ide_terminal_service.rb123
1 files changed, 123 insertions, 0 deletions
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