From e374ac89d95d34c9fbe97113a2dd5fc8433c1b91 Mon Sep 17 00:00:00 2001 From: Jake Scaltreto Date: Mon, 11 Mar 2024 09:34:14 -0400 Subject: [PATCH] Add Protection to Branch struct Details regarding branch protection are provided APIs which return the "Branch With Protection" schema, such as '[Get a branch](https://docs.github.com/en/rest/branches/branches?apiVersion=2022-11-28#get-a-branch)'. This allows for getting branch protection information without needing to explicitly call the "Get branch protection" API. As the latter requires `administration:read` permissions while the former only requires `contents:read`, this enables users view branch protection information without requiring elevated permissions. The '[List branches](https://docs.github.com/en/rest/branches/branches?apiVersion=2022-11-28#list-branches)' API returns the `Short Branch` schema, which does not include `protection`, but since `protected` will still be `true`, a user could subsequently call 'Get a branch' to get further details. --- github/github-accessors.go | 8 ++++++++ github/github-accessors_test.go | 7 +++++++ github/repos.go | 8 ++++++++ github/repos_test.go | 14 ++++++++++++-- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/github/github-accessors.go b/github/github-accessors.go index 89728d38df9..18aa42dd672 100644 --- a/github/github-accessors.go +++ b/github/github-accessors.go @@ -1574,6 +1574,14 @@ func (b *Branch) GetProtected() bool { return *b.Protected } +// GetProtection returns the Protection field. +func (b *Branch) GetProtection() *Protection { + if b == nil { + return nil + } + return b.Protection +} + // GetCommit returns the Commit field. func (b *BranchCommit) GetCommit() *Commit { if b == nil { diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go index 1dcb4dc2bb9..e187cd4aba5 100644 --- a/github/github-accessors_test.go +++ b/github/github-accessors_test.go @@ -1881,6 +1881,13 @@ func TestBranch_GetProtected(tt *testing.T) { b.GetProtected() } +func TestBranch_GetProtection(tt *testing.T) { + b := &Branch{} + b.GetProtection() + b = nil + b.GetProtection() +} + func TestBranchCommit_GetCommit(tt *testing.T) { b := &BranchCommit{} b.GetCommit() diff --git a/github/repos.go b/github/repos.go index 2fb4c6f190a..6fb0030a3b2 100644 --- a/github/repos.go +++ b/github/repos.go @@ -1003,6 +1003,14 @@ type Branch struct { Name *string `json:"name,omitempty"` Commit *RepositoryCommit `json:"commit,omitempty"` Protected *bool `json:"protected,omitempty"` + + // Protection will always be included in APIs which return the + // 'Branch With Protection' schema such as 'Get a branch', but may + // not be included in APIs that return the `Short Branch` schema + // such as 'List branches'. In such cases, if branch protection is + // enabled, Protected will be `true` but this will be nil, and + // additional protection details can be obtained by calling GetBranch(). + Protection *Protection `json:"protection,omitempty"` } // Protection represents a repository branch's protection. diff --git a/github/repos_test.go b/github/repos_test.go index 0ea381ebb56..2b742bef904 100644 --- a/github/repos_test.go +++ b/github/repos_test.go @@ -930,7 +930,7 @@ func TestRepositoriesService_GetBranch(t *testing.T) { for _, test := range tests { mux.HandleFunc(test.urlPath, func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true}`) + fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true, "protection":{"required_status_checks":{"contexts":["c"]}}}`) }) ctx := context.Background() @@ -948,6 +948,11 @@ func TestRepositoriesService_GetBranch(t *testing.T) { }, }, Protected: Bool(true), + Protection: &Protection{ + RequiredStatusChecks: &RequiredStatusChecks{ + Contexts: &[]string{"c"}, + }, + }, } if !cmp.Equal(branch, want) { @@ -1000,7 +1005,7 @@ func TestRepositoriesService_GetBranch_StatusMovedPermanently_followRedirects(t }) mux.HandleFunc("/repos/o/r/branches/br", func(w http.ResponseWriter, r *http.Request) { testMethod(t, r, "GET") - fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true}`) + fmt.Fprint(w, `{"name":"n", "commit":{"sha":"s","commit":{"message":"m"}}, "protected":true, "protection":{"required_status_checks":{"contexts":["c"]}}}`) }) ctx := context.Background() branch, resp, err := client.Repositories.GetBranch(ctx, "o", "r", "b", 1) @@ -1020,6 +1025,11 @@ func TestRepositoriesService_GetBranch_StatusMovedPermanently_followRedirects(t }, }, Protected: Bool(true), + Protection: &Protection{ + RequiredStatusChecks: &RequiredStatusChecks{ + Contexts: &[]string{"c"}, + }, + }, } if !cmp.Equal(branch, want) { t.Errorf("Repositories.GetBranch returned %+v, want %+v", branch, want)