Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for plans to be partially successful #4709

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 19 additions & 16 deletions server/events/comment_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,20 +31,22 @@ import (
)

const (
workspaceFlagLong = "workspace"
workspaceFlagShort = "w"
dirFlagLong = "dir"
dirFlagShort = "d"
projectFlagLong = "project"
projectFlagShort = "p"
policySetFlagLong = "policy-set"
policySetFlagShort = ""
autoMergeDisabledFlagLong = "auto-merge-disabled"
autoMergeDisabledFlagShort = ""
verboseFlagLong = "verbose"
verboseFlagShort = ""
clearPolicyApprovalFlagLong = "clear-policy-approval"
clearPolicyApprovalFlagShort = ""
workspaceFlagLong = "workspace"
workspaceFlagShort = "w"
dirFlagLong = "dir"
dirFlagShort = "d"
projectFlagLong = "project"
projectFlagShort = "p"
policySetFlagLong = "policy-set"
policySetFlagShort = ""
autoMergeDisabledFlagLong = "auto-merge-disabled"
autoMergeDisabledFlagShort = ""
verboseFlagLong = "verbose"
verboseFlagShort = ""
clearPolicyApprovalFlagLong = "clear-policy-approval"
clearPolicyApprovalFlagShort = ""
allowPartialSuccessVerboseFlagLong = "allow-partial-success"
allowPartialSuccessVerboseFlagShort = ""
)

// multiLineRegex is used to ignore multi-line comments since those aren't valid
Expand Down Expand Up @@ -226,7 +228,7 @@ func (e *CommentParser) Parse(rawComment string, vcsHost models.VCSHostType) Com
var project string
var policySet string
var clearPolicyApproval bool
var verbose, autoMergeDisabled bool
var verbose, autoMergeDisabled, allowPartialSuccess bool
var flagSet *pflag.FlagSet
var name command.Name

Expand All @@ -240,6 +242,7 @@ func (e *CommentParser) Parse(rawComment string, vcsHost models.VCSHostType) Com
flagSet.StringVarP(&dir, dirFlagLong, dirFlagShort, "", "Which directory to run plan in relative to root of repo, ex. 'child/dir'.")
flagSet.StringVarP(&project, projectFlagLong, projectFlagShort, "", "Which project to run plan for. Refers to the name of the project configured in a repo config file. Cannot be used at same time as workspace or dir flags.")
flagSet.BoolVarP(&verbose, verboseFlagLong, verboseFlagShort, false, "Append Atlantis log to comment.")
flagSet.BoolVarP(&allowPartialSuccess, allowPartialSuccessVerboseFlagLong, allowPartialSuccessVerboseFlagLong, false, "Allow for some plans to succeed even when auto merge is enabled (the default is an atomic action which deletes all plans upon failure of at least one other plan).")
case command.Apply.String():
name = command.Apply
flagSet = pflag.NewFlagSet(command.Apply.String(), pflag.ContinueOnError)
Expand Down Expand Up @@ -318,7 +321,7 @@ func (e *CommentParser) Parse(rawComment string, vcsHost models.VCSHostType) Com
}

return CommentParseResult{
Command: NewCommentCommand(dir, extraArgs, name, subName, verbose, autoMergeDisabled, workspace, project, policySet, clearPolicyApproval),
Command: NewCommentCommand(dir, extraArgs, name, subName, verbose, autoMergeDisabled, workspace, project, policySet, clearPolicyApproval, allowPartialSuccess),
}
}

Expand Down
7 changes: 5 additions & 2 deletions server/events/event_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ type CommentCommand struct {
PolicySet string
// ClearPolicyApproval is true if approvals should be cleared out for specified policies.
ClearPolicyApproval bool
// AllowPartialSuccess is true if plans should be saved even if there were partial failures (only relevant if automerge is true)
AllowPartialSuccess bool
}

// IsForSpecificProject returns true if the command is for a specific dir, workspace
Expand Down Expand Up @@ -177,11 +179,11 @@ func (c CommentCommand) IsAutoplan() bool {

// String returns a string representation of the command.
func (c CommentCommand) String() string {
return fmt.Sprintf("command=%q verbose=%t dir=%q workspace=%q project=%q policyset=%q, clear-policy-approval=%t, flags=%q", c.Name.String(), c.Verbose, c.RepoRelDir, c.Workspace, c.ProjectName, c.PolicySet, c.ClearPolicyApproval, strings.Join(c.Flags, ","))
return fmt.Sprintf("command=%q verbose=%t dir=%q workspace=%q project=%q policyset=%q, clear-policy-approval=%t, allow-partial-success=%t, flags=%q", c.Name.String(), c.Verbose, c.RepoRelDir, c.Workspace, c.ProjectName, c.PolicySet, c.ClearPolicyApproval, c.AllowPartialSuccess, strings.Join(c.Flags, ","))
}

// NewCommentCommand constructs a CommentCommand, setting all missing fields to defaults.
func NewCommentCommand(repoRelDir string, flags []string, name command.Name, subName string, verbose, autoMergeDisabled bool, workspace string, project string, policySet string, clearPolicyApproval bool) *CommentCommand {
func NewCommentCommand(repoRelDir string, flags []string, name command.Name, subName string, verbose, autoMergeDisabled bool, workspace string, project string, policySet string, clearPolicyApproval bool, allowPartialSuccess bool) *CommentCommand {
// If repoRelDir was empty we want to keep it that way to indicate that it
// wasn't specified in the comment.
if repoRelDir != "" {
Expand All @@ -201,6 +203,7 @@ func NewCommentCommand(repoRelDir string, flags []string, name command.Name, sub
ProjectName: project,
PolicySet: policySet,
ClearPolicyApproval: clearPolicyApproval,
AllowPartialSuccess: allowPartialSuccess,
}
}

Expand Down
2 changes: 1 addition & 1 deletion server/events/plan_command_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,7 @@ func (p *PlanCommandRunner) run(ctx *command.Context, cmd *CommentCommand) {
result = runProjectCmds(projectCmds, p.prjCmdRunner.Plan)
}

if p.autoMerger.automergeEnabled(projectCmds) && result.HasErrors() {
if !cmd.AllowPartialSuccess && p.autoMerger.automergeEnabled(projectCmds) && result.HasErrors() {
ctx.Log.Info("deleting plans because there were errors and automerge requires all plans succeed")
p.deletePlans(ctx)
result.PlansDeleted = true
Expand Down
Loading