Add API branch protection endpoint (#9311)
* add API branch protection endpoint * lint * Change to use team names instead of ids. * Status codes. * fix * Fix * Add new branch protection options (BlockOnRejectedReviews, DismissStaleApprovals, RequireSignedCommits) * Do xorm query directly * fix xorm GetUserNamesByIDs * Add some tests * Improved GetTeamNamesByID * http status created for CreateBranchProtection * Correct status code in integration test Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com> Co-authored-by: zeripath <art27@cantab.net>
This commit is contained in:
parent
908f8952be
commit
9ff4e1d2d9
10 changed files with 1352 additions and 28 deletions
|
@ -30,6 +30,54 @@ func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
|
||||||
assert.EqualValues(t, branchName, branch.Name)
|
assert.EqualValues(t, branchName, branch.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testAPIGetBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||||
|
session := loginUser(t, "user2")
|
||||||
|
token := getTokenForLoggedInUser(t, session)
|
||||||
|
req := NewRequestf(t, "GET", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token)
|
||||||
|
resp := session.MakeRequest(t, req, expectedHTTPStatus)
|
||||||
|
|
||||||
|
if resp.Code == 200 {
|
||||||
|
var branchProtection api.BranchProtection
|
||||||
|
DecodeJSON(t, resp, &branchProtection)
|
||||||
|
assert.EqualValues(t, branchName, branchProtection.BranchName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAPICreateBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||||
|
session := loginUser(t, "user2")
|
||||||
|
token := getTokenForLoggedInUser(t, session)
|
||||||
|
req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/branch_protections?token="+token, &api.BranchProtection{
|
||||||
|
BranchName: branchName,
|
||||||
|
})
|
||||||
|
resp := session.MakeRequest(t, req, expectedHTTPStatus)
|
||||||
|
|
||||||
|
if resp.Code == 201 {
|
||||||
|
var branchProtection api.BranchProtection
|
||||||
|
DecodeJSON(t, resp, &branchProtection)
|
||||||
|
assert.EqualValues(t, branchName, branchProtection.BranchName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAPIEditBranchProtection(t *testing.T, branchName string, body *api.BranchProtection, expectedHTTPStatus int) {
|
||||||
|
session := loginUser(t, "user2")
|
||||||
|
token := getTokenForLoggedInUser(t, session)
|
||||||
|
req := NewRequestWithJSON(t, "PATCH", "/api/v1/repos/user2/repo1/branch_protections/"+branchName+"?token="+token, body)
|
||||||
|
resp := session.MakeRequest(t, req, expectedHTTPStatus)
|
||||||
|
|
||||||
|
if resp.Code == 200 {
|
||||||
|
var branchProtection api.BranchProtection
|
||||||
|
DecodeJSON(t, resp, &branchProtection)
|
||||||
|
assert.EqualValues(t, branchName, branchProtection.BranchName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAPIDeleteBranchProtection(t *testing.T, branchName string, expectedHTTPStatus int) {
|
||||||
|
session := loginUser(t, "user2")
|
||||||
|
token := getTokenForLoggedInUser(t, session)
|
||||||
|
req := NewRequestf(t, "DELETE", "/api/v1/repos/user2/repo1/branch_protections/%s?token=%s", branchName, token)
|
||||||
|
session.MakeRequest(t, req, expectedHTTPStatus)
|
||||||
|
}
|
||||||
|
|
||||||
func TestAPIGetBranch(t *testing.T) {
|
func TestAPIGetBranch(t *testing.T) {
|
||||||
for _, test := range []struct {
|
for _, test := range []struct {
|
||||||
BranchName string
|
BranchName string
|
||||||
|
@ -43,3 +91,23 @@ func TestAPIGetBranch(t *testing.T) {
|
||||||
testAPIGetBranch(t, test.BranchName, test.Exists)
|
testAPIGetBranch(t, test.BranchName, test.Exists)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAPIBranchProtection(t *testing.T) {
|
||||||
|
defer prepareTestEnv(t)()
|
||||||
|
|
||||||
|
// Branch protection only on branch that exist
|
||||||
|
testAPICreateBranchProtection(t, "master/doesnotexist", http.StatusNotFound)
|
||||||
|
// Get branch protection on branch that exist but not branch protection
|
||||||
|
testAPIGetBranchProtection(t, "master", http.StatusNotFound)
|
||||||
|
|
||||||
|
testAPICreateBranchProtection(t, "master", http.StatusCreated)
|
||||||
|
// Can only create once
|
||||||
|
testAPICreateBranchProtection(t, "master", http.StatusForbidden)
|
||||||
|
|
||||||
|
testAPIGetBranchProtection(t, "master", http.StatusOK)
|
||||||
|
testAPIEditBranchProtection(t, "master", &api.BranchProtection{
|
||||||
|
EnablePush: true,
|
||||||
|
}, http.StatusOK)
|
||||||
|
|
||||||
|
testAPIDeleteBranchProtection(t, "master", http.StatusNoContent)
|
||||||
|
}
|
||||||
|
|
|
@ -553,6 +553,23 @@ func GetTeam(orgID int64, name string) (*Team, error) {
|
||||||
return getTeam(x, orgID, name)
|
return getTeam(x, orgID, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTeamIDsByNames returns a slice of team ids corresponds to names.
|
||||||
|
func GetTeamIDsByNames(orgID int64, names []string, ignoreNonExistent bool) ([]int64, error) {
|
||||||
|
ids := make([]int64, 0, len(names))
|
||||||
|
for _, name := range names {
|
||||||
|
u, err := GetTeam(orgID, name)
|
||||||
|
if err != nil {
|
||||||
|
if ignoreNonExistent {
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ids = append(ids, u.ID)
|
||||||
|
}
|
||||||
|
return ids, nil
|
||||||
|
}
|
||||||
|
|
||||||
// getOwnerTeam returns team by given team name and organization.
|
// getOwnerTeam returns team by given team name and organization.
|
||||||
func getOwnerTeam(e Engine, orgID int64) (*Team, error) {
|
func getOwnerTeam(e Engine, orgID int64) (*Team, error) {
|
||||||
return getTeam(e, orgID, ownerTeamName)
|
return getTeam(e, orgID, ownerTeamName)
|
||||||
|
@ -574,6 +591,22 @@ func GetTeamByID(teamID int64) (*Team, error) {
|
||||||
return getTeamByID(x, teamID)
|
return getTeamByID(x, teamID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetTeamNamesByID returns team's lower name from a list of team ids.
|
||||||
|
func GetTeamNamesByID(teamIDs []int64) ([]string, error) {
|
||||||
|
if len(teamIDs) == 0 {
|
||||||
|
return []string{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var teamNames []string
|
||||||
|
err := x.Table("team").
|
||||||
|
Select("lower_name").
|
||||||
|
In("id", teamIDs).
|
||||||
|
Asc("name").
|
||||||
|
Find(&teamNames)
|
||||||
|
|
||||||
|
return teamNames, err
|
||||||
|
}
|
||||||
|
|
||||||
// UpdateTeam updates information of team.
|
// UpdateTeam updates information of team.
|
||||||
func UpdateTeam(t *Team, authChanged bool, includeAllChanged bool) (err error) {
|
func UpdateTeam(t *Team, authChanged bool, includeAllChanged bool) (err error) {
|
||||||
if len(t.Name) == 0 {
|
if len(t.Name) == 0 {
|
||||||
|
|
|
@ -1386,6 +1386,17 @@ func GetMaileableUsersByIDs(ids []int64) ([]*User, error) {
|
||||||
Find(&ous)
|
Find(&ous)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetUserNamesByIDs returns usernames for all resolved users from a list of Ids.
|
||||||
|
func GetUserNamesByIDs(ids []int64) ([]string, error) {
|
||||||
|
unames := make([]string, 0, len(ids))
|
||||||
|
err := x.In("id", ids).
|
||||||
|
Table("user").
|
||||||
|
Asc("name").
|
||||||
|
Cols("name").
|
||||||
|
Find(&unames)
|
||||||
|
return unames, err
|
||||||
|
}
|
||||||
|
|
||||||
// GetUsersByIDs returns all resolved users from a list of Ids.
|
// GetUsersByIDs returns all resolved users from a list of Ids.
|
||||||
func GetUsersByIDs(ids []int64) ([]*User, error) {
|
func GetUsersByIDs(ids []int64) ([]*User, error) {
|
||||||
ous := make([]*User, 0, len(ids))
|
ous := make([]*User, 0, len(ids))
|
||||||
|
|
|
@ -30,28 +30,86 @@ func ToEmail(email *models.EmailAddress) *api.Email {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToBranch convert a git.Commit and git.Branch to an api.Branch
|
// 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 {
|
if bp == nil {
|
||||||
return &api.Branch{
|
return &api.Branch{
|
||||||
Name: b.Name,
|
Name: b.Name,
|
||||||
Commit: ToCommit(repo, c),
|
Commit: ToCommit(repo, c),
|
||||||
Protected: false,
|
Protected: false,
|
||||||
RequiredApprovals: 0,
|
RequiredApprovals: 0,
|
||||||
EnableStatusCheck: false,
|
EnableStatusCheck: false,
|
||||||
StatusCheckContexts: []string{},
|
StatusCheckContexts: []string{},
|
||||||
UserCanPush: true,
|
UserCanPush: true,
|
||||||
UserCanMerge: true,
|
UserCanMerge: true,
|
||||||
|
EffectiveBranchProtectionName: "",
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
branchProtectionName := ""
|
||||||
|
if isRepoAdmin {
|
||||||
|
branchProtectionName = bp.BranchName
|
||||||
|
}
|
||||||
|
|
||||||
return &api.Branch{
|
return &api.Branch{
|
||||||
Name: b.Name,
|
Name: b.Name,
|
||||||
Commit: ToCommit(repo, c),
|
Commit: ToCommit(repo, c),
|
||||||
Protected: true,
|
Protected: true,
|
||||||
RequiredApprovals: bp.RequiredApprovals,
|
RequiredApprovals: bp.RequiredApprovals,
|
||||||
EnableStatusCheck: bp.EnableStatusCheck,
|
EnableStatusCheck: bp.EnableStatusCheck,
|
||||||
StatusCheckContexts: bp.StatusCheckContexts,
|
StatusCheckContexts: bp.StatusCheckContexts,
|
||||||
UserCanPush: bp.CanUserPush(user.ID),
|
UserCanPush: bp.CanUserPush(user.ID),
|
||||||
UserCanMerge: bp.IsUserMergeWhitelisted(user.ID),
|
UserCanMerge: bp.IsUserMergeWhitelisted(user.ID),
|
||||||
|
EffectiveBranchProtectionName: branchProtectionName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
pushWhitelistTeams, err := models.GetTeamNamesByID(bp.WhitelistTeamIDs)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("GetTeamNamesByID (WhitelistTeamIDs): %v", err)
|
||||||
|
}
|
||||||
|
mergeWhitelistTeams, err := models.GetTeamNamesByID(bp.MergeWhitelistTeamIDs)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("GetTeamNamesByID (MergeWhitelistTeamIDs): %v", err)
|
||||||
|
}
|
||||||
|
approvalsWhitelistTeams, err := models.GetTeamNamesByID(bp.ApprovalsWhitelistTeamIDs)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("GetTeamNamesByID (ApprovalsWhitelistTeamIDs): %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &api.BranchProtection{
|
||||||
|
BranchName: bp.BranchName,
|
||||||
|
EnablePush: bp.CanPush,
|
||||||
|
EnablePushWhitelist: bp.EnableWhitelist,
|
||||||
|
PushWhitelistUsernames: pushWhitelistUsernames,
|
||||||
|
PushWhitelistTeams: pushWhitelistTeams,
|
||||||
|
PushWhitelistDeployKeys: bp.WhitelistDeployKeys,
|
||||||
|
EnableMergeWhitelist: bp.EnableMergeWhitelist,
|
||||||
|
MergeWhitelistUsernames: mergeWhitelistUsernames,
|
||||||
|
MergeWhitelistTeams: mergeWhitelistTeams,
|
||||||
|
EnableStatusCheck: bp.EnableStatusCheck,
|
||||||
|
StatusCheckContexts: bp.StatusCheckContexts,
|
||||||
|
RequiredApprovals: bp.RequiredApprovals,
|
||||||
|
EnableApprovalsWhitelist: bp.EnableApprovalsWhitelist,
|
||||||
|
ApprovalsWhitelistUsernames: approvalsWhitelistUsernames,
|
||||||
|
ApprovalsWhitelistTeams: approvalsWhitelistTeams,
|
||||||
|
BlockOnRejectedReviews: bp.BlockOnRejectedReviews,
|
||||||
|
DismissStaleApprovals: bp.DismissStaleApprovals,
|
||||||
|
RequireSignedCommits: bp.RequireSignedCommits,
|
||||||
|
Created: bp.CreatedUnix.AsTime(),
|
||||||
|
Updated: bp.UpdatedUnix.AsTime(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,14 +4,88 @@
|
||||||
|
|
||||||
package structs
|
package structs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
// Branch represents a repository branch
|
// Branch represents a repository branch
|
||||||
type Branch struct {
|
type Branch struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Commit *PayloadCommit `json:"commit"`
|
Commit *PayloadCommit `json:"commit"`
|
||||||
Protected bool `json:"protected"`
|
Protected bool `json:"protected"`
|
||||||
RequiredApprovals int64 `json:"required_approvals"`
|
RequiredApprovals int64 `json:"required_approvals"`
|
||||||
EnableStatusCheck bool `json:"enable_status_check"`
|
EnableStatusCheck bool `json:"enable_status_check"`
|
||||||
StatusCheckContexts []string `json:"status_check_contexts"`
|
StatusCheckContexts []string `json:"status_check_contexts"`
|
||||||
UserCanPush bool `json:"user_can_push"`
|
UserCanPush bool `json:"user_can_push"`
|
||||||
UserCanMerge bool `json:"user_can_merge"`
|
UserCanMerge bool `json:"user_can_merge"`
|
||||||
|
EffectiveBranchProtectionName string `json:"effective_branch_protection_name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BranchProtection represents a branch protection for a repository
|
||||||
|
type BranchProtection struct {
|
||||||
|
BranchName string `json:"branch_name"`
|
||||||
|
EnablePush bool `json:"enable_push"`
|
||||||
|
EnablePushWhitelist bool `json:"enable_push_whitelist"`
|
||||||
|
PushWhitelistUsernames []string `json:"push_whitelist_usernames"`
|
||||||
|
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||||
|
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||||
|
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||||
|
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||||
|
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||||
|
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"`
|
||||||
|
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||||
|
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||||
|
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||||
|
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||||
|
// 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"`
|
||||||
|
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||||
|
PushWhitelistDeployKeys bool `json:"push_whitelist_deploy_keys"`
|
||||||
|
EnableMergeWhitelist bool `json:"enable_merge_whitelist"`
|
||||||
|
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||||
|
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||||
|
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"`
|
||||||
|
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||||
|
BlockOnRejectedReviews bool `json:"block_on_rejected_reviews"`
|
||||||
|
DismissStaleApprovals bool `json:"dismiss_stale_approvals"`
|
||||||
|
RequireSignedCommits bool `json:"require_signed_commits"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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"`
|
||||||
|
PushWhitelistTeams []string `json:"push_whitelist_teams"`
|
||||||
|
PushWhitelistDeployKeys *bool `json:"push_whitelist_deploy_keys"`
|
||||||
|
EnableMergeWhitelist *bool `json:"enable_merge_whitelist"`
|
||||||
|
MergeWhitelistUsernames []string `json:"merge_whitelist_usernames"`
|
||||||
|
MergeWhitelistTeams []string `json:"merge_whitelist_teams"`
|
||||||
|
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"`
|
||||||
|
ApprovalsWhitelistTeams []string `json:"approvals_whitelist_teams"`
|
||||||
|
BlockOnRejectedReviews *bool `json:"block_on_rejected_reviews"`
|
||||||
|
DismissStaleApprovals *bool `json:"dismiss_stale_approvals"`
|
||||||
|
RequireSignedCommits *bool `json:"require_signed_commits"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -656,6 +656,15 @@ func RegisterRoutes(m *macaron.Macaron) {
|
||||||
m.Get("", repo.ListBranches)
|
m.Get("", repo.ListBranches)
|
||||||
m.Get("/*", context.RepoRefByType(context.RepoRefBranch), repo.GetBranch)
|
m.Get("/*", context.RepoRefByType(context.RepoRefBranch), repo.GetBranch)
|
||||||
}, reqRepoReader(models.UnitTypeCode))
|
}, reqRepoReader(models.UnitTypeCode))
|
||||||
|
m.Group("/branch_protections", func() {
|
||||||
|
m.Get("", repo.ListBranchProtections)
|
||||||
|
m.Post("", bind(api.CreateBranchProtectionOption{}), repo.CreateBranchProtection)
|
||||||
|
m.Group("/:name", func() {
|
||||||
|
m.Get("", repo.GetBranchProtection)
|
||||||
|
m.Patch("", bind(api.EditBranchProtectionOption{}), repo.EditBranchProtection)
|
||||||
|
m.Delete("", repo.DeleteBranchProtection)
|
||||||
|
})
|
||||||
|
}, reqToken(), reqAdmin())
|
||||||
m.Group("/tags", func() {
|
m.Group("/tags", func() {
|
||||||
m.Get("", repo.ListTags)
|
m.Get("", repo.ListTags)
|
||||||
}, reqRepoReader(models.UnitTypeCode), context.ReferencesGitRepo(true))
|
}, reqRepoReader(models.UnitTypeCode), context.ReferencesGitRepo(true))
|
||||||
|
|
|
@ -8,6 +8,7 @@ package repo
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/context"
|
"code.gitea.io/gitea/modules/context"
|
||||||
"code.gitea.io/gitea/modules/convert"
|
"code.gitea.io/gitea/modules/convert"
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
@ -71,7 +72,7 @@ func GetBranch(ctx *context.APIContext) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.User))
|
ctx.JSON(http.StatusOK, convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.User, ctx.Repo.IsAdmin()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListBranches list all the branches of a repository
|
// ListBranches list all the branches of a repository
|
||||||
|
@ -114,8 +115,509 @@ func ListBranches(ctx *context.APIContext) {
|
||||||
ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err)
|
ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
apiBranches[i] = convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.User)
|
apiBranches[i] = convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.User, ctx.Repo.IsAdmin())
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.JSON(http.StatusOK, &apiBranches)
|
ctx.JSON(http.StatusOK, &apiBranches)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetBranchProtection gets a branch protection
|
||||||
|
func GetBranchProtection(ctx *context.APIContext) {
|
||||||
|
// swagger:operation GET /repos/{owner}/{repo}/branch_protections/{name} repository repoGetBranchProtection
|
||||||
|
// ---
|
||||||
|
// summary: Get a specific branch protection for the repository
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: owner
|
||||||
|
// in: path
|
||||||
|
// description: owner of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: repo
|
||||||
|
// in: path
|
||||||
|
// description: name of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: name
|
||||||
|
// in: path
|
||||||
|
// description: name of protected branch
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/BranchProtection"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
|
repo := ctx.Repo.Repository
|
||||||
|
bpName := ctx.Params(":name")
|
||||||
|
bp, err := models.GetProtectedBranchBy(repo.ID, bpName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetProtectedBranchByID", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if bp == nil || bp.RepoID != repo.ID {
|
||||||
|
ctx.NotFound()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, convert.ToBranchProtection(bp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ListBranchProtections list branch protections for a repo
|
||||||
|
func ListBranchProtections(ctx *context.APIContext) {
|
||||||
|
// swagger:operation GET /repos/{owner}/{repo}/branch_protections repository repoListBranchProtection
|
||||||
|
// ---
|
||||||
|
// summary: List branch protections for a repository
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: owner
|
||||||
|
// in: path
|
||||||
|
// description: owner of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: repo
|
||||||
|
// in: path
|
||||||
|
// description: name of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/BranchProtectionList"
|
||||||
|
|
||||||
|
repo := ctx.Repo.Repository
|
||||||
|
bps, err := repo.GetProtectedBranches()
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetProtectedBranches", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
apiBps := make([]*api.BranchProtection, len(bps))
|
||||||
|
for i := range bps {
|
||||||
|
apiBps[i] = convert.ToBranchProtection(bps[i])
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, apiBps)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateBranchProtection creates a branch protection for a repo
|
||||||
|
func CreateBranchProtection(ctx *context.APIContext, form api.CreateBranchProtectionOption) {
|
||||||
|
// swagger:operation POST /repos/{owner}/{repo}/branch_protections repository repoCreateBranchProtection
|
||||||
|
// ---
|
||||||
|
// summary: Create a branch protections for a repository
|
||||||
|
// consumes:
|
||||||
|
// - application/json
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: owner
|
||||||
|
// in: path
|
||||||
|
// description: owner of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: repo
|
||||||
|
// in: path
|
||||||
|
// description: name of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: body
|
||||||
|
// in: body
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/CreateBranchProtectionOption"
|
||||||
|
// responses:
|
||||||
|
// "201":
|
||||||
|
// "$ref": "#/responses/BranchProtection"
|
||||||
|
// "403":
|
||||||
|
// "$ref": "#/responses/forbidden"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
// "422":
|
||||||
|
// "$ref": "#/responses/validationError"
|
||||||
|
|
||||||
|
repo := ctx.Repo.Repository
|
||||||
|
|
||||||
|
// Currently protection must match an actual branch
|
||||||
|
if !git.IsBranchExist(ctx.Repo.Repository.RepoPath(), form.BranchName) {
|
||||||
|
ctx.NotFound()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
protectBranch, err := models.GetProtectedBranchBy(repo.ID, form.BranchName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetProtectBranchOfRepoByName", err)
|
||||||
|
return
|
||||||
|
} else if protectBranch != nil {
|
||||||
|
ctx.Error(http.StatusForbidden, "Create branch protection", "Branch protection already exist")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var requiredApprovals int64
|
||||||
|
if form.RequiredApprovals > 0 {
|
||||||
|
requiredApprovals = form.RequiredApprovals
|
||||||
|
}
|
||||||
|
|
||||||
|
whitelistUsers, err := models.GetUserIDsByNames(form.PushWhitelistUsernames, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrUserNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mergeWhitelistUsers, err := models.GetUserIDsByNames(form.MergeWhitelistUsernames, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrUserNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
approvalsWhitelistUsers, err := models.GetUserIDsByNames(form.ApprovalsWhitelistUsernames, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrUserNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var whitelistTeams, mergeWhitelistTeams, approvalsWhitelistTeams []int64
|
||||||
|
if repo.Owner.IsOrganization() {
|
||||||
|
whitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.PushWhitelistTeams, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrTeamNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mergeWhitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.MergeWhitelistTeams, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrTeamNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
approvalsWhitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.ApprovalsWhitelistTeams, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrTeamNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protectBranch = &models.ProtectedBranch{
|
||||||
|
RepoID: ctx.Repo.Repository.ID,
|
||||||
|
BranchName: form.BranchName,
|
||||||
|
CanPush: form.EnablePush,
|
||||||
|
EnableWhitelist: form.EnablePush && form.EnablePushWhitelist,
|
||||||
|
EnableMergeWhitelist: form.EnableMergeWhitelist,
|
||||||
|
WhitelistDeployKeys: form.EnablePush && form.EnablePushWhitelist && form.PushWhitelistDeployKeys,
|
||||||
|
EnableStatusCheck: form.EnableStatusCheck,
|
||||||
|
StatusCheckContexts: form.StatusCheckContexts,
|
||||||
|
EnableApprovalsWhitelist: form.EnableApprovalsWhitelist,
|
||||||
|
RequiredApprovals: requiredApprovals,
|
||||||
|
BlockOnRejectedReviews: form.BlockOnRejectedReviews,
|
||||||
|
DismissStaleApprovals: form.DismissStaleApprovals,
|
||||||
|
RequireSignedCommits: form.RequireSignedCommits,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.UpdateProtectBranch(ctx.Repo.Repository, protectBranch, models.WhitelistOptions{
|
||||||
|
UserIDs: whitelistUsers,
|
||||||
|
TeamIDs: whitelistTeams,
|
||||||
|
MergeUserIDs: mergeWhitelistUsers,
|
||||||
|
MergeTeamIDs: mergeWhitelistTeams,
|
||||||
|
ApprovalsUserIDs: approvalsWhitelistUsers,
|
||||||
|
ApprovalsTeamIDs: approvalsWhitelistTeams,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "UpdateProtectBranch", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload from db to get all whitelists
|
||||||
|
bp, err := models.GetProtectedBranchBy(ctx.Repo.Repository.ID, form.BranchName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetProtectedBranchByID", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if bp == nil || bp.RepoID != ctx.Repo.Repository.ID {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "New branch protection not found", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusCreated, convert.ToBranchProtection(bp))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// EditBranchProtection edits a branch protection for a repo
|
||||||
|
func EditBranchProtection(ctx *context.APIContext, form api.EditBranchProtectionOption) {
|
||||||
|
// swagger:operation PATCH /repos/{owner}/{repo}/branch_protections/{name} repository repoEditBranchProtection
|
||||||
|
// ---
|
||||||
|
// summary: Edit a branch protections for a repository. Only fields that are set will be changed
|
||||||
|
// consumes:
|
||||||
|
// - application/json
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: owner
|
||||||
|
// in: path
|
||||||
|
// description: owner of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: repo
|
||||||
|
// in: path
|
||||||
|
// description: name of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: name
|
||||||
|
// in: path
|
||||||
|
// description: name of protected branch
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: body
|
||||||
|
// in: body
|
||||||
|
// schema:
|
||||||
|
// "$ref": "#/definitions/EditBranchProtectionOption"
|
||||||
|
// responses:
|
||||||
|
// "200":
|
||||||
|
// "$ref": "#/responses/BranchProtection"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
// "422":
|
||||||
|
// "$ref": "#/responses/validationError"
|
||||||
|
|
||||||
|
repo := ctx.Repo.Repository
|
||||||
|
bpName := ctx.Params(":name")
|
||||||
|
protectBranch, err := models.GetProtectedBranchBy(repo.ID, bpName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetProtectedBranchByID", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if protectBranch == nil || protectBranch.RepoID != repo.ID {
|
||||||
|
ctx.NotFound()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if form.EnablePush != nil {
|
||||||
|
if !*form.EnablePush {
|
||||||
|
protectBranch.CanPush = false
|
||||||
|
protectBranch.EnableWhitelist = false
|
||||||
|
protectBranch.WhitelistDeployKeys = false
|
||||||
|
} else {
|
||||||
|
protectBranch.CanPush = true
|
||||||
|
if form.EnablePushWhitelist != nil {
|
||||||
|
if !*form.EnablePushWhitelist {
|
||||||
|
protectBranch.EnableWhitelist = false
|
||||||
|
protectBranch.WhitelistDeployKeys = false
|
||||||
|
} else {
|
||||||
|
protectBranch.EnableWhitelist = true
|
||||||
|
if form.PushWhitelistDeployKeys != nil {
|
||||||
|
protectBranch.WhitelistDeployKeys = *form.PushWhitelistDeployKeys
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if form.EnableMergeWhitelist != nil {
|
||||||
|
protectBranch.EnableMergeWhitelist = *form.EnableMergeWhitelist
|
||||||
|
}
|
||||||
|
|
||||||
|
if form.EnableStatusCheck != nil {
|
||||||
|
protectBranch.EnableStatusCheck = *form.EnableStatusCheck
|
||||||
|
}
|
||||||
|
if protectBranch.EnableStatusCheck {
|
||||||
|
protectBranch.StatusCheckContexts = form.StatusCheckContexts
|
||||||
|
}
|
||||||
|
|
||||||
|
if form.RequiredApprovals != nil && *form.RequiredApprovals >= 0 {
|
||||||
|
protectBranch.RequiredApprovals = *form.RequiredApprovals
|
||||||
|
}
|
||||||
|
|
||||||
|
if form.EnableApprovalsWhitelist != nil {
|
||||||
|
protectBranch.EnableApprovalsWhitelist = *form.EnableApprovalsWhitelist
|
||||||
|
}
|
||||||
|
|
||||||
|
if form.BlockOnRejectedReviews != nil {
|
||||||
|
protectBranch.BlockOnRejectedReviews = *form.BlockOnRejectedReviews
|
||||||
|
}
|
||||||
|
|
||||||
|
if form.DismissStaleApprovals != nil {
|
||||||
|
protectBranch.DismissStaleApprovals = *form.DismissStaleApprovals
|
||||||
|
}
|
||||||
|
|
||||||
|
if form.RequireSignedCommits != nil {
|
||||||
|
protectBranch.RequireSignedCommits = *form.RequireSignedCommits
|
||||||
|
}
|
||||||
|
|
||||||
|
var whitelistUsers []int64
|
||||||
|
if form.PushWhitelistUsernames != nil {
|
||||||
|
whitelistUsers, err = models.GetUserIDsByNames(form.PushWhitelistUsernames, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrUserNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
whitelistUsers = protectBranch.WhitelistUserIDs
|
||||||
|
}
|
||||||
|
var mergeWhitelistUsers []int64
|
||||||
|
if form.MergeWhitelistUsernames != nil {
|
||||||
|
mergeWhitelistUsers, err = models.GetUserIDsByNames(form.MergeWhitelistUsernames, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrUserNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mergeWhitelistUsers = protectBranch.MergeWhitelistUserIDs
|
||||||
|
}
|
||||||
|
var approvalsWhitelistUsers []int64
|
||||||
|
if form.ApprovalsWhitelistUsernames != nil {
|
||||||
|
approvalsWhitelistUsers, err = models.GetUserIDsByNames(form.ApprovalsWhitelistUsernames, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrUserNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "User does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetUserIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
approvalsWhitelistUsers = protectBranch.ApprovalsWhitelistUserIDs
|
||||||
|
}
|
||||||
|
|
||||||
|
var whitelistTeams, mergeWhitelistTeams, approvalsWhitelistTeams []int64
|
||||||
|
if repo.Owner.IsOrganization() {
|
||||||
|
if form.PushWhitelistTeams != nil {
|
||||||
|
whitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.PushWhitelistTeams, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrTeamNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
whitelistTeams = protectBranch.WhitelistTeamIDs
|
||||||
|
}
|
||||||
|
if form.MergeWhitelistTeams != nil {
|
||||||
|
mergeWhitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.MergeWhitelistTeams, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrTeamNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mergeWhitelistTeams = protectBranch.MergeWhitelistTeamIDs
|
||||||
|
}
|
||||||
|
if form.ApprovalsWhitelistTeams != nil {
|
||||||
|
approvalsWhitelistTeams, err = models.GetTeamIDsByNames(repo.OwnerID, form.ApprovalsWhitelistTeams, false)
|
||||||
|
if err != nil {
|
||||||
|
if models.IsErrTeamNotExist(err) {
|
||||||
|
ctx.Error(http.StatusUnprocessableEntity, "Team does not exist", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetTeamIDsByNames", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
approvalsWhitelistTeams = protectBranch.ApprovalsWhitelistTeamIDs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = models.UpdateProtectBranch(ctx.Repo.Repository, protectBranch, models.WhitelistOptions{
|
||||||
|
UserIDs: whitelistUsers,
|
||||||
|
TeamIDs: whitelistTeams,
|
||||||
|
MergeUserIDs: mergeWhitelistUsers,
|
||||||
|
MergeTeamIDs: mergeWhitelistTeams,
|
||||||
|
ApprovalsUserIDs: approvalsWhitelistUsers,
|
||||||
|
ApprovalsTeamIDs: approvalsWhitelistTeams,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "UpdateProtectBranch", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reload from db to ensure get all whitelists
|
||||||
|
bp, err := models.GetProtectedBranchBy(repo.ID, bpName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetProtectedBranchBy", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if bp == nil || bp.RepoID != ctx.Repo.Repository.ID {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "New branch protection not found", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.JSON(http.StatusOK, convert.ToBranchProtection(bp))
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeleteBranchProtection deletes a branch protection for a repo
|
||||||
|
func DeleteBranchProtection(ctx *context.APIContext) {
|
||||||
|
// swagger:operation DELETE /repos/{owner}/{repo}/branch_protections/{name} repository repoDeleteBranchProtection
|
||||||
|
// ---
|
||||||
|
// summary: Delete a specific branch protection for the repository
|
||||||
|
// produces:
|
||||||
|
// - application/json
|
||||||
|
// parameters:
|
||||||
|
// - name: owner
|
||||||
|
// in: path
|
||||||
|
// description: owner of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: repo
|
||||||
|
// in: path
|
||||||
|
// description: name of the repo
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// - name: name
|
||||||
|
// in: path
|
||||||
|
// description: name of protected branch
|
||||||
|
// type: string
|
||||||
|
// required: true
|
||||||
|
// responses:
|
||||||
|
// "204":
|
||||||
|
// "$ref": "#/responses/empty"
|
||||||
|
// "404":
|
||||||
|
// "$ref": "#/responses/notFound"
|
||||||
|
|
||||||
|
repo := ctx.Repo.Repository
|
||||||
|
bpName := ctx.Params(":name")
|
||||||
|
bp, err := models.GetProtectedBranchBy(repo.ID, bpName)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "GetProtectedBranchByID", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if bp == nil || bp.RepoID != repo.ID {
|
||||||
|
ctx.NotFound()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := ctx.Repo.Repository.DeleteProtectedBranch(bp.ID); err != nil {
|
||||||
|
ctx.Error(http.StatusInternalServerError, "DeleteProtectedBranch", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Status(http.StatusNoContent)
|
||||||
|
}
|
||||||
|
|
|
@ -128,4 +128,10 @@ type swaggerParameterBodies struct {
|
||||||
|
|
||||||
// in:body
|
// in:body
|
||||||
EditReactionOption api.EditReactionOption
|
EditReactionOption api.EditReactionOption
|
||||||
|
|
||||||
|
// in:body
|
||||||
|
CreateBranchProtectionOption api.CreateBranchProtectionOption
|
||||||
|
|
||||||
|
// in:body
|
||||||
|
EditBranchProtectionOption api.EditBranchProtectionOption
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,20 @@ type swaggerResponseBranchList struct {
|
||||||
Body []api.Branch `json:"body"`
|
Body []api.Branch `json:"body"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BranchProtection
|
||||||
|
// swagger:response BranchProtection
|
||||||
|
type swaggerResponseBranchProtection struct {
|
||||||
|
// in:body
|
||||||
|
Body api.BranchProtection `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// BranchProtectionList
|
||||||
|
// swagger:response BranchProtectionList
|
||||||
|
type swaggerResponseBranchProtectionList struct {
|
||||||
|
// in:body
|
||||||
|
Body []api.BranchProtection `json:"body"`
|
||||||
|
}
|
||||||
|
|
||||||
// TagList
|
// TagList
|
||||||
// swagger:response TagList
|
// swagger:response TagList
|
||||||
type swaggerResponseTagList struct {
|
type swaggerResponseTagList struct {
|
||||||
|
|
|
@ -1797,6 +1797,227 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/repos/{owner}/{repo}/branch_protections": {
|
||||||
|
"get": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"repository"
|
||||||
|
],
|
||||||
|
"summary": "List branch protections for a repository",
|
||||||
|
"operationId": "repoListBranchProtection",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "owner of the repo",
|
||||||
|
"name": "owner",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the repo",
|
||||||
|
"name": "repo",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/BranchProtectionList"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"post": {
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"repository"
|
||||||
|
],
|
||||||
|
"summary": "Create a branch protections for a repository",
|
||||||
|
"operationId": "repoCreateBranchProtection",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "owner of the repo",
|
||||||
|
"name": "owner",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the repo",
|
||||||
|
"name": "repo",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/CreateBranchProtectionOption"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"201": {
|
||||||
|
"$ref": "#/responses/BranchProtection"
|
||||||
|
},
|
||||||
|
"403": {
|
||||||
|
"$ref": "#/responses/forbidden"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"$ref": "#/responses/validationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/repos/{owner}/{repo}/branch_protections/{name}": {
|
||||||
|
"get": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"repository"
|
||||||
|
],
|
||||||
|
"summary": "Get a specific branch protection for the repository",
|
||||||
|
"operationId": "repoGetBranchProtection",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "owner of the repo",
|
||||||
|
"name": "owner",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the repo",
|
||||||
|
"name": "repo",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of protected branch",
|
||||||
|
"name": "name",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/BranchProtection"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delete": {
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"repository"
|
||||||
|
],
|
||||||
|
"summary": "Delete a specific branch protection for the repository",
|
||||||
|
"operationId": "repoDeleteBranchProtection",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "owner of the repo",
|
||||||
|
"name": "owner",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the repo",
|
||||||
|
"name": "repo",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of protected branch",
|
||||||
|
"name": "name",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"204": {
|
||||||
|
"$ref": "#/responses/empty"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"patch": {
|
||||||
|
"consumes": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"produces": [
|
||||||
|
"application/json"
|
||||||
|
],
|
||||||
|
"tags": [
|
||||||
|
"repository"
|
||||||
|
],
|
||||||
|
"summary": "Edit a branch protections for a repository. Only fields that are set will be changed",
|
||||||
|
"operationId": "repoEditBranchProtection",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "owner of the repo",
|
||||||
|
"name": "owner",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of the repo",
|
||||||
|
"name": "repo",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"description": "name of protected branch",
|
||||||
|
"name": "name",
|
||||||
|
"in": "path",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "body",
|
||||||
|
"in": "body",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/EditBranchProtectionOption"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"$ref": "#/responses/BranchProtection"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"$ref": "#/responses/notFound"
|
||||||
|
},
|
||||||
|
"422": {
|
||||||
|
"$ref": "#/responses/validationError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/repos/{owner}/{repo}/branches": {
|
"/repos/{owner}/{repo}/branches": {
|
||||||
"get": {
|
"get": {
|
||||||
"produces": [
|
"produces": [
|
||||||
|
@ -9394,6 +9615,10 @@
|
||||||
"commit": {
|
"commit": {
|
||||||
"$ref": "#/definitions/PayloadCommit"
|
"$ref": "#/definitions/PayloadCommit"
|
||||||
},
|
},
|
||||||
|
"effective_branch_protection_name": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "EffectiveBranchProtectionName"
|
||||||
|
},
|
||||||
"enable_status_check": {
|
"enable_status_check": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"x-go-name": "EnableStatusCheck"
|
"x-go-name": "EnableStatusCheck"
|
||||||
|
@ -9429,6 +9654,117 @@
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
|
"BranchProtection": {
|
||||||
|
"description": "BranchProtection represents a branch protection for a repository",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"approvals_whitelist_teams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "ApprovalsWhitelistTeams"
|
||||||
|
},
|
||||||
|
"approvals_whitelist_username": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "ApprovalsWhitelistUsernames"
|
||||||
|
},
|
||||||
|
"block_on_rejected_reviews": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "BlockOnRejectedReviews"
|
||||||
|
},
|
||||||
|
"branch_name": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "BranchName"
|
||||||
|
},
|
||||||
|
"created_at": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"x-go-name": "Created"
|
||||||
|
},
|
||||||
|
"dismiss_stale_approvals": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "DismissStaleApprovals"
|
||||||
|
},
|
||||||
|
"enable_approvals_whitelist": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnableApprovalsWhitelist"
|
||||||
|
},
|
||||||
|
"enable_merge_whitelist": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnableMergeWhitelist"
|
||||||
|
},
|
||||||
|
"enable_push": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnablePush"
|
||||||
|
},
|
||||||
|
"enable_push_whitelist": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnablePushWhitelist"
|
||||||
|
},
|
||||||
|
"enable_status_check": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnableStatusCheck"
|
||||||
|
},
|
||||||
|
"merge_whitelist_teams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "MergeWhitelistTeams"
|
||||||
|
},
|
||||||
|
"merge_whitelist_usernames": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "MergeWhitelistUsernames"
|
||||||
|
},
|
||||||
|
"push_whitelist_deploy_keys": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "PushWhitelistDeployKeys"
|
||||||
|
},
|
||||||
|
"push_whitelist_teams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "PushWhitelistTeams"
|
||||||
|
},
|
||||||
|
"push_whitelist_usernames": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "PushWhitelistUsernames"
|
||||||
|
},
|
||||||
|
"require_signed_commits": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "RequireSignedCommits"
|
||||||
|
},
|
||||||
|
"required_approvals": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"x-go-name": "RequiredApprovals"
|
||||||
|
},
|
||||||
|
"status_check_contexts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "StatusCheckContexts"
|
||||||
|
},
|
||||||
|
"updated_at": {
|
||||||
|
"type": "string",
|
||||||
|
"format": "date-time",
|
||||||
|
"x-go-name": "Updated"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
"Comment": {
|
"Comment": {
|
||||||
"description": "Comment represents a comment on a commit or issue",
|
"description": "Comment represents a comment on a commit or issue",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -9634,6 +9970,107 @@
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
|
"CreateBranchProtectionOption": {
|
||||||
|
"description": "CreateBranchProtectionOption options for creating a branch protection",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"approvals_whitelist_teams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "ApprovalsWhitelistTeams"
|
||||||
|
},
|
||||||
|
"approvals_whitelist_username": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "ApprovalsWhitelistUsernames"
|
||||||
|
},
|
||||||
|
"block_on_rejected_reviews": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "BlockOnRejectedReviews"
|
||||||
|
},
|
||||||
|
"branch_name": {
|
||||||
|
"type": "string",
|
||||||
|
"x-go-name": "BranchName"
|
||||||
|
},
|
||||||
|
"dismiss_stale_approvals": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "DismissStaleApprovals"
|
||||||
|
},
|
||||||
|
"enable_approvals_whitelist": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnableApprovalsWhitelist"
|
||||||
|
},
|
||||||
|
"enable_merge_whitelist": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnableMergeWhitelist"
|
||||||
|
},
|
||||||
|
"enable_push": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnablePush"
|
||||||
|
},
|
||||||
|
"enable_push_whitelist": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnablePushWhitelist"
|
||||||
|
},
|
||||||
|
"enable_status_check": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnableStatusCheck"
|
||||||
|
},
|
||||||
|
"merge_whitelist_teams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "MergeWhitelistTeams"
|
||||||
|
},
|
||||||
|
"merge_whitelist_usernames": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "MergeWhitelistUsernames"
|
||||||
|
},
|
||||||
|
"push_whitelist_deploy_keys": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "PushWhitelistDeployKeys"
|
||||||
|
},
|
||||||
|
"push_whitelist_teams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "PushWhitelistTeams"
|
||||||
|
},
|
||||||
|
"push_whitelist_usernames": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "PushWhitelistUsernames"
|
||||||
|
},
|
||||||
|
"require_signed_commits": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "RequireSignedCommits"
|
||||||
|
},
|
||||||
|
"required_approvals": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"x-go-name": "RequiredApprovals"
|
||||||
|
},
|
||||||
|
"status_check_contexts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "StatusCheckContexts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
"CreateEmailOption": {
|
"CreateEmailOption": {
|
||||||
"description": "CreateEmailOption options when creating email addresses",
|
"description": "CreateEmailOption options when creating email addresses",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -10318,6 +10755,103 @@
|
||||||
},
|
},
|
||||||
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
},
|
},
|
||||||
|
"EditBranchProtectionOption": {
|
||||||
|
"description": "EditBranchProtectionOption options for editing a branch protection",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"approvals_whitelist_teams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "ApprovalsWhitelistTeams"
|
||||||
|
},
|
||||||
|
"approvals_whitelist_username": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "ApprovalsWhitelistUsernames"
|
||||||
|
},
|
||||||
|
"block_on_rejected_reviews": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "BlockOnRejectedReviews"
|
||||||
|
},
|
||||||
|
"dismiss_stale_approvals": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "DismissStaleApprovals"
|
||||||
|
},
|
||||||
|
"enable_approvals_whitelist": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnableApprovalsWhitelist"
|
||||||
|
},
|
||||||
|
"enable_merge_whitelist": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnableMergeWhitelist"
|
||||||
|
},
|
||||||
|
"enable_push": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnablePush"
|
||||||
|
},
|
||||||
|
"enable_push_whitelist": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnablePushWhitelist"
|
||||||
|
},
|
||||||
|
"enable_status_check": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "EnableStatusCheck"
|
||||||
|
},
|
||||||
|
"merge_whitelist_teams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "MergeWhitelistTeams"
|
||||||
|
},
|
||||||
|
"merge_whitelist_usernames": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "MergeWhitelistUsernames"
|
||||||
|
},
|
||||||
|
"push_whitelist_deploy_keys": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "PushWhitelistDeployKeys"
|
||||||
|
},
|
||||||
|
"push_whitelist_teams": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "PushWhitelistTeams"
|
||||||
|
},
|
||||||
|
"push_whitelist_usernames": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "PushWhitelistUsernames"
|
||||||
|
},
|
||||||
|
"require_signed_commits": {
|
||||||
|
"type": "boolean",
|
||||||
|
"x-go-name": "RequireSignedCommits"
|
||||||
|
},
|
||||||
|
"required_approvals": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int64",
|
||||||
|
"x-go-name": "RequiredApprovals"
|
||||||
|
},
|
||||||
|
"status_check_contexts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"x-go-name": "StatusCheckContexts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"x-go-package": "code.gitea.io/gitea/modules/structs"
|
||||||
|
},
|
||||||
"EditDeadlineOption": {
|
"EditDeadlineOption": {
|
||||||
"description": "EditDeadlineOption options for creating a deadline",
|
"description": "EditDeadlineOption options for creating a deadline",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
|
@ -12880,6 +13414,21 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"BranchProtection": {
|
||||||
|
"description": "BranchProtection",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/definitions/BranchProtection"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"BranchProtectionList": {
|
||||||
|
"description": "BranchProtectionList",
|
||||||
|
"schema": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/BranchProtection"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Comment": {
|
"Comment": {
|
||||||
"description": "Comment",
|
"description": "Comment",
|
||||||
"schema": {
|
"schema": {
|
||||||
|
@ -13410,7 +13959,7 @@
|
||||||
"parameterBodies": {
|
"parameterBodies": {
|
||||||
"description": "parameterBodies",
|
"description": "parameterBodies",
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/definitions/EditReactionOption"
|
"$ref": "#/definitions/EditBranchProtectionOption"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"redirect": {
|
"redirect": {
|
||||||
|
|
Loading…
Reference in a new issue