diff --git a/github/repos_rules.go b/github/repos_rules.go index 22c555313ef..b6635705a0f 100644 --- a/github/repos_rules.go +++ b/github/repos_rules.go @@ -9,15 +9,18 @@ import ( "context" "fmt" "iter" + "net/url" ) // ListRulesForBranch gets all the repository rules that apply to the specified branch. // +// Note: the branch name is URL path escaped for you. See: https://pkg.go.dev/net/url#PathEscape . +// // GitHub API docs: https://docs.github.com/rest/repos/rules?apiVersion=2022-11-28#get-rules-for-a-branch // //meta:operation GET /repos/{owner}/{repo}/rules/branches/{branch} func (s *RepositoriesService) ListRulesForBranch(ctx context.Context, owner, repo, branch string, opts *ListOptions) (*BranchRules, *Response, error) { - u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, branch) + u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, url.PathEscape(branch)) u, err := addOptions(u, opts) if err != nil { diff --git a/github/repos_rules_test.go b/github/repos_rules_test.go index bae001a69f7..37815bc5f5d 100644 --- a/github/repos_rules_test.go +++ b/github/repos_rules_test.go @@ -63,6 +63,59 @@ func TestRepositoriesService_ListRulesForBranch(t *testing.T) { }) } +func TestRepositoriesService_ListRulesForBranch_EscapeBranch(t *testing.T) { + t.Parallel() + for _, tt := range []struct { + branch string + escapedBranch string + }{ + {branch: "main", escapedBranch: "main"}, + {branch: "feature/login", escapedBranch: "feature%2Flogin"}, + {branch: "fix/#123-login", escapedBranch: "fix%2F%23123-login"}, + {branch: "release%25", escapedBranch: "release%2525"}, + {branch: "release%ready", escapedBranch: "release%25ready"}, + } { + for _, options := range []struct { + name string + opts *ListOptions + query values + }{ + {name: "no_options", query: values{}}, + { + name: "pagination", + opts: &ListOptions{Page: 2, PerPage: 35}, + query: values{ + "page": "2", + "per_page": "35", + }, + }, + } { + t.Run(tt.branch+"/"+options.name, func(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + if got, want := r.URL.EscapedPath(), "/repos/o/repo/rules/branches/"+tt.escapedBranch; got != want { + t.Errorf("Request path = %q, want %q", got, want) + } + if got, want := r.URL.Path, "/repos/o/repo/rules/branches/"+tt.branch; got != want { + t.Errorf("Decoded request path = %q, want %q", got, want) + } + testFormValues(t, r, options.query) + fmt.Fprint(w, `[]`) + }) + + ctx := t.Context() + _, _, err := client.Repositories.ListRulesForBranch(ctx, "o", "repo", tt.branch, options.opts) + if err != nil { + t.Fatalf("Repositories.ListRulesForBranch returned error: %v", err) + } + }) + } + } +} + func TestRepositoriesService_ListRulesForBranchIter(t *testing.T) { t.Parallel() client, mux, _ := setup(t)