Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit0faee8e

Browse files
authored
feat(coderd): notify on task completion/failure (#20327)
Adds notifications on task transitions to completed or failure state.Authored by Claude, I reviewed it and it appears to be legit.
1 parent3fa438f commit0faee8e

10 files changed

+397
-2
lines changed

‎coderd/aitasks_test.go‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1061,6 +1061,64 @@ func TestTasksNotification(t *testing.T) {
10611061
notificationTemplate:notifications.TemplateTaskIdle,
10621062
taskPrompt:"This is a very long task prompt that should be truncated to 160 characters. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
10631063
},
1064+
// Should send TemplateTaskCompleted when the AI task transitions to 'Complete'.
1065+
{
1066+
name:"TemplateTaskCompleted",
1067+
latestAppStatuses: []codersdk.WorkspaceAppStatusState{codersdk.WorkspaceAppStatusStateWorking},
1068+
newAppStatus:codersdk.WorkspaceAppStatusStateComplete,
1069+
isAITask:true,
1070+
isNotificationSent:true,
1071+
notificationTemplate:notifications.TemplateTaskCompleted,
1072+
taskPrompt:"TemplateTaskCompleted",
1073+
},
1074+
// Should send TemplateTaskFailed when the AI task transitions to 'Failure'.
1075+
{
1076+
name:"TemplateTaskFailed",
1077+
latestAppStatuses: []codersdk.WorkspaceAppStatusState{codersdk.WorkspaceAppStatusStateWorking},
1078+
newAppStatus:codersdk.WorkspaceAppStatusStateFailure,
1079+
isAITask:true,
1080+
isNotificationSent:true,
1081+
notificationTemplate:notifications.TemplateTaskFailed,
1082+
taskPrompt:"TemplateTaskFailed",
1083+
},
1084+
// Should send TemplateTaskCompleted when the AI task transitions from 'Idle' to 'Complete'.
1085+
{
1086+
name:"TemplateTaskCompletedFromIdle",
1087+
latestAppStatuses: []codersdk.WorkspaceAppStatusState{codersdk.WorkspaceAppStatusStateIdle},
1088+
newAppStatus:codersdk.WorkspaceAppStatusStateComplete,
1089+
isAITask:true,
1090+
isNotificationSent:true,
1091+
notificationTemplate:notifications.TemplateTaskCompleted,
1092+
taskPrompt:"TemplateTaskCompletedFromIdle",
1093+
},
1094+
// Should send TemplateTaskFailed when the AI task transitions from 'Idle' to 'Failure'.
1095+
{
1096+
name:"TemplateTaskFailedFromIdle",
1097+
latestAppStatuses: []codersdk.WorkspaceAppStatusState{codersdk.WorkspaceAppStatusStateIdle},
1098+
newAppStatus:codersdk.WorkspaceAppStatusStateFailure,
1099+
isAITask:true,
1100+
isNotificationSent:true,
1101+
notificationTemplate:notifications.TemplateTaskFailed,
1102+
taskPrompt:"TemplateTaskFailedFromIdle",
1103+
},
1104+
// Should NOT send notification when transitioning from 'Complete' to 'Complete' (no change).
1105+
{
1106+
name:"NoNotificationCompleteToComplete",
1107+
latestAppStatuses: []codersdk.WorkspaceAppStatusState{codersdk.WorkspaceAppStatusStateComplete},
1108+
newAppStatus:codersdk.WorkspaceAppStatusStateComplete,
1109+
isAITask:true,
1110+
isNotificationSent:false,
1111+
taskPrompt:"NoNotificationCompleteToComplete",
1112+
},
1113+
// Should NOT send notification when transitioning from 'Failure' to 'Failure' (no change).
1114+
{
1115+
name:"NoNotificationFailureToFailure",
1116+
latestAppStatuses: []codersdk.WorkspaceAppStatusState{codersdk.WorkspaceAppStatusStateFailure},
1117+
newAppStatus:codersdk.WorkspaceAppStatusStateFailure,
1118+
isAITask:true,
1119+
isNotificationSent:false,
1120+
taskPrompt:"NoNotificationFailureToFailure",
1121+
},
10641122
} {
10651123
t.Run(tc.name,func(t*testing.T) {
10661124
t.Parallel()
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
-- Remove Task 'completed' transition template notification
2+
DELETEFROM notification_templatesWHERE id='8c5a4d12-9f7e-4b3a-a1c8-6e4f2d9b5a7c';
3+
4+
-- Remove Task 'failed' transition template notification
5+
DELETEFROM notification_templatesWHERE id='3b7e8f1a-4c2d-49a6-b5e9-7f3a1c8d6b4e';
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
-- Task transition to 'complete' status
2+
INSERT INTO notification_templates (
3+
id,
4+
name,
5+
title_template,
6+
body_template,
7+
actions,
8+
"group",
9+
method,
10+
kind,
11+
enabled_by_default
12+
)VALUES (
13+
'8c5a4d12-9f7e-4b3a-a1c8-6e4f2d9b5a7c',
14+
'Task Completed',
15+
E'Task''{{.Labels.workspace}}'' completed',
16+
E'The task''{{.Labels.task}}'' has completed successfully.',
17+
'[
18+
{
19+
"label": "View task",
20+
"url": "{{base_url}}/tasks/{{.UserUsername}}/{{.Labels.workspace}}"
21+
},
22+
{
23+
"label": "View workspace",
24+
"url": "{{base_url}}/@{{.UserUsername}}/{{.Labels.workspace}}"
25+
}
26+
]'::jsonb,
27+
'Task Events',
28+
NULL,
29+
'system'::notification_template_kind,
30+
true
31+
);
32+
33+
-- Task transition to 'failed' status
34+
INSERT INTO notification_templates (
35+
id,
36+
name,
37+
title_template,
38+
body_template,
39+
actions,
40+
"group",
41+
method,
42+
kind,
43+
enabled_by_default
44+
)VALUES (
45+
'3b7e8f1a-4c2d-49a6-b5e9-7f3a1c8d6b4e',
46+
'Task Failed',
47+
E'Task''{{.Labels.workspace}}'' failed',
48+
E'The task''{{.Labels.task}}'' has failed. Check the logs for more details.',
49+
'[
50+
{
51+
"label": "View task",
52+
"url": "{{base_url}}/tasks/{{.UserUsername}}/{{.Labels.workspace}}"
53+
},
54+
{
55+
"label": "View workspace",
56+
"url": "{{base_url}}/@{{.UserUsername}}/{{.Labels.workspace}}"
57+
}
58+
]'::jsonb,
59+
'Task Events',
60+
NULL,
61+
'system'::notification_template_kind,
62+
true
63+
);

‎coderd/notifications/events.go‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ var (
5555

5656
// Task-related events.
5757
var (
58-
TemplateTaskWorking=uuid.MustParse("bd4b7168-d05e-4e19-ad0f-3593b77aa90f")
59-
TemplateTaskIdle=uuid.MustParse("d4a6271c-cced-4ed0-84ad-afd02a9c7799")
58+
TemplateTaskWorking=uuid.MustParse("bd4b7168-d05e-4e19-ad0f-3593b77aa90f")
59+
TemplateTaskIdle=uuid.MustParse("d4a6271c-cced-4ed0-84ad-afd02a9c7799")
60+
TemplateTaskCompleted=uuid.MustParse("8c5a4d12-9f7e-4b3a-a1c8-6e4f2d9b5a7c")
61+
TemplateTaskFailed=uuid.MustParse("3b7e8f1a-4c2d-49a6-b5e9-7f3a1c8d6b4e")
6062
)

‎coderd/notifications/notifications_test.go‎

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1301,6 +1301,34 @@ func TestNotificationTemplates_Golden(t *testing.T) {
13011301
Data:map[string]any{},
13021302
},
13031303
},
1304+
{
1305+
name:"TemplateTaskCompleted",
1306+
id:notifications.TemplateTaskCompleted,
1307+
payload: types.MessagePayload{
1308+
UserName:"Bobby",
1309+
UserEmail:"bobby@coder.com",
1310+
UserUsername:"bobby",
1311+
Labels:map[string]string{
1312+
"task":"my-task",
1313+
"workspace":"my-workspace",
1314+
},
1315+
Data:map[string]any{},
1316+
},
1317+
},
1318+
{
1319+
name:"TemplateTaskFailed",
1320+
id:notifications.TemplateTaskFailed,
1321+
payload: types.MessagePayload{
1322+
UserName:"Bobby",
1323+
UserEmail:"bobby@coder.com",
1324+
UserUsername:"bobby",
1325+
Labels:map[string]string{
1326+
"task":"my-task",
1327+
"workspace":"my-workspace",
1328+
},
1329+
Data:map[string]any{},
1330+
},
1331+
},
13041332
}
13051333

13061334
// We must have a test case for every notification_template. This is enforced below:
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
From: system@coder.com
2+
To: bobby@coder.com
3+
Subject: Task 'my-workspace' completed
4+
Message-Id: 02ee4935-73be-4fa1-a290-ff9999026b13@blush-whale-48
5+
Date: Fri, 11 Oct 2024 09:03:06 +0000
6+
Content-Type: multipart/alternative; boundary=bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
7+
MIME-Version: 1.0
8+
9+
--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
10+
Content-Transfer-Encoding: quoted-printable
11+
Content-Type: text/plain; charset=UTF-8
12+
13+
Hi Bobby,
14+
15+
The task 'my-task' has completed successfully.
16+
17+
18+
View task: http://test.com/tasks/bobby/my-workspace
19+
20+
View workspace: http://test.com/@bobby/my-workspace
21+
22+
--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
23+
Content-Transfer-Encoding: quoted-printable
24+
Content-Type: text/html; charset=UTF-8
25+
26+
<!doctype html>
27+
<html lang=3D"en">
28+
<head>
29+
<meta charset=3D"UTF-8" />
30+
<meta name=3D"viewport" content=3D"width=3Ddevice-width, initial-scale=
31+
=3D1.0" />
32+
<title>Task 'my-workspace' completed</title>
33+
</head>
34+
<body style=3D"margin: 0; padding: 0; font-family: -apple-system, system-=
35+
ui, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarel=
36+
l', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; color: #020617=
37+
; background: #f8fafc;">
38+
<div style=3D"max-width: 600px; margin: 20px auto; padding: 60px; borde=
39+
r: 1px solid #e2e8f0; border-radius: 8px; background-color: #fff; text-alig=
40+
n: left; font-size: 14px; line-height: 1.5;">
41+
<div style=3D"text-align: center;">
42+
<img src=3D"https://coder.com/coder-logo-horizontal.png" alt=3D"Cod=
43+
er Logo" style=3D"height: 40px;" />
44+
</div>
45+
<h1 style=3D"text-align: center; font-size: 24px; font-weight: 400; m=
46+
argin: 8px 0 32px; line-height: 1.5;">
47+
Task 'my-workspace' completed
48+
</h1>
49+
<div style=3D"line-height: 1.5;">
50+
<p>Hi Bobby,</p>
51+
<p>The task &lsquo;my-task&rsquo; has completed successfully.</p>
52+
</div>
53+
<div style=3D"text-align: center; margin-top: 32px;">
54+
=20
55+
<a href=3D"http://test.com/tasks/bobby/my-workspace" style=3D"displ=
56+
ay: inline-block; padding: 13px 24px; background-color: #020617; color: #f8=
57+
fafc; text-decoration: none; border-radius: 8px; margin: 0 4px;">
58+
View task
59+
</a>
60+
=20
61+
<a href=3D"http://test.com/@bobby/my-workspace" style=3D"display: i=
62+
nline-block; padding: 13px 24px; background-color: #020617; color: #f8fafc;=
63+
text-decoration: none; border-radius: 8px; margin: 0 4px;">
64+
View workspace
65+
</a>
66+
=20
67+
</div>
68+
<div style=3D"border-top: 1px solid #e2e8f0; color: #475569; font-siz=
69+
e: 12px; margin-top: 64px; padding-top: 24px; line-height: 1.6;">
70+
<p>&copy;&nbsp;2024&nbsp;Coder. All rights reserved&nbsp;-&nbsp;<a =
71+
href=3D"http://test.com" style=3D"color: #2563eb; text-decoration: none;">h=
72+
ttp://test.com</a></p>
73+
<p><a href=3D"http://test.com/settings/notifications" style=3D"colo=
74+
r: #2563eb; text-decoration: none;">Click here to manage your notification =
75+
settings</a></p>
76+
<p><a href=3D"http://test.com/settings/notifications?disabled=3D8c5=
77+
a4d12-9f7e-4b3a-a1c8-6e4f2d9b5a7c" style=3D"color: #2563eb; text-decoration=
78+
: none;">Stop receiving emails like this</a></p>
79+
</div>
80+
</div>
81+
</body>
82+
</html>
83+
84+
--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4--
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
From: system@coder.com
2+
To: bobby@coder.com
3+
Subject: Task 'my-workspace' failed
4+
Message-Id: 02ee4935-73be-4fa1-a290-ff9999026b13@blush-whale-48
5+
Date: Fri, 11 Oct 2024 09:03:06 +0000
6+
Content-Type: multipart/alternative; boundary=bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
7+
MIME-Version: 1.0
8+
9+
--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
10+
Content-Transfer-Encoding: quoted-printable
11+
Content-Type: text/plain; charset=UTF-8
12+
13+
Hi Bobby,
14+
15+
The task 'my-task' has failed. Check the logs for more details.
16+
17+
18+
View task: http://test.com/tasks/bobby/my-workspace
19+
20+
View workspace: http://test.com/@bobby/my-workspace
21+
22+
--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
23+
Content-Transfer-Encoding: quoted-printable
24+
Content-Type: text/html; charset=UTF-8
25+
26+
<!doctype html>
27+
<html lang=3D"en">
28+
<head>
29+
<meta charset=3D"UTF-8" />
30+
<meta name=3D"viewport" content=3D"width=3Ddevice-width, initial-scale=
31+
=3D1.0" />
32+
<title>Task 'my-workspace' failed</title>
33+
</head>
34+
<body style=3D"margin: 0; padding: 0; font-family: -apple-system, system-=
35+
ui, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarel=
36+
l', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; color: #020617=
37+
; background: #f8fafc;">
38+
<div style=3D"max-width: 600px; margin: 20px auto; padding: 60px; borde=
39+
r: 1px solid #e2e8f0; border-radius: 8px; background-color: #fff; text-alig=
40+
n: left; font-size: 14px; line-height: 1.5;">
41+
<div style=3D"text-align: center;">
42+
<img src=3D"https://coder.com/coder-logo-horizontal.png" alt=3D"Cod=
43+
er Logo" style=3D"height: 40px;" />
44+
</div>
45+
<h1 style=3D"text-align: center; font-size: 24px; font-weight: 400; m=
46+
argin: 8px 0 32px; line-height: 1.5;">
47+
Task 'my-workspace' failed
48+
</h1>
49+
<div style=3D"line-height: 1.5;">
50+
<p>Hi Bobby,</p>
51+
<p>The task &lsquo;my-task&rsquo; has failed. Check the logs for mo=
52+
re details.</p>
53+
</div>
54+
<div style=3D"text-align: center; margin-top: 32px;">
55+
=20
56+
<a href=3D"http://test.com/tasks/bobby/my-workspace" style=3D"displ=
57+
ay: inline-block; padding: 13px 24px; background-color: #020617; color: #f8=
58+
fafc; text-decoration: none; border-radius: 8px; margin: 0 4px;">
59+
View task
60+
</a>
61+
=20
62+
<a href=3D"http://test.com/@bobby/my-workspace" style=3D"display: i=
63+
nline-block; padding: 13px 24px; background-color: #020617; color: #f8fafc;=
64+
text-decoration: none; border-radius: 8px; margin: 0 4px;">
65+
View workspace
66+
</a>
67+
=20
68+
</div>
69+
<div style=3D"border-top: 1px solid #e2e8f0; color: #475569; font-siz=
70+
e: 12px; margin-top: 64px; padding-top: 24px; line-height: 1.6;">
71+
<p>&copy;&nbsp;2024&nbsp;Coder. All rights reserved&nbsp;-&nbsp;<a =
72+
href=3D"http://test.com" style=3D"color: #2563eb; text-decoration: none;">h=
73+
ttp://test.com</a></p>
74+
<p><a href=3D"http://test.com/settings/notifications" style=3D"colo=
75+
r: #2563eb; text-decoration: none;">Click here to manage your notification =
76+
settings</a></p>
77+
<p><a href=3D"http://test.com/settings/notifications?disabled=3D3b7=
78+
e8f1a-4c2d-49a6-b5e9-7f3a1c8d6b4e" style=3D"color: #2563eb; text-decoration=
79+
: none;">Stop receiving emails like this</a></p>
80+
</div>
81+
</div>
82+
</body>
83+
</html>
84+
85+
--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4--
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"_version": "1.1",
3+
"msg_id": "00000000-0000-0000-0000-000000000000",
4+
"payload": {
5+
"_version": "1.2",
6+
"notification_name": "Task Completed",
7+
"notification_template_id": "00000000-0000-0000-0000-000000000000",
8+
"user_id": "00000000-0000-0000-0000-000000000000",
9+
"user_email": "bobby@coder.com",
10+
"user_name": "Bobby",
11+
"user_username": "bobby",
12+
"actions": [
13+
{
14+
"label": "View task",
15+
"url": "http://test.com/tasks/bobby/my-workspace"
16+
},
17+
{
18+
"label": "View workspace",
19+
"url": "http://test.com/@bobby/my-workspace"
20+
}
21+
],
22+
"labels": {
23+
"task": "my-task",
24+
"workspace": "my-workspace"
25+
},
26+
"data": {},
27+
"targets": null
28+
},
29+
"title": "Task 'my-workspace' completed",
30+
"title_markdown": "Task 'my-workspace' completed",
31+
"body": "The task 'my-task' has completed successfully.",
32+
"body_markdown": "The task 'my-task' has completed successfully."
33+
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp