From 104710a8414e3ae5e0bc382dc759c815fd23701d Mon Sep 17 00:00:00 2001 From: shuv0id Date: Tue, 24 Feb 2026 01:22:40 +0530 Subject: [PATCH 1/3] feat: Add support for repository fine-grained permissions --- github/orgs_custom_repository_roles.go | 29 +++++++++++ github/orgs_custom_repository_roles_test.go | 53 +++++++++++++++++++++ 2 files changed, 82 insertions(+) diff --git a/github/orgs_custom_repository_roles.go b/github/orgs_custom_repository_roles.go index 44408db1418..0f4b3dd6478 100644 --- a/github/orgs_custom_repository_roles.go +++ b/github/orgs_custom_repository_roles.go @@ -38,6 +38,12 @@ type CreateOrUpdateCustomRepoRoleOptions struct { Permissions []string `json:"permissions"` } +// RepoFineGrainedPermission represents a fine-grained permission that can be used in a custom repository role. +type RepoFineGrainedPermission struct { + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` +} + // ListCustomRepoRoles lists the custom repository roles available in this organization. // In order to see custom repository roles in an organization, the authenticated user must be an organization owner. // @@ -152,3 +158,26 @@ func (s *OrganizationsService) DeleteCustomRepoRole(ctx context.Context, org str return resp, nil } + +// ListRepositoryFineGrainedPermissions lists the fine-grained permissions that can be used in custom repository roles for an organization. +// The authenticated user must be an administrator of the organization or of a repository of the organization to use this endpoint. +// +// GitHub API docs: https://docs.github.com/enterprise-cloud@latest/rest/orgs/custom-roles#list-repository-fine-grained-permissions-for-an-organization +// +//meta:operation GET /orgs/{org}/repository-fine-grained-permissions +func (s *OrganizationsService) ListRepositoryFineGrainedPermissions(ctx context.Context, org string) ([]*RepoFineGrainedPermission, *Response, error) { + u := fmt.Sprintf("orgs/%v/repository-fine-grained-permissions", org) + + req, err := s.client.NewRequest("GET", u, nil) + if err != nil { + return nil, nil, err + } + + var perms []*RepoFineGrainedPermission + resp, err := s.client.Do(ctx, req, &perms) + if err != nil { + return nil, resp, err + } + + return perms, resp, nil +} diff --git a/github/orgs_custom_repository_roles_test.go b/github/orgs_custom_repository_roles_test.go index 94acfcdca87..fc4ceb794cc 100644 --- a/github/orgs_custom_repository_roles_test.go +++ b/github/orgs_custom_repository_roles_test.go @@ -283,3 +283,56 @@ func TestOrganizationsService_DeleteCustomRepoRole(t *testing.T) { return err }) } + +func TestOrganizationsService_ListRepositoryFineGrainedPermissions(t *testing.T) { + t.Parallel() + client, mux, _ := setup(t) + + mux.HandleFunc("/orgs/o/repository-fine-grained-permissions", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, "GET") + fmt.Fprint(w, `[ + { + "name": "add_assignee", + "description": "Assign or remove a user" + }, + { + "name": "add_label", + "description": "Add or remove a label" + } + ]`) + }) + + ctx := t.Context() + perms, _, err := client.Organizations.ListRepositoryFineGrainedPermissions(ctx, "o") + if err != nil { + t.Errorf("Organizations.ListRepositoryFineGrainedPermissions returned error: %v", err) + } + + want := []*RepoFineGrainedPermission{ + { + Name: Ptr("add_assignee"), + Description: Ptr("Assign or remove a user"), + }, + { + Name: Ptr("add_label"), + Description: Ptr("Add or remove a label"), + }, + } + if !cmp.Equal(perms, want) { + t.Errorf("Organizations.ListRepositoryFineGrainedPermissions returned %+v, want %+v", perms, want) + } + + const methodName = "ListRepositoryFineGrainedPermissions" + testBadOptions(t, methodName, func() (err error) { + _, _, err = client.Organizations.ListRepositoryFineGrainedPermissions(ctx, "\no") + return err + }) + + testNewRequestAndDoFailure(t, methodName, client, func() (*Response, error) { + got, resp, err := client.Organizations.ListRepositoryFineGrainedPermissions(ctx, "o") + if got != nil { + t.Errorf("testNewRequestAndDoFailure %v = %#v, want nil", methodName, got) + } + return resp, err + }) +} From 99dbcdf7c4d1b5fc261dd18336d72a8c40bcf6b4 Mon Sep 17 00:00:00 2001 From: shuv0id <110290476+shuv0id@users.noreply.github.com> Date: Tue, 24 Feb 2026 18:29:35 +0530 Subject: [PATCH 2/3] chore: run fmt, tests, lint and generate code --- github/github-accessors.go | 16 ++++++++++++++++ github/github-accessors_test.go | 22 ++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/github/github-accessors.go b/github/github-accessors.go index ec77299f2fe..b03d6c2b756 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -23510,6 +23510,22 @@ func (r *RepoDependencies) GetVersionInfo() string { return *r.VersionInfo } +// GetDescription returns the Description field if it's non-nil, zero value otherwise. +func (r *RepoFineGrainedPermission) GetDescription() string { + if r == nil || r.Description == nil { + return "" + } + return *r.Description +} + +// GetName returns the Name field if it's non-nil, zero value otherwise. +func (r *RepoFineGrainedPermission) GetName() string { + if r == nil || r.Name == nil { + return "" + } + return *r.Name +} + // GetBranch returns the Branch field if it's non-nil, zero value otherwise. func (r *RepoMergeUpstreamRequest) GetBranch() string { if r == nil || r.Branch == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 08332e3776d..bd96edc488a 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -30393,6 +30393,28 @@ func TestRepoDependencies_GetVersionInfo(tt *testing.T) { r.GetVersionInfo() } +func TestRepoFineGrainedPermission_GetDescription(tt *testing.T) { + tt.Parallel() + var zeroValue string + r := &RepoFineGrainedPermission{Description: &zeroValue} + r.GetDescription() + r = &RepoFineGrainedPermission{} + r.GetDescription() + r = nil + r.GetDescription() +} + +func TestRepoFineGrainedPermission_GetName(tt *testing.T) { + tt.Parallel() + var zeroValue string + r := &RepoFineGrainedPermission{Name: &zeroValue} + r.GetName() + r = &RepoFineGrainedPermission{} + r.GetName() + r = nil + r.GetName() +} + func TestRepoMergeUpstreamRequest_GetBranch(tt *testing.T) { tt.Parallel() var zeroValue string From b76c10a2f41f14a20e78683cb240e790bcb75462 Mon Sep 17 00:00:00 2001 From: shuv0id Date: Wed, 25 Feb 2026 10:49:15 +0530 Subject: [PATCH 3/3] Remove pointers from `RepoFineGrainedPermission` fields --- github/github-accessors.go | 16 --------------- github/github-accessors_test.go | 22 --------------------- github/orgs_custom_repository_roles.go | 4 ++-- github/orgs_custom_repository_roles_test.go | 8 ++++---- 4 files changed, 6 insertions(+), 44 deletions(-) diff --git a/github/github-accessors.go b/github/github-accessors.go index b03d6c2b756..ec77299f2fe 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -23510,22 +23510,6 @@ func (r *RepoDependencies) GetVersionInfo() string { return *r.VersionInfo } -// GetDescription returns the Description field if it's non-nil, zero value otherwise. -func (r *RepoFineGrainedPermission) GetDescription() string { - if r == nil || r.Description == nil { - return "" - } - return *r.Description -} - -// GetName returns the Name field if it's non-nil, zero value otherwise. -func (r *RepoFineGrainedPermission) GetName() string { - if r == nil || r.Name == nil { - return "" - } - return *r.Name -} - // GetBranch returns the Branch field if it's non-nil, zero value otherwise. func (r *RepoMergeUpstreamRequest) GetBranch() string { if r == nil || r.Branch == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index bd96edc488a..08332e3776d 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -30393,28 +30393,6 @@ func TestRepoDependencies_GetVersionInfo(tt *testing.T) { r.GetVersionInfo() } -func TestRepoFineGrainedPermission_GetDescription(tt *testing.T) { - tt.Parallel() - var zeroValue string - r := &RepoFineGrainedPermission{Description: &zeroValue} - r.GetDescription() - r = &RepoFineGrainedPermission{} - r.GetDescription() - r = nil - r.GetDescription() -} - -func TestRepoFineGrainedPermission_GetName(tt *testing.T) { - tt.Parallel() - var zeroValue string - r := &RepoFineGrainedPermission{Name: &zeroValue} - r.GetName() - r = &RepoFineGrainedPermission{} - r.GetName() - r = nil - r.GetName() -} - func TestRepoMergeUpstreamRequest_GetBranch(tt *testing.T) { tt.Parallel() var zeroValue string diff --git a/github/orgs_custom_repository_roles.go b/github/orgs_custom_repository_roles.go index 0f4b3dd6478..192ab63a6f7 100644 --- a/github/orgs_custom_repository_roles.go +++ b/github/orgs_custom_repository_roles.go @@ -40,8 +40,8 @@ type CreateOrUpdateCustomRepoRoleOptions struct { // RepoFineGrainedPermission represents a fine-grained permission that can be used in a custom repository role. type RepoFineGrainedPermission struct { - Name *string `json:"name,omitempty"` - Description *string `json:"description,omitempty"` + Name string `json:"name"` + Description string `json:"description"` } // ListCustomRepoRoles lists the custom repository roles available in this organization. diff --git a/github/orgs_custom_repository_roles_test.go b/github/orgs_custom_repository_roles_test.go index fc4ceb794cc..8b221e0862d 100644 --- a/github/orgs_custom_repository_roles_test.go +++ b/github/orgs_custom_repository_roles_test.go @@ -310,12 +310,12 @@ func TestOrganizationsService_ListRepositoryFineGrainedPermissions(t *testing.T) want := []*RepoFineGrainedPermission{ { - Name: Ptr("add_assignee"), - Description: Ptr("Assign or remove a user"), + Name: "add_assignee", + Description: "Assign or remove a user", }, { - Name: Ptr("add_label"), - Description: Ptr("Add or remove a label"), + Name: "add_label", + Description: "Add or remove a label", }, } if !cmp.Equal(perms, want) {