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: support custom notifications#19751

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
ssncferreira merged 12 commits intomainfromssncferreira/support_custom_notifications
Sep 11, 2025
Merged
Show file tree
Hide file tree
Changes from1 commit
Commits
Show all changes
12 commits
Select commitHold shift + click to select a range
2ab1c4d
feat: support custom notifications
ssncferreiraSep 9, 2025
327ec0d
fix: block system users from sending custom notifications
ssncferreiraSep 10, 2025
0d1144a
fix: cli/notificatins_test.go imports
ssncferreiraSep 10, 2025
203668d
chore: add kind 'custom' type to notification template kind enum
ssncferreiraSep 10, 2025
d3ffd1a
chore: update custom notification request with a content object
ssncferreiraSep 10, 2025
938d010
chore: improve cli description
ssncferreiraSep 10, 2025
9a39693
chore: bypass the per-day notification dedupe
ssncferreiraSep 10, 2025
6b8636d
Merge remote-tracking branch 'origin/main' into ssncferreira/support_…
ssncferreiraSep 10, 2025
80c6b22
fix: fix migration numbers
ssncferreiraSep 10, 2025
657a230
chore: address comments
ssncferreiraSep 11, 2025
681a29f
chore: require both title and message
ssncferreiraSep 11, 2025
14e155e
Merge remote-tracking branch 'origin/main' into ssncferreira/support_…
ssncferreiraSep 11, 2025
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
NextNext commit
feat: support custom notifications
  • Loading branch information
@ssncferreira
ssncferreira committedSep 10, 2025
commit2ab1c4d7151e2f0646bd67fa63f76593f14ef22c
34 changes: 32 additions & 2 deletionscli/notifications.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -16,17 +16,21 @@ func (r *RootCmd) notifications() *serpent.Command {
Short: "Manage Coder notifications",
Long: "Administrators can use these commands to change notification settings.\n" + FormatExamples(
Example{
Description: "Pause Coder notifications. Administrators can temporarily stop notifiers from dispatching messages in case of the target outage (for example: unavailable SMTP server or Webhook not responding).",
Description: "Pause Coder notifications. Administrators can temporarily stop notifiers from dispatching messages in case of the target outage (for example: unavailable SMTP server or Webhook not responding)",
Command: "coder notifications pause",
},
Example{
Description: "Resume Coder notifications",
Command: "coder notifications resume",
},
Example{
Description: "Send a test notification. Administrators can use this to verify the notification target settings.",
Description: "Send a test notification. Administrators can use this to verify the notification target settings",
Command: "coder notifications test",
},
Example{
Description: "Send a custom notification to the requesting user. The recipient is always the requesting user as targeting other users or groups isn’t supported yet",
Command: "coder notifications custom \"Custom Title\" \"Custom Message\"",
},
),
Aliases: []string{"notification"},
Handler: func(inv *serpent.Invocation) error {
Expand All@@ -36,6 +40,7 @@ func (r *RootCmd) notifications() *serpent.Command {
r.pauseNotifications(),
r.resumeNotifications(),
r.testNotifications(),
r.customNotifications(),
},
}
return cmd
Expand DownExpand Up@@ -109,3 +114,28 @@ func (r *RootCmd) testNotifications() *serpent.Command {
}
return cmd
}

func (r *RootCmd) customNotifications() *serpent.Command {
client := new(codersdk.Client)
cmd := &serpent.Command{
Use: "custom <title> <message>",
Short: "Send a custom notification",
Middleware: serpent.Chain(
serpent.RequireNArgs(2),
r.InitClient(client),
),
Handler: func(inv *serpent.Invocation) error {
err := client.PostCustomNotification(inv.Context(), codersdk.CustomNotification{
Title: inv.Args[0],
Message: inv.Args[1],
})
if err != nil {
return xerrors.Errorf("unable to post custom notification: %w", err)
}

_, _ = fmt.Fprintln(inv.Stderr, "A custom notification has been sent.")
return nil
},
}
return cmd
}
63 changes: 63 additions & 0 deletionscli/notifications_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -166,3 +166,66 @@ func TestNotificationsTest(t *testing.T) {
require.Len(t, sent, 0)
})
}

func TestCustomNotifications(t *testing.T) {
t.Parallel()

t.Run("BadRequest", func(t *testing.T) {
t.Parallel()

notifyEnq := &notificationstest.FakeEnqueuer{}

// Given: A member user
ownerClient := coderdtest.New(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
NotificationsEnqueuer: notifyEnq,
})
ownerUser := coderdtest.CreateFirstUser(t, ownerClient)
memberClient, _ := coderdtest.CreateAnotherUser(t, ownerClient, ownerUser.OrganizationID)

// When: The member user attempts to send a custom notification with empty title and message
inv, root := clitest.New(t, "notifications", "custom", "", "")
clitest.SetupConfig(t, memberClient, root)

// Then: an error is expected with no notifications sent
err := inv.Run()
var sdkError *codersdk.Error
require.Error(t, err)
require.ErrorAsf(t, err, &sdkError, "error should be of type *codersdk.Error")
assert.Equal(t, http.StatusBadRequest, sdkError.StatusCode())
require.Equal(t, "Invalid request body", sdkError.Message)

sent := notifyEnq.Sent(notificationstest.WithTemplateID(notifications.TemplateTestNotification))
require.Len(t, sent, 0)
})

t.Run("Success", func(t *testing.T) {
t.Parallel()

notifyEnq := &notificationstest.FakeEnqueuer{}

// Given: A member user
ownerClient := coderdtest.New(t, &coderdtest.Options{
DeploymentValues: coderdtest.DeploymentValues(t),
NotificationsEnqueuer: notifyEnq,
})
ownerUser := coderdtest.CreateFirstUser(t, ownerClient)
memberClient, memberUser := coderdtest.CreateAnotherUser(t, ownerClient, ownerUser.OrganizationID)

// When: The member user attempts to send a custom notification
inv, root := clitest.New(t, "notifications", "custom", "Custom Title", "Custom Message")
clitest.SetupConfig(t, memberClient, root)

// Then: we expect a custom notification to be sent to the member user
err := inv.Run()
require.NoError(t, err)

sent := notifyEnq.Sent(notificationstest.WithTemplateID(notifications.TemplateCustomNotification))
require.Len(t, sent, 1)
require.Equal(t, memberUser.ID, sent[0].UserID)
require.Len(t, sent[0].Labels, 2)
require.Equal(t, "Custom Title", sent[0].Labels["custom_title"])
require.Equal(t, "Custom Message", sent[0].Labels["custom_message"])
require.Equal(t, memberUser.ID.String(), sent[0].CreatedBy)
})
}
11 changes: 9 additions & 2 deletionscli/testdata/coder_notifications_--help.golden
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -12,7 +12,7 @@ USAGE:
from
dispatching messages in case of the target outage (for example: unavailable
SMTP
server or Webhook not responding).:
server or Webhook not responding):

$ coder notifications pause

Expand All@@ -22,11 +22,18 @@ USAGE:

- Send a test notification. Administrators can use this to verify the
notification
target settings.:
target settings:

$ coder notifications test

- Send a custom notification to the requesting user. The recipient is always
the
requesting user as targeting other users or groups isn’t supported yet:

$ coder notifications custom "Custom Title" "Custom Message"

SUBCOMMANDS:
custom Send a custom notification
pause Pause notifications
resume Resume notifications
test Send a test notification
Expand Down
9 changes: 9 additions & 0 deletionscli/testdata/coder_notifications_custom_--help.golden
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
coder v0.0.0-devel

USAGE:
coder notifications custom <title> <message>

Send a custom notification

———
Run `coder --help` for a list of global options.
59 changes: 59 additions & 0 deletionscoderd/apidoc/docs.go
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

53 changes: 53 additions & 0 deletionscoderd/apidoc/swagger.json
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

1 change: 1 addition & 0 deletionscoderd/coderd.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1581,6 +1581,7 @@ func New(options *Options) *API {
})
r.Get("/dispatch-methods", api.notificationDispatchMethods)
r.Post("/test", api.postTestNotification)
r.Post("/custom", api.postCustomNotification)
})
r.Route("/tailnet", func(r chi.Router) {
r.Use(apiKeyMiddleware)
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
DELETE FROM notification_templates WHERE id = '39b1e189-c857-4b0c-877a-511144c18516';

View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
INSERT INTO notification_templates (
id,
name,
title_template,
body_template,
actions,
"group",
method,
kind,
enabled_by_default
)VALUES (
'39b1e189-c857-4b0c-877a-511144c18516',
'Custom Notification',
'{{.Labels.custom_title}}',
'{{.Labels.custom_message}}',
'[]',
'Custom Events',
NULL,
'system'::notification_template_kind,
Copy link
ContributorAuthor

@ssncferreirassncferreiraSep 10, 2025
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

It might make sense to introduce a new notification kindcustom rather than reusingsystem.system notifications are triggered by events within the system, whereas this custom notification is user-initiated and typically relates to events happening outside the system.

This would also require adding a/notifications/custom endpoint and updating the front-end (e.g.,/deployment/notifications) to retrieve both system and custom templates.

Wdyt?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think we should do this. I don't like the idea of piggy-backing on top of "system" notifications here.

ssncferreira reacted with thumbs up emoji
Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Addressed in203668d
I will add the front-end changes to/deployment/notifications in a follow-up PR

true
);
Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp