Repository: google/go-github
Pull request #2709 (2023-03-17 15:44:47)

Add fields to update repository API and create branch protection API to match GitHub APIs

codecov[bot]: ## [Codecov](https://codecov.io/gh/google/go-github/pull/2709?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) Report
> Merging [#2709](https://codecov.io/gh/google/go-github/pull/2709?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (2b4ee89) into [master](https://codecov.io/gh/google/go-github/commit/9bfbc0063c544ba14ebd5298242f4ba9bdbe8c6f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) (9bfbc00) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##           master    #2709   +/-   ##
=======================================
  Coverage   98.05%   98.05%           
=======================================
  Files         131      131           
  Lines       11459    11459           
=======================================
  Hits        11236    11236           
  Misses        152      152           
  Partials       71       71           
```


| [Impacted Files](https://codecov.io/gh/google/go-github/pull/2709?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google) | Coverage Δ | |
|---|---|---|
| [github/repos.go](https://codecov.io/gh/google/go-github/pull/2709?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google#diff-Z2l0aHViL3JlcG9zLmdv) | `98.84% <ø> (ø)` | |

Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=google)


Patch:
diff --git a/github/github-accessors.go b/github/github-accessors.go
index eba1036f..beeb2def 100644
--- a/github/github-accessors.go
+++ b/github/github-accessors.go
@@ -1766,6 +1766,14 @@ func (b *Blob) GetURL() string {
 	return *b.URL
 }
 
+// GetEnabled returns the Enabled field if it's non-nil, zero value otherwise.
+func (b *BlockCreations) GetEnabled() bool {
+	if b == nil || b.Enabled == nil {
+		return false
+	}
+	return *b.Enabled
+}
+
 // GetCommit returns the Commit field.
 func (b *Branch) GetCommit() *RepositoryCommit {
 	if b == nil {
@@ -12830,6 +12838,14 @@ func (p *Protection) GetAllowForkSyncing() *AllowForkSyncing {
 	return p.AllowForkSyncing
 }
 
+// GetBlockCreations returns the BlockCreations field.
+func (p *Protection) GetBlockCreations() *BlockCreations {
+	if p == nil {
+		return nil
+	}
+	return p.BlockCreations
+}
+
 // GetEnforceAdmins returns the EnforceAdmins field.
 func (p *Protection) GetEnforceAdmins() *AdminEnforcement {
 	if p == nil {
@@ -13022,6 +13038,30 @@ func (p *ProtectionRequest) GetAllowForcePushes() bool {
 	return *p.AllowForcePushes
 }
 
+// GetAllowForkSyncing returns the AllowForkSyncing field if it's non-nil, zero value otherwise.
+func (p *ProtectionRequest) GetAllowForkSyncing() bool {
+	if p == nil || p.AllowForkSyncing == nil {
+		return false
+	}
+	return *p.AllowForkSyncing
+}
+
+// GetBlockCreations returns the BlockCreations field if it's non-nil, zero value otherwise.
+func (p *ProtectionRequest) GetBlockCreations() bool {
+	if p == nil || p.BlockCreations == nil {
+		return false
+	}
+	return *p.BlockCreations
+}
+
+// GetLockBranch returns the LockBranch field if it's non-nil, zero value otherwise.
+func (p *ProtectionRequest) GetLockBranch() bool {
+	if p == nil || p.LockBranch == nil {
+		return false
+	}
+	return *p.LockBranch
+}
+
 // GetRequiredConversationResolution returns the RequiredConversationResolution field if it's non-nil, zero value otherwise.
 func (p *ProtectionRequest) GetRequiredConversationResolution() bool {
 	if p == nil || p.RequiredConversationResolution == nil {
@@ -16246,6 +16286,14 @@ func (r *Repository) GetWatchersCount() int {
 	return *r.WatchersCount
 }
 
+// GetWebCommitSignoffRequired returns the WebCommitSignoffRequired field if it's non-nil, zero value otherwise.
+func (r *Repository) GetWebCommitSignoffRequired() bool {
+	if r == nil || r.WebCommitSignoffRequired == nil {
+		return false
+	}
+	return *r.WebCommitSignoffRequired
+}
+
 // GetAccessLevel returns the AccessLevel field if it's non-nil, zero value otherwise.
 func (r *RepositoryActionsAccessLevel) GetAccessLevel() string {
 	if r == nil || r.AccessLevel == nil {
diff --git a/github/repos.go b/github/repos.go
index 1f6a3181..fad152e2 100644
--- a/github/repos.go
+++ b/github/repos.go
@@ -68,6 +68,7 @@ type Repository struct {
 	AllowMergeCommit          *bool           `json:"allow_merge_commit,omitempty"`
 	AllowAutoMerge            *bool           `json:"allow_auto_merge,omitempty"`
 	AllowForking              *bool           `json:"allow_forking,omitempty"`
+	WebCommitSignoffRequired  *bool           `json:"web_commit_signoff_required,omitempty"`
 	DeleteBranchOnMerge       *bool           `json:"delete_branch_on_merge,omitempty"`
 	UseSquashPRTitleAsDefault *bool           `json:"use_squash_pr_title_as_default,omitempty"`
 	SquashMergeCommitTitle    *string         `json:"squash_merge_commit_title,omitempty"`   // Can be one of: "PR_TITLE", "COMMIT_OR_PR_TITLE"
@@ -843,10 +844,18 @@ type Protection struct {
 	AllowForcePushes               *AllowForcePushes               `json:"allow_force_pushes"`
 	AllowDeletions                 *AllowDeletions                 `json:"allow_deletions"`
 	RequiredConversationResolution *RequiredConversationResolution `json:"required_conversation_resolution"`
+	BlockCreations                 *BlockCreations                 `json:"block_creations,omitempty"`
 	LockBranch                     *LockBranch                     `json:"lock_branch,omitempty"`
 	AllowForkSyncing               *AllowForkSyncing               `json:"allow_fork_syncing,omitempty"`
 }
 
+// BlockCreations represents whether users can push changes that create branches. If this is true, this
+// setting blocks pushes that create new branches, unless the push is initiated by a user, team, or app
+// which has the ability to push.
+type BlockCreations struct {
+	Enabled *bool `json:"enabled,omitempty"`
+}
+
 // LockBranch represents if the branch is marked as read-only. If this is true, users will not be able to push to the branch.
 type LockBranch struct {
 	Enabled *bool `json:"enabled,omitempty"`
@@ -994,6 +1003,14 @@ type ProtectionRequest struct {
 	// RequiredConversationResolution, if set to true, requires all comments
 	// on the pull request to be resolved before it can be merged to a protected branch.
 	RequiredConversationResolution *bool `json:"required_conversation_resolution,omitempty"`
+	// BlockCreations, if set to true, will cause the restrictions setting to also block pushes
+	// which create new branches, unless initiated by a user, team, app with the ability to push.
+	BlockCreations *bool `json:"block_creations,omitempty"`
+	// LockBranch, if set to true, will prevent users from pushing to the branch.
+	LockBranch *bool `json:"lock_branch,omitempty"`
+	// AllowForkSyncing, if set to true, will allow users to pull changes from upstream
+	// when the branch is locked.
+	AllowForkSyncing *bool `json:"allow_fork_syncing,omitempty"`
 }
 
 // RequiredStatusChecks represents the protection status of a individual branch.


Test patch:
diff --git a/github/github-accessors_test.go b/github/github-accessors_test.go
index 044a45bd..3cc4001e 100644
--- a/github/github-accessors_test.go
+++ b/github/github-accessors_test.go
@@ -2121,6 +2121,16 @@ func TestBlob_GetURL(tt *testing.T) {
 	b.GetURL()
 }
 
+func TestBlockCreations_GetEnabled(tt *testing.T) {
+	var zeroValue bool
+	b := &BlockCreations{Enabled: &zeroValue}
+	b.GetEnabled()
+	b = &BlockCreations{}
+	b.GetEnabled()
+	b = nil
+	b.GetEnabled()
+}
+
 func TestBranch_GetCommit(tt *testing.T) {
 	b := &Branch{}
 	b.GetCommit()
@@ -14988,6 +14998,13 @@ func TestProtection_GetAllowForkSyncing(tt *testing.T) {
 	p.GetAllowForkSyncing()
 }
 
+func TestProtection_GetBlockCreations(tt *testing.T) {
+	p := &Protection{}
+	p.GetBlockCreations()
+	p = nil
+	p.GetBlockCreations()
+}
+
 func TestProtection_GetEnforceAdmins(tt *testing.T) {
 	p := &Protection{}
 	p.GetEnforceAdmins()
@@ -15162,6 +15179,36 @@ func TestProtectionRequest_GetAllowForcePushes(tt *testing.T) {
 	p.GetAllowForcePushes()
 }
 
+func TestProtectionRequest_GetAllowForkSyncing(tt *testing.T) {
+	var zeroValue bool
+	p := &ProtectionRequest{AllowForkSyncing: &zeroValue}
+	p.GetAllowForkSyncing()
+	p = &ProtectionRequest{}
+	p.GetAllowForkSyncing()
+	p = nil
+	p.GetAllowForkSyncing()
+}
+
+func TestProtectionRequest_GetBlockCreations(tt *testing.T) {
+	var zeroValue bool
+	p := &ProtectionRequest{BlockCreations: &zeroValue}
+	p.GetBlockCreations()
+	p = &ProtectionRequest{}
+	p.GetBlockCreations()
+	p = nil
+	p.GetBlockCreations()
+}
+
+func TestProtectionRequest_GetLockBranch(tt *testing.T) {
+	var zeroValue bool
+	p := &ProtectionRequest{LockBranch: &zeroValue}
+	p.GetLockBranch()
+	p = &ProtectionRequest{}
+	p.GetLockBranch()
+	p = nil
+	p.GetLockBranch()
+}
+
 func TestProtectionRequest_GetRequiredConversationResolution(tt *testing.T) {
 	var zeroValue bool
 	p := &ProtectionRequest{RequiredConversationResolution: &zeroValue}
@@ -18913,6 +18960,16 @@ func TestRepository_GetWatchersCount(tt *testing.T) {
 	r.GetWatchersCount()
 }
 
+func TestRepository_GetWebCommitSignoffRequired(tt *testing.T) {
+	var zeroValue bool
+	r := &Repository{WebCommitSignoffRequired: &zeroValue}
+	r.GetWebCommitSignoffRequired()
+	r = &Repository{}
+	r.GetWebCommitSignoffRequired()
+	r = nil
+	r.GetWebCommitSignoffRequired()
+}
+
 func TestRepositoryActionsAccessLevel_GetAccessLevel(tt *testing.T) {
 	var zeroValue string
 	r := &RepositoryActionsAccessLevel{AccessLevel: &zeroValue}
diff --git a/github/github-stringify_test.go b/github/github-stringify_test.go
index e2ec62b2..f83ce4ce 100644
--- a/github/github-stringify_test.go
+++ b/github/github-stringify_test.go
@@ -1560,6 +1560,7 @@ func TestRepository_String(t *testing.T) {
 		AllowMergeCommit:          Bool(false),
 		AllowAutoMerge:            Bool(false),
 		AllowForking:              Bool(false),
+		WebCommitSignoffRequired:  Bool(false),
 		DeleteBranchOnMerge:       Bool(false),
 		UseSquashPRTitleAsDefault: Bool(false),
 		SquashMergeCommitTitle:    String(""),
@@ -1622,7 +1623,7 @@ func TestRepository_String(t *testing.T) {
 		Visibility:                String(""),
 		RoleName:                  String(""),
 	}
-	want := `github.Repository{ID:0, NodeID:"", Owner:github.User{}, Name:"", FullName:"", Description:"", Homepage:"", CodeOfConduct:github.CodeOfConduct{}, DefaultBranch:"", MasterBranch:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, PushedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, HTMLURL:"", CloneURL:"", GitURL:"", MirrorURL:"", SSHURL:"", SVNURL:"", Language:"", Fork:false, ForksCount:0, NetworkCount:0, OpenIssuesCount:0, OpenIssues:0, StargazersCount:0, SubscribersCount:0, WatchersCount:0, Watchers:0, Size:0, AutoInit:false, Parent:github.Repository{}, Source:github.Repository{}, TemplateRepository:github.Repository{}, Organization:github.Organization{}, AllowRebaseMerge:false, AllowUpdateBranch:false, AllowSquashMerge:false, AllowMergeCommit:false, AllowAutoMerge:false, AllowForking:false, DeleteBranchOnMerge:false, UseSquashPRTitleAsDefault:false, SquashMergeCommitTitle:"", SquashMergeCommitMessage:"", MergeCommitTitle:"", MergeCommitMessage:"", Topics:[""], Archived:false, Disabled:false, License:github.License{}, Private:false, HasIssues:false, HasWiki:false, HasPages:false, HasProjects:false, HasDownloads:false, HasDiscussions:false, IsTemplate:false, LicenseTemplate:"", GitignoreTemplate:"", SecurityAndAnalysis:github.SecurityAndAnalysis{}, TeamID:0, URL:"", ArchiveURL:"", AssigneesURL:"", BlobsURL:"", BranchesURL:"", CollaboratorsURL:"", CommentsURL:"", CommitsURL:"", CompareURL:"", ContentsURL:"", ContributorsURL:"", DeploymentsURL:"", DownloadsURL:"", EventsURL:"", ForksURL:"", GitCommitsURL:"", GitRefsURL:"", GitTagsURL:"", HooksURL:"", IssueCommentURL:"", IssueEventsURL:"", IssuesURL:"", KeysURL:"", LabelsURL:"", LanguagesURL:"", MergesURL:"", MilestonesURL:"", NotificationsURL:"", PullsURL:"", ReleasesURL:"", StargazersURL:"", StatusesURL:"", SubscribersURL:"", SubscriptionURL:"", TagsURL:"", TreesURL:"", TeamsURL:"", Visibility:"", RoleName:""}`
+	want := `github.Repository{ID:0, NodeID:"", Owner:github.User{}, Name:"", FullName:"", Description:"", Homepage:"", CodeOfConduct:github.CodeOfConduct{}, DefaultBranch:"", MasterBranch:"", CreatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, PushedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, UpdatedAt:github.Timestamp{0001-01-01 00:00:00 +0000 UTC}, HTMLURL:"", CloneURL:"", GitURL:"", MirrorURL:"", SSHURL:"", SVNURL:"", Language:"", Fork:false, ForksCount:0, NetworkCount:0, OpenIssuesCount:0, OpenIssues:0, StargazersCount:0, SubscribersCount:0, WatchersCount:0, Watchers:0, Size:0, AutoInit:false, Parent:github.Repository{}, Source:github.Repository{}, TemplateRepository:github.Repository{}, Organization:github.Organization{}, AllowRebaseMerge:false, AllowUpdateBranch:false, AllowSquashMerge:false, AllowMergeCommit:false, AllowAutoMerge:false, AllowForking:false, WebCommitSignoffRequired:false, DeleteBranchOnMerge:false, UseSquashPRTitleAsDefault:false, SquashMergeCommitTitle:"", SquashMergeCommitMessage:"", MergeCommitTitle:"", MergeCommitMessage:"", Topics:[""], Archived:false, Disabled:false, License:github.License{}, Private:false, HasIssues:false, HasWiki:false, HasPages:false, HasProjects:false, HasDownloads:false, HasDiscussions:false, IsTemplate:false, LicenseTemplate:"", GitignoreTemplate:"", SecurityAndAnalysis:github.SecurityAndAnalysis{}, TeamID:0, URL:"", ArchiveURL:"", AssigneesURL:"", BlobsURL:"", BranchesURL:"", CollaboratorsURL:"", CommentsURL:"", CommitsURL:"", CompareURL:"", ContentsURL:"", ContributorsURL:"", DeploymentsURL:"", DownloadsURL:"", EventsURL:"", ForksURL:"", GitCommitsURL:"", GitRefsURL:"", GitTagsURL:"", HooksURL:"", IssueCommentURL:"", IssueEventsURL:"", IssuesURL:"", KeysURL:"", LabelsURL:"", LanguagesURL:"", MergesURL:"", MilestonesURL:"", NotificationsURL:"", PullsURL:"", ReleasesURL:"", StargazersURL:"", StatusesURL:"", SubscribersURL:"", SubscriptionURL:"", TagsURL:"", TreesURL:"", TeamsURL:"", Visibility:"", RoleName:""}`
 	if got := v.String(); got != want {
 		t.Errorf("Repository.String = %v, want %v", got, want)
 	}
diff --git a/github/repos_test.go b/github/repos_test.go
index 5f59216b..e86d8079 100644
--- a/github/repos_test.go
+++ b/github/repos_test.go
@@ -1096,6 +1096,15 @@ func TestRepositoriesService_GetBranchProtection(t *testing.T) {
 					},
 					"required_conversation_resolution": {
 						"enabled": true
+					},
+					"block_creations": {
+						"enabled": false
+					},
+					"lock_branch": {
+						"enabled": false
+					},
+					"allow_fork_syncing": {
+						"enabled": false
 					}
 				}`)
 	})
@@ -1151,6 +1160,15 @@ func TestRepositoriesService_GetBranchProtection(t *testing.T) {
 		RequiredConversationResolution: &RequiredConversationResolution{
 			Enabled: true,
 		},
+		BlockCreations: &BlockCreations{
+			Enabled: Bool(false),
+		},
+		LockBranch: &LockBranch{
+			Enabled: Bool(false),
+		},
+		AllowForkSyncing: &AllowForkSyncing{
+			Enabled: Bool(false),
+		},
 	}
 	if !cmp.Equal(protection, want) {
 		t.Errorf("Repositories.GetBranchProtection returned %+v, want %+v", protection, want)
@@ -1299,6 +1317,9 @@ func TestRepositoriesService_UpdateBranchProtection_Contexts(t *testing.T) {
 			Teams: []string{"t"},
 			Apps:  []string{"a"},
 		},
+		BlockCreations:   Bool(true),
+		LockBranch:       Bool(true),
+		AllowForkSyncing: Bool(true),
 	}
 
 	mux.HandleFunc("/repos/o/r/branches/b/protection", func(w http.ResponseWriter, r *http.Request) {
@@ -1350,6 +1371,15 @@ func TestRepositoriesService_UpdateBranchProtection_Contexts(t *testing.T) {
 				"users":[{"id":1,"login":"u"}],
 				"teams":[{"id":2,"slug":"t"}],
 				"apps":[{"id":3,"slug":"a"}]
+			},
+			"block_creations": {
+				"enabled": true
+			},
+			"lock_branch": {
+				"enabled": true
+			},
+			"allow_fork_syncing": {
+				"enabled": true
 			}
 		}`)
 	})
@@ -1407,6 +1437,15 @@ func TestRepositoriesService_UpdateBranchProtection_Contexts(t *testing.T) {
 				{Slug: String("a"), ID: Int64(3)},
 			},
 		},
+		BlockCreations: &BlockCreations{
+			Enabled: Bool(true),
+		},
+		LockBranch: &LockBranch{
+			Enabled: Bool(true),
+		},
+		AllowForkSyncing: &AllowForkSyncing{
+			Enabled: Bool(true),
+		},
 	}
 	if !cmp.Equal(protection, want) {
 		t.Errorf("Repositories.UpdateBranchProtection returned %+v, want %+v", protection, want)
diff --git a/test/integration/repos_test.go b/test/integration/repos_test.go
index 8efed472..124e0055 100644
--- a/test/integration/repos_test.go
+++ b/test/integration/repos_test.go
@@ -112,7 +112,10 @@ func TestRepositories_EditBranches(t *testing.T) {
 		// TODO: Only organization repositories can have users and team restrictions.
 		//       In order to be able to test these Restrictions, need to add support
 		//       for creating temporary organization repositories.
-		Restrictions: nil,
+		Restrictions:     nil,
+		BlockCreations:   github.Bool(false),
+		LockBranch:       github.Bool(false),
+		AllowForkSyncing: github.Bool(false),
 	}
 
 	protection, _, err := client.Repositories.UpdateBranchProtection(context.Background(), *repo.Owner.Login, *repo.Name, "master", protectionRequest)
@@ -134,6 +137,15 @@ func TestRepositories_EditBranches(t *testing.T) {
 			Enabled: true,
 		},
 		Restrictions: nil,
+		BlockCreations: &github.BlockCreations{
+			Enabled: github.Bool(false),
+		},
+		LockBranch: &github.LockBranch{
+			Enabled: github.Bool(false),
+		},
+		AllowForkSyncing: &github.AllowForkSyncing{
+			Enabled: github.Bool(false),
+		},
 	}
 	if !cmp.Equal(protection, want) {
 		t.Errorf("Repositories.UpdateBranchProtection() returned %+v, want %+v", protection, want)