Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API branch protection endpoint #9311

Merged
merged 23 commits into from
Feb 12, 2020
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
5e0302a
add API branch protection endpoint
davidsvantesson Nov 17, 2019
f0e082d
lint
davidsvantesson Dec 10, 2019
44a6bb2
Merge branch 'master' into api-branch-protection
davidsvantesson Jan 18, 2020
a46dbc2
Change to use team names instead of ids.
davidsvantesson Jan 18, 2020
637d10f
Status codes.
davidsvantesson Jan 18, 2020
5d83df5
fix
davidsvantesson Jan 18, 2020
8d38799
Merge branch 'master' into api-branch-protection
davidsvantesson Jan 25, 2020
2234a59
Fix
davidsvantesson Jan 25, 2020
606fbbc
Add new branch protection options (BlockOnRejectedReviews, DismissSta…
davidsvantesson Jan 25, 2020
ba86c20
Do xorm query directly
davidsvantesson Jan 26, 2020
2d86ed1
fix xorm GetUserNamesByIDs
davidsvantesson Jan 26, 2020
92583c3
Add some tests
davidsvantesson Jan 26, 2020
ed778e6
Improved GetTeamNamesByID
davidsvantesson Jan 27, 2020
cf41723
Merge branch 'master' into api-branch-protection
davidsvantesson Jan 27, 2020
3ccc769
http status created for CreateBranchProtection
davidsvantesson Feb 4, 2020
9b285d3
Correct status code in integration test
davidsvantesson Feb 4, 2020
9a49639
Merge branch 'master' into api-branch-protection
davidsvantesson Feb 4, 2020
28ddd9b
Merge branch 'master' into api-branch-protection
lunny Feb 7, 2020
dba6051
Merge branch 'master' into api-branch-protection
davidsvantesson Feb 7, 2020
afdd144
Merge branch 'master' into api-branch-protection
lunny Feb 7, 2020
4cd0cf0
Merge branch 'master' into api-branch-protection
davidsvantesson Feb 10, 2020
122fb8c
Merge branch 'master' into api-branch-protection
lunny Feb 11, 2020
35300c3
Merge branch 'master' into api-branch-protection
zeripath Feb 12, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,16 @@ func GetMaileableUsersByIDs(ids []int64) ([]*User, error) {
Find(&ous)
}

// GetUsernamesByIDs returns usernames for all resolved users from a list of Ids.
func GetUsernamesByIDs(ids []int64) ([]string, error) {
davidsvantesson marked this conversation as resolved.
Show resolved Hide resolved
ous, err := GetUsersByIDs(ids)
unames := make([]string, 0, len(ous))
for _, u := range ous {
davidsvantesson marked this conversation as resolved.
Show resolved Hide resolved
unames = append(unames, u.Name)
}
return unames, err
}

// GetUsersByIDs returns all resolved users from a list of Ids.
func GetUsersByIDs(ids []int64) ([]*User, error) {
ous := make([]*User, 0, len(ids))
Expand Down
82 changes: 65 additions & 17 deletions modules/convert/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,28 +30,76 @@ func ToEmail(email *models.EmailAddress) *api.Email {
}

// ToBranch convert a git.Commit and git.Branch to an api.Branch
func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit, bp *models.ProtectedBranch, user *models.User) *api.Branch {
func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit, bp *models.ProtectedBranch, user *models.User, isRepoAdmin bool) *api.Branch {
if bp == nil {
return &api.Branch{
Name: b.Name,
Commit: ToCommit(repo, c),
Protected: false,
RequiredApprovals: 0,
EnableStatusCheck: false,
StatusCheckContexts: []string{},
UserCanPush: true,
UserCanMerge: true,
Name: b.Name,
Commit: ToCommit(repo, c),
Protected: false,
RequiredApprovals: 0,
EnableStatusCheck: false,
StatusCheckContexts: []string{},
UserCanPush: true,
UserCanMerge: true,
EffectiveBranchProtectionName: "",
EffectiveBRanchProtectionID: 0,
davidsvantesson marked this conversation as resolved.
Show resolved Hide resolved
}
}
branchProtectionName := ""
var branchProtectionID int64
if isRepoAdmin {
branchProtectionName = bp.BranchName
davidsvantesson marked this conversation as resolved.
Show resolved Hide resolved
branchProtectionID = bp.ID
}

return &api.Branch{
Name: b.Name,
Commit: ToCommit(repo, c),
Protected: true,
RequiredApprovals: bp.RequiredApprovals,
EnableStatusCheck: bp.EnableStatusCheck,
StatusCheckContexts: bp.StatusCheckContexts,
UserCanPush: bp.CanUserPush(user.ID),
UserCanMerge: bp.CanUserMerge(user.ID),
Name: b.Name,
Commit: ToCommit(repo, c),
Protected: true,
RequiredApprovals: bp.RequiredApprovals,
EnableStatusCheck: bp.EnableStatusCheck,
StatusCheckContexts: bp.StatusCheckContexts,
UserCanPush: bp.CanUserPush(user.ID),
UserCanMerge: bp.CanUserMerge(user.ID),
EffectiveBranchProtectionName: branchProtectionName,
EffectiveBRanchProtectionID: branchProtectionID,
davidsvantesson marked this conversation as resolved.
Show resolved Hide resolved
}
}

// ToBranchProtection convert a ProtectedBranch to api.BranchProtection
func ToBranchProtection(bp *models.ProtectedBranch) *api.BranchProtection {
pushWhitelistUsernames, err := models.GetUsernamesByIDs(bp.WhitelistUserIDs)
if err != nil {
log.Error("GetUsernamesByIDs (WhitelistUserIDs): %v", err)
}
mergeWhitelistUsernames, err := models.GetUsernamesByIDs(bp.MergeWhitelistUserIDs)
if err != nil {
log.Error("GetUsernamesByIDs (MergeWhitelistUserIDs): %v", err)
}
approvalsWhitelistUsernames, err := models.GetUsernamesByIDs(bp.ApprovalsWhitelistUserIDs)
if err != nil {
log.Error("GetUsernamesByIDs (ApprovalsWhitelistUserIDs): %v", err)
}

return &api.BranchProtection{
ID: bp.ID,
BranchName: bp.BranchName,
EnablePush: bp.CanPush,
EnablePushWhitelist: bp.EnableWhitelist,
PushWhitelistUsernames: pushWhitelistUsernames,
PushWhitelistTeamIDs: bp.WhitelistTeamIDs,
PushWhitelistDeployKeys: bp.WhitelistDeployKeys,
EnableMergeWhitelist: bp.EnableMergeWhitelist,
MergeWhitelistUsernames: mergeWhitelistUsernames,
MergeWhitelistTeamIDs: bp.MergeWhitelistTeamIDs,
EnableStatusCheck: bp.EnableStatusCheck,
StatusCheckContexts: bp.StatusCheckContexts,
RequiredApprovals: bp.RequiredApprovals,
EnableApprovalsWhitelist: bp.EnableApprovalsWhitelist,
ApprovalsWhitelistUsernames: approvalsWhitelistUsernames,
ApprovalsWhitelistTeamIDs: bp.ApprovalsWhitelistTeamIDs,
davidsvantesson marked this conversation as resolved.
Show resolved Hide resolved
Created: bp.CreatedUnix.AsTime(),
Updated: bp.UpdatedUnix.AsTime(),
}
}

Expand Down
83 changes: 75 additions & 8 deletions modules/structs/repo_branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,81 @@

package structs

import (
"time"
)

// Branch represents a repository branch
type Branch struct {
Name string `json:"name"`
Commit *PayloadCommit `json:"commit"`
Protected bool `json:"protected"`
RequiredApprovals int64 `json:"required_approvals"`
EnableStatusCheck bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
UserCanPush bool `json:"user_can_push"`
UserCanMerge bool `json:"user_can_merge"`
Name string `json:"name"`
Commit *PayloadCommit `json:"commit"`
Protected bool `json:"protected"`
RequiredApprovals int64 `json:"required_approvals"`
EnableStatusCheck bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
UserCanPush bool `json:"user_can_push"`
UserCanMerge bool `json:"user_can_merge"`
EffectiveBranchProtectionName string `json:"effective_branch_protection_name"`
EffectiveBRanchProtectionID int64 `json:"effective_branch_protection_id"`
}

// BranchProtection represents a branch protection for a repository
type BranchProtection struct {
ID int64 `json:"id"`
BranchName string `json:"branch_name"`
EnablePush bool `json:"enable_push"`
EnablePushWhitelist bool `json:"enable_push_whitelist"`
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
PushWhitelistTeamIDs []int64 `json:"push_whitelist_team_ids"`
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
MergeWhitelistTeamIDs []int64 `json:"merge_whitelist_ids"`
EnableStatusCheck bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
RequiredApprovals int64 `json:"required_approvals"`
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
ApprovalsWhitelistTeamIDs []int64 `json:"approvals_whitelist_team_ids"`
// swagger:strfmt date-time
Created time.Time `json:"created_at"`
// swagger:strfmt date-time
Updated time.Time `json:"updated_at"`
}

// CreateBranchProtectionOption options for creating a branch protection
type CreateBranchProtectionOption struct {
BranchName string `json:"branch_name"`
EnablePush bool `json:"enable_push"`
EnablePushWhitelist bool `json:"enable_push_whitelist"`
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
PushWhitelistTeamIDs []int64 `json:"push_whitelist_team_ids"`
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
MergeWhitelistTeamIDs []int64 `json:"merge_whitelist_team_ids"`
davidsvantesson marked this conversation as resolved.
Show resolved Hide resolved
EnableStatusCheck bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
RequiredApprovals int64 `json:"required_approvals"`
EnableApprovalsWhitelist bool `json:"enable_approvals_whitelist"`
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
ApprovalsWhitelistTeamIDs []int64 `json:"approvals_whitelist_team_ids"`
}

// EditBranchProtectionOption options for editing a branch protection
type EditBranchProtectionOption struct {
EnablePush *bool `json:"enable_push"`
EnablePushWhitelist *bool `json:"enable_push_whitelist"`
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
PushWhitelistTeamIDs []int64 `json:"push_whitelist_team_ids"`
PushWhitelistDeployKeys *bool `json:"push_whitelist_deploy_keys"`
EnableMergeWhitelist *bool `json:"enable_merge_whitelist"`
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
MergeWhitelistTeamIDs []int64 `json:"merge_whitelist_team_ids"`
EnableStatusCheck *bool `json:"enable_status_check"`
StatusCheckContexts []string `json:"status_check_contexts"`
RequiredApprovals *int64 `json:"required_approvals"`
EnableApprovalsWhitelist *bool `json:"enable_approvals_whitelist"`
ApprovalsWhitelistUsernames []string `json:"approvals_whitelist_username"`
ApprovalsWhitelistTeamIDs []int64 `json:"approvals_whitelist_team_ids"`
}
9 changes: 9 additions & 0 deletions routers/api/v1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,15 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Get("", repo.ListBranches)
m.Get("/*", context.RepoRefByType(context.RepoRefBranch), repo.GetBranch)
}, reqRepoReader(models.UnitTypeCode))
m.Group("/branch_protections", func() {
m.Get("", repo.ListBranchProtections)
m.Post("", bind(api.CreateBranchProtectionOption{}), repo.CreateBranchProtection)
m.Group("/:id", func() {
m.Get("", repo.GetBranchProtection)
m.Put("", bind(api.EditBranchProtectionOption{}), repo.EditBranchProtection)
davidsvantesson marked this conversation as resolved.
Show resolved Hide resolved
m.Delete("", repo.DeleteBranchProtection)
})
}, reqToken(), reqAdmin())
m.Group("/tags", func() {
m.Get("", repo.ListTags)
}, reqRepoReader(models.UnitTypeCode), context.ReferencesGitRepo(true))
Expand Down
Loading