Browse code

Tools for checking CLI conventions

Fabiano Franz authored on 2016/10/05 09:19:22
Showing 4 changed files
... ...
@@ -70,6 +70,7 @@ verify: build
70 70
 	hack/verify-generated-clientsets.sh
71 71
 	hack/verify-generated-completions.sh
72 72
 	hack/verify-generated-docs.sh
73
+	hack/verify-cli-conventions.sh
73 74
 	PROTO_OPTIONAL=1 hack/verify-generated-protobuf.sh
74 75
 	hack/verify-generated-swagger-descriptions.sh
75 76
 	hack/verify-generated-swagger-spec.sh
76 77
new file mode 100755
... ...
@@ -0,0 +1,29 @@
0
+#!/bin/bash
1
+source "$(dirname "${BASH_SOURCE}")/lib/init.sh"
2
+
3
+echo "===== Verifying CLI Conventions ====="
4
+
5
+# ensure we have the latest compiled binaries
6
+"${OS_ROOT}/hack/build-go.sh" tools/clicheck
7
+
8
+# Find binary
9
+clicheck="$(os::build::find-binary clicheck)"
10
+
11
+if [[ -z "$clicheck" ]]; then
12
+  {
13
+    echo "It looks as if you don't have a compiled clicheck binary"
14
+    echo
15
+    echo "If you are running from a clone of the git repo, please run"
16
+    echo "'./hack/build-go.sh tools/clicheck'."
17
+  } >&2
18
+  exit 1
19
+fi
20
+
21
+if ! output=`$clicheck 2>&1`
22
+then
23
+	echo "FAILURE: CLI is not following one or more required conventions:"
24
+	echo "$output"
25
+	exit 1
26
+else
27
+  echo "SUCCESS: CLI is following all tested conventions."
28
+fi
0 29
new file mode 100644
... ...
@@ -0,0 +1,78 @@
0
+package sanity
1
+
2
+import (
3
+	"fmt"
4
+	"os"
5
+	"strings"
6
+
7
+	"github.com/openshift/origin/pkg/cmd/templates"
8
+	"github.com/spf13/cobra"
9
+)
10
+
11
+type CmdCheck func(cmd *cobra.Command) []error
12
+
13
+var (
14
+	AllCmdChecks = []CmdCheck{
15
+		CheckLongDesc,
16
+		CheckExamples,
17
+	}
18
+)
19
+
20
+func CheckCmdTree(cmd *cobra.Command, checks []CmdCheck, skip []string) []error {
21
+	cmdPath := cmd.CommandPath()
22
+
23
+	for _, skipCmdPath := range skip {
24
+		if cmdPath == skipCmdPath {
25
+			fmt.Fprintf(os.Stdout, "-----+ skipping command %s\n", cmdPath)
26
+			return []error{}
27
+		}
28
+	}
29
+
30
+	errors := []error{}
31
+
32
+	if cmd.HasSubCommands() {
33
+		for _, subCmd := range cmd.Commands() {
34
+			errors = append(errors, CheckCmdTree(subCmd, checks, skip)...)
35
+		}
36
+	}
37
+
38
+	fmt.Fprintf(os.Stdout, "-----+ checking command %s\n", cmdPath)
39
+
40
+	for _, check := range checks {
41
+		if err := check(cmd); err != nil && len(err) > 0 {
42
+			errors = append(errors, err...)
43
+		}
44
+	}
45
+
46
+	return errors
47
+}
48
+
49
+func CheckLongDesc(cmd *cobra.Command) []error {
50
+	cmdPath := cmd.CommandPath()
51
+	long := cmd.Long
52
+	if len(long) > 0 {
53
+		if strings.Trim(long, " \t\n") != long {
54
+			return []error{fmt.Errorf(`command %q: long description is not normalized
55
+ ↳ make sure you are calling templates.LongDesc (from pkg/cmd/templates) before assigning cmd.Long`, cmdPath)}
56
+		}
57
+	}
58
+	return nil
59
+}
60
+
61
+func CheckExamples(cmd *cobra.Command) []error {
62
+	cmdPath := cmd.CommandPath()
63
+	examples := cmd.Example
64
+	errors := []error{}
65
+	if len(examples) > 0 {
66
+		for _, line := range strings.Split(examples, "\n") {
67
+			if !strings.HasPrefix(line, templates.Indentation) {
68
+				errors = append(errors, fmt.Errorf(`command %q: examples are not normalized
69
+ ↳ make sure you are calling templates.Examples (from pkg/cmd/templates) before assigning cmd.Example`, cmdPath))
70
+			}
71
+			if trimmed := strings.TrimSpace(line); strings.HasPrefix(trimmed, "//") {
72
+				errors = append(errors, fmt.Errorf(`command %q: we use # to start comments in examples instead of //`, cmdPath))
73
+			}
74
+		}
75
+	}
76
+	return errors
77
+}
0 78
new file mode 100644
... ...
@@ -0,0 +1,37 @@
0
+package main
1
+
2
+import (
3
+	"fmt"
4
+	"os"
5
+
6
+	"github.com/openshift/origin/pkg/cmd/openshift"
7
+	cmdsanity "github.com/openshift/origin/pkg/cmd/util/sanity"
8
+)
9
+
10
+var (
11
+	skip = []string{
12
+		"openshift kube",             // TODO enable when we upstream all these conventions
13
+		"openshift start kubernetes", // TODO enable when we upstream all these conventions
14
+		"openshift cli create quota", // TODO has examples starting with '//', enable when we upstream all these conventions
15
+		"openshift cli adm",          // already checked in 'openshift admin'
16
+		"openshift ex",               // we will only care about experimental when they get promoted
17
+		"openshift cli types",
18
+	}
19
+)
20
+
21
+func main() {
22
+	errors := []error{}
23
+
24
+	oc := openshift.NewCommandOpenShift("openshift")
25
+	result := cmdsanity.CheckCmdTree(oc, cmdsanity.AllCmdChecks, skip)
26
+	errors = append(errors, result...)
27
+
28
+	if len(errors) > 0 {
29
+		for i, err := range errors {
30
+			fmt.Fprintf(os.Stderr, "%d. %s\n\n", i+1, err)
31
+		}
32
+		os.Exit(1)
33
+	}
34
+
35
+	fmt.Fprintln(os.Stdout, "Congrats, CLI looks good!")
36
+}