diff --git a/pkg/cmd/ruleset/list/fixtures/rulesetList.json b/pkg/cmd/ruleset/list/fixtures/rulesetList.json index 560c9fb4c..d7c631623 100644 --- a/pkg/cmd/ruleset/list/fixtures/rulesetList.json +++ b/pkg/cmd/ruleset/list/fixtures/rulesetList.json @@ -9,6 +9,10 @@ "name": "test", "target": "BRANCH", "enforcement": "EVALUATE", + "source": { + "__typename": "Repository", + "owner": "OWNER/REPO" + }, "conditions": { "refName": { "include": [ @@ -27,6 +31,10 @@ "name": "asdf", "target": "BRANCH", "enforcement": "ACTIVE", + "source": { + "__typename": "Repository", + "owner": "OWNER/REPO" + }, "conditions": { "refName": { "include": [ @@ -45,6 +53,10 @@ "name": "foobar", "target": "BRANCH", "enforcement": "DISABLED", + "source": { + "__typename": "Organization", + "owner": "Org-Name" + }, "conditions": { "refName": { "include": [ diff --git a/pkg/cmd/ruleset/list/list.go b/pkg/cmd/ruleset/list/list.go index 1b8a9cc00..e49e573f0 100644 --- a/pkg/cmd/ruleset/list/list.go +++ b/pkg/cmd/ruleset/list/list.go @@ -161,14 +161,13 @@ func listRun(opts *ListOptions) error { } tp := tableprinter.New(opts.IO) - tp.HeaderRow("ID", "NAME", "SOURCE", "STATUS", "TARGET", "RULES") + tp.HeaderRow("ID", "NAME", "SOURCE", "STATUS", "RULES") for _, rs := range result.Rulesets { tp.AddField(strconv.Itoa(rs.DatabaseId)) tp.AddField(rs.Name, tableprinter.WithColor(cs.Bold)) tp.AddField(shared.RulesetSource(rs)) tp.AddField(strings.ToLower(rs.Enforcement)) - tp.AddField(strings.ToLower(rs.Target)) tp.AddField(strconv.Itoa(rs.Rules.TotalCount)) tp.EndRow() } diff --git a/pkg/cmd/ruleset/list/list_test.go b/pkg/cmd/ruleset/list/list_test.go index 0a44b5438..8e25a87fc 100644 --- a/pkg/cmd/ruleset/list/list_test.go +++ b/pkg/cmd/ruleset/list/list_test.go @@ -125,10 +125,10 @@ func Test_listRun(t *testing.T) { Showing 3 of 3 rulesets in OWNER/REPO - ID NAME STATUS TARGET - 4 test evaluate branch - 42 asdf active branch - 77 foobar disabled branch + ID NAME SOURCE STATUS RULES + 4 test OWNER/REPO (repo) evaluate 1 + 42 asdf OWNER/REPO (repo) active 2 + 77 foobar Org-Name (org) disabled 4 `), wantStderr: "", }, @@ -142,10 +142,10 @@ func Test_listRun(t *testing.T) { Showing 3 of 3 rulesets in my-org - ID NAME STATUS TARGET - 4 test evaluate branch - 42 asdf active branch - 77 foobar disabled branch + ID NAME SOURCE STATUS RULES + 4 test OWNER/REPO (repo) evaluate 1 + 42 asdf OWNER/REPO (repo) active 2 + 77 foobar Org-Name (org) disabled 4 `), wantStderr: "", }, @@ -153,9 +153,9 @@ func Test_listRun(t *testing.T) { name: "machine-readable", isTTY: false, wantStdout: heredoc.Doc(` - 4 test evaluate branch - 42 asdf active branch - 77 foobar disabled branch + 4 test OWNER/REPO (repo) evaluate 1 + 42 asdf OWNER/REPO (repo) active 2 + 77 foobar Org-Name (org) disabled 4 `), wantStderr: "", }, diff --git a/pkg/cmd/ruleset/shared/shared.go b/pkg/cmd/ruleset/shared/shared.go index 682eafb38..0299f056a 100644 --- a/pkg/cmd/ruleset/shared/shared.go +++ b/pkg/cmd/ruleset/shared/shared.go @@ -35,7 +35,10 @@ type RulesetREST struct { // TODO is this source field used? SourceType string `json:"source_type"` Source string - Rules []struct{} + Rules []struct { + Type string + Parameters map[string]interface{} + } } // Returns the source of the ruleset in the format "owner/name (repo)" or "owner (org)" diff --git a/pkg/cmd/ruleset/view/view.go b/pkg/cmd/ruleset/view/view.go index 0c642e838..df4930de7 100644 --- a/pkg/cmd/ruleset/view/view.go +++ b/pkg/cmd/ruleset/view/view.go @@ -3,7 +3,6 @@ package view import ( "fmt" "net/http" - "reflect" "sort" "strconv" "strings" @@ -189,7 +188,9 @@ func viewRun(opts *ViewOptions) error { fmt.Fprintf(w, "\n%s\n", cs.Bold(rs.Name)) fmt.Fprintf(w, "ID: %d\n", rs.Id) + fmt.Fprintf(w, "Source: %s (%s)\n", rs.Source, rs.SourceType) + fmt.Fprint(w, "Enforceument: ") switch rs.Enforcement { case "disabled": fmt.Fprintf(w, "%s\n", cs.Red("Disabled")) @@ -198,7 +199,7 @@ func viewRun(opts *ViewOptions) error { case "active": fmt.Fprintf(w, "%s\n", cs.Green("Active")) default: - fmt.Fprintf(w, "Enforcement: %s\n", rs.Enforcement) + fmt.Fprintf(w, "%s\n", rs.Enforcement) } fmt.Fprintf(w, "\n%s\n", cs.Bold("Bypassing")) @@ -246,27 +247,7 @@ func viewRun(opts *ViewOptions) error { sort.Strings(subkeys) for _, n := range subkeys { - rawVal := condition[n] - - k := reflect.TypeOf(rawVal).Kind() - if rawVal == nil || - ((k == reflect.Slice || k == reflect.Map) && len(rawVal.([]interface{})) == 0) { - continue - } - - printVal := fmt.Sprint(rawVal) - - // fmt.Fprintf(w, "n: %s, type: %s\n", n, reflect.TypeOf(rawVal).String()) - - // switch val := rawVal.(type) { - // case []interface{}: - // // currently only string arrays are returned by the API at this level - // printVal = fmt.Sprint(val) - // default: - // printVal = fmt.Sprint(val) - // } - - fmt.Fprintf(w, "[%s: %s] ", n, printVal) + fmt.Fprintf(w, "[%s: %v] ", n, condition[n]) } fmt.Fprint(w, "\n") @@ -274,7 +255,35 @@ func viewRun(opts *ViewOptions) error { } fmt.Fprintf(w, "\n%s\n", cs.Bold("Rules")) - fmt.Fprintf(w, "%d configured\n", reflect.ValueOf(rs.Rules).Len()) + if len(rs.Rules) == 0 { + fmt.Fprintf(w, "No rules configured\n") + } else { + // sort keys for consistent responses + sort.SliceStable(rs.Rules, func(i, j int) bool { + return rs.Rules[i].Type < rs.Rules[j].Type + }) + + for _, rule := range rs.Rules { + fmt.Fprintf(w, "- %s", rule.Type) + + if rule.Parameters != nil && len(rule.Parameters) > 0 { + fmt.Fprintf(w, ": ") + + // sort these keys too for consistency + params := make([]string, 0, len(rule.Parameters)) + for p := range rule.Parameters { + params = append(params, p) + } + sort.Strings(params) + + for _, n := range params { + fmt.Fprintf(w, "[%s: %v] ", n, rule.Parameters[n]) + } + } + + fmt.Fprint(w, "\n") + } + } return nil }