diff --git a/github/github-accessors.go b/github/github-accessors.go index eba1036f6c2..beeb2defce6 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/github-accessors_test.go b/github/github-accessors_test.go index 044a45bd486..3cc4001ed4a 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 e2ec62b2838..f83ce4ced81 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.go b/github/repos.go index 1f6a3181ea6..fad152e22f2 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. diff --git a/github/repos_test.go b/github/repos_test.go index 5f59216b2b9..e86d80796f8 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 8efed472da5..124e00551a9 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)