Skip to content

Commit aeea0d2

Browse files
authored
refactor!: Change GetRulesForBranch to ListRulesForBranch (#4229)
BREAKING CHANGE: `RepositoriesService.GetRulesForBranch` is now `RepositoriesService.ListRulesForBranch`.
1 parent 40ed57f commit aeea0d2

2 files changed

Lines changed: 227 additions & 15 deletions

File tree

github/repos_rules.go

Lines changed: 144 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ package github
88
import (
99
"context"
1010
"fmt"
11+
"iter"
1112
)
1213

13-
// GetRulesForBranch gets all the repository rules that apply to the specified branch.
14+
// ListRulesForBranch gets all the repository rules that apply to the specified branch.
1415
//
1516
// GitHub API docs: https://docs.github.com/rest/repos/rules?apiVersion=2022-11-28#get-rules-for-a-branch
1617
//
1718
//meta:operation GET /repos/{owner}/{repo}/rules/branches/{branch}
18-
func (s *RepositoriesService) GetRulesForBranch(ctx context.Context, owner, repo, branch string, opts *ListOptions) (*BranchRules, *Response, error) {
19+
func (s *RepositoriesService) ListRulesForBranch(ctx context.Context, owner, repo, branch string, opts *ListOptions) (*BranchRules, *Response, error) {
1920
u := fmt.Sprintf("repos/%v/%v/rules/branches/%v", owner, repo, branch)
2021

2122
u, err := addOptions(u, opts)
@@ -37,6 +38,147 @@ func (s *RepositoriesService) GetRulesForBranch(ctx context.Context, owner, repo
3738
return rules, resp, nil
3839
}
3940

41+
// ListRulesForBranchIter returns an iterator that paginates through all results of ListRulesForBranch.
42+
//
43+
// Note that since [BranchRules] contains a large number of slices, this iterator
44+
// returns type `any` and it is therefore the responsibility of the caller to perform a
45+
// type switch to determine what item is being returned for each iteration.
46+
func (s *RepositoriesService) ListRulesForBranchIter(ctx context.Context, owner, repo, branch string, opts *ListOptions) iter.Seq2[any, error] {
47+
return func(yield func(any, error) bool) {
48+
// Create a copy of opts to avoid mutating the caller's struct
49+
if opts == nil {
50+
opts = &ListOptions{}
51+
} else {
52+
opts = Ptr(*opts)
53+
}
54+
55+
for {
56+
results, resp, err := s.ListRulesForBranch(ctx, owner, repo, branch, opts)
57+
if err != nil {
58+
yield(nil, err)
59+
return
60+
}
61+
62+
// Now iterate through ALL possible results from [BranchRules].
63+
for _, item := range results.Creation {
64+
if !yield(item, nil) {
65+
return
66+
}
67+
}
68+
for _, item := range results.Update {
69+
if !yield(item, nil) {
70+
return
71+
}
72+
}
73+
for _, item := range results.Deletion {
74+
if !yield(item, nil) {
75+
return
76+
}
77+
}
78+
for _, item := range results.RequiredLinearHistory {
79+
if !yield(item, nil) {
80+
return
81+
}
82+
}
83+
for _, item := range results.MergeQueue {
84+
if !yield(item, nil) {
85+
return
86+
}
87+
}
88+
for _, item := range results.RequiredDeployments {
89+
if !yield(item, nil) {
90+
return
91+
}
92+
}
93+
for _, item := range results.RequiredSignatures {
94+
if !yield(item, nil) {
95+
return
96+
}
97+
}
98+
for _, item := range results.PullRequest {
99+
if !yield(item, nil) {
100+
return
101+
}
102+
}
103+
for _, item := range results.RequiredStatusChecks {
104+
if !yield(item, nil) {
105+
return
106+
}
107+
}
108+
for _, item := range results.NonFastForward {
109+
if !yield(item, nil) {
110+
return
111+
}
112+
}
113+
for _, item := range results.CommitMessagePattern {
114+
if !yield(item, nil) {
115+
return
116+
}
117+
}
118+
for _, item := range results.CommitAuthorEmailPattern {
119+
if !yield(item, nil) {
120+
return
121+
}
122+
}
123+
for _, item := range results.CommitterEmailPattern {
124+
if !yield(item, nil) {
125+
return
126+
}
127+
}
128+
for _, item := range results.BranchNamePattern {
129+
if !yield(item, nil) {
130+
return
131+
}
132+
}
133+
for _, item := range results.TagNamePattern {
134+
if !yield(item, nil) {
135+
return
136+
}
137+
}
138+
for _, item := range results.Workflows {
139+
if !yield(item, nil) {
140+
return
141+
}
142+
}
143+
for _, item := range results.CodeScanning {
144+
if !yield(item, nil) {
145+
return
146+
}
147+
}
148+
for _, item := range results.CopilotCodeReview {
149+
if !yield(item, nil) {
150+
return
151+
}
152+
}
153+
for _, item := range results.FileExtensionRestriction {
154+
if !yield(item, nil) {
155+
return
156+
}
157+
}
158+
for _, item := range results.FilePathRestriction {
159+
if !yield(item, nil) {
160+
return
161+
}
162+
}
163+
for _, item := range results.MaxFilePathLength {
164+
if !yield(item, nil) {
165+
return
166+
}
167+
}
168+
for _, item := range results.MaxFileSize {
169+
if !yield(item, nil) {
170+
return
171+
}
172+
}
173+
174+
if resp.NextPage == 0 {
175+
break
176+
}
177+
opts.Page = resp.NextPage
178+
}
179+
}
180+
}
181+
40182
// RepositoryListRulesetsOptions specifies optional parameters to the
41183
// RepositoriesService.GetAllRulesets method.
42184
type RepositoryListRulesetsOptions struct {

github/repos_rules_test.go

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
"github.com/google/go-cmp/cmp"
1515
)
1616

17-
func TestRepositoriesService_GetRulesForBranch(t *testing.T) {
17+
func TestRepositoriesService_ListRulesForBranch(t *testing.T) {
1818
t.Parallel()
1919
client, mux, _ := setup(t)
2020

@@ -40,9 +40,9 @@ func TestRepositoriesService_GetRulesForBranch(t *testing.T) {
4040
})
4141

4242
ctx := t.Context()
43-
rules, _, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch", nil)
43+
rules, _, err := client.Repositories.ListRulesForBranch(ctx, "o", "repo", "branch", nil)
4444
if err != nil {
45-
t.Errorf("Repositories.GetRulesForBranch returned error: %v", err)
45+
t.Errorf("Repositories.ListRulesForBranch returned error: %v", err)
4646
}
4747

4848
want := &BranchRules{
@@ -51,19 +51,89 @@ func TestRepositoriesService_GetRulesForBranch(t *testing.T) {
5151
}
5252

5353
if !cmp.Equal(rules, want) {
54-
t.Errorf("Repositories.GetRulesForBranch returned %+v, want %+v", rules, want)
54+
t.Errorf("Repositories.ListRulesForBranch returned %+v, want %+v", rules, want)
5555
}
5656

57-
const methodName = "GetRulesForBranch"
57+
const methodName = "ListRulesForBranch"
5858
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
59-
got, resp, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch", nil)
59+
got, resp, err := client.Repositories.ListRulesForBranch(ctx, "o", "repo", "branch", nil)
6060
if got != nil {
6161
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
6262
}
6363
return resp, err
6464
})
6565
}
6666

67+
func TestRepositoriesService_ListRulesForBranchIter(t *testing.T) {
68+
t.Parallel()
69+
client, mux, _ := setup(t)
70+
var callNum int
71+
mux.HandleFunc("/", func(w http.ResponseWriter, _ *http.Request) {
72+
callNum++
73+
switch callNum {
74+
case 1:
75+
w.Header().Set("Link", `<https://api.github.com/?page=1>; rel="next"`)
76+
fmt.Fprint(w, `[{"type":"creation"},{"type":"deletion"},{"type":"update"}]`)
77+
case 2:
78+
fmt.Fprint(w, `[{"type":"creation"},{"type":"deletion"},{"type":"update"},{"type":"workflows"}]`)
79+
case 3, 5:
80+
fmt.Fprint(w, `[{"type":"creation"},{"type":"deletion"}]`)
81+
case 4:
82+
w.WriteHeader(http.StatusNotFound)
83+
}
84+
})
85+
86+
iter := client.Repositories.ListRulesForBranchIter(t.Context(), "o", "r", "b", nil)
87+
var gotItems int
88+
for _, err := range iter {
89+
gotItems++
90+
if err != nil {
91+
t.Errorf("Unexpected error: %v", err)
92+
}
93+
}
94+
if want := 7; gotItems != want {
95+
t.Errorf("client.Repositories.ListRulesForBranchIter call 1 got %v items; want %v", gotItems, want)
96+
}
97+
98+
opts := &ListOptions{}
99+
iter = client.Repositories.ListRulesForBranchIter(t.Context(), "o", "r", "b", opts)
100+
gotItems = 0
101+
for _, err := range iter {
102+
gotItems++
103+
if err != nil {
104+
t.Errorf("Unexpected error: %v", err)
105+
}
106+
}
107+
if want := 2; gotItems != want {
108+
t.Errorf("client.Repositories.ListRulesForBranchIter call 2 got %v items; want %v", gotItems, want)
109+
}
110+
111+
iter = client.Repositories.ListRulesForBranchIter(t.Context(), "o", "r", "b", nil)
112+
gotItems = 0
113+
for _, err := range iter {
114+
gotItems++
115+
if err == nil {
116+
t.Error("expected error; got nil")
117+
}
118+
}
119+
if gotItems != 1 {
120+
t.Errorf("client.Repositories.ListRulesForBranchIter call 3 got %v items; want 1 (an error)", gotItems)
121+
}
122+
123+
iter = client.Repositories.ListRulesForBranchIter(t.Context(), "o", "r", "b", nil)
124+
gotItems = 0
125+
iter(func(_ any, err error) bool {
126+
gotItems++
127+
if err != nil {
128+
t.Errorf("Unexpected error: %v", err)
129+
}
130+
return false
131+
})
132+
if gotItems != 1 {
133+
t.Errorf("client.Repositories.ListRulesForBranchIter call 4 got %v items; want 1 (an error)", gotItems)
134+
}
135+
}
136+
67137
func TestRepositoriesService_UpdateRuleset_OmitZero_Nil(t *testing.T) {
68138
t.Parallel()
69139
client, mux, _ := setup(t)
@@ -132,7 +202,7 @@ func TestRepositoriesService_UpdateRuleset_OmitZero_EmptySlice(t *testing.T) {
132202
}
133203
}
134204

135-
func TestRepositoriesService_GetRulesForBranch_ListOptions(t *testing.T) {
205+
func TestRepositoriesService_ListRulesForBranch_ListOptions(t *testing.T) {
136206
t.Parallel()
137207
client, mux, _ := setup(t)
138208

@@ -152,27 +222,27 @@ func TestRepositoriesService_GetRulesForBranch_ListOptions(t *testing.T) {
152222

153223
opts := &ListOptions{Page: 2, PerPage: 35}
154224
ctx := t.Context()
155-
rules, _, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch", opts)
225+
rules, _, err := client.Repositories.ListRulesForBranch(ctx, "o", "repo", "branch", opts)
156226
if err != nil {
157-
t.Errorf("Repositories.GetRulesForBranch returned error: %v", err)
227+
t.Errorf("Repositories.ListRulesForBranch returned error: %v", err)
158228
}
159229

160230
want := &BranchRules{
161231
Creation: []*BranchRuleMetadata{{RulesetID: 42069}},
162232
}
163233

164234
if !cmp.Equal(rules, want) {
165-
t.Errorf("Repositories.GetRulesForBranch returned %+v, want %+v", rules, want)
235+
t.Errorf("Repositories.ListRulesForBranch returned %+v, want %+v", rules, want)
166236
}
167237

168-
const methodName = "GetRulesForBranch"
238+
const methodName = "ListRulesForBranch"
169239
testBadOptions(t, methodName, func() (err error) {
170-
_, _, err = client.Repositories.GetRulesForBranch(ctx, "\n", "\n", "\n", opts)
240+
_, _, err = client.Repositories.ListRulesForBranch(ctx, "\n", "\n", "\n", opts)
171241
return err
172242
})
173243

174244
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
175-
got, resp, err := client.Repositories.GetRulesForBranch(ctx, "o", "repo", "branch", opts)
245+
got, resp, err := client.Repositories.ListRulesForBranch(ctx, "o", "repo", "branch", opts)
176246
if got != nil {
177247
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
178248
}

0 commit comments

Comments
 (0)