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

Update autoplan so commit status is set only after finding projects #955

Closed
wants to merge 4 commits into from
Closed
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
5 changes: 5 additions & 0 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const (
RequireApprovalFlag = "require-approval"
RequireMergeableFlag = "require-mergeable"
SilenceForkPRErrorsFlag = "silence-fork-pr-errors"
SilenceVCSStatusNoPlans = "silence-vcs-status-no-plans"
SilenceWhitelistErrorsFlag = "silence-whitelist-errors"
SlackTokenFlag = "slack-token"
SSLCertFileFlag = "ssl-cert-file"
Expand Down Expand Up @@ -264,6 +265,10 @@ var boolFlags = map[string]boolFlag{
description: "Silences the posting of fork pull requests not allowed error comments.",
defaultValue: false,
},
SilenceVCSStatusNoPlans: {
description: "Silences VCS commit status when autoplan finds no projects to plan.",
defaultValue: false,
},
SilenceWhitelistErrorsFlag: {
description: "Silences the posting of whitelist error comments.",
defaultValue: false,
Expand Down
14 changes: 14 additions & 0 deletions cmd/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ func TestExecute_Defaults(t *testing.T) {
Equals(t, false, passedConfig.RequireApproval)
Equals(t, false, passedConfig.RequireMergeable)
Equals(t, false, passedConfig.SilenceForkPRErrors)
Equals(t, false, passedConfig.SilenceVCSStatusNoPlans)
Equals(t, false, passedConfig.SilenceWhitelistErrors)
Equals(t, "", passedConfig.SlackToken)
Equals(t, "", passedConfig.SSLCertFile)
Expand Down Expand Up @@ -517,6 +518,7 @@ func TestExecute_Flags(t *testing.T) {
cmd.RequireApprovalFlag: true,
cmd.RequireMergeableFlag: true,
cmd.SilenceForkPRErrorsFlag: true,
cmd.SilenceVCSStatusNoPlans: true,
cmd.SilenceWhitelistErrorsFlag: true,
cmd.SlackTokenFlag: "slack-token",
cmd.SSLCertFileFlag: "cert-file",
Expand Down Expand Up @@ -560,6 +562,7 @@ func TestExecute_Flags(t *testing.T) {
Equals(t, true, passedConfig.RequireApproval)
Equals(t, true, passedConfig.RequireMergeable)
Equals(t, true, passedConfig.SilenceForkPRErrors)
Equals(t, true, passedConfig.SilenceVCSStatusNoPlans)
Equals(t, true, passedConfig.SilenceWhitelistErrors)
Equals(t, "slack-token", passedConfig.SlackToken)
Equals(t, "cert-file", passedConfig.SSLCertFile)
Expand Down Expand Up @@ -604,6 +607,7 @@ repo-whitelist: "github.com/runatlantis/atlantis"
require-approval: true
require-mergeable: true
silence-fork-pr-errors: true
silence-vcs-status-no-plans: true
silence-whitelist-errors: true
slack-token: slack-token
ssl-cert-file: cert-file
Expand Down Expand Up @@ -651,6 +655,7 @@ write-git-creds: true
Equals(t, true, passedConfig.RequireApproval)
Equals(t, true, passedConfig.RequireMergeable)
Equals(t, true, passedConfig.SilenceForkPRErrors)
Equals(t, true, passedConfig.SilenceVCSStatusNoPlans)
Equals(t, true, passedConfig.SilenceWhitelistErrors)
Equals(t, "slack-token", passedConfig.SlackToken)
Equals(t, "cert-file", passedConfig.SSLCertFile)
Expand Down Expand Up @@ -694,6 +699,7 @@ port: 8181
repo-whitelist: "github.com/runatlantis/atlantis"
require-approval: true
silence-fork-pr-errors: true
silence-vcs-status-no-plans: true
silence-whitelist-errors: true
slack-token: slack-token
ssl-cert-file: cert-file
Expand Down Expand Up @@ -738,6 +744,7 @@ write-git-creds: true
"REQUIRE_APPROVAL": "false",
"REQUIRE_MERGEABLE": "false",
"SILENCE_FORK_PR_ERRORS": "false",
"SILENCE_VCS_STATUS_NO_PLANS": "false",
"SILENCE_WHITELIST_ERRORS": "false",
"SLACK_TOKEN": "override-slack-token",
"SSL_CERT_FILE": "override-cert-file",
Expand Down Expand Up @@ -785,6 +792,7 @@ write-git-creds: true
Equals(t, false, passedConfig.RequireApproval)
Equals(t, false, passedConfig.RequireMergeable)
Equals(t, false, passedConfig.SilenceForkPRErrors)
Equals(t, false, passedConfig.SilenceVCSStatusNoPlans)
Equals(t, false, passedConfig.SilenceWhitelistErrors)
Equals(t, "override-slack-token", passedConfig.SlackToken)
Equals(t, "override-cert-file", passedConfig.SSLCertFile)
Expand Down Expand Up @@ -829,6 +837,7 @@ repo-whitelist: "github.com/runatlantis/atlantis"
require-approval: true
require-mergeable: true
silence-fork-pr-errors: true
silence-vcs-status-no-plans: true
silence-whitelist-errors: true
slack-token: slack-token
ssl-cert-file: cert-file
Expand Down Expand Up @@ -873,6 +882,7 @@ write-git-creds: true
cmd.RequireApprovalFlag: false,
cmd.RequireMergeableFlag: false,
cmd.SilenceForkPRErrorsFlag: false,
cmd.SilenceVCSStatusNoPlans: false,
cmd.SilenceWhitelistErrorsFlag: false,
cmd.SlackTokenFlag: "override-slack-token",
cmd.SSLCertFileFlag: "override-cert-file",
Expand Down Expand Up @@ -914,6 +924,7 @@ write-git-creds: true
Equals(t, false, passedConfig.RequireApproval)
Equals(t, false, passedConfig.RequireMergeable)
Equals(t, false, passedConfig.SilenceForkPRErrors)
Equals(t, false, passedConfig.SilenceVCSStatusNoPlans)
Equals(t, false, passedConfig.SilenceWhitelistErrors)
Equals(t, "override-slack-token", passedConfig.SlackToken)
Equals(t, "override-cert-file", passedConfig.SSLCertFile)
Expand Down Expand Up @@ -960,6 +971,7 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
"REQUIRE_APPROVAL": "true",
"REQUIRE_MERGEABLE": "true",
"SILENCE_FORK_PR_ERRORS": "true",
"SILENCE_VCS_STATUS_NO_PLANS": "true",
"SILENCE_WHITELIST_ERRORS": "true",
"SLACK_TOKEN": "slack-token",
"SSL_CERT_FILE": "cert-file",
Expand Down Expand Up @@ -1012,6 +1024,7 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
cmd.RequireApprovalFlag: false,
cmd.RequireMergeableFlag: false,
cmd.SilenceForkPRErrorsFlag: false,
cmd.SilenceVCSStatusNoPlans: false,
cmd.SilenceWhitelistErrorsFlag: false,
cmd.SlackTokenFlag: "override-slack-token",
cmd.SSLCertFileFlag: "override-cert-file",
Expand Down Expand Up @@ -1055,6 +1068,7 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
Equals(t, false, passedConfig.RequireApproval)
Equals(t, false, passedConfig.RequireMergeable)
Equals(t, false, passedConfig.SilenceForkPRErrors)
Equals(t, false, passedConfig.SilenceVCSStatusNoPlans)
Equals(t, false, passedConfig.SilenceWhitelistErrors)
Equals(t, "override-slack-token", passedConfig.SlackToken)
Equals(t, "override-cert-file", passedConfig.SSLCertFile)
Expand Down
25 changes: 16 additions & 9 deletions server/events/command_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ type DefaultCommandRunner struct {
// this in our error message back to the user on a forked PR so they know
// how to disable error comment
SilenceForkPRErrorsFlag string
// SilenceVCSStatusNoPlans is whether autoplan should set commit status if no plans
// are found
SilenceVCSStatusNoPlans bool
ProjectCommandBuilder ProjectCommandBuilder
ProjectCommandRunner ProjectCommandRunner
// GlobalAutomerge is true if we should automatically merge pull requests if all
Expand All @@ -110,10 +113,6 @@ func (c *DefaultCommandRunner) RunAutoplanCommand(baseRepo models.Repo, headRepo
return
}

if err := c.CommitStatusUpdater.UpdateCombined(ctx.BaseRepo, ctx.Pull, models.PendingCommitStatus, models.PlanCommand); err != nil {
ctx.Log.Warn("unable to update commit status: %s", err)
}

projectCmds, err := c.ProjectCommandBuilder.BuildAutoplanCommands(ctx)
if err != nil {
if statusErr := c.CommitStatusUpdater.UpdateCombined(ctx.BaseRepo, ctx.Pull, models.FailedCommitStatus, models.PlanCommand); statusErr != nil {
Expand All @@ -125,15 +124,23 @@ func (c *DefaultCommandRunner) RunAutoplanCommand(baseRepo models.Repo, headRepo
}
if len(projectCmds) == 0 {
log.Info("determined there was no project to run plan in")
// If there were no projects modified, we set a successful commit status
// with 0/0 projects planned successfully because we've already set an
// in-progress status and we don't want that to be "in progress" forever.
if err := c.CommitStatusUpdater.UpdateCombinedCount(baseRepo, pull, models.SuccessCommitStatus, models.PlanCommand, 0, 0); err != nil {
ctx.Log.Warn("unable to update commit status: %s", err)
if !c.SilenceVCSStatusNoPlans {
// If SilenceVCSStatusNoPlans is not set and no projects were modified
// we set a successful commit status with 0/0 projects planned successfully
// to indicate that Atlantis has finished working
ctx.Log.Debug("setting VCS status to success with no projects found")
if err := c.CommitStatusUpdater.UpdateCombinedCount(baseRepo, pull, models.SuccessCommitStatus, models.PlanCommand, 0, 0); err != nil {
ctx.Log.Warn("unable to update commit status: %s", err)
}
}
return
}

// At this point we are sure Atlantis has work to do, so set commit status to pending
if err := c.CommitStatusUpdater.UpdateCombined(ctx.BaseRepo, ctx.Pull, models.PendingCommitStatus, models.PlanCommand); err != nil {
ctx.Log.Warn("unable to update commit status: %s", err)
}

result := c.runProjectCmds(projectCmds, models.PlanCommand)
if c.automergeEnabled(ctx, projectCmds) && result.HasErrors() {
ctx.Log.Info("deleting plans because there were errors and automerge requires all plans succeed")
Expand Down
1 change: 1 addition & 0 deletions server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,7 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
AllowForkPRsFlag: config.AllowForkPRsFlag,
SilenceForkPRErrors: userConfig.SilenceForkPRErrors,
SilenceForkPRErrorsFlag: config.SilenceForkPRErrorsFlag,
SilenceVCSStatusNoPlans: userConfig.SilenceVCSStatusNoPlans,
DisableApplyAll: userConfig.DisableApplyAll,
ProjectCommandBuilder: &events.DefaultProjectCommandBuilder{
ParserValidator: validator,
Expand Down
29 changes: 16 additions & 13 deletions server/user_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,19 +39,22 @@ type UserConfig struct {
RequireApproval bool `mapstructure:"require-approval"`
// RequireMergeable is whether to require pull requests to be mergeable before
// allowing terraform apply's to run.
RequireMergeable bool `mapstructure:"require-mergeable"`
SilenceForkPRErrors bool `mapstructure:"silence-fork-pr-errors"`
SilenceWhitelistErrors bool `mapstructure:"silence-whitelist-errors"`
SlackToken string `mapstructure:"slack-token"`
SSLCertFile string `mapstructure:"ssl-cert-file"`
SSLKeyFile string `mapstructure:"ssl-key-file"`
TFDownloadURL string `mapstructure:"tf-download-url"`
TFEHostname string `mapstructure:"tfe-hostname"`
TFEToken string `mapstructure:"tfe-token"`
VCSStatusName string `mapstructure:"vcs-status-name"`
DefaultTFVersion string `mapstructure:"default-tf-version"`
Webhooks []WebhookConfig `mapstructure:"webhooks"`
WriteGitCreds bool `mapstructure:"write-git-creds"`
RequireMergeable bool `mapstructure:"require-mergeable"`
SilenceForkPRErrors bool `mapstructure:"silence-fork-pr-errors"`
// SilenceVCSStatusNoPlans is whether autoplan should set commit status if no plans
// are found
SilenceVCSStatusNoPlans bool `mapstructure:"silence-vcs-status-no-plans"`
SilenceWhitelistErrors bool `mapstructure:"silence-whitelist-errors"`
SlackToken string `mapstructure:"slack-token"`
SSLCertFile string `mapstructure:"ssl-cert-file"`
SSLKeyFile string `mapstructure:"ssl-key-file"`
TFDownloadURL string `mapstructure:"tf-download-url"`
TFEHostname string `mapstructure:"tfe-hostname"`
TFEToken string `mapstructure:"tfe-token"`
VCSStatusName string `mapstructure:"vcs-status-name"`
DefaultTFVersion string `mapstructure:"default-tf-version"`
Webhooks []WebhookConfig `mapstructure:"webhooks"`
WriteGitCreds bool `mapstructure:"write-git-creds"`
}

// ToLogLevel returns the LogLevel object corresponding to the user-passed
Expand Down