Skip to content

Commit

Permalink
Tools for checking CLI conventions
Browse files Browse the repository at this point in the history
  • Loading branch information
fabianofranz committed Oct 13, 2016
1 parent f57ae28 commit 5ec5ff6
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 0 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ verify: build
hack/verify-generated-clientsets.sh
hack/verify-generated-completions.sh
hack/verify-generated-docs.sh
hack/verify-cli-conventions.sh
PROTO_OPTIONAL=1 hack/verify-generated-protobuf.sh
hack/verify-generated-swagger-descriptions.sh
hack/verify-generated-swagger-spec.sh
Expand Down
29 changes: 29 additions & 0 deletions hack/verify-cli-conventions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash
source "$(dirname "${BASH_SOURCE}")/lib/init.sh"

echo "===== Verifying CLI Conventions ====="

# ensure we have the latest compiled binaries
"${OS_ROOT}/hack/build-go.sh" tools/checkcli

# Find binary
checkcli="$(os::build::find-binary checkcli)"

if [[ -z "$checkcli" ]]; then
{
echo "It looks as if you don't have a compiled checkcli binary"
echo
echo "If you are running from a clone of the git repo, please run"
echo "'./hack/build-go.sh tools/checkcli'."
} >&2
exit 1
fi

if ! output=`$checkcli 2>&1`
then
echo "FAILURE: CLI is not following one or more required conventions:"
echo "$output"
exit 1
else
echo "SUCCESS: CLI is following all tested conventions."
fi
109 changes: 109 additions & 0 deletions tools/checkcli/check_cli_conventions.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package main

import (
"fmt"
"os"
"strings"

"github.com/spf13/cobra"

"github.com/openshift/origin/pkg/cmd/openshift"
"github.com/openshift/origin/pkg/cmd/templates"
)

var (
skip = []string{
"openshift kube", // TODO enable when we upstream all these conventions
"openshift start kubernetes", // TODO enable when we upstream all these conventions
"openshift cli create quota", // TODO has examples starting with '//', enable when we upstream all these conventions
"openshift cli adm", // already checked in 'openshift admin'
"openshift ex", // we will only care about experimental when they get promoted
"openshift cli types",
}
)

func main() {
errors := []error{}

cmd := openshift.NewCommandOpenShift("openshift")
errors = append(errors, recursiveCheckCmd(cmd)...)

if len(errors) > 0 {
for i, err := range errors {
fmt.Fprintf(os.Stderr, "%d. %s\n\n", i+1, err)
}
os.Exit(1)
}

fmt.Fprintln(os.Stdout, "Congrats, CLI looks good!")
}

func recursiveCheckCmd(cmd *cobra.Command) []error {
cmdPath := cmd.CommandPath()

if skipped(cmdPath) {
fmt.Fprintf(os.Stdout, "-----+ skipping command %s\n", cmdPath)
return []error{}
}

errors := []error{}

if cmd.HasSubCommands() {
for _, subCmd := range cmd.Commands() {
errors = append(errors, recursiveCheckCmd(subCmd)...)
}
}

fmt.Fprintf(os.Stdout, "-----+ checking command %s\n", cmdPath)

checks := []func(cmd *cobra.Command) error{
checkLongDesc,
checkExamples,
}

for _, check := range checks {
if err := check(cmd); err != nil {
errors = append(errors, err)
}
}

return errors
}

func skipped(cmdPath string) bool {
for _, skipCmdPath := range skip {
if cmdPath == skipCmdPath {
return true
}
}
return false
}

func checkLongDesc(cmd *cobra.Command) error {
cmdPath := cmd.CommandPath()
long := cmd.Long
if len(long) > 0 {
if strings.Trim(long, " \t\n") != long {
return fmt.Errorf(`command %q: long description is not normalized
↳ make sure you are calling templates.LongDesc (from pkg/cmd/templates) before assigning cmd.Long`, cmdPath)
}
}
return nil
}

func checkExamples(cmd *cobra.Command) error {
cmdPath := cmd.CommandPath()
examples := cmd.Example
if len(examples) > 0 {
for _, line := range strings.Split(examples, "\n") {
if !strings.HasPrefix(line, templates.Indentation) {
return fmt.Errorf(`command %q: examples are not normalized
↳ make sure you are calling templates.Examples (from pkg/cmd/templates) before assigning cmd.Example`, cmdPath)
}
if trimmed := strings.TrimSpace(line); strings.HasPrefix(trimmed, "//") {
return fmt.Errorf(`command %q: we use # to start comments in examples instead of //`, cmdPath)
}
}
}
return nil
}

0 comments on commit 5ec5ff6

Please sign in to comment.