-
Notifications
You must be signed in to change notification settings - Fork 903
feat: notify owner about failed autobuild #13891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 9 commits
450db4d
422fe8b
8970be7
3ace8c6
1001bc1
881dc5e
1852953
42a1c69
e6a5aef
a4a5511
660c2d6
68ae258
3dd09d2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DELETE FROM notification_templates WHERE id = '381df2a9-c0c0-4749-420f-80a9280c66f9'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
INSERT INTO notification_templates (id, name, title_template, body_template, "group", actions) | ||
VALUES ('381df2a9-c0c0-4749-420f-80a9280c66f9', 'Workspace Autobuild Failed', E'Workspace "{{.Labels.name}}" autobuild failed', | ||
E'Hi {{.UserName}}\n\Automatic build of your workspace **{{.Labels.name}}** failed.\nThe specified reason was "**{{.Labels.reason}}**".', | ||
'Workspace Events', '[ | ||
{ | ||
"label": "View workspaces", | ||
"url": "{{ base_url }}/workspaces" | ||
} | ||
]'::jsonb); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1687,14 +1687,127 @@ func TestNotifications(t *testing.T) { | |
require.Contains(t, notifEnq.sent[0].targets, workspace.OrganizationID) | ||
require.Contains(t, notifEnq.sent[0].targets, user.ID) | ||
if tc.deletionReason == database.BuildReasonInitiator { | ||
require.Equal(t, notifEnq.sent[0].labels["initiatedBy"], initiator.Username) | ||
require.Equal(t, notifEnq.sent[0].labels["initiator"], initiator.Username) | ||
} | ||
} else { | ||
require.Len(t, notifEnq.sent, 0) | ||
} | ||
}) | ||
} | ||
}) | ||
|
||
t.Run("Workspace build failed", func(t *testing.T) { | ||
t.Parallel() | ||
|
||
tests := []struct { | ||
name string | ||
|
||
buildReason database.BuildReason | ||
shouldNotify bool | ||
}{ | ||
{ | ||
name: "initiated by owner", | ||
buildReason: database.BuildReasonInitiator, | ||
shouldNotify: false, | ||
}, | ||
{ | ||
name: "initiated by autostart", | ||
buildReason: database.BuildReasonAutostart, | ||
shouldNotify: true, | ||
}, | ||
} | ||
|
||
for _, tc := range tests { | ||
t.Run(tc.name, func(t *testing.T) { | ||
t.Parallel() | ||
|
||
ctx := context.Background() | ||
notifEnq := &fakeNotificationEnqueuer{} | ||
|
||
// Otherwise `(*Server).FailJob` fails with: | ||
// audit log - get build {"error": "sql: no rows in result set"} | ||
ignoreLogErrors := true | ||
srv, db, ps, pd := setup(t, ignoreLogErrors, &overrides{ | ||
notificationEnqueuer: notifEnq, | ||
}) | ||
|
||
user := dbgen.User(t, db, database.User{}) | ||
initiator := user | ||
|
||
template := dbgen.Template(t, db, database.Template{ | ||
Name: "template", | ||
Provisioner: database.ProvisionerTypeEcho, | ||
OrganizationID: pd.OrganizationID, | ||
}) | ||
template, err := db.GetTemplateByID(ctx, template.ID) | ||
require.NoError(t, err) | ||
file := dbgen.File(t, db, database.File{CreatedBy: user.ID}) | ||
workspace := dbgen.Workspace(t, db, database.Workspace{ | ||
TemplateID: template.ID, | ||
OwnerID: user.ID, | ||
OrganizationID: pd.OrganizationID, | ||
}) | ||
version := dbgen.TemplateVersion(t, db, database.TemplateVersion{ | ||
OrganizationID: pd.OrganizationID, | ||
TemplateID: uuid.NullUUID{ | ||
UUID: template.ID, | ||
Valid: true, | ||
}, | ||
JobID: uuid.New(), | ||
}) | ||
build := dbgen.WorkspaceBuild(t, db, database.WorkspaceBuild{ | ||
WorkspaceID: workspace.ID, | ||
TemplateVersionID: version.ID, | ||
InitiatorID: initiator.ID, | ||
Transition: database.WorkspaceTransitionDelete, | ||
Reason: tc.buildReason, | ||
}) | ||
job := dbgen.ProvisionerJob(t, db, ps, database.ProvisionerJob{ | ||
FileID: file.ID, | ||
Type: database.ProvisionerJobTypeWorkspaceBuild, | ||
Input: must(json.Marshal(provisionerdserver.WorkspaceProvisionJob{ | ||
WorkspaceBuildID: build.ID, | ||
})), | ||
OrganizationID: pd.OrganizationID, | ||
}) | ||
_, err = db.AcquireProvisionerJob(ctx, database.AcquireProvisionerJobParams{ | ||
OrganizationID: pd.OrganizationID, | ||
WorkerID: uuid.NullUUID{ | ||
UUID: pd.ID, | ||
Valid: true, | ||
}, | ||
Types: []database.ProvisionerType{database.ProvisionerTypeEcho}, | ||
}) | ||
require.NoError(t, err) | ||
Comment on lines
+1729
to
+1781
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: all the common bits here could be moved out to a helper func. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, my problem with this idea is that we already have I think I will pass on it. |
||
|
||
_, err = srv.FailJob(ctx, &proto.FailedJob{ | ||
JobId: job.ID.String(), | ||
Type: &proto.FailedJob_WorkspaceBuild_{ | ||
WorkspaceBuild: &proto.FailedJob_WorkspaceBuild{ | ||
State: []byte{}, | ||
}, | ||
}, | ||
}) | ||
require.NoError(t, err) | ||
|
||
workspace, err = db.GetWorkspaceByID(ctx, workspace.ID) | ||
require.NoError(t, err) | ||
|
||
if tc.shouldNotify { | ||
mtojek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Validate that the notification was sent and contained the expected values. | ||
require.Len(t, notifEnq.sent, 1) | ||
require.Equal(t, notifEnq.sent[0].userID, user.ID) | ||
require.Contains(t, notifEnq.sent[0].targets, template.ID) | ||
require.Contains(t, notifEnq.sent[0].targets, workspace.ID) | ||
require.Contains(t, notifEnq.sent[0].targets, workspace.OrganizationID) | ||
require.Contains(t, notifEnq.sent[0].targets, user.ID) | ||
require.Equal(t, notifEnq.sent[0].labels["initiator"], "autobuild") | ||
} else { | ||
require.Len(t, notifEnq.sent, 0) | ||
} | ||
}) | ||
} | ||
}) | ||
} | ||
|
||
type overrides struct { | ||
|
Uh oh!
There was an error while loading. Please reload this page.