Skip to content

Commit 36cadeb

Browse files
committed
Merge remote-tracking branch 'origin/main' into fix-password-validation
2 parents f37ef9e + 5ad4747 commit 36cadeb

Some content is hidden

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

48 files changed

+1259
-276
lines changed

.github/workflows/ci.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ jobs:
9090
- "coderd/**"
9191
- "enterprise/**"
9292
- "examples/*"
93+
- "helm/**"
9394
- "provisioner/**"
9495
- "provisionerd/**"
9596
- "provisionersdk/**"

.github/workflows/security.yaml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ jobs:
9696
# version in the comments will differ. This is also defined in
9797
# ci.yaml.
9898
set -x
99-
cd dogfood
99+
cd dogfood/contents
100100
DOCKER_BUILDKIT=1 docker build . --target proto -t protoc
101101
protoc_path=/usr/local/bin/protoc
102102
docker run --rm --entrypoint cat protoc /tmp/bin/protoc > $protoc_path
@@ -144,16 +144,6 @@ jobs:
144144
path: trivy-results.sarif
145145
retention-days: 7
146146

147-
# Prisma cloud scan runs last because it fails the entire job if it
148-
# detects vulnerabilities. :|
149-
- name: Run Prisma Cloud image scan
150-
uses: PaloAltoNetworks/prisma-cloud-scan@124b48d8325c23f58a35da0f1b4d9a6b54301d05 # v1.6.7
151-
with:
152-
pcc_console_url: ${{ secrets.PRISMA_CLOUD_URL }}
153-
pcc_user: ${{ secrets.PRISMA_CLOUD_ACCESS_KEY }}
154-
pcc_pass: ${{ secrets.PRISMA_CLOUD_SECRET_KEY }}
155-
image_name: ${{ steps.build.outputs.image }}
156-
157147
- name: Send Slack notification on failure
158148
if: ${{ failure() }}
159149
run: |
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DELETE FROM notification_templates WHERE 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/httpapi/websocket.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@ package httpapi
22

33
import (
44
"context"
5+
"errors"
56
"time"
67

8+
"golang.org/x/xerrors"
79
"nhooyr.io/websocket"
810

911
"cdr.dev/slog"
@@ -31,7 +33,8 @@ func Heartbeat(ctx context.Context, conn *websocket.Conn) {
3133
// Heartbeat loops to ping a WebSocket to keep it alive. It calls `exit` on ping
3234
// failure.
3335
func HeartbeatClose(ctx context.Context, logger slog.Logger, exit func(), conn *websocket.Conn) {
34-
ticker := time.NewTicker(15 * time.Second)
36+
interval := 15 * time.Second
37+
ticker := time.NewTicker(interval)
3538
defer ticker.Stop()
3639

3740
for {
@@ -40,12 +43,26 @@ func HeartbeatClose(ctx context.Context, logger slog.Logger, exit func(), conn *
4043
return
4144
case <-ticker.C:
4245
}
43-
err := conn.Ping(ctx)
46+
err := pingWithTimeout(ctx, conn, interval)
4447
if err != nil {
48+
// context.DeadlineExceeded is expected when the client disconnects without sending a close frame
49+
if !errors.Is(err, context.DeadlineExceeded) {
50+
logger.Error(ctx, "failed to heartbeat ping", slog.Error(err))
51+
}
4552
_ = conn.Close(websocket.StatusGoingAway, "Ping failed")
46-
logger.Info(ctx, "failed to heartbeat ping", slog.Error(err))
4753
exit()
4854
return
4955
}
5056
}
5157
}
58+
59+
func pingWithTimeout(ctx context.Context, conn *websocket.Conn, timeout time.Duration) error {
60+
ctx, cancel := context.WithTimeout(ctx, timeout)
61+
defer cancel()
62+
err := conn.Ping(ctx)
63+
if err != nil {
64+
return xerrors.Errorf("failed to ping: %w", err)
65+
}
66+
67+
return nil
68+
}

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/fetcher.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,15 @@ import (
77
"text/template"
88

99
"golang.org/x/xerrors"
10-
11-
"cdr.dev/slog"
1210
)
1311

1412
func (n *notifier) fetchHelpers(ctx context.Context) (map[string]any, error) {
1513
appName, err := n.fetchAppName(ctx)
1614
if err != nil {
17-
n.log.Error(ctx, "failed to fetch app name", slog.Error(err))
1815
return nil, xerrors.Errorf("fetch app name: %w", err)
1916
}
2017
logoURL, err := n.fetchLogoURL(ctx)
2118
if err != nil {
22-
n.log.Error(ctx, "failed to fetch logo URL", slog.Error(err))
2319
return nil, xerrors.Errorf("fetch logo URL: %w", err)
2420
}
2521

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:

coderd/notifications/notifier.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package notifications
33
import (
44
"context"
55
"encoding/json"
6+
"fmt"
67
"sync"
78
"text/template"
89

@@ -27,7 +28,22 @@ const (
2728
notificationsDefaultAppName = "Coder"
2829
)
2930

30-
var errDecorateHelpersFailed = xerrors.New("failed to decorate helpers")
31+
type decorateHelpersError struct {
32+
inner error
33+
}
34+
35+
func (e decorateHelpersError) Error() string {
36+
return fmt.Sprintf("failed to decorate helpers: %s", e.inner.Error())
37+
}
38+
39+
func (e decorateHelpersError) Unwrap() error {
40+
return e.inner
41+
}
42+
43+
func (decorateHelpersError) Is(other error) bool {
44+
_, ok := other.(decorateHelpersError)
45+
return ok
46+
}
3147

3248
// notifier is a consumer of the notifications_messages queue. It dequeues messages from that table and processes them
3349
// through a pipeline of fetch -> prepare -> render -> acquire handler -> deliver.
@@ -164,8 +180,12 @@ func (n *notifier) process(ctx context.Context, success chan<- dispatchResult, f
164180
// A message failing to be prepared correctly should not affect other messages.
165181
deliverFn, err := n.prepare(ctx, msg)
166182
if err != nil {
167-
n.log.Warn(ctx, "dispatcher construction failed", slog.F("msg_id", msg.ID), slog.Error(err))
168-
failure <- n.newFailedDispatch(msg, err, xerrors.Is(err, errDecorateHelpersFailed))
183+
if database.IsQueryCanceledError(err) {
184+
n.log.Debug(ctx, "dispatcher construction canceled", slog.F("msg_id", msg.ID), slog.Error(err))
185+
} else {
186+
n.log.Error(ctx, "dispatcher construction failed", slog.F("msg_id", msg.ID), slog.Error(err))
187+
}
188+
failure <- n.newFailedDispatch(msg, err, xerrors.Is(err, decorateHelpersError{}))
169189
n.metrics.PendingUpdates.Set(float64(len(success) + len(failure)))
170190
continue
171191
}
@@ -226,7 +246,7 @@ func (n *notifier) prepare(ctx context.Context, msg database.AcquireNotification
226246

227247
helpers, err := n.fetchHelpers(ctx)
228248
if err != nil {
229-
return nil, errDecorateHelpersFailed
249+
return nil, decorateHelpersError{err}
230250
}
231251

232252
var title, body string
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+
}

0 commit comments

Comments
 (0)