Skip to content
This repository was archived by the owner on Oct 6, 2021. It is now read-only.

Commit 1471c1f

Browse files
committed
Add delete source branch on merge.
This is based on an abandoned PR (runatlantis#1189) from Zack Arnold (zparnold).
1 parent d5a6f46 commit 1471c1f

File tree

12 files changed

+327
-49
lines changed

12 files changed

+327
-49
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ require (
2828
github.com/hashicorp/terraform-config-inspect v0.0.0-20200806211835-c481b8bfa41e
2929
github.com/inconshreveable/mousetrap v1.0.0 // indirect
3030
github.com/leodido/go-urn v1.2.0 // indirect
31-
github.com/mcdafydd/go-azuredevops v0.11.1
31+
github.com/mcdafydd/go-azuredevops v0.11.2
3232
github.com/microcosm-cc/bluemonday v1.0.1
3333
github.com/mitchellh/colorstring v0.0.0-20150917214807-8631ce90f286
3434
github.com/mitchellh/go-homedir v1.0.0

go.sum

+3
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0
219219
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
220220
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
221221
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
222+
github.com/magiconair/properties v1.7.3/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
222223
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
223224
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
224225
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
@@ -230,6 +231,8 @@ github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
230231
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
231232
github.com/mcdafydd/go-azuredevops v0.11.1 h1:NO4wlkyFpdxqZZzNzn5m3fJc4box0jnkC8LBhAaPXeA=
232233
github.com/mcdafydd/go-azuredevops v0.11.1/go.mod h1:B4UDyn7WEj1/97f45j3VnzEfkWKe05+/dCcAPdOET4A=
234+
github.com/mcdafydd/go-azuredevops v0.11.2 h1:M8t1io1bfUD7N1ZQHJVk3DvvEBy41FNkYgIwWoQnywk=
235+
github.com/mcdafydd/go-azuredevops v0.11.2/go.mod h1:B4UDyn7WEj1/97f45j3VnzEfkWKe05+/dCcAPdOET4A=
233236
github.com/microcosm-cc/bluemonday v1.0.1 h1:SIYunPjnlXcW+gVfvm0IlSeR5U3WZUOLfVmqg85Go44=
234237
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
235238
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=

server/events/command_runner.go

+11-2
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,7 @@ func (c *DefaultCommandRunner) RunCommentCommand(baseRepo models.Repo, maybeHead
345345
c.updateCommitStatus(ctx, cmd.Name, pullStatus)
346346

347347
if cmd.Name == models.ApplyCommand && c.automergeEnabled(ctx, projectCmds) {
348-
c.automerge(ctx, pullStatus)
348+
c.automerge(ctx, pullStatus, c.deleteSourceBranchOnMerge(ctx, projectCmds))
349349
}
350350
}
351351

@@ -381,7 +381,7 @@ func (c *DefaultCommandRunner) updateCommitStatus(ctx *CommandContext, cmd model
381381
}
382382
}
383383

384-
func (c *DefaultCommandRunner) automerge(ctx *CommandContext, pullStatus models.PullStatus) {
384+
func (c *DefaultCommandRunner) automerge(ctx *CommandContext, pullStatus models.PullStatus, shouldDeleteSourceBranch bool) {
385385
// We only automerge if all projects have been successfully applied.
386386
for _, p := range pullStatus.Projects {
387387
if p.Status != models.AppliedPlanStatus {
@@ -398,6 +398,9 @@ func (c *DefaultCommandRunner) automerge(ctx *CommandContext, pullStatus models.
398398

399399
// Make the API call to perform the merge.
400400
ctx.Log.Info("automerging pull request")
401+
if shouldDeleteSourceBranch {
402+
ctx.Pull.DeleteSourceBranchOnMerge = true
403+
}
401404
err := c.VCSClient.MergePull(ctx.Pull)
402405

403406
if err != nil {
@@ -603,6 +606,12 @@ func (c *DefaultCommandRunner) automergeEnabled(ctx *CommandContext, projectCmds
603606
(len(projectCmds) > 0 && projectCmds[0].AutomergeEnabled)
604607
}
605608

609+
// deleteSourceBranchOnMerge returns true if we should delete the source branch on merge in this context.
610+
func (c *DefaultCommandRunner) deleteSourceBranchOnMerge(ctx *CommandContext, projectCmds []models.ProjectCommandContext) bool {
611+
// check if this repo is configured for automerging.
612+
return (len(projectCmds) > 0 && projectCmds[0].DeleteSourceBranchOnMerge)
613+
}
614+
606615
// parallelApplyEnabled returns true if parallel apply is enabled in this context.
607616
func (c *DefaultCommandRunner) parallelApplyEnabled(ctx *CommandContext, projectCmds []models.ProjectCommandContext) bool {
608617
return len(projectCmds) > 0 && projectCmds[0].ParallelApplyEnabled

server/events/models/models.go

+4
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,8 @@ type PullRequest struct {
164164
State PullRequestState
165165
// BaseRepo is the repository that the pull request will be merged into.
166166
BaseRepo Repo
167+
// DeleteSourceBranchOnMerge will set a field that tells the VCS to delete the source branch when the PR is merged
168+
DeleteSourceBranchOnMerge bool
167169
}
168170

169171
type PullRequestState int
@@ -317,6 +319,8 @@ type ProjectCommandContext struct {
317319
AutoplanEnabled bool
318320
// BaseRepo is the repository that the pull request will be merged into.
319321
BaseRepo Repo
322+
// DeleteSourceBranchOnMerge will attempt to allow a branch to be deleted when merged (AzureDevOps Support Only)
323+
DeleteSourceBranchOnMerge bool
320324
// EscapedCommentArgs are the extra arguments that were added to the atlantis
321325
// command, ex. atlantis plan -- -target=resource. We then escape them
322326
// by adding a \ before each character so that they can be used within

server/events/project_command_builder.go

+31-25
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ const (
3030
DefaultParallelApplyEnabled = false
3131
// DefaultParallelPlanEnabled is the default for the parallel plan setting.
3232
DefaultParallelPlanEnabled = false
33+
// DefaultDeleteSourceBranchOnMerge being false is the default setting whether or not to remove a source branch on merge
34+
DefaultDeleteSourceBranchOnMerge = false
3335
)
3436

3537
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_project_command_builder.go ProjectCommandBuilder
@@ -175,7 +177,7 @@ func (p *DefaultProjectCommandBuilder) buildPlanAllCommands(ctx *CommandContext,
175177
for _, mp := range matchingProjects {
176178
ctx.Log.Debug("determining config for project at dir: %q workspace: %q", mp.Dir, mp.Workspace)
177179
mergedCfg := p.GlobalCfg.MergeProjectCfg(ctx.Log, ctx.Pull.BaseRepo.ID(), mp, repoCfg)
178-
projCtxs = append(projCtxs, p.buildCtx(ctx, models.PlanCommand, mergedCfg, commentFlags, repoCfg.Automerge, repoCfg.ParallelApply, repoCfg.ParallelPlan, verbose, repoDir))
180+
projCtxs = append(projCtxs, p.buildCtx(ctx, models.PlanCommand, mergedCfg, commentFlags, repoCfg.Automerge, repoCfg.ParallelApply, repoCfg.ParallelPlan, verbose, repoDir, repoCfg.DeleteSourceBranchOnMerge))
179181
}
180182
} else {
181183
// If there is no config file, then we'll plan each project that
@@ -186,7 +188,7 @@ func (p *DefaultProjectCommandBuilder) buildPlanAllCommands(ctx *CommandContext,
186188
for _, mp := range modifiedProjects {
187189
ctx.Log.Debug("determining config for project at dir: %q", mp.Path)
188190
pCfg := p.GlobalCfg.DefaultProjCfg(ctx.Log, ctx.Pull.BaseRepo.ID(), mp.Path, DefaultWorkspace)
189-
projCtxs = append(projCtxs, p.buildCtx(ctx, models.PlanCommand, pCfg, commentFlags, DefaultAutomergeEnabled, DefaultParallelApplyEnabled, DefaultParallelPlanEnabled, verbose, repoDir))
191+
projCtxs = append(projCtxs, p.buildCtx(ctx, models.PlanCommand, pCfg, commentFlags, DefaultAutomergeEnabled, DefaultParallelApplyEnabled, DefaultParallelPlanEnabled, verbose, repoDir, DefaultDeleteSourceBranchOnMerge))
190192
}
191193
}
192194

@@ -321,12 +323,14 @@ func (p *DefaultProjectCommandBuilder) buildProjectCommandCtx(
321323
automerge := DefaultAutomergeEnabled
322324
parallelApply := DefaultParallelApplyEnabled
323325
parallelPlan := DefaultParallelPlanEnabled
326+
deleteBranchOnMerge := DefaultDeleteSourceBranchOnMerge
324327
if repoCfgPtr != nil {
325328
automerge = repoCfgPtr.Automerge
326329
parallelApply = repoCfgPtr.ParallelApply
327330
parallelPlan = repoCfgPtr.ParallelPlan
331+
deleteBranchOnMerge = repoCfgPtr.DeleteSourceBranchOnMerge
328332
}
329-
return p.buildCtx(ctx, cmd, projCfg, commentFlags, automerge, parallelApply, parallelPlan, verbose, repoDir), nil
333+
return p.buildCtx(ctx, cmd, projCfg, commentFlags, automerge, parallelApply, parallelPlan, verbose, repoDir, deleteBranchOnMerge), nil
330334
}
331335

332336
// getCfg returns the atlantis.yaml config (if it exists) for this project. If
@@ -418,7 +422,8 @@ func (p *DefaultProjectCommandBuilder) buildCtx(ctx *CommandContext,
418422
parallelApplyEnabled bool,
419423
parallelPlanEnabled bool,
420424
verbose bool,
421-
absRepoDir string) models.ProjectCommandContext {
425+
absRepoDir string,
426+
deleteBranchOnMerge bool) models.ProjectCommandContext {
422427

423428
var steps []valid.Step
424429
switch cmd {
@@ -435,27 +440,28 @@ func (p *DefaultProjectCommandBuilder) buildCtx(ctx *CommandContext,
435440
}
436441

437442
return models.ProjectCommandContext{
438-
ApplyCmd: p.CommentBuilder.BuildApplyComment(projCfg.RepoRelDir, projCfg.Workspace, projCfg.Name),
439-
BaseRepo: ctx.Pull.BaseRepo,
440-
EscapedCommentArgs: p.escapeArgs(commentArgs),
441-
AutomergeEnabled: automergeEnabled,
442-
ParallelApplyEnabled: parallelApplyEnabled,
443-
ParallelPlanEnabled: parallelPlanEnabled,
444-
AutoplanEnabled: projCfg.AutoplanEnabled,
445-
Steps: steps,
446-
HeadRepo: ctx.HeadRepo,
447-
Log: ctx.Log,
448-
PullMergeable: ctx.PullMergeable,
449-
Pull: ctx.Pull,
450-
ProjectName: projCfg.Name,
451-
ApplyRequirements: projCfg.ApplyRequirements,
452-
RePlanCmd: p.CommentBuilder.BuildPlanComment(projCfg.RepoRelDir, projCfg.Workspace, projCfg.Name, commentArgs),
453-
RepoRelDir: projCfg.RepoRelDir,
454-
RepoConfigVersion: projCfg.RepoCfgVersion,
455-
TerraformVersion: projCfg.TerraformVersion,
456-
User: ctx.User,
457-
Verbose: verbose,
458-
Workspace: projCfg.Workspace,
443+
ApplyCmd: p.CommentBuilder.BuildApplyComment(projCfg.RepoRelDir, projCfg.Workspace, projCfg.Name),
444+
BaseRepo: ctx.Pull.BaseRepo,
445+
EscapedCommentArgs: p.escapeArgs(commentArgs),
446+
AutomergeEnabled: automergeEnabled,
447+
DeleteSourceBranchOnMerge: deleteBranchOnMerge,
448+
ParallelApplyEnabled: parallelApplyEnabled,
449+
ParallelPlanEnabled: parallelPlanEnabled,
450+
AutoplanEnabled: projCfg.AutoplanEnabled,
451+
Steps: steps,
452+
HeadRepo: ctx.HeadRepo,
453+
Log: ctx.Log,
454+
PullMergeable: ctx.PullMergeable,
455+
Pull: ctx.Pull,
456+
ProjectName: projCfg.Name,
457+
ApplyRequirements: projCfg.ApplyRequirements,
458+
RePlanCmd: p.CommentBuilder.BuildPlanComment(projCfg.RepoRelDir, projCfg.Workspace, projCfg.Name, commentArgs),
459+
RepoRelDir: projCfg.RepoRelDir,
460+
RepoConfigVersion: projCfg.RepoCfgVersion,
461+
TerraformVersion: projCfg.TerraformVersion,
462+
User: ctx.User,
463+
Verbose: verbose,
464+
Workspace: projCfg.Workspace,
459465
}
460466
}
461467

server/events/vcs/azuredevops_client.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ func (g *AzureDevopsClient) MergePull(pull models.PullRequest) error {
328328
completionOpts := azuredevops.GitPullRequestCompletionOptions{
329329
BypassPolicy: new(bool),
330330
BypassReason: azuredevops.String(""),
331-
DeleteSourceBranch: new(bool),
331+
DeleteSourceBranch: &pull.DeleteSourceBranchOnMerge,
332332
MergeCommitMessage: azuredevops.String(common.AutomergeCommitMsg),
333333
MergeStrategy: &mcm,
334334
SquashMerge: new(bool),

server/events/vcs/gitlab_client.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ func (g *GitlabClient) MergePull(pull models.PullRequest) error {
220220
pull.BaseRepo.FullName,
221221
pull.Num,
222222
&gitlab.AcceptMergeRequestOptions{
223-
MergeCommitMessage: &commitMsg,
223+
MergeCommitMessage: &commitMsg,
224+
ShouldRemoveSourceBranch: &pull.DeleteSourceBranchOnMerge,
224225
})
225226
return errors.Wrap(err, "unable to merge merge request, it may not be in a mergeable state")
226227
}

server/events/yaml/raw/repo_cfg.go

+22-12
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@ const DefaultParallelApply = false
1616
// DefaultParallelPlan is the default setting for parallel plan
1717
const DefaultParallelPlan = false
1818

19+
// DefaultDeleteSourceBranchOnMerge being false is the default setting whether or not to remove a source branch on merge
20+
const DefaultDeleteSourceBranchOnMerge = false
21+
1922
// RepoCfg is the raw schema for repo-level atlantis.yaml config.
2023
type RepoCfg struct {
21-
Version *int `yaml:"version,omitempty"`
22-
Projects []Project `yaml:"projects,omitempty"`
23-
Workflows map[string]Workflow `yaml:"workflows,omitempty"`
24-
Automerge *bool `yaml:"automerge,omitempty"`
25-
ParallelApply *bool `yaml:"parallel_apply,omitempty"`
26-
ParallelPlan *bool `yaml:"parallel_plan,omitempty"`
24+
Version *int `yaml:"version,omitempty"`
25+
Projects []Project `yaml:"projects,omitempty"`
26+
Workflows map[string]Workflow `yaml:"workflows,omitempty"`
27+
Automerge *bool `yaml:"automerge,omitempty"`
28+
ParallelApply *bool `yaml:"parallel_apply,omitempty"`
29+
ParallelPlan *bool `yaml:"parallel_plan,omitempty"`
30+
DeleteSourceBranchOnMerge *bool `yaml:"delete_source_branch_on_merge,omitempty"`
2731
}
2832

2933
func (r RepoCfg) Validate() error {
@@ -70,12 +74,18 @@ func (r RepoCfg) ToValid() valid.RepoCfg {
7074
parallelPlan = *r.ParallelPlan
7175
}
7276

77+
deleteBranchOnMerge := DefaultDeleteSourceBranchOnMerge
78+
if r.DeleteSourceBranchOnMerge != nil {
79+
deleteBranchOnMerge = *r.DeleteSourceBranchOnMerge
80+
}
81+
7382
return valid.RepoCfg{
74-
Version: *r.Version,
75-
Projects: validProjects,
76-
Workflows: validWorkflows,
77-
Automerge: automerge,
78-
ParallelApply: parallelApply,
79-
ParallelPlan: parallelPlan,
83+
Version: *r.Version,
84+
Projects: validProjects,
85+
Workflows: validWorkflows,
86+
Automerge: automerge,
87+
ParallelApply: parallelApply,
88+
ParallelPlan: parallelPlan,
89+
DeleteSourceBranchOnMerge: deleteBranchOnMerge,
8090
}
8191
}

server/events/yaml/valid/repo_cfg.go

+7-6
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import version "github.com/hashicorp/go-version"
77
// RepoCfg is the atlantis.yaml config after it's been parsed and validated.
88
type RepoCfg struct {
99
// Version is the version of the atlantis YAML file.
10-
Version int
11-
Projects []Project
12-
Workflows map[string]Workflow
13-
Automerge bool
14-
ParallelApply bool
15-
ParallelPlan bool
10+
Version int
11+
Projects []Project
12+
Workflows map[string]Workflow
13+
Automerge bool
14+
ParallelApply bool
15+
ParallelPlan bool
16+
DeleteSourceBranchOnMerge bool
1617
}
1718

1819
func (r RepoCfg) FindProjectsByDirWorkspace(repoRelDir string, workspace string) []Project {

0 commit comments

Comments
 (0)