Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit a171882

Browse files
authored
Error coder sh commands if the env requires a rebuild (#163)
1 parent 03d2d8b commit a171882

File tree

12 files changed

+82
-70
lines changed

12 files changed

+82
-70
lines changed

coder-sdk/env.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,6 @@ type RebuildMessage struct {
3939
Text string `json:"text"`
4040
Required bool `json:"required"`
4141
AutoOffThreshold xjson.MSDuration `json:"auto_off_threshold" tab:"-"`
42-
RebuildMessages []struct {
43-
Text string `json:"text"`
44-
Required bool `json:"required"`
45-
} `json:"rebuild_messages" tab:"-"`
4642
}
4743

4844
// EnvironmentStat represents the state of an environment

docs/coder_sh.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ coder sh [environment_name] [<command [args...]>] [flags]
1414

1515
```
1616
coder sh backend-env
17+
coder sh front-end-dev cat ~/config.json
1718
```
1819

1920
### Options

internal/cmd/cmd.go

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,24 @@ func Make() *cobra.Command {
2121
}
2222

2323
app.AddCommand(
24-
makeLoginCmd(),
25-
makeLogoutCmd(),
26-
makeShellCmd(),
27-
makeUsersCmd(),
28-
makeConfigSSHCmd(),
29-
makeSecretsCmd(),
30-
envsCommand(),
31-
makeSyncCmd(),
32-
makeURLCmd(),
24+
loginCmd(),
25+
logoutCmd(),
26+
shCmd(),
27+
usersCmd(),
28+
configSSHCmd(),
29+
secretsCmd(),
30+
envsCmd(),
31+
syncCmd(),
32+
urlCmd(),
3333
resourceCmd(),
34-
completionCmd,
35-
genDocs(app),
34+
completionCmd(),
35+
genDocsCmd(app),
3636
)
3737
app.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "show verbose output")
3838
return app
3939
}
4040

41-
func genDocs(rootCmd *cobra.Command) *cobra.Command {
41+
func genDocsCmd(rootCmd *cobra.Command) *cobra.Command {
4242
return &cobra.Command{
4343
Use: "gen-docs [dir_path]",
4444
Short: "Generate a markdown documentation tree for the root command.",
@@ -52,17 +52,18 @@ func genDocs(rootCmd *cobra.Command) *cobra.Command {
5252
}
5353

5454
// reference: https://github.com/spf13/cobra/blob/master/shell_completions.md
55-
var completionCmd = &cobra.Command{
56-
Use: "completion [bash|zsh|fish|powershell]",
57-
Short: "Generate completion script",
58-
Example: `coder completion fish > ~/.config/fish/completions/coder.fish
55+
func completionCmd() *cobra.Command {
56+
return &cobra.Command{
57+
Use: "completion [bash|zsh|fish|powershell]",
58+
Short: "Generate completion script",
59+
Example: `coder completion fish > ~/.config/fish/completions/coder.fish
5960
coder completion zsh > "${fpath[1]}/_coder"
6061
6162
Linux:
6263
$ coder completion bash > /etc/bash_completion.d/coder
6364
MacOS:
6465
$ coder completion bash > /usr/local/etc/bash_completion.d/coder`,
65-
Long: `To load completions:
66+
Long: `To load completions:
6667
6768
Bash:
6869
@@ -93,19 +94,20 @@ $ coder completion fish | source
9394
To load completions for each session, execute once:
9495
$ coder completion fish > ~/.config/fish/completions/coder.fish
9596
`,
96-
DisableFlagsInUseLine: true,
97-
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
98-
Args: cobra.ExactValidArgs(1),
99-
Run: func(cmd *cobra.Command, args []string) {
100-
switch args[0] {
101-
case "bash":
102-
_ = cmd.Root().GenBashCompletion(os.Stdout) // Best effort.
103-
case "zsh":
104-
_ = cmd.Root().GenZshCompletion(os.Stdout) // Best effort.
105-
case "fish":
106-
_ = cmd.Root().GenFishCompletion(os.Stdout, true) // Best effort.
107-
case "powershell":
108-
_ = cmd.Root().GenPowerShellCompletion(os.Stdout) // Best effort.
109-
}
110-
},
97+
DisableFlagsInUseLine: true,
98+
ValidArgs: []string{"bash", "zsh", "fish", "powershell"},
99+
Args: cobra.ExactValidArgs(1),
100+
Run: func(cmd *cobra.Command, args []string) {
101+
switch args[0] {
102+
case "bash":
103+
_ = cmd.Root().GenBashCompletion(os.Stdout) // Best effort.
104+
case "zsh":
105+
_ = cmd.Root().GenZshCompletion(os.Stdout) // Best effort.
106+
case "fish":
107+
_ = cmd.Root().GenFishCompletion(os.Stdout, true) // Best effort.
108+
case "powershell":
109+
_ = cmd.Root().GenPowerShellCompletion(os.Stdout) // Best effort.
110+
}
111+
},
112+
}
111113
}

internal/cmd/configssh.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
"golang.org/x/xerrors"
1919
)
2020

21-
func makeConfigSSHCmd() *cobra.Command {
21+
func configSSHCmd() *cobra.Command {
2222
var (
2323
configpath string
2424
remove = false

internal/cmd/envs.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717

1818
const defaultImgTag = "latest"
1919

20-
func envsCommand() *cobra.Command {
20+
func envsCmd() *cobra.Command {
2121
var user string
2222
cmd := &cobra.Command{
2323
Use: "envs",
@@ -28,12 +28,12 @@ func envsCommand() *cobra.Command {
2828

2929
cmd.AddCommand(
3030
lsEnvsCommand(&user),
31-
stopEnvsCommand(&user),
32-
rmEnvsCommand(&user),
31+
stopEnvsCmd(&user),
32+
rmEnvsCmd(&user),
3333
watchBuildLogCommand(&user),
3434
rebuildEnvCommand(&user),
35-
createEnvCommand(&user),
36-
editEnvCommand(&user),
35+
createEnvCmd(&user),
36+
editEnvCmd(&user),
3737
)
3838
return cmd
3939
}
@@ -84,7 +84,7 @@ func lsEnvsCommand(user *string) *cobra.Command {
8484
return cmd
8585
}
8686

87-
func stopEnvsCommand(user *string) *cobra.Command {
87+
func stopEnvsCmd(user *string) *cobra.Command {
8888
return &cobra.Command{
8989
Use: "stop [...environment_names]",
9090
Short: "stop Coder environments by name",
@@ -131,7 +131,7 @@ coder envs --user charlie@coder.com ls -o json \
131131
}
132132
}
133133

134-
func createEnvCommand(user *string) *cobra.Command {
134+
func createEnvCmd(user *string) *cobra.Command {
135135
var (
136136
org string
137137
img string
@@ -239,7 +239,7 @@ coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955
239239
return cmd
240240
}
241241

242-
func editEnvCommand(user *string) *cobra.Command {
242+
func editEnvCmd(user *string) *cobra.Command {
243243
var (
244244
org string
245245
img string
@@ -336,7 +336,7 @@ coder envs edit back-end-env --disk 20`,
336336
return cmd
337337
}
338338

339-
func rmEnvsCommand(user *string) *cobra.Command {
339+
func rmEnvsCmd(user *string) *cobra.Command {
340340
var force bool
341341
cmd := &cobra.Command{
342342
Use: "rm [...environment_names]",

internal/cmd/login.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import (
1818
"golang.org/x/xerrors"
1919
)
2020

21-
func makeLoginCmd() *cobra.Command {
21+
func loginCmd() *cobra.Command {
2222
return &cobra.Command{
2323
Use: "login [Coder Enterprise URL eg. https://my.coder.domain/]",
2424
Short: "Authenticate this client for future operations",

internal/cmd/logout.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"golang.org/x/xerrors"
1010
)
1111

12-
func makeLogoutCmd() *cobra.Command {
12+
func logoutCmd() *cobra.Command {
1313
return &cobra.Command{
1414
Use: "logout",
1515
Short: "Remove local authentication credentials if any exist",

internal/cmd/secrets.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"cdr.dev/coder-cli/internal/x/xtabwriter"
1515
)
1616

17-
func makeSecretsCmd() *cobra.Command {
17+
func secretsCmd() *cobra.Command {
1818
var user string
1919
cmd := &cobra.Command{
2020
Use: "secrets",
@@ -26,28 +26,28 @@ func makeSecretsCmd() *cobra.Command {
2626
&cobra.Command{
2727
Use: "ls",
2828
Short: "List all secrets owned by the active user",
29-
RunE: listSecrets(&user),
29+
RunE: listSecretsCmd(&user),
3030
},
31-
makeCreateSecret(&user),
31+
createSecretCmd(&user),
3232
&cobra.Command{
3333
Use: "rm [...secret_name]",
3434
Short: "Remove one or more secrets by name",
3535
Args: cobra.MinimumNArgs(1),
36-
RunE: makeRemoveSecrets(&user),
36+
RunE: removeSecretsCmd(&user),
3737
Example: "coder secrets rm mysql-password mysql-user",
3838
},
3939
&cobra.Command{
4040
Use: "view [secret_name]",
4141
Short: "View a secret by name",
4242
Args: cobra.ExactArgs(1),
43-
RunE: makeViewSecret(&user),
43+
RunE: viewSecretCmd(&user),
4444
Example: "coder secrets view mysql-password",
4545
},
4646
)
4747
return cmd
4848
}
4949

50-
func makeCreateSecret(userEmail *string) *cobra.Command {
50+
func createSecretCmd(userEmail *string) *cobra.Command {
5151
var (
5252
fromFile string
5353
fromLiteral string
@@ -136,7 +136,7 @@ coder secrets create aws-credentials --from-file ./credentials.json`,
136136
return cmd
137137
}
138138

139-
func listSecrets(userEmail *string) func(cmd *cobra.Command, _ []string) error {
139+
func listSecretsCmd(userEmail *string) func(cmd *cobra.Command, _ []string) error {
140140
return func(cmd *cobra.Command, _ []string) error {
141141
client, err := newClient()
142142
if err != nil {
@@ -169,7 +169,7 @@ func listSecrets(userEmail *string) func(cmd *cobra.Command, _ []string) error {
169169
}
170170
}
171171

172-
func makeViewSecret(userEmail *string) func(cmd *cobra.Command, args []string) error {
172+
func viewSecretCmd(userEmail *string) func(cmd *cobra.Command, args []string) error {
173173
return func(cmd *cobra.Command, args []string) error {
174174
var (
175175
name = args[0]
@@ -196,7 +196,7 @@ func makeViewSecret(userEmail *string) func(cmd *cobra.Command, args []string) e
196196
}
197197
}
198198

199-
func makeRemoveSecrets(userEmail *string) func(c *cobra.Command, args []string) error {
199+
func removeSecretsCmd(userEmail *string) func(c *cobra.Command, args []string) error {
200200
return func(cmd *cobra.Command, args []string) error {
201201
client, err := newClient()
202202
if err != nil {

internal/cmd/shell.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ import (
2323

2424
func getEnvsForCompletion(user string) func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
2525
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
26+
ctx := cmd.Context()
2627
client, err := newClient()
2728
if err != nil {
2829
return nil, cobra.ShellCompDirectiveDefault
2930
}
30-
envs, err := getEnvs(context.TODO(), client, user)
31+
envs, err := getEnvs(ctx, client, user)
3132
if err != nil {
3233
return nil, cobra.ShellCompDirectiveDefault
3334
}
@@ -40,7 +41,7 @@ func getEnvsForCompletion(user string) func(cmd *cobra.Command, args []string, t
4041
}
4142
}
4243

43-
func makeShellCmd() *cobra.Command {
44+
func shCmd() *cobra.Command {
4445
return &cobra.Command{
4546
Use: "sh [environment_name] [<command [args...]>]",
4647
Short: "Open a shell and execute commands in a Coder environment",
@@ -49,13 +50,13 @@ func makeShellCmd() *cobra.Command {
4950
DisableFlagParsing: true,
5051
ValidArgsFunction: getEnvsForCompletion(coder.Me),
5152
RunE: shell,
52-
Example: "coder sh backend-env",
53+
Example: `coder sh backend-env
54+
coder sh front-end-dev cat ~/config.json`,
5355
}
5456
}
5557

56-
func shell(_ *cobra.Command, cmdArgs []string) error {
57-
ctx := context.Background()
58-
58+
func shell(cmd *cobra.Command, cmdArgs []string) error {
59+
ctx := cmd.Context()
5960
command := "sh"
6061
args := []string{"-c"}
6162
if len(cmdArgs) > 1 {
@@ -106,6 +107,18 @@ func runCommand(ctx context.Context, envName, command string, args []string) err
106107
return xerrors.Errorf("find environment: %w", err)
107108
}
108109

110+
// check if a rebuild is required before attempting to open a shell
111+
for _, r := range env.RebuildMessages {
112+
// use the first rebuild message that is required
113+
if r.Required {
114+
return clog.Error(
115+
fmt.Sprintf(`environment "%s" requires a rebuild`, env.Name),
116+
clog.Causef(r.Text), clog.BlankLine,
117+
clog.Tipf(`run "coder envs rebuild %s" to rebuild`, env.Name),
118+
)
119+
}
120+
}
121+
109122
termFD := os.Stdout.Fd()
110123

111124
isInteractive := terminal.IsTerminal(int(termFD))

internal/cmd/sync.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
"golang.org/x/xerrors"
1616
)
1717

18-
func makeSyncCmd() *cobra.Command {
18+
func syncCmd() *cobra.Command {
1919
var init bool
2020
cmd := &cobra.Command{
2121
Use: "sync [local directory] [<env name>:<remote directory>]",

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy