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

Commit095c979

Browse files
feat: notify users on template deprecation (#15195)
Closes#15117Notify users when a template has been deprecated.
1 parentbcd68ee commit095c979

File tree

8 files changed

+255
-2
lines changed

8 files changed

+255
-2
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DELETEFROM notification_templatesWHERE id='f40fae84-55a2-42cd-99fa-b41c1ca64894';
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
INSERT INTO notification_templates
2+
(id, name, title_template, body_template,"group", actions)
3+
VALUES (
4+
'f40fae84-55a2-42cd-99fa-b41c1ca64894',
5+
'Template Deprecated',
6+
E'Template''{{.Labels.template}}'' has been deprecated',
7+
E'Hello {{.UserName}},\n\n'||
8+
E'The template **{{.Labels.template}}** has been deprecated with the following message:\n\n'||
9+
E'**{{.Labels.message}}**\n\n'||
10+
E'New workspaces may not be created from this template. Existing workspaces will continue to function normally.',
11+
'Template Events',
12+
'[
13+
{
14+
"label": "See affected workspaces",
15+
"url": "{{base_url}}/workspaces?filter=owner%3Ame+template%3A{{.Labels.template}}"
16+
},
17+
{
18+
"label": "View template",
19+
"url": "{{base_url}}/templates/{{.Labels.organization}}/{{.Labels.template}}"
20+
}
21+
]'::jsonb
22+
);

‎coderd/notifications/events.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ var (
3030

3131
// Template-related events.
3232
var (
33-
TemplateTemplateDeleted=uuid.MustParse("29a09665-2a4c-403f-9648-54301670e7be")
33+
TemplateTemplateDeleted=uuid.MustParse("29a09665-2a4c-403f-9648-54301670e7be")
34+
TemplateTemplateDeprecated=uuid.MustParse("f40fae84-55a2-42cd-99fa-b41c1ca64894")
3435

3536
TemplateWorkspaceBuildsFailedReport=uuid.MustParse("34a20db2-e9cc-4a93-b0e4-8569699d7a00")
3637
)

‎coderd/notifications/notifications_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,20 @@ func TestNotificationTemplates_Golden(t *testing.T) {
10211021
appName:"Custom Application Name",
10221022
logoURL:"https://custom.application/logo.png",
10231023
},
1024+
{
1025+
name:"TemplateTemplateDeprecated",
1026+
id:notifications.TemplateTemplateDeprecated,
1027+
payload: types.MessagePayload{
1028+
UserName:"Bobby",
1029+
UserEmail:"bobby@coder.com",
1030+
UserUsername:"bobby",
1031+
Labels:map[string]string{
1032+
"template":"alpha",
1033+
"message":"This template has been replaced by beta",
1034+
"organization":"coder",
1035+
},
1036+
},
1037+
},
10241038
}
10251039

10261040
// We must have a test case for every notification_template. This is enforced below:
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
From: system@coder.com
2+
To: bobby@coder.com
3+
Subject: Template 'alpha' has been deprecated
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+
Hello Bobby,
14+
15+
The template alpha has been deprecated with the following message:
16+
17+
This template has been replaced by beta
18+
19+
New workspaces may not be created from this template. Existing workspaces w=
20+
ill continue to function normally.
21+
22+
23+
See affected workspaces: http://test.com/workspaces?filter=3Downer%3Ame+tem=
24+
plate%3Aalpha
25+
26+
View template: http://test.com/templates/coder/alpha
27+
28+
--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
29+
Content-Transfer-Encoding: quoted-printable
30+
Content-Type: text/html; charset=UTF-8
31+
32+
<!doctype html>
33+
<html lang=3D"en">
34+
<head>
35+
<meta charset=3D"UTF-8" />
36+
<meta name=3D"viewport" content=3D"width=3Ddevice-width, initial-scale=
37+
=3D1.0" />
38+
<title>Template 'alpha' has been deprecated</title>
39+
</head>
40+
<body style=3D"margin: 0; padding: 0; font-family: -apple-system, system-=
41+
ui, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarel=
42+
l', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; color: #020617=
43+
; background: #f8fafc;">
44+
<div style=3D"max-width: 600px; margin: 20px auto; padding: 60px; borde=
45+
r: 1px solid #e2e8f0; border-radius: 8px; background-color: #fff; text-alig=
46+
n: left; font-size: 14px; line-height: 1.5;">
47+
<div style=3D"text-align: center;">
48+
<img src=3D"https://coder.com/coder-logo-horizontal.png" alt=3D"Cod=
49+
er Logo" style=3D"height: 40px;" />
50+
</div>
51+
<h1 style=3D"text-align: center; font-size: 24px; font-weight: 400; m=
52+
argin: 8px 0 32px; line-height: 1.5;">
53+
Template 'alpha' has been deprecated
54+
</h1>
55+
<div style=3D"line-height: 1.5;">
56+
<p>Hello Bobby,</p>
57+
58+
<p>The template <strong>alpha</strong> has been deprecated with the followi=
59+
ng message:</p>
60+
61+
<p><strong>This template has been replaced by beta</strong></p>
62+
63+
<p>New workspaces may not be created from this template. Existing workspace=
64+
s will continue to function normally.</p>
65+
</div>
66+
<div style=3D"text-align: center; margin-top: 32px;">
67+
=20
68+
<a href=3D"http://test.com/workspaces?filter=3Downer%3Ame+template%=
69+
3Aalpha" style=3D"display: inline-block; padding: 13px 24px; background-col=
70+
or: #020617; color: #f8fafc; text-decoration: none; border-radius: 8px; mar=
71+
gin: 0 4px;">
72+
See affected workspaces
73+
</a>
74+
=20
75+
<a href=3D"http://test.com/templates/coder/alpha" style=3D"display:=
76+
inline-block; padding: 13px 24px; background-color: #020617; color: #f8faf=
77+
c; text-decoration: none; border-radius: 8px; margin: 0 4px;">
78+
View template
79+
</a>
80+
=20
81+
</div>
82+
<div style=3D"border-top: 1px solid #e2e8f0; color: #475569; font-siz=
83+
e: 12px; margin-top: 64px; padding-top: 24px; line-height: 1.6;">
84+
<p>&copy;&nbsp;2024&nbsp;Coder. All rights reserved&nbsp;-&nbsp;<a =
85+
href=3D"http://test.com" style=3D"color: #2563eb; text-decoration: none;">h=
86+
ttp://test.com</a></p>
87+
<p><a href=3D"http://test.com/settings/notifications" style=3D"colo=
88+
r: #2563eb; text-decoration: none;">Click here to manage your notification =
89+
settings</a></p>
90+
<p><a href=3D"http://test.com/settings/notifications?disabled=3Df40=
91+
fae84-55a2-42cd-99fa-b41c1ca64894" style=3D"color: #2563eb; text-decoration=
92+
: none;">Stop receiving emails like this</a></p>
93+
</div>
94+
</div>
95+
</body>
96+
</html>
97+
98+
--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.1",
6+
"notification_name": "Template Deprecated",
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": "See affected workspaces",
15+
"url": "http://test.com/workspaces?filter=owner%3Ame+template%3Aalpha"
16+
},
17+
{
18+
"label": "View template",
19+
"url": "http://test.com/templates/coder/alpha"
20+
}
21+
],
22+
"labels": {
23+
"message": "This template has been replaced by beta",
24+
"organization": "coder",
25+
"template": "alpha"
26+
},
27+
"data": null
28+
},
29+
"title": "Template 'alpha' has been deprecated",
30+
"title_markdown": "Template 'alpha' has been deprecated",
31+
"body": "Hello Bobby,\n\nThe template alpha has been deprecated with the following message:\n\nThis template has been replaced by beta\n\nNew workspaces may not be created from this template. Existing workspaces will continue to function normally.",
32+
"body_markdown": "Hello Bobby,\n\nThe template **alpha** has been deprecated with the following message:\n\n**This template has been replaced by beta**\n\nNew workspaces may not be created from this template. Existing workspaces will continue to function normally."
33+
}

‎coderd/templates.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,12 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
845845
return
846846
}
847847

848+
iftemplate.Deprecated!=updated.Deprecated&&updated.Deprecated!="" {
849+
iferr:=api.notifyUsersOfTemplateDeprecation(ctx,updated);err!=nil {
850+
api.Logger.Error(ctx,"failed to notify users of template deprecation",slog.Error(err))
851+
}
852+
}
853+
848854
ifupdated.UpdatedAt.IsZero() {
849855
aReq.New=template
850856
rw.WriteHeader(http.StatusNotModified)
@@ -855,6 +861,42 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
855861
httpapi.Write(ctx,rw,http.StatusOK,api.convertTemplate(updated))
856862
}
857863

864+
func (api*API)notifyUsersOfTemplateDeprecation(ctx context.Context,template database.Template)error {
865+
workspaces,err:=api.Database.GetWorkspaces(ctx, database.GetWorkspacesParams{
866+
TemplateIDs: []uuid.UUID{template.ID},
867+
})
868+
iferr!=nil {
869+
returnxerrors.Errorf("get workspaces by template id: %w",err)
870+
}
871+
872+
users:=make(map[uuid.UUID]struct{})
873+
for_,workspace:=rangeworkspaces {
874+
users[workspace.OwnerID]=struct{}{}
875+
}
876+
877+
errs:= []error{}
878+
879+
foruserID:=rangeusers {
880+
_,err=api.NotificationsEnqueuer.Enqueue(
881+
//nolint:gocritic // We need the system auth context to be able to send the deprecation notification.
882+
dbauthz.AsSystemRestricted(ctx),
883+
userID,
884+
notifications.TemplateTemplateDeprecated,
885+
map[string]string{
886+
"template":template.Name,
887+
"message":template.Deprecated,
888+
"organization":template.OrganizationName,
889+
},
890+
"notify-users-of-template-deprecation",
891+
)
892+
iferr!=nil {
893+
errs=append(errs,xerrors.Errorf("enqueue notification: %w",err))
894+
}
895+
}
896+
897+
returnerrors.Join(errs...)
898+
}
899+
858900
// @Summary Get template DAUs by ID
859901
// @ID get-template-daus-by-id
860902
// @Security CoderSessionToken

‎enterprise/coderd/templates_test.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"bytes"
55
"context"
66
"net/http"
7+
"slices"
78
"testing"
89
"time"
910

@@ -38,21 +39,36 @@ func TestTemplates(t *testing.T) {
3839
t.Run("Deprecated",func(t*testing.T) {
3940
t.Parallel()
4041

42+
notifyEnq:=&testutil.FakeNotificationsEnqueuer{}
4143
owner,user:=coderdenttest.New(t,&coderdenttest.Options{
4244
Options:&coderdtest.Options{
4345
IncludeProvisionerDaemon:true,
46+
NotificationsEnqueuer:notifyEnq,
4447
},
4548
LicenseOptions:&coderdenttest.LicenseOptions{
4649
Features: license.Features{
4750
codersdk.FeatureAccessControl:1,
4851
},
4952
},
5053
})
51-
client,_:=coderdtest.CreateAnotherUser(t,owner,user.OrganizationID,rbac.RoleTemplateAdmin())
54+
client,secondUser:=coderdtest.CreateAnotherUser(t,owner,user.OrganizationID,rbac.RoleTemplateAdmin())
55+
otherClient,otherUser:=coderdtest.CreateAnotherUser(t,owner,user.OrganizationID,rbac.RoleTemplateAdmin())
56+
5257
version:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
5358
template:=coderdtest.CreateTemplate(t,client,user.OrganizationID,version.ID)
5459
coderdtest.AwaitTemplateVersionJobCompleted(t,client,version.ID)
5560

61+
_=coderdtest.CreateWorkspace(t,owner,template.ID)
62+
_=coderdtest.CreateWorkspace(t,client,template.ID)
63+
64+
// Create another template for testing that users of another template do not
65+
// get a notification.
66+
secondVersion:=coderdtest.CreateTemplateVersion(t,client,user.OrganizationID,nil)
67+
secondTemplate:=coderdtest.CreateTemplate(t,client,user.OrganizationID,secondVersion.ID)
68+
coderdtest.AwaitTemplateVersionJobCompleted(t,client,secondVersion.ID)
69+
70+
_=coderdtest.CreateWorkspace(t,otherClient,secondTemplate.ID)
71+
5672
ctx,cancel:=context.WithTimeout(context.Background(),testutil.WaitLong)
5773
defercancel()
5874

@@ -65,6 +81,32 @@ func TestTemplates(t *testing.T) {
6581
assert.True(t,updated.Deprecated)
6682
assert.NotEmpty(t,updated.DeprecationMessage)
6783

84+
notifs:= []*testutil.Notification{}
85+
for_,notif:=rangenotifyEnq.Sent {
86+
ifnotif.TemplateID==notifications.TemplateTemplateDeprecated {
87+
notifs=append(notifs,notif)
88+
}
89+
}
90+
require.Equal(t,2,len(notifs))
91+
92+
expectedSentTo:= []string{user.UserID.String(),secondUser.ID.String()}
93+
slices.Sort(expectedSentTo)
94+
95+
sentTo:= []string{}
96+
for_,notif:=rangenotifs {
97+
sentTo=append(sentTo,notif.UserID.String())
98+
}
99+
slices.Sort(sentTo)
100+
101+
// Require the notification to have only been sent to the expected users
102+
assert.Equal(t,expectedSentTo,sentTo)
103+
104+
// The previous check should verify this but we're double checking that
105+
// the notification wasn't sent to users not using the template.
106+
for_,notif:=rangenotifs {
107+
assert.NotEqual(t,otherUser.ID,notif.UserID)
108+
}
109+
68110
_,err=client.CreateWorkspace(ctx,user.OrganizationID,codersdk.Me, codersdk.CreateWorkspaceRequest{
69111
TemplateID:template.ID,
70112
Name:"foobar",

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp