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

Commit68bcfb0

Browse files
committed
Merge branch 'main' of github.com:/coder/coder into bq/implement-notifications
2 parents95c784a +a5e4bf3 commit68bcfb0

File tree

60 files changed

+478
-301
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+478
-301
lines changed

‎.github/actions/setup-tf/action.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ runs:
77
-name:Install Terraform
88
uses:hashicorp/setup-terraform@v3
99
with:
10-
terraform_version:1.8.4
10+
terraform_version:1.9.2
1111
terraform_wrapper:false

‎.github/workflows/ci.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ jobs:
170170
171171
# Check for any typos
172172
-name:Check for typos
173-
uses:crate-ci/typos@v1.23.1
173+
uses:crate-ci/typos@v1.23.2
174174
with:
175175
config:.github/workflows/typos.toml
176176

‎.github/workflows/security.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ jobs:
114114
echo "image=$(cat "$image_job")" >> $GITHUB_OUTPUT
115115
116116
-name:Run Trivy vulnerability scanner
117-
uses:aquasecurity/trivy-action@7c2007bcb556501da015201bcba5aa14069b74e2
117+
uses:aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8
118118
with:
119119
image-ref:${{ steps.build.outputs.image }}
120120
format:sarif
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DELETEFROM notification_templatesWHERE id='381df2a9-c0c0-4749-420f-80a9280c66f9';
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
INSERT INTO notification_templates (id, name, title_template, body_template,"group", actions)
2+
VALUES ('381df2a9-c0c0-4749-420f-80a9280c66f9','Workspace Autobuild Failed', E'Workspace "{{.Labels.name}}" autobuild failed',
3+
E'Hi {{.UserName}}\n\Automatic build of your workspace **{{.Labels.name}}** failed.\nThe specified reason was "**{{.Labels.reason}}**".',
4+
'Workspace Events','[
5+
{
6+
"label": "View workspace",
7+
"url": "{{ base_url }}/@{{.UserName}}/{{.Labels.name}}"
8+
}
9+
]'::jsonb);

‎coderd/notifications/enqueuer.go‎

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func (s *StoreEnqueuer) Enqueue(ctx context.Context, userID, templateID uuid.UUI
8080
// buildPayload creates the payload that the notification will for variable substitution and/or routing.
8181
// The payload contains information about the recipient, the event that triggered the notification, and any subsequent
8282
// actions which can be taken by the recipient.
83-
func (s*StoreEnqueuer)buildPayload(ctx context.Context,userID uuid.UUID,templateID uuid.UUID,labelsmap[string]string) (*types.MessagePayload,error) {
83+
func (s*StoreEnqueuer)buildPayload(ctx context.Context,userID,templateID uuid.UUID,labelsmap[string]string) (*types.MessagePayload,error) {
8484
metadata,err:=s.store.FetchNewMessageMetadata(ctx, database.FetchNewMessageMetadataParams{
8585
UserID:userID,
8686
NotificationTemplateID:templateID,
@@ -89,8 +89,21 @@ func (s *StoreEnqueuer) buildPayload(ctx context.Context, userID uuid.UUID, temp
8989
returnnil,xerrors.Errorf("new message metadata: %w",err)
9090
}
9191

92+
payload:= types.MessagePayload{
93+
Version:"1.0",
94+
95+
NotificationName:metadata.NotificationName,
96+
97+
UserID:metadata.UserID.String(),
98+
UserEmail:metadata.UserEmail,
99+
UserName:metadata.UserName,
100+
101+
Labels:labels,
102+
// No actions yet
103+
}
104+
92105
// Execute any templates in actions.
93-
out,err:=render.GoTemplate(string(metadata.Actions),types.MessagePayload{},s.helpers)
106+
out,err:=render.GoTemplate(string(metadata.Actions),payload,s.helpers)
94107
iferr!=nil {
95108
returnnil,xerrors.Errorf("render actions: %w",err)
96109
}
@@ -100,19 +113,8 @@ func (s *StoreEnqueuer) buildPayload(ctx context.Context, userID uuid.UUID, temp
100113
iferr=json.Unmarshal(metadata.Actions,&actions);err!=nil {
101114
returnnil,xerrors.Errorf("new message metadata: parse template actions: %w",err)
102115
}
103-
104-
return&types.MessagePayload{
105-
Version:"1.0",
106-
107-
NotificationName:metadata.NotificationName,
108-
109-
UserID:metadata.UserID.String(),
110-
UserEmail:metadata.UserEmail,
111-
UserName:metadata.UserName,
112-
113-
Actions:actions,
114-
Labels:labels,
115-
},nil
116+
payload.Actions=actions
117+
return&payload,nil
116118
}
117119

118120
// NoopEnqueuer implements the Enqueuer interface but performs a noop.

‎coderd/notifications/events.go‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,8 @@ import "github.com/google/uuid"
66
// TODO: autogenerate these.
77

88
// Workspace-related events.
9-
varTemplateWorkspaceDeleted=uuid.MustParse("f517da0b-cdc9-410f-ab89-a86107c420ed")
10-
varTemplateWorkspaceDormant=uuid.MustParse("123e4567-e89b-12d3-a456-426614174000")
9+
var (
10+
TemplateWorkspaceDeleted=uuid.MustParse("f517da0b-cdc9-410f-ab89-a86107c420ed")
11+
WorkspaceAutobuildFailed=uuid.MustParse("381df2a9-c0c0-4749-420f-80a9280c66f9")
12+
TemplateWorkspaceDormant=uuid.MustParse("123e4567-e89b-12d3-a456-426614174000")
13+
)

‎coderd/notifications/manager_test.go‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,11 @@ func TestBuildPayload(t *testing.T) {
9898

9999
// GIVEN: a set of helpers to be injected into the templates
100100
constlabel="Click here!"
101-
consturl="http://xyz.com/"
101+
constbaseURL="http://xyz.com"
102+
consturl=baseURL+"/@bobby/my-workspace"
102103
helpers:=map[string]any{
103104
"my_label":func()string {returnlabel },
104-
"my_url":func()string {returnurl },
105+
"my_url":func()string {returnbaseURL },
105106
}
106107

107108
// GIVEN: an enqueue interceptor which returns mock metadata
@@ -112,7 +113,7 @@ func TestBuildPayload(t *testing.T) {
112113
actions:= []types.TemplateAction{
113114
{
114115
Label:"{{ my_label }}",
115-
URL:"{{ my_url }}",
116+
URL:"{{ my_url }}/@{{.UserName}}/{{.Labels.name}}",
116117
},
117118
}
118119
out,err:=json.Marshal(actions)
@@ -131,7 +132,9 @@ func TestBuildPayload(t *testing.T) {
131132
require.NoError(t,err)
132133

133134
// WHEN: a notification is enqueued
134-
_,err=enq.Enqueue(ctx,uuid.New(),notifications.TemplateWorkspaceDeleted,nil,"test")
135+
_,err=enq.Enqueue(ctx,uuid.New(),notifications.TemplateWorkspaceDeleted,map[string]string{
136+
"name":"my-workspace",
137+
},"test")
135138
require.NoError(t,err)
136139

137140
// THEN: expect that a payload will be constructed and have the expected values

‎coderd/notifications/render/gotmpl_test.go‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,23 @@ func TestGoTemplate(t *testing.T) {
3838
expectedOutput:userEmail,
3939
expectedErr:nil,
4040
},
41+
{
42+
name:"render workspace URL",
43+
in:`[{
44+
"label": "View workspace",
45+
"url": "{{ base_url }}/@{{.UserName}}/{{.Labels.name}}"
46+
}]`,
47+
payload: types.MessagePayload{
48+
UserName:"johndoe",
49+
Labels:map[string]string{
50+
"name":"my-workspace",
51+
},
52+
},
53+
expectedOutput:`[{
54+
"label": "View workspace",
55+
"url": "https://mocked-server-address/@johndoe/my-workspace"
56+
}]`,
57+
},
4158
}
4259

4360
for_,tc:=rangetests {
@@ -46,7 +63,9 @@ func TestGoTemplate(t *testing.T) {
4663
t.Run(tc.name,func(t*testing.T) {
4764
t.Parallel()
4865

49-
out,err:=render.GoTemplate(tc.in,tc.payload,nil)
66+
out,err:=render.GoTemplate(tc.in,tc.payload,map[string]any{
67+
"base_url":func()string {return"https://mocked-server-address" },
68+
})
5069
iftc.expectedErr==nil {
5170
require.NoError(t,err)
5271
}else {

‎coderd/provisionerdserver/provisionerdserver.go‎

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -982,12 +982,18 @@ func (s *server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*proto.
982982
}
983983

984984
varbuild database.WorkspaceBuild
985+
varworkspace database.Workspace
985986
err=s.Database.InTx(func(db database.Store)error {
986987
build,err=db.GetWorkspaceBuildByID(ctx,input.WorkspaceBuildID)
987988
iferr!=nil {
988989
returnxerrors.Errorf("get workspace build: %w",err)
989990
}
990991

992+
workspace,err=db.GetWorkspaceByID(ctx,build.WorkspaceID)
993+
iferr!=nil {
994+
returnxerrors.Errorf("get workspace: %w",err)
995+
}
996+
991997
ifjobType.WorkspaceBuild.State!=nil {
992998
err=db.UpdateWorkspaceBuildProvisionerStateByID(ctx, database.UpdateWorkspaceBuildProvisionerStateByIDParams{
993999
ID:input.WorkspaceBuildID,
@@ -1014,6 +1020,8 @@ func (s *server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*proto.
10141020
returnnil,err
10151021
}
10161022

1023+
s.notifyWorkspaceBuildFailed(ctx,workspace,build)
1024+
10171025
err=s.Pubsub.Publish(codersdk.WorkspaceNotifyChannel(build.WorkspaceID), []byte{})
10181026
iferr!=nil {
10191027
returnnil,xerrors.Errorf("update workspace: %w",err)
@@ -1087,6 +1095,27 @@ func (s *server) FailJob(ctx context.Context, failJob *proto.FailedJob) (*proto.
10871095
return&proto.Empty{},nil
10881096
}
10891097

1098+
func (s*server)notifyWorkspaceBuildFailed(ctx context.Context,workspace database.Workspace,build database.WorkspaceBuild) {
1099+
varreasonstring
1100+
ifbuild.Reason.Valid()&&build.Reason==database.BuildReasonInitiator {
1101+
return// failed workspace build initiated by a user should not notify
1102+
}
1103+
reason=string(build.Reason)
1104+
initiator:="autobuild"
1105+
1106+
if_,err:=s.NotificationEnqueuer.Enqueue(ctx,workspace.OwnerID,notifications.WorkspaceAutobuildFailed,
1107+
map[string]string{
1108+
"name":workspace.Name,
1109+
"initiator":initiator,
1110+
"reason":reason,
1111+
},"provisionerdserver",
1112+
// Associate this notification with all the related entities.
1113+
workspace.ID,workspace.OwnerID,workspace.TemplateID,workspace.OrganizationID,
1114+
);err!=nil {
1115+
s.Logger.Warn(ctx,"failed to notify of failed workspace autobuild",slog.Error(err))
1116+
}
1117+
}
1118+
10901119
// CompleteJob is triggered by a provision daemon to mark a provisioner job as completed.
10911120
func (s*server)CompleteJob(ctx context.Context,completed*proto.CompletedJob) (*proto.Empty,error) {
10921121
ctx,span:=s.startTrace(ctx,tracing.FuncName())
@@ -1523,6 +1552,7 @@ func (s *server) CompleteJob(ctx context.Context, completed *proto.CompletedJob)
15231552

15241553
func (s*server)notifyWorkspaceDeleted(ctx context.Context,workspace database.Workspace,build database.WorkspaceBuild) {
15251554
varreasonstring
1555+
initiator:=build.InitiatorByUsername
15261556
ifbuild.Reason.Valid() {
15271557
switchbuild.Reason {
15281558
casedatabase.BuildReasonInitiator:
@@ -1534,6 +1564,7 @@ func (s *server) notifyWorkspaceDeleted(ctx context.Context, workspace database.
15341564
reason="initiated by user"
15351565
casedatabase.BuildReasonAutodelete:
15361566
reason="autodeleted due to dormancy"
1567+
initiator="autobuild"
15371568
default:
15381569
reason=string(build.Reason)
15391570
}
@@ -1545,9 +1576,9 @@ func (s *server) notifyWorkspaceDeleted(ctx context.Context, workspace database.
15451576

15461577
if_,err:=s.NotificationEnqueuer.Enqueue(ctx,workspace.OwnerID,notifications.TemplateWorkspaceDeleted,
15471578
map[string]string{
1548-
"name":workspace.Name,
1549-
"initiatedBy":build.InitiatorByUsername,
1550-
"reason":reason,
1579+
"name":workspace.Name,
1580+
"reason":reason,
1581+
"initiator":initiator,
15511582
},"provisionerdserver",
15521583
// Associate this notification with all the related entities.
15531584
workspace.ID,workspace.OwnerID,workspace.TemplateID,workspace.OrganizationID,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp