Skip to content

Commit 1f06b86

Browse files
committed
WIP
1 parent 0cceede commit 1f06b86

File tree

2 files changed

+20
-77
lines changed

2 files changed

+20
-77
lines changed

coderd/notifications/reports/generator.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ func reportFailedWorkspaceBuilds(ctx context.Context, logger slog.Logger, db dat
104104
now := clk.Now()
105105
since := now.Add(-failedWorkspaceBuildsReportFrequencyDays * 24 * time.Hour)
106106

107-
// TODO skip new templates
108107
statsRows, err := db.GetWorkspaceBuildStatsByTemplates(ctx, dbtime.Time(since).UTC())
109108
if err != nil {
110109
return xerrors.Errorf("unable to fetch failed workspace builds: %w", err)
@@ -249,6 +248,8 @@ func buildDataForReportFailedWorkspaceBuilds(frequencyDays int, stats database.G
249248
"build_number": failedBuild.WorkspaceBuildNumber,
250249
})
251250
templateVersions[c-1]["failed_builds"] = builds
251+
//nolint:errorlint,forcetypeassert // only this function prepares the notification model
252+
templateVersions[c-1]["failed_count"] = templateVersions[c-1]["failed_count"].(int) + 1
252253
}
253254

254255
return map[string]any{

coderd/notifications/reports/generator_internal_test.go

Lines changed: 18 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ func TestReportFailedWorkspaceBuilds(t *testing.T) {
7575
_ = dbgen.OrganizationMember(t, db, database.OrganizationMember{UserID: user1.ID, OrganizationID: org.ID})
7676
user2 := dbgen.User(t, db, database.User{})
7777
_ = dbgen.OrganizationMember(t, db, database.OrganizationMember{UserID: user2.ID, OrganizationID: org.ID})
78-
user3 := dbgen.User(t, db, database.User{})
79-
// user in some other org
8078

8179
// Templates
8280
t1 := dbgen.Template(t, db, database.Template{Name: "template-1", DisplayName: "First Template", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID})
@@ -91,7 +89,7 @@ func TestReportFailedWorkspaceBuilds(t *testing.T) {
9189
// Workspaces
9290
w1 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID})
9391
w2 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t2.ID, OwnerID: user2.ID, OrganizationID: org.ID})
94-
w3 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t1.ID, OwnerID: user3.ID, OrganizationID: org.ID})
92+
w3 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID})
9593
w4 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t2.ID, OwnerID: user2.ID, OrganizationID: org.ID})
9694

9795
now := clk.Now()
@@ -136,7 +134,23 @@ func TestReportFailedWorkspaceBuilds(t *testing.T) {
136134
require.Equal(t, notifEnq.Sent[0].Data["failed_builds"], int64(3))
137135
require.Equal(t, notifEnq.Sent[0].Data["total_builds"], int64(4))
138136
require.Equal(t, notifEnq.Sent[0].Data["report_frequency"], "week")
139-
// require.Contains(t, notifEnq.Sent[0].Data["template_versions"], "?")
137+
require.Equal(t, notifEnq.Sent[0].Data["template_versions"], []map[string]interface{}{
138+
{
139+
"failed_builds": []map[string]interface{}{
140+
{"build_number": int32(7), "workspace_name": w3.Name, "workspace_owner_username": user1.Username},
141+
{"build_number": int32(1), "workspace_name": w1.Name, "workspace_owner_username": user1.Username},
142+
},
143+
"failed_count": 2,
144+
"template_version_name": t1v1.Name,
145+
},
146+
{
147+
"failed_builds": []map[string]interface{}{
148+
{"build_number": int32(3), "workspace_name": w1.Name, "workspace_owner_username": user1.Username},
149+
},
150+
"failed_count": 1,
151+
"template_version_name": t1v2.Name,
152+
},
153+
})
140154

141155
require.Equal(t, notifEnq.Sent[1].UserID, templateAdmin2.ID)
142156
require.Equal(t, notifEnq.Sent[1].TemplateID, notifications.TemplateWorkspaceBuildsFailedReport)
@@ -257,78 +271,6 @@ func TestReportFailedWorkspaceBuilds(t *testing.T) {
257271

258272
require.Len(t, notifEnq.Sent, 0) // all jobs succeeded so no report
259273
})
260-
261-
t.Run("FailedBuilds_TemplateAdminOptOut_NoReport", func(t *testing.T) {
262-
t.Parallel()
263-
264-
if !dbtestutil.WillUsePostgres() {
265-
t.Skip("notification preferences depend on database trigger")
266-
}
267-
268-
// Setup
269-
ctx, logger, db, ps, notifEnq, clk := setup(t)
270-
271-
// Given
272-
// Organization
273-
org := dbgen.Organization(t, db, database.Organization{})
274-
275-
// Template admins
276-
templateAdmin1 := dbgen.User(t, db, database.User{Username: "template-admin-1", RBACRoles: []string{rbac.RoleTemplateAdmin().Name}})
277-
_ = dbgen.OrganizationMember(t, db, database.OrganizationMember{UserID: templateAdmin1.ID, OrganizationID: org.ID})
278-
templateAdmin2 := dbgen.User(t, db, database.User{Username: "template-admin-2", RBACRoles: []string{rbac.RoleTemplateAdmin().Name}})
279-
_ = dbgen.OrganizationMember(t, db, database.OrganizationMember{UserID: templateAdmin2.ID, OrganizationID: org.ID})
280-
_, err := db.UpdateUserNotificationPreferences(ctx, database.UpdateUserNotificationPreferencesParams{
281-
UserID: templateAdmin2.ID,
282-
NotificationTemplateIds: []uuid.UUID{notifications.TemplateWorkspaceBuildsFailedReport},
283-
Disableds: []bool{true},
284-
})
285-
require.NoError(t, err)
286-
287-
// Regular users
288-
user1 := dbgen.User(t, db, database.User{})
289-
_ = dbgen.OrganizationMember(t, db, database.OrganizationMember{UserID: user1.ID, OrganizationID: org.ID})
290-
291-
// Templates
292-
t1 := dbgen.Template(t, db, database.Template{Name: "template-1", DisplayName: "First Template", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID})
293-
294-
// Template versions
295-
t1v1 := dbgen.TemplateVersion(t, db, database.TemplateVersion{Name: "template-1-version-1", CreatedBy: templateAdmin1.ID, OrganizationID: org.ID, TemplateID: uuid.NullUUID{UUID: t1.ID, Valid: true}, JobID: uuid.New()})
296-
297-
// Workspaces
298-
w1 := dbgen.Workspace(t, db, database.Workspace{TemplateID: t1.ID, OwnerID: user1.ID, OrganizationID: org.ID})
299-
300-
now := clk.Now()
301-
302-
// Workspace builds
303-
w1wb1pj := dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: org.ID, Error: jobError, ErrorCode: jobErrorCode, CompletedAt: sql.NullTime{Time: now.Add(-6 * dayDuration), Valid: true}})
304-
_ = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{WorkspaceID: w1.ID, BuildNumber: 1, TemplateVersionID: t1v1.ID, JobID: w1wb1pj.ID, CreatedAt: now.Add(-6 * dayDuration), Transition: database.WorkspaceTransitionStart, Reason: database.BuildReasonInitiator})
305-
w1wb2pj := dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{OrganizationID: org.ID, CompletedAt: sql.NullTime{Time: now.Add(-5 * dayDuration), Valid: true}})
306-
_ = dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{WorkspaceID: w1.ID, BuildNumber: 2, TemplateVersionID: t1v1.ID, JobID: w1wb2pj.ID, CreatedAt: now.Add(-5 * dayDuration), Transition: database.WorkspaceTransitionStart, Reason: database.BuildReasonInitiator})
307-
308-
// Database is ready, so we can clear notifications queue
309-
notifEnq.Clear()
310-
311-
// When
312-
err = reportFailedWorkspaceBuilds(ctx, logger, authedDB(db, logger), notifEnq, clk)
313-
314-
// Then
315-
require.NoError(t, err)
316-
317-
require.Len(t, notifEnq.Sent, 1) // one job failed, but only one template admin enabled reports
318-
require.Equal(t, notifEnq.Sent[0].UserID, templateAdmin1.ID)
319-
require.Equal(t, notifEnq.Sent[0].TemplateID, notifications.TemplateWorkspaceBuildsFailedReport)
320-
require.Equal(t, notifEnq.Sent[0].Labels["template_name"], t1.Name)
321-
require.Equal(t, notifEnq.Sent[0].Labels["template_display_name"], t1.DisplayName)
322-
require.Equal(t, notifEnq.Sent[0].Data["failed_builds"], int64(1))
323-
require.Equal(t, notifEnq.Sent[0].Data["total_builds"], int64(2))
324-
require.Equal(t, notifEnq.Sent[0].Data["report_frequency"], "week")
325-
// require.Contains(t, notifEnq.Sent[0].Data["template_versions"], "?")
326-
})
327-
328-
t.Run("FreshTemplate_FailedBuilds_TemplateAdminIn_NoReport", func(t *testing.T) {
329-
t.Parallel()
330-
// TODO
331-
})
332274
}
333275

334276
func setup(t *testing.T) (context.Context, slog.Logger, database.Store, pubsub.Pubsub, *testutil.FakeNotificationsEnqueuer, *quartz.Mock) {

0 commit comments

Comments
 (0)