Skip to content
Prev Previous commit
Next Next commit
use --output specifier instead
  • Loading branch information
johnstcn committed Apr 5, 2023
commit 1f403a203e4df1602796676678bccae296c4daf4
113 changes: 59 additions & 54 deletions cli/version.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package cli

import (
"encoding/json"
"fmt"
"strings"
"time"
Expand All @@ -11,69 +10,75 @@ import (
"github.com/coder/coder/cli/cliui"
)

// version prints the coder version
func (*RootCmd) version() *clibase.Cmd {
handleHuman := func(inv *clibase.Invocation) error {
var str strings.Builder
_, _ = str.WriteString("Coder ")
if buildinfo.IsAGPL() {
_, _ = str.WriteString("(AGPL) ")
}
_, _ = str.WriteString(buildinfo.Version())
buildTime, valid := buildinfo.Time()
if valid {
_, _ = str.WriteString(" " + buildTime.Format(time.UnixDate))
}
_, _ = str.WriteString("\r\n" + buildinfo.ExternalURL() + "\r\n\r\n")
// versionInfo wraps the stuff we get from buildinfo so that it's
// easier to emit in different formats.
type versionInfo struct {
Version string `json:"version"`
BuildTime time.Time `json:"build_time"`
ExternalURL string `json:"external_url"`
Slim bool `json:"slim"`
AGPL bool `json:"agpl"`
}

if buildinfo.IsSlim() {
_, _ = str.WriteString(fmt.Sprintf("Slim build of Coder, does not support the %s subcommand.\n", cliui.Styles.Code.Render("server")))
} else {
_, _ = str.WriteString(fmt.Sprintf("Full build of Coder, supports the %s subcommand.\n", cliui.Styles.Code.Render("server")))
}
// String() implements Stringer
func (vi versionInfo) String() string {
var str strings.Builder
_, _ = str.WriteString("Coder ")
if vi.AGPL {
_, _ = str.WriteString("(AGPL) ")
}
_, _ = str.WriteString(vi.Version)

_, _ = fmt.Fprint(inv.Stdout, str.String())
return nil
if !vi.BuildTime.IsZero() {
_, _ = str.WriteString(" " + vi.BuildTime.Format(time.UnixDate))
}
_, _ = str.WriteString("\r\n" + vi.ExternalURL + "\r\n\r\n")

handleJSON := func(inv *clibase.Invocation) error {
buildTime, _ := buildinfo.Time()
versionInfo := struct {
Version string `json:"version"`
BuildTime string `json:"build_time"`
ExternalURL string `json:"external_url"`
Slim bool `json:"slim"`
AGPL bool `json:"agpl"`
}{
Version: buildinfo.Version(),
BuildTime: buildTime.Format(time.RFC3339),
ExternalURL: buildinfo.ExternalURL(),
Slim: buildinfo.IsSlim(),
AGPL: buildinfo.IsAGPL(),
}
if vi.Slim {
_, _ = str.WriteString(fmt.Sprintf("Slim build of Coder, does not support the %s subcommand.", cliui.Styles.Code.Render("server")))
} else {
_, _ = str.WriteString(fmt.Sprintf("Full build of Coder, supports the %s subcommand.", cliui.Styles.Code.Render("server")))
}
return str.String()
}

enc := json.NewEncoder(inv.Stdout)
enc.SetIndent("", " ")
return enc.Encode(versionInfo)
func defaultVersionInfo() *versionInfo {
buildTime, _ := buildinfo.Time()
return &versionInfo{
Version: buildinfo.Version(),
BuildTime: buildTime,
ExternalURL: buildinfo.ExternalURL(),
Slim: buildinfo.IsSlim(),
AGPL: buildinfo.IsAGPL(),
}
}

var outputJSON bool
// version prints the coder version
func (*RootCmd) version(versionInfo func() *versionInfo) *clibase.Cmd {
var (
formatter = cliui.NewOutputFormatter(
cliui.TextFormat(),
cliui.JSONFormat(),
)
vi = versionInfo()
)

return &clibase.Cmd{
Use: "version",
Short: "Show coder version",
Options: clibase.OptionSet{
{
Flag: "json",
Description: "Emit version information in machine-readable JSON format.",
Value: clibase.BoolOf(&outputJSON),
},
},
cmd := &clibase.Cmd{
Use: "version",
Short: "Show coder version",
Options: clibase.OptionSet{},
Handler: func(inv *clibase.Invocation) error {
if outputJSON {
return handleJSON(inv)
out, err := formatter.Format(inv.Context(), vi)
if err != nil {
return err
}
return handleHuman(inv)

_, err = fmt.Fprintln(inv.Stdout, out)
return err
},
}

formatter.AttachOptions(&cmd.Options)

return cmd
}
11 changes: 8 additions & 3 deletions cli/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import (

func TestVersion(t *testing.T) {
t.Parallel()
expectedHuman := `Coder v0.0.0-devel
expectedText := `Coder v0.0.0-devel
https://github.com/coder/coder

Full build of Coder, supports the server subcommand.
Expand All @@ -35,13 +35,18 @@ Full build of Coder, supports the server subcommand.
{
Name: "Defaults to human-readable output",
Args: []string{"version"},
Expected: expectedHuman,
Expected: expectedText,
},
{
Name: "JSON output",
Args: []string{"version", "--json"},
Args: []string{"version", "--output=json"},
Expected: expectedJSON,
},
{
Name: "Text output",
Args: []string{"version", "--output=text"},
Expected: expectedText,
},
} {
tt := tt
t.Run(tt.Name, func(t *testing.T) {
Expand Down