Skip to content

Commit 8060b66

Browse files
committed
feat: Rename config-ssh --diff to --dry-run
Since the intent between diff and dry-run are different, this change allows for interactive prompts to be shown during `--dry-run`, previously prompts were disabled. Dry-run can also be chanied with `--yes` and `--use-previous-options` for non-interactive modes. Dry-run is like a normal run with changes replaced by diff. Fixes #2530
1 parent 7f77831 commit 8060b66

File tree

2 files changed

+49
-57
lines changed

2 files changed

+49
-57
lines changed

cli/configssh.go

+29-57
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,6 @@ func (o sshConfigOptions) equal(other sshConfigOptions) bool {
5757
return slices.Equal(opt1, opt2)
5858
}
5959

60-
func (o sshConfigOptions) asArgs() (args []string) {
61-
for _, opt := range o.sshOptions {
62-
args = append(args, "--ssh-option", fmt.Sprintf("%q", opt))
63-
}
64-
return args
65-
}
66-
6760
func (o sshConfigOptions) asList() (list []string) {
6861
for _, opt := range o.sshOptions {
6962
list = append(list, fmt.Sprintf("ssh-option: %s", opt))
@@ -140,11 +133,8 @@ func configSSH() *cobra.Command {
140133
sshConfigOpts sshConfigOptions
141134
usePreviousOpts bool
142135
coderConfigFile string
143-
showDiff bool
136+
dryRun bool
144137
skipProxyCommand bool
145-
146-
// Diff should exit with status 1 when files differ.
147-
filesDiffer bool
148138
)
149139
cmd := &cobra.Command{
150140
Annotations: workspaceCommand,
@@ -156,14 +146,9 @@ func configSSH() *cobra.Command {
156146
157147
` + cliui.Styles.Code.Render("$ coder config-ssh -o ForwardAgent=yes") + `
158148
159-
- You can use -D (or --diff) to display the changes that will be made.
149+
- You can use --dry-run (or -n) to see the changes that will be made.
160150
161-
` + cliui.Styles.Code.Render("$ coder config-ssh --diff"),
162-
PostRun: func(cmd *cobra.Command, args []string) {
163-
if showDiff && filesDiffer {
164-
os.Exit(1) //nolint: revive
165-
}
166-
},
151+
` + cliui.Styles.Code.Render("$ coder config-ssh --dry-run"),
167152
RunE: func(cmd *cobra.Command, args []string) error {
168153
client, err := createClient(cmd)
169154
if err != nil {
@@ -173,7 +158,9 @@ func configSSH() *cobra.Command {
173158
recvWorkspaceConfigs := sshPrepareWorkspaceConfigs(cmd.Context(), client)
174159

175160
out := cmd.OutOrStdout()
176-
if showDiff {
161+
if dryRun {
162+
// Print everything except diff to stderr so
163+
// that it's possible to capture the diff.
177164
out = cmd.OutOrStderr()
178165
}
179166
binaryFile, err := currentBinPath(out)
@@ -186,7 +173,6 @@ func configSSH() *cobra.Command {
186173
return xerrors.Errorf("user home dir failed: %w", err)
187174
}
188175

189-
sshConfigFileOrig := sshConfigFile
190176
if strings.HasPrefix(sshConfigFile, "~/") {
191177
sshConfigFile = filepath.Join(homedir, sshConfigFile[2:])
192178
}
@@ -221,7 +207,7 @@ func configSSH() *cobra.Command {
221207
// or when a previous config does not exist.
222208
if usePreviousOpts && lastConfig != nil {
223209
sshConfigOpts = *lastConfig
224-
} else if !showDiff && lastConfig != nil && !sshConfigOpts.equal(*lastConfig) {
210+
} else if lastConfig != nil && !sshConfigOpts.equal(*lastConfig) {
225211
newOpts := sshConfigOpts.asList()
226212
newOptsMsg := "\n\n New options: none"
227213
if len(newOpts) > 0 {
@@ -244,7 +230,10 @@ func configSSH() *cobra.Command {
244230
// Selecting "no" will use the last config.
245231
sshConfigOpts = *lastConfig
246232
}
247-
_, _ = fmt.Fprint(out, "\n")
233+
// Only print when prompts are shown.
234+
if yes, _ := cmd.Flags().GetBool("yes"); !yes {
235+
_, _ = fmt.Fprint(out, "\n")
236+
}
248237
}
249238

250239
configModified := configRaw
@@ -316,15 +305,21 @@ func configSSH() *cobra.Command {
316305
configModified = buf.Bytes()
317306
}
318307

319-
if showDiff {
320-
if len(changes) > 0 {
321-
// Write to stderr to avoid dirtying the diff output.
322-
_, _ = fmt.Fprint(out, "The following changes will be made to your SSH configuration:\n\n")
323-
for _, change := range changes {
324-
_, _ = fmt.Fprintf(out, " * %s\n", change)
325-
}
308+
if len(changes) > 0 {
309+
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
310+
Text: fmt.Sprintf("The following changes will be made to your SSH configuration:\n\n * %s\n\n Continue?", strings.Join(changes, "\n * ")),
311+
IsConfirm: true,
312+
})
313+
if err != nil {
314+
return nil
326315
}
316+
// Only print when prompts are shown.
317+
if yes, _ := cmd.Flags().GetBool("yes"); !yes {
318+
_, _ = fmt.Fprint(out, "\n")
319+
}
320+
}
327321

322+
if dryRun {
328323
color := isTTYOut(cmd)
329324
diffFns := []func() ([]byte, error){
330325
func() ([]byte, error) { return diffBytes(sshConfigFile, configRaw, configModified, color) },
@@ -340,34 +335,11 @@ func configSSH() *cobra.Command {
340335
return xerrors.Errorf("diff failed: %w", err)
341336
}
342337
if len(diff) > 0 {
343-
filesDiffer = true
344-
// Always write to stdout.
338+
// Write diff to stdout.
345339
_, _ = fmt.Fprintf(cmd.OutOrStdout(), "\n%s", diff)
346340
}
347341
}
348-
349-
return nil
350-
}
351-
352-
if len(changes) > 0 {
353-
// In diff mode we don't prompt re-using the previous
354-
// configuration, so we output the entire command.
355-
var args []string
356-
if sshConfigFileOrig != sshDefaultConfigFileName {
357-
args = append(args, "--ssh-config-file", sshConfigFileOrig)
358-
}
359-
args = append(args, sshConfigOpts.asArgs()...)
360-
args = append(args, "--diff")
361-
diffCommand := fmt.Sprintf("$ %s %s", cmd.CommandPath(), strings.Join(args, " "))
362-
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
363-
Text: fmt.Sprintf("The following changes will be made to your SSH configuration:\n\n * %s\n\n To see changes, run diff:\n\n %s\n\n Continue?", strings.Join(changes, "\n * "), diffCommand),
364-
IsConfirm: true,
365-
})
366-
if err != nil {
367-
return nil
368-
}
369-
_, _ = fmt.Fprint(out, "\n")
370-
342+
} else {
371343
if !bytes.Equal(configRaw, configModified) {
372344
err = writeWithTempFileAndMove(sshConfigFile, bytes.NewReader(configModified))
373345
if err != nil {
@@ -394,7 +366,7 @@ func configSSH() *cobra.Command {
394366
}
395367
cliflag.StringVarP(cmd.Flags(), &sshConfigFile, "ssh-config-file", "", "CODER_SSH_CONFIG_FILE", sshDefaultConfigFileName, "Specifies the path to an SSH config.")
396368
cmd.Flags().StringArrayVarP(&sshConfigOpts.sshOptions, "ssh-option", "o", []string{}, "Specifies additional SSH options to embed in each host stanza.")
397-
cmd.Flags().BoolVarP(&showDiff, "diff", "D", false, "Show diff of changes that will be made.")
369+
cmd.Flags().BoolVarP(&dryRun, "dry-run", "n", false, "Perform a trial run with no changes made, showing a diff at the end.")
398370
cmd.Flags().BoolVarP(&skipProxyCommand, "skip-proxy-command", "", false, "Specifies whether the ProxyCommand option should be skipped. Useful for testing.")
399371
_ = cmd.Flags().MarkHidden("skip-proxy-command")
400372
cliflag.BoolVarP(cmd.Flags(), &usePreviousOpts, "use-previous-options", "", "CODER_SSH_USE_PREVIOUS_OPTIONS", false, "Specifies whether or not to keep options from previous run of config-ssh.")
@@ -575,7 +547,7 @@ func diffBytes(name string, b1, b2 []byte, color bool) ([]byte, error) {
575547
if color {
576548
opts = append(opts, write.TerminalColor())
577549
}
578-
err := diff.Text(name, name+".new", b1, b2, &buf, opts...)
550+
err := diff.Text(name, name, b1, b2, &buf, opts...)
579551
if err != nil {
580552
return nil, err
581553
}
@@ -584,7 +556,7 @@ func diffBytes(name string, b1, b2 []byte, color bool) ([]byte, error) {
584556
//
585557
// Example:
586558
// --- /home/user/.ssh/config
587-
// +++ /home/user/.ssh/config.new
559+
// +++ /home/user/.ssh/config
588560
if bytes.Count(b, []byte{'\n'}) == 2 {
589561
b = nil
590562
}

cli/configssh_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,26 @@ func TestConfigSSH_FileWriteAndOptionsFlow(t *testing.T) {
494494
"--yes",
495495
},
496496
},
497+
{
498+
name: "Do not overwrite config when using --dry-run",
499+
writeConfig: writeConfig{
500+
ssh: strings.Join([]string{
501+
baseHeader,
502+
"",
503+
}, "\n"),
504+
},
505+
wantConfig: wantConfig{
506+
ssh: strings.Join([]string{
507+
baseHeader,
508+
"",
509+
}, "\n"),
510+
},
511+
args: []string{
512+
"--ssh-option", "ForwardAgent=yes",
513+
"--dry-run",
514+
"--yes",
515+
},
516+
},
497517

498518
// Tests for deprecated split coder config.
499519
{

0 commit comments

Comments
 (0)