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

feat: notify users on template deprecation#15195

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
DanielleMaywood merged 11 commits intomainfromdm-notify-users-on-template-deprecation
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
11 commits
Select commitHold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
DELETE FROM notification_templates WHERE id = 'f40fae84-55a2-42cd-99fa-b41c1ca64894';
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
INSERT INTO notification_templates
(id, name, title_template, body_template, "group", actions)
VALUES (
'f40fae84-55a2-42cd-99fa-b41c1ca64894',
'Template Deprecated',
E'Template ''{{.Labels.template}}'' has been deprecated',
E'Hello {{.UserName}},\n\n'||
E'The template **{{.Labels.template}}** has been deprecated with the following message:\n\n' ||
E'**{{.Labels.message}}**\n\n' ||
E'New workspaces may not be created from this template. Existing workspaces will continue to function normally.',
'Template Events',
'[
{
"label": "See affected workspaces",
"url": "{{base_url}}/workspaces?filter=owner%3Ame+template%3A{{.Labels.template}}"
},
{
"label": "View template",
"url": "{{base_url}}/templates/{{.Labels.organization}}/{{.Labels.template}}"
}
]'::jsonb
);
3 changes: 2 additions & 1 deletioncoderd/notifications/events.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -30,7 +30,8 @@ var (

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

TemplateWorkspaceBuildsFailedReport = uuid.MustParse("34a20db2-e9cc-4a93-b0e4-8569699d7a00")
)
14 changes: 14 additions & 0 deletionscoderd/notifications/notifications_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1021,6 +1021,20 @@ func TestNotificationTemplates_Golden(t *testing.T) {
appName: "Custom Application Name",
logoURL: "https://custom.application/logo.png",
},
{
name: "TemplateTemplateDeprecated",
id: notifications.TemplateTemplateDeprecated,
payload: types.MessagePayload{
UserName: "Bobby",
UserEmail: "bobby@coder.com",
UserUsername: "bobby",
Labels: map[string]string{
"template": "alpha",
"message": "This template has been replaced by beta",
"organization": "coder",
},
},
},
}

// We must have a test case for every notification_template. This is enforced below:
Expand Down
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
From: system@coder.com
To: bobby@coder.com
Subject: Template 'alpha' has been deprecated
Message-Id: 02ee4935-73be-4fa1-a290-ff9999026b13@blush-whale-48
Date: Fri, 11 Oct 2024 09:03:06 +0000
Content-Type: multipart/alternative; boundary=bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
MIME-Version: 1.0

--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain; charset=UTF-8

Hello Bobby,

The template alpha has been deprecated with the following message:

This template has been replaced by beta

New workspaces may not be created from this template. Existing workspaces w=
ill continue to function normally.


See affected workspaces: http://test.com/workspaces?filter=3Downer%3Ame+tem=
plate%3Aalpha

View template: http://test.com/templates/coder/alpha

--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4
Content-Transfer-Encoding: quoted-printable
Content-Type: text/html; charset=UTF-8

<!doctype html>
<html lang=3D"en">
<head>
<meta charset=3D"UTF-8" />
<meta name=3D"viewport" content=3D"width=3Ddevice-width, initial-scale=
=3D1.0" />
<title>Template 'alpha' has been deprecated</title>
</head>
<body style=3D"margin: 0; padding: 0; font-family: -apple-system, system-=
ui, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarel=
l', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif; color: #020617=
; background: #f8fafc;">
<div style=3D"max-width: 600px; margin: 20px auto; padding: 60px; borde=
r: 1px solid #e2e8f0; border-radius: 8px; background-color: #fff; text-alig=
n: left; font-size: 14px; line-height: 1.5;">
<div style=3D"text-align: center;">
<img src=3D"https://coder.com/coder-logo-horizontal.png" alt=3D"Cod=
er Logo" style=3D"height: 40px;" />
</div>
<h1 style=3D"text-align: center; font-size: 24px; font-weight: 400; m=
argin: 8px 0 32px; line-height: 1.5;">
Template 'alpha' has been deprecated
</h1>
<div style=3D"line-height: 1.5;">
<p>Hello Bobby,</p>

<p>The template <strong>alpha</strong> has been deprecated with the followi=
ng message:</p>

<p><strong>This template has been replaced by beta</strong></p>

<p>New workspaces may not be created from this template. Existing workspace=
s will continue to function normally.</p>
</div>
<div style=3D"text-align: center; margin-top: 32px;">
=20
<a href=3D"http://test.com/workspaces?filter=3Downer%3Ame+template%=
3Aalpha" style=3D"display: inline-block; padding: 13px 24px; background-col=
or: #020617; color: #f8fafc; text-decoration: none; border-radius: 8px; mar=
gin: 0 4px;">
See affected workspaces
</a>
=20
<a href=3D"http://test.com/templates/coder/alpha" style=3D"display:=
inline-block; padding: 13px 24px; background-color: #020617; color: #f8faf=
c; text-decoration: none; border-radius: 8px; margin: 0 4px;">
View template
</a>
=20
</div>
<div style=3D"border-top: 1px solid #e2e8f0; color: #475569; font-siz=
e: 12px; margin-top: 64px; padding-top: 24px; line-height: 1.6;">
<p>&copy;&nbsp;2024&nbsp;Coder. All rights reserved&nbsp;-&nbsp;<a =
href=3D"http://test.com" style=3D"color: #2563eb; text-decoration: none;">h=
ttp://test.com</a></p>
<p><a href=3D"http://test.com/settings/notifications" style=3D"colo=
r: #2563eb; text-decoration: none;">Click here to manage your notification =
settings</a></p>
<p><a href=3D"http://test.com/settings/notifications?disabled=3Df40=
fae84-55a2-42cd-99fa-b41c1ca64894" style=3D"color: #2563eb; text-decoration=
: none;">Stop receiving emails like this</a></p>
</div>
</div>
</body>
</html>

--bbe61b741255b6098bb6b3c1f41b885773df633cb18d2a3002b68e4bc9c4--
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
{
"_version": "1.1",
"msg_id": "00000000-0000-0000-0000-000000000000",
"payload": {
"_version": "1.1",
"notification_name": "Template Deprecated",
"notification_template_id": "00000000-0000-0000-0000-000000000000",
"user_id": "00000000-0000-0000-0000-000000000000",
"user_email": "bobby@coder.com",
"user_name": "Bobby",
"user_username": "bobby",
"actions": [
{
"label": "See affected workspaces",
"url": "http://test.com/workspaces?filter=owner%3Ame+template%3Aalpha"
},
{
"label": "View template",
"url": "http://test.com/templates/coder/alpha"
}
],
"labels": {
"message": "This template has been replaced by beta",
"organization": "coder",
"template": "alpha"
},
"data": null
},
"title": "Template 'alpha' has been deprecated",
"title_markdown": "Template 'alpha' has been deprecated",
"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.",
"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."
}
42 changes: 42 additions & 0 deletionscoderd/templates.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -845,6 +845,12 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
return
}

if template.Deprecated != updated.Deprecated && updated.Deprecated != "" {
if err := api.notifyUsersOfTemplateDeprecation(ctx, updated); err != nil {
api.Logger.Error(ctx, "failed to notify users of template deprecation", slog.Error(err))
}
}

if updated.UpdatedAt.IsZero() {
aReq.New = template
rw.WriteHeader(http.StatusNotModified)
Expand All@@ -855,6 +861,42 @@ func (api *API) patchTemplateMeta(rw http.ResponseWriter, r *http.Request) {
httpapi.Write(ctx, rw, http.StatusOK, api.convertTemplate(updated))
}

func (api *API) notifyUsersOfTemplateDeprecation(ctx context.Context, template database.Template) error {
workspaces, err := api.Database.GetWorkspaces(ctx, database.GetWorkspacesParams{
TemplateIDs: []uuid.UUID{template.ID},
})
if err != nil {
return xerrors.Errorf("get workspaces by template id: %w", err)
}

users := make(map[uuid.UUID]struct{})
for _, workspace := range workspaces {
users[workspace.OwnerID] = struct{}{}
}

errs := []error{}

for userID := range users {
_, err = api.NotificationsEnqueuer.Enqueue(
//nolint:gocritic // We need the system auth context to be able to send the deprecation notification.
dbauthz.AsSystemRestricted(ctx),
userID,
notifications.TemplateTemplateDeprecated,
map[string]string{
"template": template.Name,
"message": template.Deprecated,
"organization": template.OrganizationName,
},
"notify-users-of-template-deprecation",
)
if err != nil {
errs = append(errs, xerrors.Errorf("enqueue notification: %w", err))
}
}

return errors.Join(errs...)
}

// @Summary Get template DAUs by ID
// @ID get-template-daus-by-id
// @Security CoderSessionToken
Expand Down
44 changes: 43 additions & 1 deletionenterprise/coderd/templates_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,6 +4,7 @@ import (
"bytes"
"context"
"net/http"
"slices"
"testing"
"time"

Expand DownExpand Up@@ -38,21 +39,36 @@ func TestTemplates(t *testing.T) {
t.Run("Deprecated", func(t *testing.T) {
t.Parallel()

notifyEnq := &testutil.FakeNotificationsEnqueuer{}
owner, user := coderdenttest.New(t, &coderdenttest.Options{
Options: &coderdtest.Options{
IncludeProvisionerDaemon: true,
NotificationsEnqueuer: notifyEnq,
},
LicenseOptions: &coderdenttest.LicenseOptions{
Features: license.Features{
codersdk.FeatureAccessControl: 1,
},
},
})
client, _ := coderdtest.CreateAnotherUser(t, owner, user.OrganizationID, rbac.RoleTemplateAdmin())
client, secondUser := coderdtest.CreateAnotherUser(t, owner, user.OrganizationID, rbac.RoleTemplateAdmin())
otherClient, otherUser := coderdtest.CreateAnotherUser(t, owner, user.OrganizationID, rbac.RoleTemplateAdmin())

version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)

_ = coderdtest.CreateWorkspace(t, owner, template.ID)
_ = coderdtest.CreateWorkspace(t, client, template.ID)

// Create another template for testing that users of another template do not
// get a notification.
secondVersion := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, nil)
secondTemplate := coderdtest.CreateTemplate(t, client, user.OrganizationID, secondVersion.ID)
coderdtest.AwaitTemplateVersionJobCompleted(t, client, secondVersion.ID)

_ = coderdtest.CreateWorkspace(t, otherClient, secondTemplate.ID)

ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

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

notifs := []*testutil.Notification{}
for _, notif := range notifyEnq.Sent {
if notif.TemplateID == notifications.TemplateTemplateDeprecated {
notifs = append(notifs, notif)
}
}
require.Equal(t, 2, len(notifs))

expectedSentTo := []string{user.UserID.String(), secondUser.ID.String()}
slices.Sort(expectedSentTo)

sentTo := []string{}
for _, notif := range notifs {
sentTo = append(sentTo, notif.UserID.String())
}
slices.Sort(sentTo)

// Require the notification to have only been sent to the expected users
assert.Equal(t, expectedSentTo, sentTo)

// The previous check should verify this but we're double checking that
// the notification wasn't sent to users not using the template.
for _, notif := range notifs {
assert.NotEqual(t, otherUser.ID, notif.UserID)
}

_, err = client.CreateWorkspace(ctx, user.OrganizationID, codersdk.Me, codersdk.CreateWorkspaceRequest{
TemplateID: template.ID,
Name: "foobar",
Expand Down
Loading

[8]ページ先頭

©2009-2025 Movatter.jp