]> source.dussan.org Git - gitea.git/commitdiff
Add checkbox to delete pull branch after successful merge (#16049)
authorJimmy Praet <jimmy.praet@telenet.be>
Mon, 12 Jul 2021 23:26:25 +0000 (01:26 +0200)
committerGitHub <noreply@github.com>
Mon, 12 Jul 2021 23:26:25 +0000 (01:26 +0200)
* Add checkbox to delete pull branch after successful merge

* Omit DeleteBranchAfterMerge field in json

* Log a warning instead of error when PR head branch deleted

* Add DefaultDeleteBranchAfterMerge to PullRequestConfig

* Add support for delete_branch_after_merge via API

* Fix for API: the branch should be deleted from the HEAD repo

If head and base repo are the same, reuse the already opened ctx.Repo.GitRepo

* Don't delegate to CleanupBranch, only reuse branch deletion code

CleanupBranch contains too much logic that has already been performed by the Merge

* Reuse gitrepo in MergePullRequest

Co-authored-by: Andrew Thornton <art27@cantab.net>
14 files changed:
models/repo_unit.go
modules/structs/repo.go
options/locale/locale_en-US.ini
routers/api/v1/repo/pull.go
routers/api/v1/repo/repo.go
routers/web/repo/pull.go
routers/web/repo/setting.go
services/forms/repo_form.go
services/pull/pull.go
services/pull/temp_repo.go
services/pull/update.go
templates/repo/issue/view_content/pull.tmpl
templates/repo/settings/options.tmpl
templates/swagger/v1_json.tmpl

index d8060d16a03c9e69603ee46fe70398eb1383b6ac..a12e056a7d5ad724dc11818b5109c334cef84144 100644 (file)
@@ -91,14 +91,15 @@ func (cfg *IssuesConfig) ToDB() ([]byte, error) {
 
 // PullRequestsConfig describes pull requests config
 type PullRequestsConfig struct {
-       IgnoreWhitespaceConflicts bool
-       AllowMerge                bool
-       AllowRebase               bool
-       AllowRebaseMerge          bool
-       AllowSquash               bool
-       AllowManualMerge          bool
-       AutodetectManualMerge     bool
-       DefaultMergeStyle         MergeStyle
+       IgnoreWhitespaceConflicts     bool
+       AllowMerge                    bool
+       AllowRebase                   bool
+       AllowRebaseMerge              bool
+       AllowSquash                   bool
+       AllowManualMerge              bool
+       AutodetectManualMerge         bool
+       DefaultDeleteBranchAfterMerge bool
+       DefaultMergeStyle             MergeStyle
 }
 
 // FromDB fills up a PullRequestsConfig from serialized format.
index cef864c0205bf29d21a36929c1a920523bbe6076..2089f4d69cd0ce0a9345e3af369ef8bb0c16d6d6 100644 (file)
@@ -172,6 +172,8 @@ type EditRepoOption struct {
        AllowManualMerge *bool `json:"allow_manual_merge,omitempty"`
        // either `true` to enable AutodetectManualMerge, or `false` to prevent it. `has_pull_requests` must be `true`, Note: In some special cases, misjudgments can occur.
        AutodetectManualMerge *bool `json:"autodetect_manual_merge,omitempty"`
+       // set to `true` to delete pr branch after merge by default
+       DefaultDeleteBranchAfterMerge *bool `json:"default_delete_branch_after_merge,omitempty"`
        // set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". `has_pull_requests` must be `true`.
        DefaultMergeStyle *string `json:"default_merge_style,omitempty"`
        // set to `true` to archive this repository.
index 191cb5de6764c2f1db1cb604974a5ef0f6a87d44..c0ea28172b38dbf05484a1474a84e76a3092ec03 100644 (file)
@@ -1664,6 +1664,7 @@ settings.pulls.allow_rebase_merge_commit = Enable Rebasing with explicit merge c
 settings.pulls.allow_squash_commits = Enable Squashing to Merge Commits
 settings.pulls.allow_manual_merge = Enable Mark PR as manually merged
 settings.pulls.enable_autodetect_manual_merge = Enable autodetect manual merge (Note: In some special cases, misjudgments can occur)
+settings.pulls.default_delete_branch_after_merge = Delete pull request branch after merge by default
 settings.projects_desc = Enable Repository Projects
 settings.admin_settings = Administrator Settings
 settings.admin_enable_health_check = Enable Repository Health Checks (git fsck)
index 0c09a9a86b0ee12306c359ee8305f1f3fb938983..66bcabfd38c41dec8a771071bb997dadcd963e6c 100644 (file)
@@ -5,6 +5,7 @@
 package repo
 
 import (
+       "errors"
        "fmt"
        "math"
        "net/http"
@@ -25,6 +26,7 @@ import (
        "code.gitea.io/gitea/services/forms"
        issue_service "code.gitea.io/gitea/services/issue"
        pull_service "code.gitea.io/gitea/services/pull"
+       repo_service "code.gitea.io/gitea/services/repository"
 )
 
 // ListPullRequests returns a list of all PRs
@@ -878,6 +880,38 @@ func MergePullRequest(ctx *context.APIContext) {
        }
 
        log.Trace("Pull request merged: %d", pr.ID)
+
+       if form.DeleteBranchAfterMerge {
+               var headRepo *git.Repository
+               if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil {
+                       headRepo = ctx.Repo.GitRepo
+               } else {
+                       headRepo, err = git.OpenRepository(pr.HeadRepo.RepoPath())
+                       if err != nil {
+                               ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err)
+                               return
+                       }
+                       defer headRepo.Close()
+               }
+               if err := repo_service.DeleteBranch(ctx.User, pr.HeadRepo, headRepo, pr.HeadBranch); err != nil {
+                       switch {
+                       case git.IsErrBranchNotExist(err):
+                               ctx.NotFound(err)
+                       case errors.Is(err, repo_service.ErrBranchIsDefault):
+                               ctx.Error(http.StatusForbidden, "DefaultBranch", fmt.Errorf("can not delete default branch"))
+                       case errors.Is(err, repo_service.ErrBranchIsProtected):
+                               ctx.Error(http.StatusForbidden, "IsProtectedBranch", fmt.Errorf("branch protected"))
+                       default:
+                               ctx.Error(http.StatusInternalServerError, "DeleteBranch", err)
+                       }
+                       return
+               }
+               if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, pr.Issue.ID, pr.HeadBranch); err != nil {
+                       // Do not fail here as branch has already been deleted
+                       log.Error("DeleteBranch: %v", err)
+               }
+       }
+
        ctx.Status(http.StatusOK)
 }
 
index 5d397191a61387e8bbf6056e91d1bb26c3ff42d9..77691b4d1561b15ffb750263a72e762db45e0277 100644 (file)
@@ -833,14 +833,15 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
                        if err != nil {
                                // Unit type doesn't exist so we make a new config file with default values
                                config = &models.PullRequestsConfig{
-                                       IgnoreWhitespaceConflicts: false,
-                                       AllowMerge:                true,
-                                       AllowRebase:               true,
-                                       AllowRebaseMerge:          true,
-                                       AllowSquash:               true,
-                                       AllowManualMerge:          true,
-                                       AutodetectManualMerge:     false,
-                                       DefaultMergeStyle:         models.MergeStyleMerge,
+                                       IgnoreWhitespaceConflicts:     false,
+                                       AllowMerge:                    true,
+                                       AllowRebase:                   true,
+                                       AllowRebaseMerge:              true,
+                                       AllowSquash:                   true,
+                                       AllowManualMerge:              true,
+                                       AutodetectManualMerge:         false,
+                                       DefaultDeleteBranchAfterMerge: false,
+                                       DefaultMergeStyle:             models.MergeStyleMerge,
                                }
                        } else {
                                config = unit.PullRequestsConfig()
@@ -867,6 +868,9 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error {
                        if opts.AutodetectManualMerge != nil {
                                config.AutodetectManualMerge = *opts.AutodetectManualMerge
                        }
+                       if opts.DefaultDeleteBranchAfterMerge != nil {
+                               config.DefaultDeleteBranchAfterMerge = *opts.DefaultDeleteBranchAfterMerge
+                       }
                        if opts.DefaultMergeStyle != nil {
                                config.DefaultMergeStyle = models.MergeStyle(*opts.DefaultMergeStyle)
                        }
index e5554e966444468c2680cf5bdba3852835f025e3..a299799647777441a0a2bac16709d0917b14c084 100644 (file)
@@ -965,6 +965,22 @@ func MergePullRequest(ctx *context.Context) {
        }
 
        log.Trace("Pull request merged: %d", pr.ID)
+
+       if form.DeleteBranchAfterMerge {
+               var headRepo *git.Repository
+               if ctx.Repo != nil && ctx.Repo.Repository != nil && pr.HeadRepoID == ctx.Repo.Repository.ID && ctx.Repo.GitRepo != nil {
+                       headRepo = ctx.Repo.GitRepo
+               } else {
+                       headRepo, err = git.OpenRepository(pr.HeadRepo.RepoPath())
+                       if err != nil {
+                               ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err)
+                               return
+                       }
+                       defer headRepo.Close()
+               }
+               deleteBranch(ctx, pr, headRepo)
+       }
+
        ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index))
 }
 
@@ -1170,19 +1186,35 @@ func CleanUpPullRequest(ctx *context.Context) {
 
        fullBranchName := pr.HeadRepo.Owner.Name + "/" + pr.HeadBranch
 
-       gitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath())
-       if err != nil {
-               ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err)
-               return
+       var gitBaseRepo *git.Repository
+
+       // Assume that the base repo is the current context (almost certainly)
+       if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.BaseRepoID && ctx.Repo.GitRepo != nil {
+               gitBaseRepo = ctx.Repo.GitRepo
+       } else {
+               // If not just open it
+               gitBaseRepo, err = git.OpenRepository(pr.BaseRepo.RepoPath())
+               if err != nil {
+                       ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.BaseRepo.RepoPath()), err)
+                       return
+               }
+               defer gitBaseRepo.Close()
        }
-       defer gitRepo.Close()
 
-       gitBaseRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath())
-       if err != nil {
-               ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.BaseRepo.RepoPath()), err)
-               return
+       // Now assume that the head repo is the same as the base repo (reasonable chance)
+       gitRepo := gitBaseRepo
+       // But if not: is it the same as the context?
+       if pr.BaseRepoID != pr.HeadRepoID && ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil {
+               gitRepo = ctx.Repo.GitRepo
+       } else if pr.BaseRepoID != pr.HeadRepoID {
+               // Otherwise just load it up
+               gitRepo, err = git.OpenRepository(pr.HeadRepo.RepoPath())
+               if err != nil {
+                       ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err)
+                       return
+               }
+               defer gitRepo.Close()
        }
-       defer gitBaseRepo.Close()
 
        defer func() {
                ctx.JSON(http.StatusOK, map[string]interface{}{
@@ -1208,6 +1240,11 @@ func CleanUpPullRequest(ctx *context.Context) {
                return
        }
 
+       deleteBranch(ctx, pr, gitRepo)
+}
+
+func deleteBranch(ctx *context.Context, pr *models.PullRequest, gitRepo *git.Repository) {
+       fullBranchName := pr.HeadRepo.Owner.Name + "/" + pr.HeadBranch
        if err := repo_service.DeleteBranch(ctx.User, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil {
                switch {
                case git.IsErrBranchNotExist(err):
@@ -1223,7 +1260,7 @@ func CleanUpPullRequest(ctx *context.Context) {
                return
        }
 
-       if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, issue.ID, pr.HeadBranch); err != nil {
+       if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, pr.IssueID, pr.HeadBranch); err != nil {
                // Do not fail here as branch has already been deleted
                log.Error("DeleteBranch: %v", err)
        }
index 5e8c2c527625147a82781731a6fba05321fc46aa..0a84f15bf0bff8e59f655c0686c23a978dfa6d63 100644 (file)
@@ -416,14 +416,15 @@ func SettingsPost(ctx *context.Context) {
                                RepoID: repo.ID,
                                Type:   models.UnitTypePullRequests,
                                Config: &models.PullRequestsConfig{
-                                       IgnoreWhitespaceConflicts: form.PullsIgnoreWhitespace,
-                                       AllowMerge:                form.PullsAllowMerge,
-                                       AllowRebase:               form.PullsAllowRebase,
-                                       AllowRebaseMerge:          form.PullsAllowRebaseMerge,
-                                       AllowSquash:               form.PullsAllowSquash,
-                                       AllowManualMerge:          form.PullsAllowManualMerge,
-                                       AutodetectManualMerge:     form.EnableAutodetectManualMerge,
-                                       DefaultMergeStyle:         models.MergeStyle(form.PullsDefaultMergeStyle),
+                                       IgnoreWhitespaceConflicts:     form.PullsIgnoreWhitespace,
+                                       AllowMerge:                    form.PullsAllowMerge,
+                                       AllowRebase:                   form.PullsAllowRebase,
+                                       AllowRebaseMerge:              form.PullsAllowRebaseMerge,
+                                       AllowSquash:                   form.PullsAllowSquash,
+                                       AllowManualMerge:              form.PullsAllowManualMerge,
+                                       AutodetectManualMerge:         form.EnableAutodetectManualMerge,
+                                       DefaultDeleteBranchAfterMerge: form.DefaultDeleteBranchAfterMerge,
+                                       DefaultMergeStyle:             models.MergeStyle(form.PullsDefaultMergeStyle),
                                },
                        })
                } else if !models.UnitTypePullRequests.UnitGlobalDisabled() {
index 71a83a8be36e2eea53267d364084f25af0a7075b..7c79c4dc21eb0bbe64927b5fea32d434a4248b4e 100644 (file)
@@ -151,6 +151,7 @@ type RepoSettingForm struct {
        PullsAllowManualMerge                 bool
        PullsDefaultMergeStyle                string
        EnableAutodetectManualMerge           bool
+       DefaultDeleteBranchAfterMerge         bool
        EnableTimetracker                     bool
        AllowOnlyContributorsToTrackTime      bool
        EnableIssueDependencies               bool
@@ -551,11 +552,12 @@ func (f *InitializeLabelsForm) Validate(req *http.Request, errs binding.Errors)
 type MergePullRequestForm struct {
        // required: true
        // enum: merge,rebase,rebase-merge,squash,manually-merged
-       Do                string `binding:"Required;In(merge,rebase,rebase-merge,squash,manually-merged)"`
-       MergeTitleField   string
-       MergeMessageField string
-       MergeCommitID     string // only used for manually-merged
-       ForceMerge        *bool  `json:"force_merge,omitempty"`
+       Do                     string `binding:"Required;In(merge,rebase,rebase-merge,squash,manually-merged)"`
+       MergeTitleField        string
+       MergeMessageField      string
+       MergeCommitID          string // only used for manually-merged
+       ForceMerge             *bool  `json:"force_merge,omitempty"`
+       DeleteBranchAfterMerge bool   `json:"delete_branch_after_merge,omitempty"`
 }
 
 // Validate validates the fields
index db216ddbf4556f69ee3dd0c11a89d025570a7372..6b3acd2004254680c78e274013ec0c42feaabc91 100644 (file)
@@ -303,7 +303,11 @@ func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSy
                for _, pr := range prs {
                        divergence, err := GetDiverging(pr)
                        if err != nil {
-                               log.Error("GetDiverging: %v", err)
+                               if models.IsErrBranchDoesNotExist(err) && !git.IsBranchExist(pr.HeadRepo.RepoPath(), pr.HeadBranch) {
+                                       log.Warn("Cannot test PR %s/%d: head_branch %s no longer exists", pr.BaseRepo.Name, pr.IssueID, pr.HeadBranch)
+                               } else {
+                                       log.Error("GetDiverging: %v", err)
+                               }
                        } else {
                                err = pr.UpdateCommitDivergence(divergence.Ahead, divergence.Behind)
                                if err != nil {
index 45cd10b65bbe498fea95308402e2004a820768b8..19b488790a0cef054f50a23de93c7e0c0862ea28 100644 (file)
@@ -141,10 +141,15 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) {
        trackingBranch := "tracking"
        // Fetch head branch
        if err := git.NewCommand("fetch", "--no-tags", remoteRepoName, git.BranchPrefix+pr.HeadBranch+":"+trackingBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil {
-               log.Error("Unable to fetch head_repo head branch [%s:%s -> tracking in %s]: %v:\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, tmpBasePath, err, outbuf.String(), errbuf.String())
                if err := models.RemoveTemporaryPath(tmpBasePath); err != nil {
                        log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err)
                }
+               if !git.IsBranchExist(pr.HeadRepo.RepoPath(), pr.HeadBranch) {
+                       return "", models.ErrBranchDoesNotExist{
+                               BranchName: pr.HeadBranch,
+                       }
+               }
+               log.Error("Unable to fetch head_repo head branch [%s:%s -> tracking in %s]: %v:\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, tmpBasePath, err, outbuf.String(), errbuf.String())
                return "", fmt.Errorf("Unable to fetch head_repo head branch [%s:%s -> tracking in tmpBasePath]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, err, outbuf.String(), errbuf.String())
        }
        outbuf.Reset()
index f4f7859a49ec1b7d5de2897c4f3d851c1c822d40..f35e47cbf820a5c7acae10aa4246ce8ed7b66378 100644 (file)
@@ -88,7 +88,9 @@ func GetDiverging(pr *models.PullRequest) (*git.DivergeObject, error) {
 
        tmpRepo, err := createTemporaryRepo(pr)
        if err != nil {
-               log.Error("CreateTemporaryPath: %v", err)
+               if !models.IsErrBranchDoesNotExist(err) {
+                       log.Error("CreateTemporaryRepo: %v", err)
+               }
                return nil, err
        }
        defer func() {
index 3bdec4becb02e2f0debdafb346c7422588b2aefd..fcb3597ae866ac16a0fabfa843cec4f800bdb7f9 100644 (file)
                                                                        <button class="ui button merge-cancel">
                                                                                {{$.i18n.Tr "cancel"}}
                                                                        </button>
+                                                                       {{if .IsPullBranchDeletable}}
+                                                                               <div class="ui checkbox ml-2">
+                                                                                       <input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}>
+                                                                                       <label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label>
+                                                                               </div>
+                                                                       {{end}}
                                                                </form>
                                                        </div>
                                                        {{end}}
                                                                        <button class="ui button merge-cancel">
                                                                                {{$.i18n.Tr "cancel"}}
                                                                        </button>
+                                                                       {{if .IsPullBranchDeletable}}
+                                                                               <div class="ui checkbox ml-2">
+                                                                                       <input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}>
+                                                                                       <label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label>
+                                                                               </div>
+                                                                       {{end}}
                                                                </form>
                                                        </div>
                                                        {{end}}
                                                                        <button class="ui button merge-cancel">
                                                                                {{$.i18n.Tr "cancel"}}
                                                                        </button>
+                                                                       {{if .IsPullBranchDeletable}}
+                                                                               <div class="ui checkbox ml-2">
+                                                                                       <input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}>
+                                                                                       <label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label>
+                                                                               </div>
+                                                                       {{end}}
                                                                </form>
                                                        </div>
                                                        {{end}}
                                                                        <button class="ui button merge-cancel">
                                                                                {{$.i18n.Tr "cancel"}}
                                                                        </button>
+                                                                       {{if .IsPullBranchDeletable}}
+                                                                               <div class="ui checkbox ml-2">
+                                                                                       <input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}>
+                                                                                       <label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label>
+                                                                               </div>
+                                                                       {{end}}
                                                                </form>
                                                        </div>
                                                        {{end}}
                                                                                <button class="ui button merge-cancel">
                                                                                        {{$.i18n.Tr "cancel"}}
                                                                                </button>
+                                                                               {{if .IsPullBranchDeletable}}
+                                                                                       <div class="ui checkbox ml-2">
+                                                                                               <input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}>
+                                                                                               <label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label>
+                                                                                       </div>
+                                                                               {{end}}
                                                                        </form>
                                                                </div>
                                                        {{end}}
index eb76a3b7200643a97ea4dc03a9b3278cabf658e6..054df7c36899cfd4d6f8491a43e3bb868ad63f52 100644 (file)
                                                                <label>{{.i18n.Tr "repo.settings.pulls.enable_autodetect_manual_merge"}}</label>
                                                        </div>
                                                </div>
+                                               <div class="field">
+                                                       <div class="ui checkbox">
+                                                               <input name="default_delete_branch_after_merge" type="checkbox" {{if or (not $pullRequestEnabled) ($prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge)}}checked{{end}}>
+                                                               <label>{{.i18n.Tr "repo.settings.pulls.default_delete_branch_after_merge"}}</label>
+                                                       </div>
+                                               </div>
                                                <div class="field">
                                                        <p>
                                                                {{.i18n.Tr "repo.settings.default_merge_style_desc"}}
index 669e3552cc5dec46744ab3daf52389e8fa50f316..de61b9dd293770dbb813d3e8103b324021c5c48b 100644 (file)
           "type": "string",
           "x-go-name": "DefaultBranch"
         },
+        "default_delete_branch_after_merge": {
+          "description": "set to `true` to delete pr branch after merge by default",
+          "type": "boolean",
+          "x-go-name": "DefaultDeleteBranchAfterMerge"
+        },
         "default_merge_style": {
           "description": "set to a merge style to be used by this repository: \"merge\", \"rebase\", \"rebase-merge\", or \"squash\". `has_pull_requests` must be `true`.",
           "type": "string",
         "MergeTitleField": {
           "type": "string"
         },
+        "delete_branch_after_merge": {
+          "type": "boolean",
+          "x-go-name": "DeleteBranchAfterMerge"
+        },
         "force_merge": {
           "type": "boolean",
           "x-go-name": "ForceMerge"