summaryrefslogtreecommitdiff
path: root/app/finders/ci/pipelines_finder.rb
blob: a2d1805286de8898f16baef97ca90d18d4f4d21e (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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# frozen_string_literal: true

module Ci
  class PipelinesFinder
    attr_reader :project, :pipelines, :params, :current_user

    ALLOWED_INDEXED_COLUMNS = %w[id status ref updated_at user_id].freeze
    ALLOWED_SCOPES = {
      RUNNING: 'running',
      PENDING: 'pending',
      FINISHED: 'finished',
      BRANCHES: 'branches',
      TAGS: 'tags'
    }.freeze

    def initialize(project, current_user, params = {})
      @project = project
      @current_user = current_user
      @pipelines = project.all_pipelines
      @params = params
    end

    def execute
      unless Ability.allowed?(current_user, :read_pipeline, project)
        return Ci::Pipeline.none
      end

      items = pipelines
      items = items.no_child unless params[:iids].present?
      items = by_iids(items)
      items = by_scope(items)
      items = by_status(items)
      items = by_ref(items)
      items = by_sha(items)
      items = by_username(items)
      items = by_yaml_errors(items)
      items = by_updated_at(items)
      items = by_source(items)
      items = by_name(items)

      sort_items(items)
    end

    private

    # rubocop: disable CodeReuse/ActiveRecord
    def ids_for_ref(refs)
      pipelines.where(ref: refs).group(:ref).select('max(id)')
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def from_ids(ids)
      pipelines.unscoped.where(project_id: project.id, id: ids)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    def branches
      project.repository.branch_names
    end

    def tags
      project.repository.tag_names
    end

    def by_iids(items)
      if params[:iids].present?
        items.for_iid(params[:iids])
      else
        items
      end
    end

    def by_scope(items)
      case params[:scope]
      when ALLOWED_SCOPES[:RUNNING]
        items.running
      when ALLOWED_SCOPES[:PENDING]
        items.pending
      when ALLOWED_SCOPES[:FINISHED]
        items.finished
      when ALLOWED_SCOPES[:BRANCHES]
        from_ids(ids_for_ref(branches))
      when ALLOWED_SCOPES[:TAGS]
        from_ids(ids_for_ref(tags))
      else
        items
      end
    end

    # rubocop: disable CodeReuse/ActiveRecord
    def by_status(items)
      return items unless Ci::HasStatus::AVAILABLE_STATUSES.include?(params[:status])

      items.where(status: params[:status])
    end
    # rubocop: enable CodeReuse/ActiveRecord

    def by_source(items)
      return items unless ::Ci::Pipeline.sources.key?(params[:source])

      items.with_pipeline_source(params[:source])
    end

    # rubocop: disable CodeReuse/ActiveRecord
    def by_ref(items)
      if params[:ref].present?
        items.where(ref: params[:ref])
      else
        items
      end
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def by_sha(items)
      if params[:sha].present?
        items.where(sha: params[:sha])
      else
        items
      end
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def by_username(items)
      return items unless params[:username].present?

      user_id = User.by_username(params[:username]).pluck_primary_key.first
      return Ci::Pipeline.none unless user_id

      items.where(user_id: user_id)
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def by_yaml_errors(items)
      case Gitlab::Utils.to_boolean(params[:yaml_errors])
      when true
        items.where.not(yaml_errors: nil)
      when false
        items.where(yaml_errors: nil)
      else
        items
      end
    end
    # rubocop: enable CodeReuse/ActiveRecord

    def by_updated_at(items)
      items = items.updated_before(params[:updated_before]) if params[:updated_before].present?
      items = items.updated_after(params[:updated_after]) if params[:updated_after].present?

      items
    end

    def by_name(items)
      return items unless
        Feature.enabled?(:pipeline_name_search, project) &&
          params[:name].present?

      items.for_name(params[:name])
    end

    # rubocop: disable CodeReuse/ActiveRecord
    def sort_items(items)
      order_by = if ALLOWED_INDEXED_COLUMNS.include?(params[:order_by])
                   params[:order_by]
                 else
                   :id
                 end

      sort = if params[:sort] =~ /\A(ASC|DESC)\z/i
               params[:sort]
             else
               :desc
             end

      items.order(order_by => sort)
    end
    # rubocop: enable CodeReuse/ActiveRecord
  end
end