Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions cmd/version.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,31 @@
package cmd

import (
"encoding/json"
"fmt"

"github.com/jongio/grut/internal/config"
"github.com/jongio/grut/internal/update"
"github.com/spf13/cobra"
)

type versionInfo struct {
Version string `json:"version"`
}

// newVersionCmd creates the version command.
func newVersionCmd() *cobra.Command {
return &cobra.Command{
var jsonOutput bool
cmd := &cobra.Command{
Use: cmdVersion,
Short: "Print the version of grut",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(config.AppVersion)
if jsonOutput {
_ = json.NewEncoder(cmd.OutOrStdout()).Encode(versionInfo{Version: config.AppVersion})
return
}

fmt.Fprintln(cmd.OutOrStdout(), config.AppVersion)
// Show update notification inline.
if info := update.CheckForUpdate(config.AppVersion); info != nil {
fmt.Fprintf(cmd.ErrOrStderr(),
Expand All @@ -23,4 +34,6 @@ func newVersionCmd() *cobra.Command {
}
},
}
cmd.Flags().BoolVar(&jsonOutput, "json", false, "Print version information as JSON")
return cmd
}
32 changes: 27 additions & 5 deletions cmd/version_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package cmd

import (
"bytes"
"encoding/json"
"testing"

"github.com/jongio/grut/internal/config"
Expand All @@ -13,17 +15,15 @@ import (
// ---------------------------------------------------------------------------

func TestVersionCmd_OutputContainsAppVersion(t *testing.T) {
// The version command uses fmt.Println which writes to os.Stdout, not
// cmd.OutOrStdout(). We verify it runs without error and check the
// version string is set correctly via the root command's Version field.
root, cleanup := buildRootCommand()
defer cleanup()
var out bytes.Buffer
root.SetOut(&out)
root.SetArgs([]string{"version"})

err := root.Execute()
require.NoError(t, err)
// The root command's Version field is what --version and the version
// subcommand use. Verify it's set correctly.
assert.Contains(t, out.String(), config.AppVersion)
assert.Equal(t, config.AppVersion, root.Version)
}

Expand All @@ -43,6 +43,28 @@ func TestVersionCmd_StructureHasCorrectUse(t *testing.T) {
assert.Equal(t, "version", cmd.Use)
}

func TestVersionCmd_JSONOutput(t *testing.T) {
cmd := newVersionCmd()
var out bytes.Buffer
cmd.SetOut(&out)
cmd.SetArgs([]string{"--json"})

err := cmd.Execute()

require.NoError(t, err)
var got versionInfo
require.NoError(t, json.Unmarshal(out.Bytes(), &got))
assert.Equal(t, config.AppVersion, got.Version)
}

func TestVersionCmd_JSONFlagRegistered(t *testing.T) {
cmd := newVersionCmd()
flag := cmd.Flags().Lookup("json")
require.NotNil(t, flag)
assert.Equal(t, "bool", flag.Value.Type())
assert.Equal(t, "false", flag.DefValue)
}

func TestVersionCmd_HasRunNotRunE(t *testing.T) {
// version uses Run (not RunE) because it always succeeds.
cmd := newVersionCmd()
Expand Down
9 changes: 9 additions & 0 deletions docs/version-json.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Version JSON

Use JSON output when scripts need the installed grut version:

```bash
grut version --json
```

The output contains a stable `version` field and does not include update notices.
Loading