10000 feat(cli): add --output={text,json} to version cmd by johnstcn · Pull Request #7010 · coder/coder · GitHub
[go: up one dir, main page]

Skip to content

feat(cli): add --output={text,json} to version cmd #7010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Apr 5, 2023
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
0