Skip to content

Commit f64b7bb

Browse files
committed
Merge remote-tracking branch 'origin/main' into cj/dbcrypt
2 parents 4d28746 + 5993f85 commit f64b7bb

37 files changed

+836
-504
lines changed

.github/dependabot.yaml

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ updates:
88
timezone: "America/Chicago"
99
labels: []
1010
commit-message:
11-
prefix: "chore"
11+
prefix: "ci"
1212
ignore:
1313
# These actions deliver the latest versions by updating the major
1414
# release tag, so ignore minor and patch versions
@@ -117,11 +117,6 @@ updates:
117117
- "@eslint*"
118118
- "@typescript-eslint/eslint-plugin"
119119
- "@typescript-eslint/parser"
120-
jest:
121-
patterns:
122-
- "jest*"
123-
- "@swc/jest"
124-
- "@types/jest"
125120

126121
- package-ecosystem: "npm"
127122
directory: "/offlinedocs/"
@@ -146,20 +141,6 @@ updates:
146141
- version-update:semver-major
147142

148143
# Update dogfood.
149-
- package-ecosystem: "docker"
150-
directory: "/dogfood/"
151-
schedule:
152-
interval: "weekly"
153-
time: "06:00"
154-
timezone: "America/Chicago"
155-
commit-message:
156-
prefix: "chore"
157-
labels: []
158-
groups:
159-
dogfood-docker:
160-
patterns:
161-
- "*"
162-
163144
- package-ecosystem: "terraform"
164145
directory: "/dogfood/"
165146
schedule:

.github/workflows/ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ jobs:
137137
138138
# Check for any typos
139139
- name: Check for typos
140-
uses: crate-ci/typos@v1.16.6
140+
uses: crate-ci/typos@v1.16.8
141141
with:
142142
config: .github/workflows/typos.toml
143143

cli/templateplan.go

Lines changed: 0 additions & 18 deletions
This file was deleted.

cli/templates.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ func (r *RootCmd) templates() *clibase.Cmd {
3737
r.templateEdit(),
3838
r.templateInit(),
3939
r.templateList(),
40-
r.templatePlan(),
4140
r.templatePush(),
4241
r.templateVersions(),
4342
r.templateDelete(),

cli/testdata/coder_templates_--help.golden

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ Templates are written in standard Terraform and describe the infrastructure for
2424
edit Edit the metadata of a template by name.
2525
init Get started with a templated template.
2626
list List all the templates available for the organization
27-
plan Plan a template push from the current directory
2827
pull Download the latest version of a template to a path.
2928
push Push a new template version from the current directory or as
3029
specified by flag

coderd/httpapi/cookie.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ func StripCoderCookies(header string) string {
2323
if name == codersdk.SessionTokenCookie ||
2424
name == codersdk.OAuth2StateCookie ||
2525
name == codersdk.OAuth2RedirectCookie ||
26-
name == codersdk.DevURLSessionTokenCookie ||
27-
name == codersdk.DevURLSignedAppTokenCookie {
26+
name == codersdk.PathAppSessionTokenCookie ||
27+
name == codersdk.SubdomainAppSessionTokenCookie ||
28+
name == codersdk.SignedAppTokenCookie {
2829
continue
2930
}
3031
cookies = append(cookies, part)

coderd/httpmw/apikey.go

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -453,10 +453,10 @@ func ExtractAPIKey(rw http.ResponseWriter, r *http.Request, cfg ExtractAPIKeyCon
453453
// APITokenFromRequest returns the api token from the request.
454454
// Find the session token from:
455455
// 1: The cookie
456-
// 1: The devurl cookie
457-
// 3: The old cookie
458-
// 4. The coder_session_token query parameter
459-
// 5. The custom auth header
456+
// 2. The coder_session_token query parameter
457+
// 3. The custom auth header
458+
//
459+
// API tokens for apps are read from workspaceapps/cookies.go.
460460
func APITokenFromRequest(r *http.Request) string {
461461
cookie, err := r.Cookie(codersdk.SessionTokenCookie)
462462
if err == nil && cookie.Value != "" {
@@ -473,11 +473,6 @@ func APITokenFromRequest(r *http.Request) string {
473473
return headerValue
474474
}
475475

476-
cookie, err = r.Cookie(codersdk.DevURLSessionTokenCookie)
477-
if err == nil && cookie.Value != "" {
478-
return cookie.Value
479-
}
480-
481476
return ""
482477
}
483478

coderd/workspaceagents.go

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/go-chi/chi/v5"
2424
"github.com/google/uuid"
2525
"golang.org/x/exp/maps"
26+
"golang.org/x/exp/slices"
2627
"golang.org/x/mod/semver"
2728
"golang.org/x/sync/errgroup"
2829
"golang.org/x/xerrors"
@@ -481,6 +482,15 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
481482
return
482483
}
483484

485+
workspace, err := api.Database.GetWorkspaceByAgentID(ctx, workspaceAgent.ID)
486+
if err != nil {
487+
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
488+
Message: "Internal error fetching workspace by agent id.",
489+
Detail: err.Error(),
490+
})
491+
return
492+
}
493+
484494
api.WebsocketWaitMutex.Lock()
485495
api.WebsocketWaitGroup.Add(1)
486496
api.WebsocketWaitMutex.Unlock()
@@ -556,7 +566,8 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
556566
go func() {
557567
defer close(bufferedLogs)
558568

559-
for {
569+
keepGoing := true
570+
for keepGoing {
560571
select {
561572
case <-ctx.Done():
562573
return
@@ -565,6 +576,18 @@ func (api *API) workspaceAgentLogs(rw http.ResponseWriter, r *http.Request) {
565576
t.Reset(recheckInterval)
566577
}
567578

579+
agents, err := api.Database.GetWorkspaceAgentsInLatestBuildByWorkspaceID(ctx, workspace.ID)
580+
if err != nil {
581+
if xerrors.Is(err, context.Canceled) {
582+
return
583+
}
584+
logger.Warn(ctx, "failed to get workspace agents in latest build", slog.Error(err))
585+
continue
586+
}
587+
// If the agent is no longer in the latest build, we can stop after
588+
// checking once.
589+
keepGoing = slices.ContainsFunc(agents, func(agent database.WorkspaceAgent) bool { return agent.ID == workspaceAgent.ID })
590+
568591
logs, err := api.Database.GetWorkspaceAgentLogsAfter(ctx, database.GetWorkspaceAgentLogsAfterParams{
569592
AgentID: workspaceAgent.ID,
570593
CreatedAfter: lastSentLogID,
@@ -878,13 +901,15 @@ func (api *API) derpMapUpdates(rw http.ResponseWriter, r *http.Request) {
878901
})
879902
return
880903
}
881-
nconn := websocket.NetConn(ctx, ws, websocket.MessageBinary)
904+
ctx, nconn := websocketNetConn(ctx, ws, websocket.MessageBinary)
882905
defer nconn.Close()
883906

884907
// Slurp all packets from the connection into io.Discard so pongs get sent
885-
// by the websocket package.
908+
// by the websocket package. We don't do any reads ourselves so this is
909+
// necessary.
886910
go func() {
887911
_, _ = io.Copy(io.Discard, nconn)
912+
_ = nconn.Close()
888913
}()
889914

890915
go func(ctx context.Context) {
@@ -899,13 +924,11 @@ func (api *API) derpMapUpdates(rw http.ResponseWriter, r *http.Request) {
899924
return
900925
}
901926

902-
// We don't need a context that times out here because the ping will
903-
// eventually go through. If the context times out, then other
904-
// websocket read operations will receive an error, obfuscating the
905-
// actual problem.
927+
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
906928
err := ws.Ping(ctx)
929+
cancel()
907930
if err != nil {
908-
_ = ws.Close(websocket.StatusInternalError, err.Error())
931+
_ = nconn.Close()
909932
return
910933
}
911934
}
@@ -920,7 +943,7 @@ func (api *API) derpMapUpdates(rw http.ResponseWriter, r *http.Request) {
920943
if lastDERPMap == nil || !tailnet.CompareDERPMaps(lastDERPMap, derpMap) {
921944
err := json.NewEncoder(nconn).Encode(derpMap)
922945
if err != nil {
923-
_ = ws.Close(websocket.StatusInternalError, err.Error())
946+
_ = nconn.Close()
924947
return
925948
}
926949
lastDERPMap = derpMap

coderd/workspaceagents_test.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,91 @@ func TestWorkspaceAgentStartupLogs(t *testing.T) {
242242
require.Equal(t, "testing", logChunk[0].Output)
243243
require.Equal(t, "testing2", logChunk[1].Output)
244244
})
245+
t.Run("Close logs on outdated build", func(t *testing.T) {
246+
t.Parallel()
247+
ctx := testutil.Context(t, testutil.WaitMedium)
248+
client := coderdtest.New(t, &coderdtest.Options{
249+
IncludeProvisionerDaemon: true,
250+
})
251+
user := coderdtest.CreateFirstUser(t, client)
252+
authToken := uuid.NewString()
253+
version := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, &echo.Responses{
254+
Parse: echo.ParseComplete,
255+
ProvisionPlan: echo.PlanComplete,
256+
ProvisionApply: []*proto.Response{{
257+
Type: &proto.Response_Apply{
258+
Apply: &proto.ApplyComplete{
259+
Resources: []*proto.Resource{{
260+
Name: "example",
261+
Type: "aws_instance",
262+
Agents: []*proto.Agent{{
263+
Id: uuid.NewString(),
264+
Auth: &proto.Agent_Token{
265+
Token: authToken,
266+
},
267+
}},
268+
}},
269+
},
270+
},
271+
}},
272+
})
273+
template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version.ID)
274+
coderdtest.AwaitTemplateVersionJob(t, client, version.ID)
275+
workspace := coderdtest.CreateWorkspace(t, client, user.OrganizationID, template.ID)
276+
build := coderdtest.AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
277+
278+
agentClient := agentsdk.New(client.URL)
279+
agentClient.SetSessionToken(authToken)
280+
err := agentClient.PatchLogs(ctx, agentsdk.PatchLogs{
281+
Logs: []agentsdk.Log{
282+
{
283+
CreatedAt: database.Now(),
284+
Output: "testing",
285+
},
286+
},
287+
})
288+
require.NoError(t, err)
289+
290+
logs, closer, err := client.WorkspaceAgentLogsAfter(ctx, build.Resources[0].Agents[0].ID, 0, true)
291+
require.NoError(t, err)
292+
defer func() {
293+
_ = closer.Close()
294+
}()
295+
296+
first := make(chan struct{})
297+
go func() {
298+
select {
299+
case <-ctx.Done():
300+
assert.Fail(t, "context done while waiting in goroutine")
301+
case <-logs:
302+
close(first)
303+
}
304+
}()
305+
select {
306+
case <-ctx.Done():
307+
require.FailNow(t, "context done while waiting for first log")
308+
case <-first:
309+
}
310+
311+
_ = coderdtest.CreateWorkspaceBuild(t, client, workspace, database.WorkspaceTransitionStart)
312+
313+
// Send a new log message to trigger a re-check.
314+
err = agentClient.PatchLogs(ctx, agentsdk.PatchLogs{
315+
Logs: []agentsdk.Log{
316+
{
317+
CreatedAt: database.Now(),
318+
Output: "testing2",
319+
},
320+
},
321+
})
322+
require.NoError(t, err)
323+
324+
select {
325+
case <-ctx.Done():
326+
require.FailNow(t, "context done while waiting for logs close")
327+
case <-logs:
328+
}
329+
})
245330
t.Run("PublishesOnOverflow", func(t *testing.T) {
246331
t.Parallel()
247332
ctx := testutil.Context(t, testutil.WaitMedium)

0 commit comments

Comments
 (0)