Skip to content

Commit 9f90ee3

Browse files
authored
Merge branch 'main' into cj/gh-1544/agent-script-wait
2 parents 5e315ef + 6f34cbf commit 9f90ee3

File tree

85 files changed

+1183
-862
lines changed

Some content is hidden

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

85 files changed

+1183
-862
lines changed

cli/cliui/prompt.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,25 +24,41 @@ type PromptOptions struct {
2424
Validate func(string) error
2525
}
2626

27+
const skipPromptFlag = "yes"
28+
2729
func AllowSkipPrompt(cmd *cobra.Command) {
28-
cmd.Flags().BoolP("yes", "y", false, "Bypass prompts")
30+
cmd.Flags().BoolP(skipPromptFlag, "y", false, "Bypass prompts")
2931
}
3032

33+
const (
34+
ConfirmYes = "yes"
35+
ConfirmNo = "no"
36+
)
37+
3138
// Prompt asks the user for input.
3239
func Prompt(cmd *cobra.Command, opts PromptOptions) (string, error) {
3340
// If the cmd has a "yes" flag for skipping confirm prompts, honor it.
3441
// If it's not a "Confirm" prompt, then don't skip. As the default value of
3542
// "yes" makes no sense.
36-
if opts.IsConfirm && cmd.Flags().Lookup("yes") != nil {
37-
if skip, _ := cmd.Flags().GetBool("yes"); skip {
38-
return "yes", nil
43+
if opts.IsConfirm && cmd.Flags().Lookup(skipPromptFlag) != nil {
44+
if skip, _ := cmd.Flags().GetBool(skipPromptFlag); skip {
45+
return ConfirmYes, nil
3946
}
4047
}
4148

4249
_, _ = fmt.Fprint(cmd.OutOrStdout(), Styles.FocusedPrompt.String()+opts.Text+" ")
4350
if opts.IsConfirm {
44-
opts.Default = "yes"
45-
_, _ = fmt.Fprint(cmd.OutOrStdout(), Styles.Placeholder.Render("("+Styles.Bold.Render("yes")+Styles.Placeholder.Render("/no) ")))
51+
if len(opts.Default) == 0 {
52+
opts.Default = ConfirmYes
53+
}
54+
renderedYes := Styles.Placeholder.Render(ConfirmYes)
55+
renderedNo := Styles.Placeholder.Render(ConfirmNo)
56+
if opts.Default == ConfirmYes {
57+
renderedYes = Styles.Bold.Render(ConfirmYes)
58+
} else {
59+
renderedNo = Styles.Bold.Render(ConfirmNo)
60+
}
61+
_, _ = fmt.Fprint(cmd.OutOrStdout(), Styles.Placeholder.Render("("+renderedYes+Styles.Placeholder.Render("/"+renderedNo+Styles.Placeholder.Render(") "))))
4662
} else if opts.Default != "" {
4763
_, _ = fmt.Fprint(cmd.OutOrStdout(), Styles.Placeholder.Render("("+opts.Default+") "))
4864
}

cli/delete.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ func deleteWorkspace() *cobra.Command {
2222
_, err := cliui.Prompt(cmd, cliui.PromptOptions{
2323
Text: "Confirm delete workspace?",
2424
IsConfirm: true,
25+
Default: cliui.ConfirmNo,
2526
})
2627
if err != nil {
2728
return err

cli/login.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ func login() *cobra.Command {
8989
}
9090
_, err := cliui.Prompt(cmd, cliui.PromptOptions{
9191
Text: "Would you like to create the first user?",
92-
Default: "yes",
92+
Default: cliui.ConfirmYes,
9393
IsConfirm: true,
9494
})
9595
if errors.Is(err, cliui.Canceled) {

cli/logout.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func logout() *cobra.Command {
2828
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
2929
Text: "Are you sure you want to log out?",
3030
IsConfirm: true,
31-
Default: "yes",
31+
Default: cliui.ConfirmYes,
3232
})
3333
if err != nil {
3434
return err

cli/root.go

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"os"
77
"strconv"
88
"strings"
9+
"text/template"
910
"time"
1011

1112
"golang.org/x/xerrors"
@@ -28,7 +29,7 @@ var (
2829
// Applied as annotations to workspace commands
2930
// so they display in a separated "help" section.
3031
workspaceCommand = map[string]string{
31-
"workspaces": " ",
32+
"workspaces": "",
3233
}
3334
)
3435

@@ -52,12 +53,8 @@ var (
5253
)
5354

5455
func init() {
55-
// Customizes the color of headings to make subcommands more visually
56-
// appealing.
57-
header := cliui.Styles.Placeholder
58-
cobra.AddTemplateFunc("usageHeader", func(s string) string {
59-
return header.Render(s)
60-
})
56+
// Set cobra template functions in init to avoid conflicts in tests.
57+
cobra.AddTemplateFuncs(templateFunctions)
6158
}
6259

6360
func Root() *cobra.Command {
@@ -311,6 +308,30 @@ func isTTYOut(cmd *cobra.Command) bool {
311308
return isatty.IsTerminal(file.Fd())
312309
}
313310

311+
var templateFunctions = template.FuncMap{
312+
"usageHeader": usageHeader,
313+
"isWorkspaceCommand": isWorkspaceCommand,
314+
}
315+
316+
func usageHeader(s string) string {
317+
// Customizes the color of headings to make subcommands more visually
318+
// appealing.
319+
return cliui.Styles.Placeholder.Render(s)
320+
}
321+
322+
func isWorkspaceCommand(cmd *cobra.Command) bool {
323+
if _, ok := cmd.Annotations["workspaces"]; ok {
324+
return true
325+
}
326+
var ws bool
327+
cmd.VisitParents(func(cmd *cobra.Command) {
328+
if _, ok := cmd.Annotations["workspaces"]; ok {
329+
ws = true
330+
}
331+
})
332+
return ws
333+
}
334+
314335
func usageTemplate() string {
315336
// usageHeader is defined in init().
316337
return `{{usageHeader "Usage:"}}
@@ -331,32 +352,34 @@ func usageTemplate() string {
331352
{{.Example}}
332353
{{end}}
333354
355+
{{- $isRootHelp := (not .HasParent)}}
334356
{{- if .HasAvailableSubCommands}}
335357
{{usageHeader "Commands:"}}
336358
{{- range .Commands}}
337-
{{- if (or (and .IsAvailableCommand (eq (len .Annotations) 0)) (eq .Name "help"))}}
359+
{{- $isRootWorkspaceCommand := (and $isRootHelp (isWorkspaceCommand .))}}
360+
{{- if (or (and .IsAvailableCommand (not $isRootWorkspaceCommand)) (eq .Name "help"))}}
338361
{{rpad .Name .NamePadding }} {{.Short}}
339362
{{- end}}
340363
{{- end}}
341364
{{end}}
342365
343-
{{- if and (not .HasParent) .HasAvailableSubCommands}}
366+
{{- if (and $isRootHelp .HasAvailableSubCommands)}}
344367
{{usageHeader "Workspace Commands:"}}
345368
{{- range .Commands}}
346-
{{- if (and .IsAvailableCommand (ne (index .Annotations "workspaces") ""))}}
369+
{{- if (and .IsAvailableCommand (isWorkspaceCommand .))}}
347370
{{rpad .Name .NamePadding }} {{.Short}}
348371
{{- end}}
349372
{{- end}}
350373
{{end}}
351374
352375
{{- if .HasAvailableLocalFlags}}
353376
{{usageHeader "Flags:"}}
354-
{{.LocalFlags.FlagUsagesWrapped 100}}
377+
{{.LocalFlags.FlagUsagesWrapped 100 | trimTrailingWhitespaces}}
355378
{{end}}
356379
357380
{{- if .HasAvailableInheritedFlags}}
358381
{{usageHeader "Global Flags:"}}
359-
{{.InheritedFlags.FlagUsagesWrapped 100}}
382+
{{.InheritedFlags.FlagUsagesWrapped 100 | trimTrailingWhitespaces}}
360383
{{end}}
361384
362385
{{- if .HasHelpSubCommands}}

cli/schedule.go

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,6 @@ import (
1717
)
1818

1919
const (
20-
scheduleDescriptionLong = `Modify scheduled stop and start times for your workspace:
21-
* schedule show: show workspace schedule
22-
* schedule start: edit workspace start schedule
23-
* schedule stop: edit workspace stop schedule
24-
* schedule override-stop: edit stop time of active workspace
25-
`
2620
scheduleShowDescriptionLong = `Shows the following information for the given workspace:
2721
* The automatic start schedule
2822
* The next scheduled start time
@@ -64,24 +58,24 @@ func schedules() *cobra.Command {
6458
Annotations: workspaceCommand,
6559
Use: "schedule { show | start | stop | override } <workspace>",
6660
Short: "Modify scheduled stop and start times for your workspace",
67-
Long: scheduleDescriptionLong,
6861
}
6962

70-
scheduleCmd.AddCommand(scheduleShow())
71-
scheduleCmd.AddCommand(scheduleStart())
72-
scheduleCmd.AddCommand(scheduleStop())
73-
scheduleCmd.AddCommand(scheduleOverride())
63+
scheduleCmd.AddCommand(
64+
scheduleShow(),
65+
scheduleStart(),
66+
scheduleStop(),
67+
scheduleOverride(),
68+
)
7469

7570
return scheduleCmd
7671
}
7772

7873
func scheduleShow() *cobra.Command {
7974
showCmd := &cobra.Command{
80-
Annotations: workspaceCommand,
81-
Use: "show <workspace-name>",
82-
Short: "Show workspace schedule",
83-
Long: scheduleShowDescriptionLong,
84-
Args: cobra.ExactArgs(1),
75+
Use: "show <workspace-name>",
76+
Short: "Show workspace schedule",
77+
Long: scheduleShowDescriptionLong,
78+
Args: cobra.ExactArgs(1),
8579
RunE: func(cmd *cobra.Command, args []string) error {
8680
client, err := createClient(cmd)
8781
if err != nil {
@@ -101,8 +95,7 @@ func scheduleShow() *cobra.Command {
10195

10296
func scheduleStart() *cobra.Command {
10397
cmd := &cobra.Command{
104-
Annotations: workspaceCommand,
105-
Use: "start <workspace-name> { <start-time> [day-of-week] [location] | manual }",
98+
Use: "start <workspace-name> { <start-time> [day-of-week] [location] | manual }",
10699
Example: formatExamples(
107100
example{
108101
Description: "Set the workspace to start at 9:30am (in Dublin) from Monday to Friday",
@@ -153,9 +146,8 @@ func scheduleStart() *cobra.Command {
153146

154147
func scheduleStop() *cobra.Command {
155148
return &cobra.Command{
156-
Annotations: workspaceCommand,
157-
Args: cobra.ExactArgs(2),
158-
Use: "stop <workspace-name> { <duration> | manual }",
149+
Args: cobra.ExactArgs(2),
150+
Use: "stop <workspace-name> { <duration> | manual }",
159151
Example: formatExamples(
160152
example{
161153
Command: "coder schedule stop my-workspace 2h30m",
@@ -200,9 +192,8 @@ func scheduleStop() *cobra.Command {
200192

201193
func scheduleOverride() *cobra.Command {
202194
overrideCmd := &cobra.Command{
203-
Args: cobra.ExactArgs(2),
204-
Annotations: workspaceCommand,
205-
Use: "override-stop <workspace-name> <duration from now>",
195+
Args: cobra.ExactArgs(2),
196+
Use: "override-stop <workspace-name> <duration from now>",
206197
Example: formatExamples(
207198
example{
208199
Command: "coder schedule override-stop my-workspace 90m",

cli/server.go

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -770,11 +770,9 @@ func configureGithubOAuth2(accessURL *url.URL, clientID, clientSecret string, al
770770
})
771771
return memberships, err
772772
},
773-
ListTeams: func(ctx context.Context, client *http.Client, org string) ([]*github.Team, error) {
774-
teams, _, err := github.NewClient(client).Teams.ListTeams(ctx, org, &github.ListOptions{
775-
PerPage: 100,
776-
})
777-
return teams, err
773+
Team: func(ctx context.Context, client *http.Client, org, teamSlug string) (*github.Team, error) {
774+
team, _, err := github.NewClient(client).Teams.GetTeamBySlug(ctx, org, teamSlug)
775+
return team, err
778776
},
779777
}, nil
780778
}

cli/templatecreate.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func templateCreate() *cobra.Command {
6060
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
6161
Text: fmt.Sprintf("Create and upload %q?", prettyDir),
6262
IsConfirm: true,
63-
Default: "yes",
63+
Default: cliui.ConfirmYes,
6464
})
6565
if err != nil {
6666
return err
@@ -127,7 +127,7 @@ func templateCreate() *cobra.Command {
127127
cmd.Flags().StringVarP(&directory, "directory", "d", currentDirectory, "Specify the directory to create from")
128128
cmd.Flags().StringVarP(&provisioner, "test.provisioner", "", "terraform", "Customize the provisioner backend")
129129
cmd.Flags().StringVarP(&parameterFile, "parameter-file", "", "", "Specify a file path with parameter values.")
130-
cmd.Flags().DurationVarP(&maxTTL, "max-ttl", "", 168*time.Hour, "Specify a maximum TTL for workspaces created from this template.")
130+
cmd.Flags().DurationVarP(&maxTTL, "max-ttl", "", 24*time.Hour, "Specify a maximum TTL for workspaces created from this template.")
131131
cmd.Flags().DurationVarP(&minAutostartInterval, "min-autostart-interval", "", time.Hour, "Specify a minimum autostart interval for workspaces created from this template.")
132132
// This is for testing!
133133
err := cmd.Flags().MarkHidden("test.provisioner")

cli/templatedelete.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func templateDelete() *cobra.Command {
7676
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
7777
Text: fmt.Sprintf("Delete these templates: %s?", cliui.Styles.Code.Render(strings.Join(templateNames, ", "))),
7878
IsConfirm: true,
79-
Default: "no",
79+
Default: cliui.ConfirmNo,
8080
})
8181
if err != nil {
8282
return err

cli/templateupdate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func templateUpdate() *cobra.Command {
5353
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
5454
Text: fmt.Sprintf("Upload %q?", prettyDir),
5555
IsConfirm: true,
56-
Default: "yes",
56+
Default: cliui.ConfirmYes,
5757
})
5858
if err != nil {
5959
return err

cli/userstatus.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func createUserStatusCommand(sdkStatus codersdk.UserStatus) *cobra.Command {
7171
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
7272
Text: fmt.Sprintf("Are you sure you want to %s this user?", verb),
7373
IsConfirm: true,
74-
Default: "yes",
74+
Default: cliui.ConfirmYes,
7575
})
7676
if err != nil {
7777
return err

cmd/cliui/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func main() {
4343
}
4444
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
4545
Text: "Do you want to accept?",
46-
Default: "yes",
46+
Default: cliui.ConfirmYes,
4747
IsConfirm: true,
4848
})
4949
if errors.Is(err, cliui.Canceled) {

coderd/coderd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func New(options *Options) *API {
134134

135135
r.Route("/api/v2", func(r chi.Router) {
136136
r.NotFound(func(rw http.ResponseWriter, r *http.Request) {
137-
httpapi.Write(rw, http.StatusNotFound, httpapi.Response{
137+
httpapi.Write(rw, http.StatusNotFound, codersdk.Response{
138138
Message: "Route not found.",
139139
})
140140
})
@@ -144,7 +144,7 @@ func New(options *Options) *API {
144144
debugLogRequest(api.Logger),
145145
)
146146
r.Get("/", func(w http.ResponseWriter, r *http.Request) {
147-
httpapi.Write(w, http.StatusOK, httpapi.Response{
147+
httpapi.Write(w, http.StatusOK, codersdk.Response{
148148
//nolint:gocritic
149149
Message: "👋",
150150
})

coderd/csp.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"net/http"
66

77
"github.com/coder/coder/coderd/httpapi"
8+
"github.com/coder/coder/codersdk"
89

910
"cdr.dev/slog"
1011
)
@@ -22,7 +23,7 @@ func (api *API) logReportCSPViolations(rw http.ResponseWriter, r *http.Request)
2223
err := dec.Decode(&v)
2324
if err != nil {
2425
api.Logger.Warn(ctx, "csp violation", slog.Error(err))
25-
httpapi.Write(rw, http.StatusBadRequest, httpapi.Response{
26+
httpapi.Write(rw, http.StatusBadRequest, codersdk.Response{
2627
Message: "Failed to read body, invalid json.",
2728
Detail: err.Error(),
2829
})

coderd/database/databasefake/databasefake.go

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ func (q *fakeQuerier) GetWorkspaceOwnerCountsByTemplateIDs(_ context.Context, te
527527

528528
counts := map[uuid.UUID]map[uuid.UUID]struct{}{}
529529
for _, templateID := range templateIDs {
530-
found := false
530+
counts[templateID] = map[uuid.UUID]struct{}{}
531531
for _, workspace := range q.workspaces {
532532
if workspace.TemplateID != templateID {
533533
continue
@@ -541,11 +541,6 @@ func (q *fakeQuerier) GetWorkspaceOwnerCountsByTemplateIDs(_ context.Context, te
541541
}
542542
countByOwnerID[workspace.OwnerID] = struct{}{}
543543
counts[templateID] = countByOwnerID
544-
found = true
545-
break
546-
}
547-
if !found {
548-
counts[templateID] = map[uuid.UUID]struct{}{}
549544
}
550545
}
551546
res := make([]database.GetWorkspaceOwnerCountsByTemplateIDsRow, 0)

coderd/database/queries.sql.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)