Welcome to mirror list, hosted at ThFree Co, Russian Federation.

create_web_ide_terminal_service.rb « ci « services « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: a78281aed161d067f3635968ed52198d80f7071f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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

        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 = ::Ide::TerminalConfigService.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