Skip to content

Commit 861fd9a

Browse files
authored
Create custom role APIs (#2494)
Fixes: #2493.
1 parent 38d7b16 commit 861fd9a

File tree

4 files changed

+279
-4
lines changed

4 files changed

+279
-4
lines changed

github/github-accessors.go

+40
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

github/github-accessors_test.go

+50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

github/orgs_custom_roles.go

+76-2
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ type OrganizationCustomRepoRoles struct {
2020
// See https://docs.github.com/en/enterprise-cloud@latest/organizations/managing-peoples-access-to-your-organization-with-roles/managing-custom-repository-roles-for-an-organization
2121
// for more information.
2222
type CustomRepoRoles struct {
23-
ID *int64 `json:"id,omitempty"`
24-
Name *string `json:"name,omitempty"`
23+
ID *int64 `json:"id,omitempty"`
24+
Name *string `json:"name,omitempty"`
25+
Description *string `json:"description,omitempty"`
26+
BaseRole *string `json:"base_role,omitempty"`
27+
Permissions []string `json:"permissions,omitempty"`
2528
}
2629

2730
// ListCustomRepoRoles lists the custom repository roles available in this organization.
@@ -44,3 +47,74 @@ func (s *OrganizationsService) ListCustomRepoRoles(ctx context.Context, org stri
4447

4548
return customRepoRoles, resp, nil
4649
}
50+
51+
// CreateOrUpdateCustomRoleOptions represents options required to create or update a custom repository role.
52+
type CreateOrUpdateCustomRoleOptions struct {
53+
Name *string `json:"name,omitempty"`
54+
Description *string `json:"description,omitempty"`
55+
BaseRole *string `json:"base_role,omitempty"`
56+
Permissions []string `json:"permissions,omitempty"`
57+
}
58+
59+
// CreateCustomRepoRole creates a custom repository role in this organization.
60+
// In order to create custom repository roles in an organization, the authenticated user must be an organization owner.
61+
//
62+
// GitHub API docs: https://docs.github.com/en/rest/orgs/custom-roles#create-a-custom-role
63+
func (s *OrganizationsService) CreateCustomRepoRole(ctx context.Context, org string, opts *CreateOrUpdateCustomRoleOptions) (*CustomRepoRoles, *Response, error) {
64+
u := fmt.Sprintf("orgs/%v/custom_roles", org)
65+
66+
req, err := s.client.NewRequest("POST", u, opts)
67+
if err != nil {
68+
return nil, nil, err
69+
}
70+
71+
resultingRole := new(CustomRepoRoles)
72+
resp, err := s.client.Do(ctx, req, resultingRole)
73+
if err != nil {
74+
return nil, resp, err
75+
}
76+
77+
return resultingRole, resp, err
78+
}
79+
80+
// UpdateCustomRepoRole updates a custom repository role in this organization.
81+
// In order to update custom repository roles in an organization, the authenticated user must be an organization owner.
82+
//
83+
// GitHub API docs: https://docs.github.com/en/rest/orgs/custom-roles#update-a-custom-role
84+
func (s *OrganizationsService) UpdateCustomRepoRole(ctx context.Context, org, roleID string, opts *CreateOrUpdateCustomRoleOptions) (*CustomRepoRoles, *Response, error) {
85+
u := fmt.Sprintf("orgs/%v/custom_roles/%v", org, roleID)
86+
87+
req, err := s.client.NewRequest("PATCH", u, opts)
88+
if err != nil {
89+
return nil, nil, err
90+
}
91+
92+
resultingRole := new(CustomRepoRoles)
93+
resp, err := s.client.Do(ctx, req, resultingRole)
94+
if err != nil {
95+
return nil, resp, err
96+
}
97+
98+
return resultingRole, resp, err
99+
}
100+
101+
// DeleteCustomRepoRole deletes an existing custom repository role in this organization.
102+
// In order to delete custom repository roles in an organization, the authenticated user must be an organization owner.
103+
//
104+
// GitHub API docs: https://docs.github.com/en/rest/orgs/custom-roles#delete-a-custom-role
105+
func (s *OrganizationsService) DeleteCustomRepoRole(ctx context.Context, org, roleID string) (*Response, error) {
106+
u := fmt.Sprintf("orgs/%v/custom_roles/%v", org, roleID)
107+
108+
req, err := s.client.NewRequest("DELETE", u, nil)
109+
if err != nil {
110+
return nil, err
111+
}
112+
113+
resultingRole := new(CustomRepoRoles)
114+
resp, err := s.client.Do(ctx, req, resultingRole)
115+
if err != nil {
116+
return resp, err
117+
}
118+
119+
return resp, nil
120+
}

github/orgs_custom_roles_test.go

+113-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func TestOrganizationsService_ListCustomRepoRoles(t *testing.T) {
2020

2121
mux.HandleFunc("/orgs/o/custom_roles", func(w http.ResponseWriter, r *http.Request) {
2222
testMethod(t, r, "GET")
23-
fmt.Fprint(w, `{"total_count": 1, "custom_roles": [{ "id": 1, "name": "Developer"}]}`)
23+
fmt.Fprint(w, `{"total_count": 1, "custom_roles": [{ "id": 1, "name": "Developer", "base_role": "write", "permissions": ["delete_alerts_code_scanning"]}]}`)
2424
})
2525

2626
ctx := context.Background()
@@ -29,7 +29,7 @@ func TestOrganizationsService_ListCustomRepoRoles(t *testing.T) {
2929
t.Errorf("Organizations.ListCustomRepoRoles returned error: %v", err)
3030
}
3131

32-
want := &OrganizationCustomRepoRoles{TotalCount: Int(1), CustomRepoRoles: []*CustomRepoRoles{{ID: Int64(1), Name: String("Developer")}}}
32+
want := &OrganizationCustomRepoRoles{TotalCount: Int(1), CustomRepoRoles: []*CustomRepoRoles{{ID: Int64(1), Name: String("Developer"), BaseRole: String("write"), Permissions: []string{"delete_alerts_code_scanning"}}}}
3333
if !cmp.Equal(apps, want) {
3434
t.Errorf("Organizations.ListCustomRepoRoles returned %+v, want %+v", apps, want)
3535
}
@@ -48,3 +48,114 @@ func TestOrganizationsService_ListCustomRepoRoles(t *testing.T) {
4848
return resp, err
4949
})
5050
}
51+
52+
func TestOrganizationsService_CreateCustomRepoRole(t *testing.T) {
53+
client, mux, _, teardown := setup()
54+
defer teardown()
55+
56+
mux.HandleFunc("/orgs/o/custom_roles", func(w http.ResponseWriter, r *http.Request) {
57+
testMethod(t, r, "POST")
58+
fmt.Fprint(w, `{"id":8030,"name":"Labeler","description":"A role for issue and PR labelers","base_role":"read","permissions":["add_label"]}`)
59+
})
60+
61+
ctx := context.Background()
62+
63+
opts := &CreateOrUpdateCustomRoleOptions{
64+
Name: String("Labeler"),
65+
Description: String("A role for issue and PR labelers"),
66+
BaseRole: String("read"),
67+
Permissions: []string{"add_label"},
68+
}
69+
apps, _, err := client.Organizations.CreateCustomRepoRole(ctx, "o", opts)
70+
if err != nil {
71+
t.Errorf("Organizations.CreateCustomRepoRole returned error: %v", err)
72+
}
73+
74+
want := &CustomRepoRoles{ID: Int64(8030), Name: String("Labeler"), BaseRole: String("read"), Permissions: []string{"add_label"}, Description: String("A role for issue and PR labelers")}
75+
76+
if !cmp.Equal(apps, want) {
77+
t.Errorf("Organizations.CreateCustomRepoRole returned %+v, want %+v", apps, want)
78+
}
79+
80+
const methodName = "CreateCustomRepoRole"
81+
testBadOptions(t, methodName, func() (err error) {
82+
_, _, err = client.Organizations.CreateCustomRepoRole(ctx, "\no", nil)
83+
return err
84+
})
85+
86+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
87+
got, resp, err := client.Organizations.CreateCustomRepoRole(ctx, "o", nil)
88+
if got != nil {
89+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
90+
}
91+
return resp, err
92+
})
93+
}
94+
95+
func TestOrganizationsService_UpdateCustomRepoRole(t *testing.T) {
96+
client, mux, _, teardown := setup()
97+
defer teardown()
98+
99+
mux.HandleFunc("/orgs/o/custom_roles/8030", func(w http.ResponseWriter, r *http.Request) {
100+
testMethod(t, r, "PATCH")
101+
fmt.Fprint(w, `{"id":8030,"name":"Updated Name","description":"Updated Description","base_role":"read","permissions":["add_label"]}`)
102+
})
103+
104+
ctx := context.Background()
105+
106+
opts := &CreateOrUpdateCustomRoleOptions{
107+
Name: String("Updated Name"),
108+
Description: String("Updated Description"),
109+
}
110+
apps, _, err := client.Organizations.UpdateCustomRepoRole(ctx, "o", "8030", opts)
111+
if err != nil {
112+
t.Errorf("Organizations.UpdateCustomRepoRole returned error: %v", err)
113+
}
114+
115+
want := &CustomRepoRoles{ID: Int64(8030), Name: String("Updated Name"), BaseRole: String("read"), Permissions: []string{"add_label"}, Description: String("Updated Description")}
116+
117+
if !cmp.Equal(apps, want) {
118+
t.Errorf("Organizations.UpdateCustomRepoRole returned %+v, want %+v", apps, want)
119+
}
120+
121+
const methodName = "UpdateCustomRepoRole"
122+
testBadOptions(t, methodName, func() (err error) {
123+
_, _, err = client.Organizations.UpdateCustomRepoRole(ctx, "\no", "8030", nil)
124+
return err
125+
})
126+
127+
testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) {
128+
got, resp, err := client.Organizations.UpdateCustomRepoRole(ctx, "o", "8030", nil)
129+
if got != nil {
130+
t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got)
131+
}
132+
return resp, err
133+
})
134+
}
135+
136+
func TestOrganizationsService_DeleteCustomRepoRole(t *testing.T) {
137+
client, mux, _, teardown := setup()
138+
defer teardown()
139+
140+
mux.HandleFunc("/orgs/o/custom_roles/8030", func(w http.ResponseWriter, r *http.Request) {
141+
testMethod(t, r, "DELETE")
142+
w.WriteHeader(http.StatusNoContent)
143+
})
144+
145+
ctx := context.Background()
146+
147+
resp, err := client.Organizations.DeleteCustomRepoRole(ctx, "o", "8030")
148+
if err != nil {
149+
t.Errorf("Organizations.DeleteCustomRepoRole returned error: %v", err)
150+
}
151+
152+
if !cmp.Equal(resp.StatusCode, 204) {
153+
t.Errorf("Organizations.DeleteCustomRepoRole returned status code %+v, want %+v", resp.StatusCode, "204")
154+
}
155+
156+
const methodName = "DeleteCustomRepoRole"
157+
testBadOptions(t, methodName, func() (err error) {
158+
_, err = client.Organizations.DeleteCustomRepoRole(ctx, "\no", "8030")
159+
return err
160+
})
161+
}

0 commit comments

Comments
 (0)