From 86cff86b46116353e4d6605ccf5a77a7ac65bc78 Mon Sep 17 00:00:00 2001 From: David Svantesson Date: Sat, 16 Nov 2019 20:39:18 +0100 Subject: [PATCH] Update branch API endpoint to show effective branch protection. (#9031) * Add API endpoint for displaying effective branch protection. * Add status checks. --- models/branches.go | 5 +++++ modules/convert/convert.go | 24 +++++++++++++++++++++--- modules/structs/repo_branch.go | 10 ++++++++-- routers/api/v1/repo/branch.go | 17 ++++++++++++++--- templates/swagger/v1_json.tmpl | 30 +++++++++++++++++++++++++++++- 5 files changed, 77 insertions(+), 9 deletions(-) diff --git a/models/branches.go b/models/branches.go index c5f227f1e..46670b18a 100644 --- a/models/branches.go +++ b/models/branches.go @@ -242,6 +242,11 @@ func (repo *Repository) GetProtectedBranches() ([]*ProtectedBranch, error) { return protectedBranches, x.Find(&protectedBranches, &ProtectedBranch{RepoID: repo.ID}) } +// GetBranchProtection get the branch protection of a branch +func (repo *Repository) GetBranchProtection(branchName string) (*ProtectedBranch, error) { + return GetProtectedBranchBy(repo.ID, branchName) +} + // IsProtectedBranch checks if branch is protected func (repo *Repository) IsProtectedBranch(branchName string, doer *User) (bool, error) { if doer == nil { diff --git a/modules/convert/convert.go b/modules/convert/convert.go index f52ed6347..f65e4b4fe 100644 --- a/modules/convert/convert.go +++ b/modules/convert/convert.go @@ -30,10 +30,28 @@ 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) *api.Branch { +func ToBranch(repo *models.Repository, b *git.Branch, c *git.Commit, bp *models.ProtectedBranch, user *models.User) *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, + } + } return &api.Branch{ - Name: b.Name, - Commit: ToCommit(repo, c), + Name: b.Name, + Commit: ToCommit(repo, c), + Protected: true, + RequiredApprovals: bp.RequiredApprovals, + EnableStatusCheck: bp.EnableStatusCheck, + StatusCheckContexts: bp.StatusCheckContexts, + UserCanPush: bp.CanUserPush(user.ID), + UserCanMerge: bp.CanUserMerge(user.ID), } } diff --git a/modules/structs/repo_branch.go b/modules/structs/repo_branch.go index a6ae6c166..42bb76389 100644 --- a/modules/structs/repo_branch.go +++ b/modules/structs/repo_branch.go @@ -6,6 +6,12 @@ package structs // Branch represents a repository branch type Branch struct { - Name string `json:"name"` - Commit *PayloadCommit `json:"commit"` + 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"` } diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 9f6a2e629..9745903a9 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -16,7 +16,7 @@ import ( func GetBranch(ctx *context.APIContext) { // swagger:operation GET /repos/{owner}/{repo}/branches/{branch} repository repoGetBranch // --- - // summary: Retrieve a specific branch from a repository + // summary: Retrieve a specific branch from a repository, including its effective branch protection // produces: // - application/json // parameters: @@ -61,7 +61,13 @@ func GetBranch(ctx *context.APIContext) { return } - ctx.JSON(200, convert.ToBranch(ctx.Repo.Repository, branch, c)) + branchProtection, err := ctx.Repo.Repository.GetBranchProtection(ctx.Repo.BranchName) + if err != nil { + ctx.Error(500, "GetBranchProtection", err) + return + } + + ctx.JSON(200, convert.ToBranch(ctx.Repo.Repository, branch, c, branchProtection, ctx.User)) } // ListBranches list all the branches of a repository @@ -98,7 +104,12 @@ func ListBranches(ctx *context.APIContext) { ctx.Error(500, "GetCommit", err) return } - apiBranches[i] = convert.ToBranch(ctx.Repo.Repository, branches[i], c) + branchProtection, err := ctx.Repo.Repository.GetBranchProtection(branches[i].Name) + if err != nil { + ctx.Error(500, "GetBranchProtection", err) + return + } + apiBranches[i] = convert.ToBranch(ctx.Repo.Repository, branches[i], c, branchProtection, ctx.User) } ctx.JSON(200, &apiBranches) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index bebe85246..6b424131c 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -1492,7 +1492,7 @@ "tags": [ "repository" ], - "summary": "Retrieve a specific branch from a repository", + "summary": "Retrieve a specific branch from a repository, including its effective branch protection", "operationId": "repoGetBranch", "parameters": [ { @@ -7583,9 +7583,37 @@ "commit": { "$ref": "#/definitions/PayloadCommit" }, + "enable_status_check": { + "type": "boolean", + "x-go-name": "EnableStatusCheck" + }, "name": { "type": "string", "x-go-name": "Name" + }, + "protected": { + "type": "boolean", + "x-go-name": "Protected" + }, + "required_approvals": { + "type": "integer", + "format": "int64", + "x-go-name": "RequiredApprovals" + }, + "status_check_contexts": { + "type": "array", + "items": { + "type": "string" + }, + "x-go-name": "StatusCheckContexts" + }, + "user_can_merge": { + "type": "boolean", + "x-go-name": "UserCanMerge" + }, + "user_can_push": { + "type": "boolean", + "x-go-name": "UserCanPush" } }, "x-go-package": "code.gitea.io/gitea/modules/structs"