Skip to content

Commit 180212c

Browse files
committed
Merge branch 'main' into jon/installmsg
2 parents fc2c926 + aeb4112 commit 180212c

File tree

119 files changed

+3835
-3619
lines changed

Some content is hidden

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

119 files changed

+3835
-3619
lines changed

.github/workflows/ci.yaml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -516,7 +516,8 @@ jobs:
516516
NODE_OPTIONS: "--max_old_space_size=4096"
517517
STORYBOOK: true
518518
with:
519-
buildScriptName: "storybook:build"
519+
# Do a fast, testing build for change previews
520+
buildScriptName: "storybook:ci"
520521
exitOnceUploaded: true
521522
# This will prevent CI from failing when Chromatic detects visual changes
522523
exitZeroOnChanges: true
@@ -530,6 +531,8 @@ jobs:
530531
# Run TurboSnap to trace file dependencies to related stories
531532
# and tell chromatic to only take snapshots of relevent stories
532533
onlyChanged: true
534+
# Avoid uploading single files, because that's very slow
535+
zip: true
533536

534537
# This is a separate step for mainline only that auto accepts and changes
535538
# instead of holding CI up. Since we squash/merge, this is defensive to
@@ -547,13 +550,16 @@ jobs:
547550
autoAcceptChanges: true
548551
# This will prevent CI from failing when Chromatic detects visual changes
549552
exitZeroOnChanges: true
553+
# Do a full build with documentation for mainline builds
550554
buildScriptName: "storybook:build"
551555
projectToken: 695c25b6cb65
552556
workingDir: "./site"
553557
storybookBaseDir: "./site"
554558
# Run TurboSnap to trace file dependencies to related stories
555559
# and tell chromatic to only take snapshots of relevent stories
556560
onlyChanged: true
561+
# Avoid uploading single files, because that's very slow
562+
zip: true
557563

558564
offlinedocs:
559565
name: offlinedocs
@@ -726,7 +732,7 @@ jobs:
726732
727733
# Define specific tags
728734
tags=("$tag" "main" "latest")
729-
735+
730736
# Create and push a multi-arch manifest for each tag
731737
# we are adding `latest` tag and keeping `main` for backward
732738
# compatibality

.vscode/settings.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,6 @@
170170
"workspaceapps",
171171
"workspacebuilds",
172172
"workspacename",
173-
"wsconncache",
174173
"wsjson",
175174
"xerrors",
176175
"xlarge",

agent/agent.go

Lines changed: 51 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141
"github.com/coder/coder/v2/agent/agentproc"
4242
"github.com/coder/coder/v2/agent/agentscripts"
4343
"github.com/coder/coder/v2/agent/agentssh"
44+
"github.com/coder/coder/v2/agent/proto"
4445
"github.com/coder/coder/v2/agent/reconnectingpty"
4546
"github.com/coder/coder/v2/buildinfo"
4647
"github.com/coder/coder/v2/cli/gitauth"
@@ -87,15 +88,12 @@ type Options struct {
8788
}
8889

8990
type Client interface {
90-
Manifest(ctx context.Context) (agentsdk.Manifest, error)
9191
Listen(ctx context.Context) (drpc.Conn, error)
9292
ReportStats(ctx context.Context, log slog.Logger, statsChan <-chan *agentsdk.Stats, setInterval func(time.Duration)) (io.Closer, error)
9393
PostLifecycle(ctx context.Context, state agentsdk.PostLifecycleRequest) error
94-
PostAppHealth(ctx context.Context, req agentsdk.PostAppHealthsRequest) error
95-
PostStartup(ctx context.Context, req agentsdk.PostStartupRequest) error
9694
PostMetadata(ctx context.Context, req agentsdk.PostMetadataRequest) error
9795
PatchLogs(ctx context.Context, req agentsdk.PatchLogs) error
98-
GetServiceBanner(ctx context.Context) (codersdk.ServiceBannerConfig, error)
96+
RewriteDERPMap(derpMap *tailcfg.DERPMap)
9997
}
10098

10199
type Agent interface {
@@ -269,7 +267,6 @@ func (a *agent) init(ctx context.Context) {
269267
func (a *agent) runLoop(ctx context.Context) {
270268
go a.reportLifecycleLoop(ctx)
271269
go a.reportMetadataLoop(ctx)
272-
go a.fetchServiceBannerLoop(ctx)
273270
go a.manageProcessPriorityLoop(ctx)
274271

275272
for retrier := retry.New(100*time.Millisecond, 10*time.Second); retrier.Wait(ctx); {
@@ -662,22 +659,23 @@ func (a *agent) setLifecycle(ctx context.Context, state codersdk.WorkspaceAgentL
662659
// fetchServiceBannerLoop fetches the service banner on an interval. It will
663660
// not be fetched immediately; the expectation is that it is primed elsewhere
664661
// (and must be done before the session actually starts).
665-
func (a *agent) fetchServiceBannerLoop(ctx context.Context) {
662+
func (a *agent) fetchServiceBannerLoop(ctx context.Context, aAPI proto.DRPCAgentClient) error {
666663
ticker := time.NewTicker(a.serviceBannerRefreshInterval)
667664
defer ticker.Stop()
668665
for {
669666
select {
670667
case <-ctx.Done():
671-
return
668+
return ctx.Err()
672669
case <-ticker.C:
673-
serviceBanner, err := a.client.GetServiceBanner(ctx)
670+
sbp, err := aAPI.GetServiceBanner(ctx, &proto.GetServiceBannerRequest{})
674671
if err != nil {
675672
if ctx.Err() != nil {
676-
return
673+
return ctx.Err()
677674
}
678675
a.logger.Error(ctx, "failed to update service banner", slog.Error(err))
679-
continue
676+
return err
680677
}
678+
serviceBanner := agentsdk.ServiceBannerFromProto(sbp)
681679
a.serviceBanner.Store(&serviceBanner)
682680
}
683681
}
@@ -693,21 +691,40 @@ func (a *agent) run(ctx context.Context) error {
693691
}
694692
a.sessionToken.Store(&sessionToken)
695693

696-
serviceBanner, err := a.client.GetServiceBanner(ctx)
694+
// Listen returns the dRPC connection we use for the Agent v2+ API
695+
conn, err := a.client.Listen(ctx)
696+
if err != nil {
697+
return err
698+
}
699+
defer func() {
700+
cErr := conn.Close()
701+
if cErr != nil {
702+
a.logger.Debug(ctx, "error closing drpc connection", slog.Error(err))
703+
}
704+
}()
705+
706+
aAPI := proto.NewDRPCAgentClient(conn)
707+
sbp, err := aAPI.GetServiceBanner(ctx, &proto.GetServiceBannerRequest{})
697708
if err != nil {
698709
return xerrors.Errorf("fetch service banner: %w", err)
699710
}
711+
serviceBanner := agentsdk.ServiceBannerFromProto(sbp)
700712
a.serviceBanner.Store(&serviceBanner)
701713

702-
manifest, err := a.client.Manifest(ctx)
714+
mp, err := aAPI.GetManifest(ctx, &proto.GetManifestRequest{})
703715
if err != nil {
704716
return xerrors.Errorf("fetch metadata: %w", err)
705717
}
706-
a.logger.Info(ctx, "fetched manifest", slog.F("manifest", manifest))
707-
718+
a.logger.Info(ctx, "fetched manifest", slog.F("manifest", mp))
719+
manifest, err := agentsdk.ManifestFromProto(mp)
720+
if err != nil {
721+
a.logger.Critical(ctx, "failed to convert manifest", slog.F("manifest", mp), slog.Error(err))
722+
return xerrors.Errorf("convert manifest: %w", err)
723+
}
708724
if manifest.AgentID == uuid.Nil {
709725
return xerrors.New("nil agentID returned by manifest")
710726
}
727+
a.client.RewriteDERPMap(manifest.DERPMap)
711728

712729
// Expand the directory and send it back to coderd so external
713730
// applications that rely on the directory can use it.
@@ -718,13 +735,18 @@ func (a *agent) run(ctx context.Context) error {
718735
if err != nil {
719736
return xerrors.Errorf("expand directory: %w", err)
720737
}
721-
err = a.client.PostStartup(ctx, agentsdk.PostStartupRequest{
738+
subsys, err := agentsdk.ProtoFromSubsystems(a.subsystems)
739+
if err != nil {
740+
a.logger.Critical(ctx, "failed to convert subsystems", slog.Error(err))
741+
return xerrors.Errorf("failed to convert subsystems: %w", err)
742+
}
743+
_, err = aAPI.UpdateStartup(ctx, &proto.UpdateStartupRequest{Startup: &proto.Startup{
722744
Version: buildinfo.Version(),
723745
ExpandedDirectory: manifest.Directory,
724-
Subsystems: a.subsystems,
725-
})
746+
Subsystems: subsys,
747+
}})
726748
if err != nil {
727-
return xerrors.Errorf("update workspace agent version: %w", err)
749+
return xerrors.Errorf("update workspace agent startup: %w", err)
728750
}
729751

730752
oldManifest := a.manifest.Swap(&manifest)
@@ -785,7 +807,7 @@ func (a *agent) run(ctx context.Context) error {
785807
appReporterCtx, appReporterCtxCancel := context.WithCancel(ctx)
786808
defer appReporterCtxCancel()
787809
go NewWorkspaceAppHealthReporter(
788-
a.logger, manifest.Apps, a.client.PostAppHealth)(appReporterCtx)
810+
a.logger, manifest.Apps, agentsdk.AppHealthPoster(aAPI))(appReporterCtx)
789811

790812
a.closeMutex.Lock()
791813
network := a.network
@@ -821,18 +843,6 @@ func (a *agent) run(ctx context.Context) error {
821843
network.SetBlockEndpoints(manifest.DisableDirectConnections)
822844
}
823845

824-
// Listen returns the dRPC connection we use for both Coordinator and DERPMap updates
825-
conn, err := a.client.Listen(ctx)
826-
if err != nil {
827-
return err
828-
}
829-
defer func() {
830-
cErr := conn.Close()
831-
if cErr != nil {
832-
a.logger.Debug(ctx, "error closing drpc connection", slog.Error(err))
833-
}
834-
}()
835-
836846
eg, egCtx := errgroup.WithContext(ctx)
837847
eg.Go(func() error {
838848
a.logger.Debug(egCtx, "running tailnet connection coordinator")
@@ -852,6 +862,15 @@ func (a *agent) run(ctx context.Context) error {
852862
return nil
853863
})
854864

865+
eg.Go(func() error {
866+
a.logger.Debug(egCtx, "running fetch server banner loop")
867+
err := a.fetchServiceBannerLoop(egCtx, aAPI)
868+
if err != nil {
869+
return xerrors.Errorf("fetch server banner loop: %w", err)
870+
}
871+
return nil
872+
})
873+
855874
return eg.Wait()
856875
}
857876

@@ -1113,6 +1132,7 @@ func (a *agent) runDERPMapSubscriber(ctx context.Context, conn drpc.Conn, networ
11131132
return xerrors.Errorf("recv DERPMap error: %w", err)
11141133
}
11151134
dm := tailnet.DERPMapFromProto(dmp)
1135+
a.client.RewriteDERPMap(dm)
11161136
network.SetDERPMap(dm)
11171137
}
11181138
}

agent/agent_test.go

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1394,56 +1394,52 @@ func TestAgent_Startup(t *testing.T) {
13941394

13951395
t.Run("EmptyDirectory", func(t *testing.T) {
13961396
t.Parallel()
1397+
ctx := testutil.Context(t, testutil.WaitShort)
13971398

13981399
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
13991400
Directory: "",
14001401
}, 0)
1401-
assert.Eventually(t, func() bool {
1402-
return client.GetStartup().Version != ""
1403-
}, testutil.WaitShort, testutil.IntervalFast)
1404-
require.Equal(t, "", client.GetStartup().ExpandedDirectory)
1402+
startup := testutil.RequireRecvCtx(ctx, t, client.GetStartup())
1403+
require.Equal(t, "", startup.GetExpandedDirectory())
14051404
})
14061405

14071406
t.Run("HomeDirectory", func(t *testing.T) {
14081407
t.Parallel()
1408+
ctx := testutil.Context(t, testutil.WaitShort)
14091409

14101410
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
14111411
Directory: "~",
14121412
}, 0)
1413-
assert.Eventually(t, func() bool {
1414-
return client.GetStartup().Version != ""
1415-
}, testutil.WaitShort, testutil.IntervalFast)
1413+
startup := testutil.RequireRecvCtx(ctx, t, client.GetStartup())
14161414
homeDir, err := os.UserHomeDir()
14171415
require.NoError(t, err)
1418-
require.Equal(t, homeDir, client.GetStartup().ExpandedDirectory)
1416+
require.Equal(t, homeDir, startup.GetExpandedDirectory())
14191417
})
14201418

14211419
t.Run("NotAbsoluteDirectory", func(t *testing.T) {
14221420
t.Parallel()
1421+
ctx := testutil.Context(t, testutil.WaitShort)
14231422

14241423
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
14251424
Directory: "coder/coder",
14261425
}, 0)
1427-
assert.Eventually(t, func() bool {
1428-
return client.GetStartup().Version != ""
1429-
}, testutil.WaitShort, testutil.IntervalFast)
1426+
startup := testutil.RequireRecvCtx(ctx, t, client.GetStartup())
14301427
homeDir, err := os.UserHomeDir()
14311428
require.NoError(t, err)
1432-
require.Equal(t, filepath.Join(homeDir, "coder/coder"), client.GetStartup().ExpandedDirectory)
1429+
require.Equal(t, filepath.Join(homeDir, "coder/coder"), startup.GetExpandedDirectory())
14331430
})
14341431

14351432
t.Run("HomeEnvironmentVariable", func(t *testing.T) {
14361433
t.Parallel()
1434+
ctx := testutil.Context(t, testutil.WaitShort)
14371435

14381436
_, client, _, _, _ := setupAgent(t, agentsdk.Manifest{
14391437
Directory: "$HOME",
14401438
}, 0)
1441-
assert.Eventually(t, func() bool {
1442-
return client.GetStartup().Version != ""
1443-
}, testutil.WaitShort, testutil.IntervalFast)
1439+
startup := testutil.RequireRecvCtx(ctx, t, client.GetStartup())
14441440
homeDir, err := os.UserHomeDir()
14451441
require.NoError(t, err)
1446-
require.Equal(t, homeDir, client.GetStartup().ExpandedDirectory)
1442+
require.Equal(t, homeDir, startup.GetExpandedDirectory())
14471443
})
14481444
}
14491445

@@ -2026,7 +2022,11 @@ func setupAgent(t *testing.T, metadata agentsdk.Manifest, ptyTimeout time.Durati
20262022
afero.Fs,
20272023
agent.Agent,
20282024
) {
2029-
logger := slogtest.Make(t, nil).Leveled(slog.LevelDebug)
2025+
logger := slogtest.Make(t, &slogtest.Options{
2026+
// Agent can drop errors when shutting down, and some, like the
2027+
// fasthttplistener connection closed error, are unexported.
2028+
IgnoreErrors: true,
2029+
}).Leveled(slog.LevelDebug)
20302030
if metadata.DERPMap == nil {
20312031
metadata.DERPMap, _ = tailnettest.RunDERPAndSTUN(t)
20322032
}
@@ -2039,6 +2039,9 @@ func setupAgent(t *testing.T, metadata agentsdk.Manifest, ptyTimeout time.Durati
20392039
if metadata.WorkspaceName == "" {
20402040
metadata.WorkspaceName = "test-workspace"
20412041
}
2042+
if metadata.WorkspaceID == uuid.Nil {
2043+
metadata.WorkspaceID = uuid.New()
2044+
}
20422045
coordinator := tailnet.NewCoordinator(logger)
20432046
t.Cleanup(func() {
20442047
_ = coordinator.Close()

0 commit comments

Comments
 (0)