@@ -2,23 +2,26 @@ package reports
2
2
3
3
import (
4
4
"context"
5
+ "database/sql"
5
6
"io"
6
7
"time"
7
8
8
9
"cdr.dev/slog"
10
+ "golang.org/x/xerrors"
9
11
10
12
"github.com/coder/coder/v2/coderd/database"
11
13
"github.com/coder/coder/v2/coderd/database/dbauthz"
12
14
"github.com/coder/coder/v2/coderd/database/dbtime"
13
15
"github.com/coder/coder/v2/coderd/notifications"
16
+ "github.com/coder/coder/v2/codersdk"
14
17
"github.com/coder/quartz"
15
18
)
16
19
17
20
const (
18
21
delay = 5 * time .Minute
19
22
)
20
23
21
- func NewReportGenerator (ctx context.Context , logger slog.Logger , db database.Store , _ notifications.Enqueuer , clk quartz.Clock ) io.Closer {
24
+ func NewReportGenerator (ctx context.Context , logger slog.Logger , db database.Store , enqueur notifications.Enqueuer , clk quartz.Clock ) io.Closer {
22
25
closed := make (chan struct {})
23
26
24
27
ctx , cancelFunc := context .WithCancel (ctx )
@@ -41,22 +44,11 @@ func NewReportGenerator(ctx context.Context, logger slog.Logger, db database.Sto
41
44
return nil
42
45
}
43
46
44
- // TODO Report - workspace_builds_failed:
45
- //
46
- // 1. Fetch template admins.
47
- // 2. Fetch templates.
48
- // 3. For every template:
49
- // 1. Fetch failed builds.
50
- // 2. If failed builds == 0, continue.
51
- // 3. Render the report.
52
- // 4. Fetch template RW users.
53
- // 5. For user := range template admins + RW users:
54
- // 1. Check if report is enabled for the person.
55
- // 2. Check `report_generator_log`.
56
- // 3. If sent recently, continue
57
- // 4. Send notification
58
- // 5. Upsert into `report_generator_log`.
59
- // 4. clean stale `report_generator_log` entries
47
+ err = reportFailedWorkspaceBuilds (ctx , logger , db , enqueur , clk )
48
+ if err != nil {
49
+ logger .Debug (ctx , "unable to report failed workspace builds" )
50
+ return err
51
+ }
60
52
61
53
logger .Info (ctx , "report generator finished" , slog .F ("duration" , clk .Since (start )))
62
54
@@ -98,3 +90,41 @@ func (i *reportGenerator) Close() error {
98
90
<- i .closed
99
91
return nil
100
92
}
93
+
94
+ func reportFailedWorkspaceBuilds (ctx context.Context , logger slog.Logger , db database.Store , _ notifications.Enqueuer , clk quartz.Clock ) error {
95
+ const frequencyDays = 7
96
+
97
+ templateAdmins , err := db .GetUsers (ctx , database.GetUsersParams {
98
+ RbacRole : []string {codersdk .RoleTemplateAdmin },
99
+ })
100
+ if err != nil {
101
+ return xerrors .Errorf ("unable to fetch template admins: %w" , err )
102
+ }
103
+
104
+ templates , err := db .GetTemplatesWithFilter (ctx , database.GetTemplatesWithFilterParams {
105
+ Deleted : false ,
106
+ Deprecated : sql.NullBool {Bool : false , Valid : true },
107
+ })
108
+ if err != nil {
109
+ return xerrors .Errorf ("unable to fetch active templates: %w" , err )
110
+ }
111
+
112
+ for _ , template := range templates {
113
+ // 1. Fetch failed builds.
114
+ // 2. If failed builds == 0, continue.
115
+ // 3. Render the report.
116
+ // 4. Fetch template RW users.
117
+ // 5. For user := range template admins + RW users:
118
+ // 1. Check if report is enabled for the person.
119
+ // 2. Check `report_generator_log`.
120
+ // 3. If sent recently, continue
121
+ // 4. Send notification
122
+ // 5. Upsert into `report_generator_log`.
123
+ }
124
+
125
+ err = db .DeleteOldReportGeneratorLogs (ctx , frequencyDays )
126
+ if err != nil {
127
+ return xerrors .Errorf ("unable to delete old report generator logs: %w" , err )
128
+ }
129
+ return nil
130
+ }
0 commit comments