summaryrefslogtreecommitdiff
path: root/lib/gitlab/ci/charts.rb
blob: 797193a6be57a4c043d898b8bd2e74103876ac76 (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
# frozen_string_literal: true

module Gitlab
  module Ci
    module Charts
      class Chart
        attr_reader :from, :to, :labels, :total, :success, :project, :pipeline_times

        def initialize(project)
          @labels = []
          @total = []
          @success = []
          @pipeline_times = []
          @project = project

          collect
        end

        private

        attr_reader :interval

        # rubocop: disable CodeReuse/ActiveRecord
        def collect
          query = project.all_pipelines
            .where(::Ci::Pipeline.arel_table['created_at'].gteq(@from))
            .where(::Ci::Pipeline.arel_table['created_at'].lteq(@to))

          totals_count  = grouped_count(query)
          success_count = grouped_count(query.success)

          current = @from
          while current <= @to
            label = current.strftime(@format)
            @labels  << label
            @total   << (totals_count[label] || 0)
            @success << (success_count[label] || 0)

            current += interval_step
          end
        end
        # rubocop: enable CodeReuse/ActiveRecord

        # rubocop: disable CodeReuse/ActiveRecord
        def grouped_count(query)
          query
            .group("date_trunc('#{interval}', #{::Ci::Pipeline.table_name}.created_at)")
            .count(:created_at)
            .transform_keys { |date| date.strftime(@format) }
        end
        # rubocop: enable CodeReuse/ActiveRecord

        def interval_step
          @interval_step ||= 1.public_send(interval) # rubocop: disable GitlabSecurity/PublicSend
        end
      end

      class YearChart < Chart
        def initialize(*)
          @to     = Date.today.end_of_month.end_of_day
          @from   = (@to - 1.year).beginning_of_month.beginning_of_day
          @interval = :month
          @format = '%B %Y'

          super
        end
      end

      class MonthChart < Chart
        def initialize(*)
          @to     = Date.today.end_of_day
          @from   = (@to - 1.month).beginning_of_day
          @interval = :day
          @format = '%d %B'

          super
        end
      end

      class WeekChart < Chart
        def initialize(*)
          @to     = Date.today.end_of_day
          @from   = (@to - 1.week).beginning_of_day
          @interval = :day
          @format = '%d %B'

          super
        end
      end

      class PipelineTime < Chart
        def collect
          commits = project.all_pipelines.last(30)

          commits.each do |commit|
            @labels << commit.short_sha
            duration = commit.duration || 0
            @pipeline_times << (duration / 60)
          end
        end
      end
    end
  end
end