Skip to content

Commit b894407

Browse files
chore: improve coder server ux (#14761)
1 parent a3ebcd7 commit b894407

File tree

9 files changed

+46
-25
lines changed

9 files changed

+46
-25
lines changed

cli/cliui/cliui.go

+5
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ type Styles struct {
2222
DateTimeStamp,
2323
Error,
2424
Field,
25+
Hyperlink,
2526
Keyword,
2627
Placeholder,
2728
Prompt,
@@ -149,6 +150,10 @@ func init() {
149150
pretty.Wrap("> ", ""),
150151
pretty.FgColor(brightBlue),
151152
},
153+
Hyperlink: pretty.Style{
154+
pretty.FgColor(magenta),
155+
pretty.Underline(),
156+
},
152157
Keyword: pretty.Style{
153158
pretty.FgColor(green),
154159
},

cli/login.go

+3
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,9 @@ func isWSL() (bool, error) {
416416

417417
// openURL opens the provided URL via user's default browser
418418
func openURL(inv *serpent.Invocation, urlToOpen string) error {
419+
if !isTTYOut(inv) {
420+
return xerrors.New("skipping browser open in non-interactive mode")
421+
}
419422
noOpen, err := inv.ParsedFlags().GetBool(varNoOpen)
420423
if err != nil {
421424
panic(err)

cli/root.go

+1-8
Original file line numberDiff line numberDiff line change
@@ -695,14 +695,7 @@ func namedWorkspace(ctx context.Context, client *codersdk.Client, identifier str
695695
func initAppearance(client *codersdk.Client, outConfig *codersdk.AppearanceConfig) serpent.MiddlewareFunc {
696696
return func(next serpent.HandlerFunc) serpent.HandlerFunc {
697697
return func(inv *serpent.Invocation) error {
698-
var err error
699-
cfg, err := client.Appearance(inv.Context())
700-
if err != nil {
701-
var sdkErr *codersdk.Error
702-
if !(xerrors.As(err, &sdkErr) && sdkErr.StatusCode() == http.StatusNotFound) {
703-
return err
704-
}
705-
}
698+
cfg, _ := client.Appearance(inv.Context())
706699
if cfg.DocsURL == "" {
707700
cfg.DocsURL = codersdk.DefaultDocsURL()
708701
}

cli/server.go

+13-4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import (
3232
"sync/atomic"
3333
"time"
3434

35+
"github.com/charmbracelet/lipgloss"
3536
"github.com/coreos/go-oidc/v3/oidc"
3637
"github.com/coreos/go-systemd/daemon"
3738
embeddedpostgres "github.com/fergusstrange/embedded-postgres"
@@ -483,8 +484,15 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd.
483484
)
484485
}
485486

486-
// A newline is added before for visibility in terminal output.
487-
cliui.Infof(inv.Stdout, "\nView the Web UI: %s", vals.AccessURL.String())
487+
accessURL := vals.AccessURL.String()
488+
cliui.Infof(inv.Stdout, lipgloss.NewStyle().
489+
Border(lipgloss.DoubleBorder()).
490+
Align(lipgloss.Center).
491+
Padding(0, 3).
492+
BorderForeground(lipgloss.Color("12")).
493+
Render(fmt.Sprintf("View the Web UI:\n%s",
494+
pretty.Sprint(cliui.DefaultStyles.Hyperlink, accessURL))))
495+
_ = openURL(inv, accessURL)
488496

489497
// Used for zero-trust instance identity with Google Cloud.
490498
googleTokenValidator, err := idtoken.NewValidator(ctx, option.WithoutAuthentication())
@@ -1438,6 +1446,7 @@ func newProvisionerDaemon(
14381446

14391447
// Omit any duplicates
14401448
provisionerTypes = slice.Unique(provisionerTypes)
1449+
provisionerLogger := logger.Named(fmt.Sprintf("provisionerd-%s", name))
14411450

14421451
// Populate the connector with the supported types.
14431452
connector := provisionerd.LocalProvisioners{}
@@ -1494,7 +1503,7 @@ func newProvisionerDaemon(
14941503
err := terraform.Serve(ctx, &terraform.ServeOptions{
14951504
ServeOptions: &provisionersdk.ServeOptions{
14961505
Listener: terraformServer,
1497-
Logger: logger.Named("terraform"),
1506+
Logger: provisionerLogger,
14981507
WorkDirectory: workDir,
14991508
},
15001509
CachePath: tfDir,
@@ -1519,7 +1528,7 @@ func newProvisionerDaemon(
15191528
// in provisionerdserver.go to learn more!
15201529
return coderAPI.CreateInMemoryProvisionerDaemon(dialCtx, name, provisionerTypes)
15211530
}, &provisionerd.Options{
1522-
Logger: logger.Named(fmt.Sprintf("provisionerd-%s", name)),
1531+
Logger: provisionerLogger,
15231532
UpdateInterval: time.Second,
15241533
ForceCancelInterval: cfg.Provisioner.ForceCancelInterval.Value(),
15251534
Connector: connector,

cli/server_test.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,8 @@ func TestServer(t *testing.T) {
221221
_ = waitAccessURL(t, cfg)
222222

223223
pty.ExpectMatch("this may cause unexpected problems when creating workspaces")
224-
pty.ExpectMatch("View the Web UI: http://localhost:3000/")
224+
pty.ExpectMatch("View the Web UI:")
225+
pty.ExpectMatch("http://localhost:3000/")
225226
})
226227

227228
// Validate that an https scheme is prepended to a remote access URL
@@ -244,7 +245,8 @@ func TestServer(t *testing.T) {
244245
_ = waitAccessURL(t, cfg)
245246

246247
pty.ExpectMatch("this may cause unexpected problems when creating workspaces")
247-
pty.ExpectMatch("View the Web UI: https://foobarbaz.mydomain")
248+
pty.ExpectMatch("View the Web UI:")
249+
pty.ExpectMatch("https://foobarbaz.mydomain")
248250
})
249251

250252
t.Run("NoWarningWithRemoteAccessURL", func(t *testing.T) {
@@ -262,7 +264,8 @@ func TestServer(t *testing.T) {
262264
// Just wait for startup
263265
_ = waitAccessURL(t, cfg)
264266

265-
pty.ExpectMatch("View the Web UI: https://google.com")
267+
pty.ExpectMatch("View the Web UI:")
268+
pty.ExpectMatch("https://google.com")
266269
})
267270

268271
t.Run("NoSchemeAccessURL", func(t *testing.T) {

coderd/coderd.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -1505,7 +1505,7 @@ func (api *API) CreateInMemoryTaggedProvisionerDaemon(dialCtx context.Context, n
15051505
}
15061506

15071507
mux := drpcmux.New()
1508-
api.Logger.Info(dialCtx, "starting in-memory provisioner daemon", slog.F("name", name))
1508+
api.Logger.Debug(dialCtx, "starting in-memory provisioner daemon", slog.F("name", name))
15091509
logger := api.Logger.Named(fmt.Sprintf("inmem-provisionerd-%s", name))
15101510
srv, err := provisionerdserver.NewServer(
15111511
api.ctx, // use the same ctx as the API

coderd/database/pubsub/pubsub.go

+4-4
Original file line numberDiff line numberDiff line change
@@ -413,15 +413,15 @@ func (d logDialer) DialContext(ctx context.Context, network, address string) (ne
413413

414414
logger := d.logger.With(slog.F("network", network), slog.F("address", address), slog.F("timeout_ms", timeoutMS))
415415

416-
logger.Info(ctx, "pubsub dialing postgres")
416+
logger.Debug(ctx, "pubsub dialing postgres")
417417
start := time.Now()
418418
conn, err := d.d.DialContext(ctx, network, address)
419419
if err != nil {
420420
logger.Error(ctx, "pubsub failed to dial postgres")
421421
return nil, err
422422
}
423423
elapsed := time.Since(start)
424-
logger.Info(ctx, "pubsub postgres TCP connection established", slog.F("elapsed_ms", elapsed.Milliseconds()))
424+
logger.Debug(ctx, "pubsub postgres TCP connection established", slog.F("elapsed_ms", elapsed.Milliseconds()))
425425
return conn, nil
426426
}
427427

@@ -466,7 +466,7 @@ func (p *PGPubsub) startListener(ctx context.Context, connectURL string) error {
466466
Listener: pq.NewConnectorListener(connector, connectURL, time.Second, time.Minute, func(t pq.ListenerEventType, err error) {
467467
switch t {
468468
case pq.ListenerEventConnected:
469-
p.logger.Info(ctx, "pubsub connected to postgres")
469+
p.logger.Debug(ctx, "pubsub connected to postgres")
470470
p.connected.Set(1.0)
471471
case pq.ListenerEventDisconnected:
472472
p.logger.Error(ctx, "pubsub disconnected from postgres", slog.Error(err))
@@ -618,7 +618,7 @@ func New(startCtx context.Context, logger slog.Logger, db *sql.DB, connectURL st
618618
return nil, err
619619
}
620620
go p.listen()
621-
logger.Info(startCtx, "pubsub has started")
621+
logger.Debug(startCtx, "pubsub has started")
622622
return p, nil
623623
}
624624

enterprise/cli/proxyserver.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
rpprof "runtime/pprof"
1515
"time"
1616

17+
"github.com/charmbracelet/lipgloss"
1718
"github.com/coreos/go-systemd/daemon"
1819
"github.com/prometheus/client_golang/prometheus"
1920
"github.com/prometheus/client_golang/prometheus/collectors"
@@ -29,6 +30,7 @@ import (
2930
"github.com/coder/coder/v2/coderd/workspaceapps/appurl"
3031
"github.com/coder/coder/v2/codersdk"
3132
"github.com/coder/coder/v2/enterprise/wsproxy"
33+
"github.com/coder/pretty"
3234
"github.com/coder/serpent"
3335
)
3436

@@ -202,8 +204,14 @@ func (r *RootCmd) proxyServer() *serpent.Command {
202204
headerTransport.Transport = httpClient.Transport
203205
httpClient.Transport = headerTransport
204206

205-
// A newline is added before for visibility in terminal output.
206-
cliui.Infof(inv.Stdout, "\nView the Web UI: %s", cfg.AccessURL.String())
207+
accessURL := cfg.AccessURL.String()
208+
cliui.Infof(inv.Stdout, lipgloss.NewStyle().
209+
Border(lipgloss.DoubleBorder()).
210+
Align(lipgloss.Center).
211+
Padding(0, 3).
212+
BorderForeground(lipgloss.Color("12")).
213+
Render(fmt.Sprintf("View the Web UI:\n%s",
214+
pretty.Sprint(cliui.DefaultStyles.Hyperlink, accessURL))))
207215

208216
var appHostnameRegex *regexp.Regexp
209217
appHostname := cfg.WildcardAccessURL.String()

tailnet/configmaps.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -147,22 +147,22 @@ func (c *configMaps) configLoop() {
147147
if c.derpMapDirty {
148148
derpMap := c.derpMapLocked()
149149
actions = append(actions, func() {
150-
c.logger.Info(context.Background(), "updating engine DERP map", slog.F("derp_map", (*derpMapStringer)(derpMap)))
150+
c.logger.Debug(context.Background(), "updating engine DERP map", slog.F("derp_map", (*derpMapStringer)(derpMap)))
151151
c.engine.SetDERPMap(derpMap)
152152
})
153153
}
154154
if c.netmapDirty {
155155
nm := c.netMapLocked()
156156
actions = append(actions, func() {
157-
c.logger.Info(context.Background(), "updating engine network map", slog.F("network_map", nm))
157+
c.logger.Debug(context.Background(), "updating engine network map", slog.F("network_map", nm))
158158
c.engine.SetNetworkMap(nm)
159159
c.reconfig(nm)
160160
})
161161
}
162162
if c.filterDirty {
163163
f := c.filterLocked()
164164
actions = append(actions, func() {
165-
c.logger.Info(context.Background(), "updating engine filter", slog.F("filter", f))
165+
c.logger.Debug(context.Background(), "updating engine filter", slog.F("filter", f))
166166
c.engine.SetFilter(f)
167167
})
168168
}

0 commit comments

Comments
 (0)