Skip to content
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

feat: migrate CLI to use cobra #114

Open
wants to merge 30 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
af0cdb0
chore: comment out the older cli code
1garo Feb 27, 2024
e35c42d
fix: move version cmd to other file
1garo Feb 27, 2024
78ed1ba
feat: add root command
1garo Feb 27, 2024
2918a69
feat: main file to call cmd.Execute()
1garo Feb 27, 2024
bdd67e1
feat: add cobra to the project
1garo Feb 27, 2024
7ad4826
feat: add flags the way cobra uses it
1garo Feb 27, 2024
d1bf455
feat: refactor to cobra style, seems to be working fine
1garo Feb 27, 2024
bc5123d
chore: default is not 0
1garo Feb 27, 2024
0f5f5e5
chore: add some comments to struct and functions
1garo Feb 27, 2024
e7dd29a
fix: refactor some of the functions
1garo Feb 28, 2024
c6cb3d3
feat(WIP): re-add tests
1garo Feb 28, 2024
6de0733
chore: remove old testing file
1garo Feb 29, 2024
36594c5
feat: add version cmd tests
1garo Feb 29, 2024
7550f12
feat: uncomment and fix other tests
1garo Feb 29, 2024
f2b2242
chore: run gofmt and remove comment
1garo Mar 8, 2024
21c4071
Merge branch 'main' into feat/migrate-to-cobra
1garo Apr 3, 2024
58a6988
chore: merge main
1garo Apr 3, 2024
7e1b9c5
chore: add quiet flag
1garo Apr 3, 2024
923d911
Update Dockerfile
1garo Apr 12, 2024
d581599
Update Dockerfile
1garo Apr 12, 2024
a561a84
Merge branch 'main' into feat/migrate-to-cobra
1garo Apr 12, 2024
66b4a3b
fix: do some cleanup after merge
1garo Apr 12, 2024
8a5c705
fix: properly resolve conflicts of last merge
1garo Apr 12, 2024
a9dddfe
chore: change from cmd/validator to main.go target
1garo Apr 12, 2024
08f83f6
chore: go mod tidy to update new deps
1garo Apr 12, 2024
4d73a9f
fix: add search_path as positional argument
1garo Apr 12, 2024
541f6f9
fix: add back quiet flag and update tests
1garo Apr 12, 2024
dad9045
chore: update readme target to main.go instead of cmd/validator.go
1garo Apr 12, 2024
e220a4a
chore: lint
1garo Apr 12, 2024
d78ef64
fix: update usage to cobra format and commands to use `--`
1garo Apr 12, 2024
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
2 changes: 1 addition & 1 deletion Dockerfile
1garo marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ RUN CGO_ENABLED=0 \
-ldflags="-w -s -extldflags '-static' -X github.com/Boeing/config-file-validator.version=$VALIDATOR_VERSION" \
-tags netgo \
-o validator \
cmd/validator/validator.go
main.go

FROM $BASE_IMAGE
COPY --from=go-builder /build/validator /
Expand Down
57 changes: 26 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@
<img src="https://img.shields.io/badge/License-Apache_2.0-blue.svg" alt="Apache 2 License">
</a>

<a href="https://github.com/avelino/awesome-go">
<img src="https://awesome.re/mentioned-badge.svg" alt="Awesome Go">
</a>

<a href="https://pkg.go.dev/github.com/Boeing/config-file-validator">
<img src="https://pkg.go.dev/badge/github.com/Boeing/config-file-validator.svg" alt="Go Reference">
</a>
Expand All @@ -31,9 +27,7 @@
## Supported config files formats:
* Apple PList XML
* CSV
* ENV
* HCL
* HOCON
* INI
* JSON
* Properties
Expand Down Expand Up @@ -97,28 +91,28 @@ go install github.com/Boeing/config-file-validator/cmd/[email protected]

## Usage
```
Usage: validator [OPTIONS] [<search_path>...]

positional arguments:
search_path: The search path on the filesystem for configuration files. Defaults to the current working directory if no search_path provided

optional flags:
-depth int
Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal
-exclude-dirs string
Subdirectories to exclude when searching for configuration files
-exclude-file-types string
A comma separated list of file types to ignore
-groupby string
Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
-output string
Destination to a file to output results
-quiet
1garo marked this conversation as resolved.
Show resolved Hide resolved
If quiet flag is set. It doesn't print any output to stdout.
-reporter string
Format of the printed report. Options are standard and json (default "standard")
-version
Version prints the release version of validator
Cross Platform tool to validate configuration files

Usage:
validator [flags]
validator [command]

Available Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
version Version prints the release version of validator

Flags:
--depth int Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal.
--exclude-dirs string Subdirectories to exclude when searching for configuration files
--exclude-file-types string A comma separated list of file types to ignore
--groupby string Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
-h, --help help for validator
--output string Destination to a file to output results
--quiet If quiet flag is set. It doesn't print any output to stdout.
--reporter string Format of the printed report. Options are standard and json (default "standard")

Use "validator [command] --help" for more information about a command.
```

### Examples
Expand Down Expand Up @@ -190,6 +184,7 @@ validator -groupby directory,pass-fail

![Groupby File Type and Pass/Fail](./img/gb-filetype-and-pass-fail.png)


### Output results to a file
Output report results to a file (default name is `result.{extension}`). Must provide reporter flag with a supported extension format. Available options are `junit` and `json`. If an existing directory is provided, create a file named default name in the given directory. If a file name is provided, create a file named the given name at the current working directory.

Expand Down Expand Up @@ -224,7 +219,7 @@ go build \
-ldflags='-w -s -extldflags "-static"' \
-tags netgo \
-o validator \
cmd/validator/validator.go
main.go
```

#### Install
Expand All @@ -243,7 +238,7 @@ go build \
-ldflags='-w -s -extldflags "-static"' \
-tags netgo \
-o validator \
cmd/validator/validator.go
main.go
```

#### Install
Expand All @@ -262,7 +257,7 @@ go build \
-ldflags='-w -s -extldflags "-static"' \
-tags netgo \
-o validator.exe \
cmd/validator/validator.go
main.go
```

#### Install
Expand Down
26 changes: 26 additions & 0 deletions cmd/validator/commands/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cmd

import (
validator "github.com/Boeing/config-file-validator/cmd/validator"
"github.com/spf13/cobra"
)

func CmdFlags(cmd *cobra.Command) {
cmd.PersistentFlags().
IntVar(&validator.Flags.Depth, "depth", 0, "Depth of recursion for the provided search paths. Set depth to 0 to disable recursive path traversal.")
cmd.PersistentFlags().
StringVar(&validator.Flags.ExcludeDirs, "exclude-dirs", "", "Subdirectories to exclude when searching for configuration files")
cmd.PersistentFlags().
StringVar(&validator.Flags.ExcludeFileTypes, "exclude-file-types", "", "A comma separated list of file types to ignore")
cmd.PersistentFlags().StringVar(&validator.Flags.Output, "output", "", "Destination to a file to output results")
cmd.PersistentFlags().
StringVar(&validator.Flags.ReportType, "reporter", "standard", "Format of the printed report. Options are standard and json")
cmd.PersistentFlags().
StringVar(&validator.Flags.GroupOutput, "groupby", "", "Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports")
cmd.PersistentFlags().
BoolVar(&validator.Flags.Quiet, "quiet", false, "If quiet flag is set. It doesn't print any output to stdout.")
}

func init() {
CmdFlags(rootCmd)
}
73 changes: 73 additions & 0 deletions cmd/validator/commands/flags_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package cmd

import (
"bytes"
"strings"
"testing"

cmd "github.com/Boeing/config-file-validator/cmd/validator"
"github.com/spf13/cobra"
)

func ExecuteTestHelper(t *testing.T, c *cobra.Command, args ...string) (string, error) {
t.Helper()

buf := new(bytes.Buffer)
c.SetOut(buf)
c.SetErr(buf)
c.SetArgs(args)

err := c.Execute()
return strings.TrimSpace(buf.String()), err
}

func Test_flags(t *testing.T) {
// We manipulate the Args to set them up for the testcases
cases := []struct {
Name string
Args []string
ExpectedExit int
}{
{"blank", []string{}, 0},
{"negative depth set", []string{"--depth", "-1", "--reporter", "standard"}, 1},
{"flags set, wrong reporter", []string{"--exclude-dirs", "subdir", "--reporter", "wrong"}, 1},
{"flags set, json reporter", []string{"--exclude-dirs", "subdir", "--reporter", "json"}, 0},
{"flags set, junit reported", []string{"--exclude-dirs", "subdir", "--reporter", "junit"}, 0},
{"bad path", []string{"/path/does/not/exit"}, 1},
{"exclude file types set", []string{"--exclude-file-types", "json"}, 0},
{"multiple paths", []string{"../../../test/fixtures/subdir/good.json", "../../../test/fixtures/good.json"}, 0},
{"output set", []string{"--output", "../../../test/output", "--reporter", "json"}, 0},

{"empty string output set", []string{"--output", "", "--reporter", "json", "."}, 0},
{"wrong output set", []string{"--output", "/path/not/exist", "--reporter", "json", "."}, 1},
{"incorrect group", []string{"--groupby", "badgroup"}, 1},
{"correct group", []string{"--groupby", "directory"}, 0},
{"grouped junit", []string{"--groupby", "directory", "--reporter", "junit", "."}, 1},
{"groupby duplicate", []string{"--groupby", "directory,directory", "."}, 1},
{"quiet flag", []string{"--quiet", "."}, 0},
}

var exitStatus int

for _, tc := range cases {
root := &cobra.Command{
Use: "root",
Run: func(c *cobra.Command, args []string) {
exitStatus = cmd.ExecRoot(c, args)
},
}
CmdFlags(root)

t.Run(tc.Name, func(t *testing.T) {
_, err := ExecuteTestHelper(t, root, tc.Args...)
if err != nil {
t.Error("ExecuteTestHelper: ", err)
}

if tc.ExpectedExit != exitStatus {
t.Errorf("Wrong exit code, expected: %v, got: %v", tc.ExpectedExit, exitStatus)
}
})
}

}
26 changes: 26 additions & 0 deletions cmd/validator/commands/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cmd

import (
"fmt"
"os"

validator "github.com/Boeing/config-file-validator/cmd/validator"
"github.com/spf13/cobra"
)

// rootCmd command configuration and setup
var rootCmd = &cobra.Command{
Use: "validator",
Short: "Cross Platform tool to validate configuration files",
Args: cobra.ArbitraryArgs,
Run: func(cmd *cobra.Command, args []string) {
os.Exit(validator.ExecRoot(cmd, args))
},
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
27 changes: 25 additions & 2 deletions version.go → cmd/validator/commands/version.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package configfilevalidator
package cmd

import "fmt"
import (
"fmt"

"github.com/spf13/cobra"
)

// Version information set by link flags during build. We fall back to these sane
// default values when not provided
Expand All @@ -18,9 +22,28 @@ func (v Version) String() string {
return fmt.Sprintf("validator version %v", v.Version)
}

// SetVersion set the version
func SetVersion(v string) {
version = v
}

// GetVersion returns the version information
func GetVersion() Version {
return Version{
Version: version,
}
}

func init() {
rootCmd.AddCommand(versionCmd)
}

// versionCmd command configuration and setup
var versionCmd = &cobra.Command{
Use: "version",
Short: "Version prints the release version of validator",
Long: ``,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(GetVersion())
},
}
33 changes: 33 additions & 0 deletions cmd/validator/commands/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package cmd

import (
"testing"

cmd "github.com/Boeing/config-file-validator/cmd/validator"
"github.com/spf13/cobra"
)

func TestFlagVersion(t *testing.T) {
var exitStatus int
expectedExit := 0
root := &cobra.Command{
Use: "root",
Run: func(c *cobra.Command, args []string) {
exitStatus = cmd.ExecRoot(c, args)
}}

SetVersion("testing")
root.AddCommand(versionCmd)

args := []string{"version"}

_, err := ExecuteTestHelper(t, root, args...)
if err != nil {
t.Error(err)
}

if expectedExit != exitStatus {
t.Errorf("Wrong exit code, expected: %v, got: %v", expectedExit, exitStatus)
}

}
Loading
Loading