summaryrefslogtreecommitdiff
path: root/app/finders/ci/pipelines_finder.rb
blob: 7347a83d294d36dff2071b698aa941b874482bde (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
# 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

    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.no_child
      items = by_scope(items)
      items = by_status(items)
      items = by_ref(items)
      items = by_sha(items)
      items = by_name(items)
      items = by_username(items)
      items = by_yaml_errors(items)
      items = by_updated_at(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_scope(items)
      case params[:scope]
      when 'running'
        items.running
      when 'pending'
        items.pending
      when 'finished'
        items.finished
      when 'branches'
        from_ids(ids_for_ref(branches))
      when '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

    # 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_name(items)
      if params[:name].present?
        items.joins(:user).where(users: { name: params[:name] })
      else
        items
      end
    end
    # rubocop: enable CodeReuse/ActiveRecord

    # rubocop: disable CodeReuse/ActiveRecord
    def by_username(items)
      if params[:username].present?
        items.joins(:user).where(users: { username: params[:username] })
      else
        items
      end
    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("yaml_errors IS NOT NULL")
      when false
        items.where("yaml_errors IS NULL")
      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

    # 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