summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--integrations/api_branch_test.go68
-rw-r--r--models/org_team.go33
-rw-r--r--models/user.go11
-rw-r--r--modules/convert/convert.go92
-rw-r--r--modules/structs/repo_branch.go90
-rw-r--r--routers/api/v1/api.go9
-rw-r--r--routers/api/v1/repo/branch.go506
-rw-r--r--routers/api/v1/swagger/options.go6
-rw-r--r--routers/api/v1/swagger/repo.go14
-rw-r--r--templates/swagger/v1_json.tmpl551
10 files changed, 1352 insertions, 28 deletions
diff --git a/integrations/api_branch_test.go b/integrations/api_branch_test.go
index 037a42deec..3fe7f23229 100644
--- a/integrations/api_branch_test.go
+++ b/integrations/api_branch_test.go
@@ -30,6 +30,54 @@ func testAPIGetBranch(t *testing.T, branchName string, exists bool) {
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) {
for _, test := range []struct {
BranchName string
@@ -43,3 +91,23 @@ func TestAPIGetBranch(t *testing.T) {
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)
+}
diff --git a/models/org_team.go b/models/org_team.go
index 214790703c..f8013d12c6 100644
--- a/models/org_team.go
+++ b/models/org_team.go
@@ -553,6 +553,23 @@ func GetTeam(orgID int64, name string) (*Team, error) {
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.
func getOwnerTeam(e Engine, orgID int64) (*Team, error) {
return getTeam(e, orgID, ownerTeamName)
@@ -574,6 +591,22 @@ func GetTeamByID(teamID int64) (*Team, error) {
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.
func UpdateTeam(t *Team, authChanged bool, includeAllChanged bool) (err error) {
if len(t.Name) == 0 {
diff --git a/models/user.go b/models/user.go
index 220a9f9a9a..0e493dbef7 100644
--- a/models/user.go
+++ b/models/user.go
@@ -1386,6 +1386,17 @@ 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) {
+ 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.
func GetUsersByIDs(ids []int64) ([]*User, error) {
ous := make([]*User, 0, len(ids))
diff --git a/modules/convert/convert.go b/modules/convert/convert.go
index a69b09a2b7..31b46bc7eb 100644
--- a/modules/convert/convert.go
+++ b/modules/convert/convert.go
@@ -30,28 +30,86 @@ 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: "",
}
}
+ branchProtectionName := ""
+ if isRepoAdmin {
+ branchProtectionName = bp.BranchName
+ }
+
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.IsUserMergeWhitelisted(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.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(),
}
}
diff --git a/modules/structs/repo_branch.go b/modules/structs/repo_branch.go
index 42bb763893..f8c9290548 100644
--- a/modules/structs/repo_branch.go
+++ b/modules/structs/repo_branch.go
@@ -4,14 +4,88 @@
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"`
+}
+
+// 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"`
}
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index 0a352f6e46..0ddf57b743 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -656,6 +656,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("/:name", func() {
+ m.Get("", repo.GetBranchProtection)
+ m.Patch("", bind(api.EditBranchProtectionOption{}), repo.EditBranchProtection)
+ m.Delete("", repo.DeleteBranchProtection)
+ })
+ }, reqToken(), reqAdmin())
m.Group("/tags", func() {
m.Get("", repo.ListTags)
}, reqRepoReader(models.UnitTypeCode), context.ReferencesGitRepo(true))
diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go
index 8f8ca15877..fccfc2bfe1 100644
--- a/routers/api/v1/repo/branch.go
+++ b/routers/api/v1/repo/branch.go
@@ -8,6 +8,7 @@ package repo
import (
"net/http"
+ "code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/convert"
"code.gitea.io/gitea/modules/git"
@@ -71,7 +72,7 @@ func GetBranch(ctx *context.APIContext) {
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
@@ -114,8 +115,509 @@ func ListBranches(ctx *context.APIContext) {
ctx.Error(http.StatusInternalServerError, "GetBranchProtection", err)
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)
}
+
+// 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)
+}
diff --git a/routers/api/v1/swagger/options.go b/routers/api/v1/swagger/options.go
index ab697811d0..679b4aa708 100644
--- a/routers/api/v1/swagger/options.go
+++ b/routers/api/v1/swagger/options.go
@@ -128,4 +128,10 @@ type swaggerParameterBodies struct {
// in:body
EditReactionOption api.EditReactionOption
+
+ // in:body
+ CreateBranchProtectionOption api.CreateBranchProtectionOption
+
+ // in:body
+ EditBranchProtectionOption api.EditBranchProtectionOption
}
diff --git a/routers/api/v1/swagger/repo.go b/routers/api/v1/swagger/repo.go
index 4ac5c6d2d5..2a657f3122 100644
--- a/routers/api/v1/swagger/repo.go
+++ b/routers/api/v1/swagger/repo.go
@@ -36,6 +36,20 @@ type swaggerResponseBranchList struct {
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
// swagger:response TagList
type swaggerResponseTagList struct {
diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl
index e6a5189928..b52145a0a9 100644
--- a/templates/swagger/v1_json.tmpl
+++ b/templates/swagger/v1_json.tmpl
@@ -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": {
"get": {
"produces": [
@@ -9394,6 +9615,10 @@
"commit": {
"$ref": "#/definitions/PayloadCommit"
},
+ "effective_branch_protection_name": {
+ "type": "string",
+ "x-go-name": "EffectiveBranchProtectionName"
+ },
"enable_status_check": {
"type": "boolean",
"x-go-name": "EnableStatusCheck"
@@ -9429,6 +9654,117 @@
},
"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": {
"description": "Comment represents a comment on a commit or issue",
"type": "object",
@@ -9634,6 +9970,107 @@
},
"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": {
"description": "CreateEmailOption options when creating email addresses",
"type": "object",
@@ -10318,6 +10755,103 @@
},
"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": {
"description": "EditDeadlineOption options for creating a deadline",
"type": "object",
@@ -12880,6 +13414,21 @@
}
}
},
+ "BranchProtection": {
+ "description": "BranchProtection",
+ "schema": {
+ "$ref": "#/definitions/BranchProtection"
+ }
+ },
+ "BranchProtectionList": {
+ "description": "BranchProtectionList",
+ "schema": {
+ "type": "array",
+ "items": {
+ "$ref": "#/definitions/BranchProtection"
+ }
+ }
+ },
"Comment": {
"description": "Comment",
"schema": {
@@ -13410,7 +13959,7 @@
"parameterBodies": {
"description": "parameterBodies",
"schema": {
- "$ref": "#/definitions/EditReactionOption"
+ "$ref": "#/definitions/EditBranchProtectionOption"
}
},
"redirect": {