allow getting parents, move list to shared package
This commit is contained in:
parent
7f81645c78
commit
3e6419237d
4 changed files with 72 additions and 45 deletions
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/cli/cli/v2/internal/ghrepo"
|
||||
"github.com/cli/cli/v2/internal/tableprinter"
|
||||
"github.com/cli/cli/v2/internal/text"
|
||||
"github.com/cli/cli/v2/pkg/cmd/ruleset/shared"
|
||||
"github.com/cli/cli/v2/pkg/cmdutil"
|
||||
"github.com/cli/cli/v2/pkg/iostreams"
|
||||
"github.com/spf13/cobra"
|
||||
|
|
@ -25,9 +26,10 @@ type ListOptions struct {
|
|||
BaseRepo func() (ghrepo.Interface, error)
|
||||
Browser browser.Browser
|
||||
|
||||
Limit int
|
||||
WebMode bool
|
||||
Organization string
|
||||
Limit int
|
||||
IncludeParents bool
|
||||
WebMode bool
|
||||
Organization string
|
||||
}
|
||||
|
||||
func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Command {
|
||||
|
|
@ -62,8 +64,9 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman
|
|||
}
|
||||
|
||||
cmd.Flags().IntVarP(&opts.Limit, "limit", "L", 30, "Maximum number of rulesets to list")
|
||||
cmd.Flags().StringVarP(&opts.Organization, "org", "o", "", "List organization-wide rulesets")
|
||||
cmd.Flags().BoolVarP(&opts.WebMode, "web", "w", false, "List rulesets in the web browser")
|
||||
cmd.Flags().StringVarP(&opts.Organization, "org", "o", "", "List organization-wide rulesets for the provided organization")
|
||||
cmd.Flags().BoolVarP(&opts.IncludeParents, "parents", "p", false, "Include rulesets configured at higher levels that also apply")
|
||||
cmd.Flags().BoolVarP(&opts.WebMode, "web", "w", false, "Open the list of rulesets in the web browser")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
@ -101,12 +104,12 @@ func listRun(opts *ListOptions) error {
|
|||
return opts.Browser.Browse(rulesetURL)
|
||||
}
|
||||
|
||||
var result *RulesetList
|
||||
var result *shared.RulesetList
|
||||
|
||||
if opts.Organization != "" {
|
||||
result, err = listOrgRulesets(httpClient, opts.Organization, opts.Limit, hostname)
|
||||
result, err = shared.ListOrgRulesets(httpClient, opts.Organization, opts.Limit, hostname, opts.IncludeParents)
|
||||
} else {
|
||||
result, err = listRepoRulesets(httpClient, repoI, opts.Limit)
|
||||
result, err = shared.ListRepoRulesets(httpClient, repoI, opts.Limit, opts.IncludeParents)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
@ -121,7 +124,11 @@ func listRun(opts *ListOptions) error {
|
|||
}
|
||||
|
||||
if result.TotalCount == 0 {
|
||||
msg := fmt.Sprintf("no rulesets found in %s", entityName)
|
||||
parentsMsg := ""
|
||||
if opts.IncludeParents {
|
||||
parentsMsg = " or its parents"
|
||||
}
|
||||
msg := fmt.Sprintf("no rulesets found in %s%s", entityName, parentsMsg)
|
||||
return cmdutil.NewNoResultsError(msg)
|
||||
}
|
||||
|
||||
|
|
@ -139,17 +146,25 @@ func listRun(opts *ListOptions) error {
|
|||
}
|
||||
|
||||
tp := tableprinter.New(opts.IO)
|
||||
tp.HeaderRow("ID", "NAME", "STATUS", "TARGET")
|
||||
tp.HeaderRow("ID", "NAME", "SOURCE", "STATUS", "TARGET", "RULES")
|
||||
|
||||
for _, rs := range result.Rulesets {
|
||||
tp.AddField(strconv.Itoa(rs.Id))
|
||||
tp.AddField(rs.Name, tableprinter.WithColor(cs.Bold))
|
||||
var ownerString string
|
||||
if rs.Source.RepoOwner != "" {
|
||||
ownerString = fmt.Sprintf("%s (repo)", rs.Source.RepoOwner)
|
||||
} else if rs.Source.OrgOwner != "" {
|
||||
ownerString = fmt.Sprintf("%s (org)", rs.Source.OrgOwner)
|
||||
} else {
|
||||
ownerString = "(unknown)"
|
||||
}
|
||||
tp.AddField(ownerString)
|
||||
tp.AddField(strings.ToLower(rs.Enforcement))
|
||||
tp.AddField(strings.ToLower(rs.Target))
|
||||
tp.AddField(strconv.Itoa(rs.RulesGql.TotalCount))
|
||||
tp.EndRow()
|
||||
}
|
||||
|
||||
return tp.Render()
|
||||
}
|
||||
|
||||
// func getRulesets()
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package list
|
||||
package shared
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
|
@ -6,14 +6,13 @@ import (
|
|||
|
||||
"github.com/cli/cli/v2/api"
|
||||
"github.com/cli/cli/v2/internal/ghrepo"
|
||||
"github.com/cli/cli/v2/pkg/cmd/ruleset/shared"
|
||||
)
|
||||
|
||||
type RulesetResponse struct {
|
||||
Level struct {
|
||||
Rulesets struct {
|
||||
TotalCount int
|
||||
Nodes []shared.Ruleset
|
||||
Nodes []Ruleset
|
||||
PageInfo struct {
|
||||
HasNextPage bool
|
||||
EndCursor string
|
||||
|
|
@ -24,21 +23,23 @@ type RulesetResponse struct {
|
|||
|
||||
type RulesetList struct {
|
||||
TotalCount int
|
||||
Rulesets []shared.Ruleset
|
||||
Rulesets []Ruleset
|
||||
}
|
||||
|
||||
func listRepoRulesets(httpClient *http.Client, repo ghrepo.Interface, limit int) (*RulesetList, error) {
|
||||
func ListRepoRulesets(httpClient *http.Client, repo ghrepo.Interface, limit int, includeParents bool) (*RulesetList, error) {
|
||||
variables := map[string]interface{}{
|
||||
"owner": repo.RepoOwner(),
|
||||
"repo": repo.RepoName(),
|
||||
"owner": repo.RepoOwner(),
|
||||
"repo": repo.RepoName(),
|
||||
"includeParents": includeParents,
|
||||
}
|
||||
|
||||
return listRulesets(httpClient, rulesetsQuery(false), variables, limit, repo.RepoHost())
|
||||
}
|
||||
|
||||
func listOrgRulesets(httpClient *http.Client, orgLogin string, limit int, host string) (*RulesetList, error) {
|
||||
func ListOrgRulesets(httpClient *http.Client, orgLogin string, limit int, host string, includeParents bool) (*RulesetList, error) {
|
||||
variables := map[string]interface{}{
|
||||
"login": orgLogin,
|
||||
"login": orgLogin,
|
||||
"includeParents": includeParents,
|
||||
}
|
||||
|
||||
return listRulesets(httpClient, rulesetsQuery(true), variables, limit, host)
|
||||
|
|
@ -48,7 +49,7 @@ func listRulesets(httpClient *http.Client, query string, variables map[string]in
|
|||
pageLimit := min(limit, 100)
|
||||
|
||||
res := RulesetList{
|
||||
Rulesets: []shared.Ruleset{},
|
||||
Rulesets: []Ruleset{},
|
||||
}
|
||||
client := api.NewClientFromHTTP(httpClient)
|
||||
|
||||
|
|
@ -90,16 +91,20 @@ func rulesetsQuery(org bool) string {
|
|||
level = "repository(owner: $owner, name: $repo)"
|
||||
}
|
||||
|
||||
str := fmt.Sprintf("query RulesetList($limit: Int!, $endCursor: String, %s) { level: %s {", args, level)
|
||||
str := fmt.Sprintf("query RulesetList($limit: Int!, $endCursor: String, $includeParents: Boolean, %s) { level: %s {", args, level)
|
||||
|
||||
return str + `
|
||||
rulesets(first: $limit, after: $endCursor) {
|
||||
rulesets(first: $limit, after: $endCursor, includeParents: $includeParents) {
|
||||
totalCount
|
||||
nodes {
|
||||
id: databaseId
|
||||
name
|
||||
target
|
||||
enforcement
|
||||
source {
|
||||
... on Repository { repoOwner: nameWithOwner }
|
||||
... on Organization { orgOwner: login }
|
||||
}
|
||||
# conditions {
|
||||
# refName {
|
||||
# include
|
||||
|
|
@ -21,6 +21,10 @@ type Ruleset struct {
|
|||
// Protected bool
|
||||
// } `json:"repository_name"`
|
||||
}
|
||||
Source struct {
|
||||
RepoOwner string
|
||||
OrgOwner string
|
||||
}
|
||||
RulesGql struct {
|
||||
TotalCount int
|
||||
}
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ func NewCmdView(f *cmdutil.Factory, runF func(*ViewOptions) error) *cobra.Comman
|
|||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&opts.WebMode, "web", "w", false, "Open the ruleset in the browser")
|
||||
cmd.Flags().StringVarP(&opts.Organization, "org", "o", "", "Organization name if the ID ")
|
||||
cmd.Flags().StringVarP(&opts.Organization, "org", "o", "", "Organization name if the provided ID is an organization-level ruleset")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
|
@ -104,22 +104,6 @@ func viewRun(opts *ViewOptions) error {
|
|||
|
||||
hostname, _ := cfg.DefaultHost()
|
||||
|
||||
if opts.WebMode {
|
||||
// TODO need to validate ruleset's existence before opening
|
||||
var rulesetURL string
|
||||
if opts.Organization != "" {
|
||||
rulesetURL = fmt.Sprintf("%sorganizations/%s/settings/rules/%s", ghinstance.HostPrefix(hostname), opts.Organization, opts.ID)
|
||||
} else {
|
||||
rulesetURL = ghrepo.GenerateRepoURL(repoI, "settings/rules/%s", opts.ID)
|
||||
}
|
||||
|
||||
if opts.IO.IsStdoutTTY() {
|
||||
fmt.Fprintf(opts.IO.Out, "Opening %s in your browser.\n", text.DisplayURL(rulesetURL))
|
||||
}
|
||||
|
||||
return opts.Browser.Browse(rulesetURL)
|
||||
}
|
||||
|
||||
var rs *shared.Ruleset
|
||||
if opts.Organization != "" {
|
||||
rs, err = viewOrgRuleset(httpClient, opts.Organization, opts.ID, hostname)
|
||||
|
|
@ -134,6 +118,25 @@ func viewRun(opts *ViewOptions) error {
|
|||
cs := opts.IO.ColorScheme()
|
||||
w := opts.IO.Out
|
||||
|
||||
if opts.WebMode {
|
||||
if rs != nil {
|
||||
var rulesetURL string
|
||||
if opts.Organization != "" {
|
||||
rulesetURL = fmt.Sprintf("%sorganizations/%s/settings/rules/%s", ghinstance.HostPrefix(hostname), opts.Organization, opts.ID)
|
||||
} else {
|
||||
rulesetURL = ghrepo.GenerateRepoURL(repoI, "settings/rules/%s", opts.ID)
|
||||
}
|
||||
|
||||
if opts.IO.IsStdoutTTY() {
|
||||
fmt.Fprintf(opts.IO.Out, "Opening %s in your browser.\n", text.DisplayURL(rulesetURL))
|
||||
}
|
||||
|
||||
return opts.Browser.Browse(rulesetURL)
|
||||
} else {
|
||||
fmt.Fprintf(w, "ruleset not found\n")
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintf(w, "\n%s\n", cs.Bold(rs.Name))
|
||||
fmt.Fprintf(w, "ID: %d\n", rs.Id)
|
||||
|
||||
|
|
@ -141,7 +144,7 @@ func viewRun(opts *ViewOptions) error {
|
|||
case "disabled":
|
||||
fmt.Fprintf(w, "%s\n", cs.Red("Disabled"))
|
||||
case "evaluate":
|
||||
fmt.Fprintf(w, "%s\n", cs.Yellow("Evaluate Mode (not being enforced)"))
|
||||
fmt.Fprintf(w, "%s\n", cs.Yellow("Evaluate Mode (not enforced)"))
|
||||
case "active":
|
||||
fmt.Fprintf(w, "%s\n", cs.Green("Active"))
|
||||
default:
|
||||
|
|
@ -165,7 +168,7 @@ func viewRun(opts *ViewOptions) error {
|
|||
|
||||
fmt.Fprintf(w, "Actor types allowed to bypass:\n")
|
||||
for name, count := range types {
|
||||
fmt.Fprintf(w, "- %s: %d actors\n", name, count)
|
||||
fmt.Fprintf(w, "- %s: %d configured\n", name, count)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -173,8 +176,8 @@ func viewRun(opts *ViewOptions) error {
|
|||
if len(rs.Conditions) == 0 {
|
||||
fmt.Fprintf(w, "No conditions configured\n")
|
||||
} else {
|
||||
// sort keys for consistent responses, mismatched types don't allow this to be broken
|
||||
// into a separate function
|
||||
// sort keys for consistent responses, can't make a separate function due to
|
||||
// mismatched types
|
||||
keys := make([]string, 0, len(rs.Conditions))
|
||||
for key := range rs.Conditions {
|
||||
keys = append(keys, key)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue