Skip to content

Commit

Permalink
Use cobra instead of urfave/cli
Browse files Browse the repository at this point in the history
Signed-off-by: Stephen Augustus <saugustus@vmware.com>
Co-authored-by: Sascha Grunert <sgrunert@suse.com>
  • Loading branch information
justaugustus and saschagrunert committed Sep 14, 2020
1 parent 20d7e8a commit c7517b2
Show file tree
Hide file tree
Showing 5 changed files with 571 additions and 147 deletions.
7 changes: 5 additions & 2 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@ linters:
- dogsled
- dupl
- errcheck
- gochecknoglobals
- gochecknoinits
- gocognit
- goconst
- gocritic
Expand Down Expand Up @@ -57,6 +55,11 @@ linters:
# a little too nitty and obtrusive.
- lll
- wsl

# Disabled
# cobra uses globals and inits to set command configuration
#- gochecknoglobals
#- gochecknoinits
linters-settings:
godox:
keywords:
Expand Down
146 changes: 37 additions & 109 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,128 +14,56 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

/* Zeitgeist is a is a language-agnostic dependency checker */
/* Zeitgeist is a language-agnostic dependency checker */

package main
package cmd

import (
"fmt"
"os"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"

log "github.com/sirupsen/logrus"
"github.com/urfave/cli"

"sigs.k8s.io/zeitgeist/dependencies"
"k8s.io/release/pkg/log"
)

// Variables set by GoReleaser on release
type rootOptions struct {
logLevel string
}

var (
version = "dev"
commit = "none" // nolint: deadcode,gochecknoglobals,unused,varcheck
date = "unknown" // nolint: deadcode,gochecknoglobals,unused,varcheck
rootOpts = &rootOptions{}

// TODO: Implement these as a separate function or subcommand to avoid the
// deadcode,unused,varcheck nolints
// Variables set by GoReleaser on release
version = "dev" // nolint: deadcode,unused,varcheck
commit = "none" // nolint: deadcode,unused,varcheck
date = "unknown" // nolint: deadcode,unused,varcheck
)

// Initialise logging level based on LOG_LEVEL env var, or the --verbose flag.
// Defaults to info
func initLogging(verbose, json bool) {
logLevelStr, ok := os.LookupEnv("LOG_LEVEL")
if !ok {
if verbose {
logLevelStr = "debug"
} else {
logLevelStr = "info"
}
}

logLevel, err := log.ParseLevel(logLevelStr)
if err != nil {
log.Fatalf("Invalid LOG_LEVEL: %v", logLevelStr)
}

log.SetLevel(logLevel)
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "zeitgeist",
Short: "Zeitgeist is a language-agnostic dependency checker",
PersistentPreRunE: initLogging,
}

if json {
log.SetFormatter(&log.JSONFormatter{})
} else {
log.SetFormatter(
&log.TextFormatter{
FullTimestamp: true,
DisableLevelTruncation: true,
},
)
// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := rootCmd.Execute(); err != nil {
logrus.Fatal(err)
}
}

func main() {
var (
verbose bool
json bool
config string
func init() {
rootCmd.PersistentFlags().StringVar(
&rootOpts.logLevel,
"log-level",
"info",
"the logging verbosity, either 'panic', 'fatal', 'error', 'warn', 'warning', 'info', 'debug' or 'trace'",
)
}

app := cli.NewApp()
app.Name = "zeitgeist"
app.Usage = "Manage your external dependencies"
app.Version = fmt.Sprintf("%v", version)
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "verbose",
Usage: "Set log level to DEBUG",
Destination: &verbose,
},
cli.BoolFlag{
Name: "json-output",
Usage: "JSON logging output",
Destination: &json,
},
cli.StringFlag{
Name: "config, c",
Usage: "Load configuration from `FILE`",
Value: "dependencies.yaml",
Destination: &config,
},
}

app.Commands = []cli.Command{
{
Name: "validate",
Aliases: []string{},
Usage: "Check dependencies locally and against upstream versions",
Action: func(c *cli.Context) error {
initLogging(verbose, json)
err := dependencies.LocalCheck(config)
if err != nil {
return err
}
updates, err := dependencies.RemoteCheck(config)
if err != nil {
return err
}
for _, update := range updates {
fmt.Printf(update + "\n")
}
return nil
},
},
{
Name: "local",
Aliases: []string{},
Usage: "Only check dependency consistency locally",
Action: func(c *cli.Context) error {
initLogging(verbose, json)
return dependencies.LocalCheck(config)
},
},
}

// Default action when no action is passed: display the help
// nolint: gocritic
app.Action = func(c *cli.Context) error {
return cli.ShowAppHelp(c)
}

err := app.Run(os.Args)
if err != nil {
log.Fatal(err)
}
func initLogging(*cobra.Command, []string) error {
return log.SetupGlobalLogger(rootOpts.logLevel)
}
73 changes: 73 additions & 0 deletions cmd/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,76 @@ limitations under the License.
*/

package cmd

import (
"fmt"

"github.com/pkg/errors"
"github.com/spf13/cobra"

"sigs.k8s.io/zeitgeist/dependencies"
)

type ValidateOptions struct {
local bool
remote bool
config string
}

var validateOpts = &ValidateOptions{}

const defaultConfigFile = "dependencies.yaml"

// validateCmd is a subcommand which invokes RunValidate()
var validateCmd = &cobra.Command{
Use: "validate",
Short: "Check dependencies locally and against upstream versions",
SilenceUsage: true,
SilenceErrors: true,
RunE: func(cmd *cobra.Command, args []string) error {
return RunValidate(validateOpts)
},
}

func init() {
// Submit types
validateCmd.PersistentFlags().BoolVar(
&validateOpts.local,
"local",
false,
"validate dependencies locally",
)

validateCmd.PersistentFlags().BoolVar(
&validateOpts.remote,
"remote",
false,
"validate dependencies against specified upstreams",
)

validateCmd.PersistentFlags().StringVar(
&validateOpts.config,
"config",
defaultConfigFile,
"location of zeitgeist configuration file",
)

rootCmd.AddCommand(validateCmd)
}

// RunValidate is the function invoked by 'krel gcbmgr', responsible for
// submitting release jobs to GCB
func RunValidate(opts *ValidateOptions) error {
if opts.remote {
updates, err := dependencies.RemoteCheck(opts.config)
if err != nil {
return errors.Wrap(err, "check remote dependencies")
}

for _, update := range updates {
fmt.Println(update)
}
}

return dependencies.LocalCheck(opts.config)
}
16 changes: 6 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,14 @@ require (
github.com/aws/aws-sdk-go v1.23.10
github.com/blang/semver v3.5.1+incompatible
github.com/cyphar/filepath-securejoin v0.2.2 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/google/go-github v17.0.0+incompatible
github.com/google/go-querystring v1.0.0 // indirect
github.com/mitchellh/mapstructure v1.1.2
github.com/pkg/errors v0.8.1 // indirect
github.com/sirupsen/logrus v1.4.2
github.com/urfave/cli v1.21.0
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 // indirect
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22
k8s.io/apimachinery v0.0.0-20190828114620-4147c925140e // indirect
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.6.0
github.com/spf13/cobra v1.0.0
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c
k8s.io/client-go v11.0.0+incompatible // indirect
k8s.io/helm v2.14.3+incompatible
k8s.io/release v0.4.0
)

0 comments on commit c7517b2

Please sign in to comment.