mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
ab28ecde88
Fixes three bugs that caused `coder update` to always re-prompt for multi-select (`list(string)`) parameters instead of reusing previous build values: 1. **`isValidTemplateParameterOption` failed for multi-select values** (`cli/parameterresolver.go`): It compared the entire JSON array string (e.g. `["vim","emacs"]`) against individual option values, which never matched. Now parses the JSON array and validates each element separately. 2. **`RichParameter` ignored previous build value for multi-select** (`cli/cliui/parameter.go`): The `list(string)` branch always used the template's default value instead of the `defaultValue` argument (which carries the previous build's value). Now uses `defaultValue` when available, falling back to the template default. 3. **Pre-existing crash when `list(string)` has no default value** (`cli/cliui/parameter.go`): `json.Unmarshal` on an empty string caused `unexpected end of JSON input`. Now skips unmarshaling when the default source is empty. Fixes #19956
113 lines
3.1 KiB
Go
113 lines
3.1 KiB
Go
package cliui
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/coder/coder/v2/codersdk"
|
|
"github.com/coder/pretty"
|
|
"github.com/coder/serpent"
|
|
)
|
|
|
|
func RichParameter(inv *serpent.Invocation, templateVersionParameter codersdk.TemplateVersionParameter, name, defaultValue string) (string, error) {
|
|
label := name
|
|
if templateVersionParameter.Ephemeral {
|
|
label += pretty.Sprint(DefaultStyles.Warn, " (build option)")
|
|
}
|
|
|
|
_, _ = fmt.Fprintln(inv.Stdout, Bold(label))
|
|
|
|
if templateVersionParameter.DescriptionPlaintext != "" {
|
|
_, _ = fmt.Fprintln(inv.Stdout, " "+strings.TrimSpace(strings.Join(strings.Split(templateVersionParameter.DescriptionPlaintext, "\n"), "\n "))+"\n")
|
|
}
|
|
|
|
var err error
|
|
var value string
|
|
switch {
|
|
case templateVersionParameter.Type == "list(string)":
|
|
// Move the cursor up a single line for nicer display!
|
|
_, _ = fmt.Fprint(inv.Stdout, "\033[1A")
|
|
|
|
var defaults []string
|
|
defaultSource := defaultValue
|
|
if defaultSource == "" {
|
|
defaultSource = templateVersionParameter.DefaultValue
|
|
}
|
|
if defaultSource != "" {
|
|
err = json.Unmarshal([]byte(defaultSource), &defaults)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
}
|
|
|
|
values, err := RichMultiSelect(inv, RichMultiSelectOptions{
|
|
Options: templateVersionParameter.Options,
|
|
Defaults: defaults,
|
|
EnableCustomInput: templateVersionParameter.FormType == "tag-select",
|
|
})
|
|
if err == nil {
|
|
v, err := json.Marshal(&values)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
_, _ = fmt.Fprintln(inv.Stdout)
|
|
pretty.Fprintf(
|
|
inv.Stdout,
|
|
DefaultStyles.Prompt, "%s\n", strings.Join(values, ", "),
|
|
)
|
|
value = string(v)
|
|
}
|
|
case len(templateVersionParameter.Options) > 0:
|
|
// Move the cursor up a single line for nicer display!
|
|
_, _ = fmt.Fprint(inv.Stdout, "\033[1A")
|
|
var richParameterOption *codersdk.TemplateVersionParameterOption
|
|
richParameterOption, err = RichSelect(inv, RichSelectOptions{
|
|
Options: templateVersionParameter.Options,
|
|
Default: defaultValue,
|
|
HideSearch: true,
|
|
})
|
|
if err == nil {
|
|
_, _ = fmt.Fprintln(inv.Stdout)
|
|
pretty.Fprintf(inv.Stdout, DefaultStyles.Prompt, "%s\n", richParameterOption.Name)
|
|
value = richParameterOption.Value
|
|
}
|
|
default:
|
|
text := "Enter a value"
|
|
if defaultValue != "" {
|
|
text += fmt.Sprintf(" (default: %q)", defaultValue)
|
|
}
|
|
text += ":"
|
|
|
|
value, err = Prompt(inv, PromptOptions{
|
|
Text: Bold(text),
|
|
Validate: func(value string) error {
|
|
// If empty, the default value will be used (if available).
|
|
if value == "" && defaultValue != "" {
|
|
value = defaultValue
|
|
}
|
|
return validateRichPrompt(value, templateVersionParameter)
|
|
},
|
|
})
|
|
value = strings.TrimSpace(value)
|
|
}
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
// If they didn't specify anything, use the default value if set.
|
|
if len(templateVersionParameter.Options) == 0 && value == "" {
|
|
value = defaultValue
|
|
}
|
|
|
|
return value, nil
|
|
}
|
|
|
|
func validateRichPrompt(value string, p codersdk.TemplateVersionParameter) error {
|
|
return codersdk.ValidateWorkspaceBuildParameter(p, &codersdk.WorkspaceBuildParameter{
|
|
Name: p.Name,
|
|
Value: value,
|
|
}, nil)
|
|
}
|