summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/pipeline/chain/validate.rb
blob: e7109425d6c6fe5749cc263377e8070a28e02cdf (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
module Gitlab
  module Ci
    module Pipeline
      module Chain
        class Validate < Chain::Base
          include Gitlab::Allowable

          def perform!
            validate_project! || validate_repository! || validate_pipeline!
          end

          def break?
           @pipeline.errors.any? || @pipeline.persisted?
          end

          def allowed_to_trigger_pipeline?
            if current_user
              allowed_to_create?
            else # legacy triggers don't have a corresponding user
              !project.protected_for?(@pipeline.ref)
            end
          end

          def allowed_to_create?
            return unless can?(current_user, :create_pipeline, project)

            access = Gitlab::UserAccess.new(current_user, project: project)

            if branch?
              access.can_update_branch?(@pipeline.ref)
            elsif tag?
              access.can_create_tag?(@pipeline.ref)
            else
              true # Allow it for now and we'll reject when we check ref existence
            end
          end

          private

          def validate_project!
            unless project.builds_enabled?
              return error('Pipeline is disabled')
            end

            unless allowed_to_trigger_pipeline?
              if can?(current_user, :create_pipeline, project)
                return error("Insufficient permissions for protected ref '#{pipeline.ref}'")
              else
                return error('Insufficient permissions to create a new pipeline')
              end
            end
          end

          def validate_repository!
            unless branch? || tag?
              return error('Reference not found')
            end

            unless pipeline.sha
              return error('Commit not found')
            end
          end

          def validate_pipeline!
            unless @pipeline.config_processor
              unless @pipeline.ci_yaml_file
                return error("Missing #{@pipeline.ci_yaml_file_path} file")
              end

              if @command.save_incompleted && @pipeline.has_yaml_errors?
                @pipeline.drop
              end

              return error(@pipeline.yaml_errors)
            end

            unless @pipeline.has_stage_seeds?
              return error('No stages / jobs for this pipeline.')
            end
          end

          ## TODO, move to Pipeline as `branch_exists?`
          #
          def branch?
            return @is_branch if defined?(@is_branch)

            @is_branch = project.repository
              .ref_exists?(Gitlab::Git::BRANCH_REF_PREFIX + pipeline.ref)
          end

          ## TODO, move to pipeline as `tag_exists?`
          #
          def tag?
            return @is_tag if defined?(@is_tag)

            @is_tag = project.repository
              .ref_exists?(Gitlab::Git::TAG_REF_PREFIX + pipeline.ref)
          end

          def error(message)
            pipeline.errors.add(:base, message)
          end
        end
      end
    end
  end
end