summaryrefslogtreecommitdiff
path: root/lib/ci/charts.rb
blob: 6063d6f45e8f46151e0cc23070ecf7226cd773e4 (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
module Ci
  module Charts
    module DailyInterval
      def grouped_count(query)
        query
          .group("DATE(#{Ci::Build.table_name}.created_at)")
          .count(:created_at)
          .transform_keys { |date| date.strftime(@format) }
      end

      def interval_step
        @interval_step ||= 1.day
      end
    end

    module MonthlyInterval
      def grouped_count(query)
        if Gitlab::Database.postgresql?
          query
            .group("to_char(#{Ci::Build.table_name}.created_at, '01 Month YYYY')")
            .count(:created_at)
            .transform_keys(&:squish)
        else
          query
            .group("DATE_FORMAT(#{Ci::Build.table_name}.created_at, '01 %M %Y')")
            .count(:created_at)
        end
      end

      def interval_step
        @interval_step ||= 1.month
      end
    end

    class Chart
      attr_reader :labels, :total, :success, :project, :build_times

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

        collect
      end

      def collect
        query = project.builds
          .where("? > #{Ci::Build.table_name}.created_at AND #{Ci::Build.table_name}.created_at > ?", @to, @from)

        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
    end

    class YearChart < Chart
      include MonthlyInterval

      def initialize(*)
        @to     = Date.today.end_of_month
        @from   = @to.years_ago(1).beginning_of_month
        @format = '%d %B %Y'

        super
      end
    end

    class MonthChart < Chart
      include DailyInterval

      def initialize(*)
        @to     = Date.today
        @from   = @to - 30.days
        @format = '%d %B'

        super
      end
    end

    class WeekChart < Chart
      include DailyInterval

      def initialize(*)
        @to     = Date.today
        @from   = @to - 7.days
        @format = '%d %B'

        super
      end
    end

    class BuildTime < Chart
      def collect
        commits = project.pipelines.last(30)

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