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

feat: introduce the --set-atlantis-apply-check-successful-if-no-changes flag to allow disabling the behavior that automatically sets the atlantis/apply status check to "passing" on a VCS pull request if the atlantis plan command results in "No Changes" #4332

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
213 changes: 109 additions & 104 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,110 +43,111 @@ const (
// 3. Add your flag's description etc. to the stringFlags, intFlags, or boolFlags slices.
const (
// Flag names.
ADWebhookPasswordFlag = "azuredevops-webhook-password" // nolint: gosec
ADWebhookUserFlag = "azuredevops-webhook-user"
ADTokenFlag = "azuredevops-token" // nolint: gosec
ADUserFlag = "azuredevops-user"
ADHostnameFlag = "azuredevops-hostname"
AllowCommandsFlag = "allow-commands"
AllowForkPRsFlag = "allow-fork-prs"
AtlantisURLFlag = "atlantis-url"
AutoDiscoverModeFlag = "autodiscover-mode"
AutomergeFlag = "automerge"
ParallelPlanFlag = "parallel-plan"
ParallelApplyFlag = "parallel-apply"
AutoplanModules = "autoplan-modules"
AutoplanModulesFromProjects = "autoplan-modules-from-projects"
AutoplanFileListFlag = "autoplan-file-list"
BitbucketBaseURLFlag = "bitbucket-base-url"
BitbucketTokenFlag = "bitbucket-token"
BitbucketUserFlag = "bitbucket-user"
BitbucketWebhookSecretFlag = "bitbucket-webhook-secret"
CheckoutDepthFlag = "checkout-depth"
CheckoutStrategyFlag = "checkout-strategy"
ConfigFlag = "config"
DataDirFlag = "data-dir"
DefaultTFVersionFlag = "default-tf-version"
DisableApplyAllFlag = "disable-apply-all"
DisableAutoplanFlag = "disable-autoplan"
DisableAutoplanLabelFlag = "disable-autoplan-label"
DisableMarkdownFoldingFlag = "disable-markdown-folding"
DisableRepoLockingFlag = "disable-repo-locking"
DisableGlobalApplyLockFlag = "disable-global-apply-lock"
DisableUnlockLabelFlag = "disable-unlock-label"
DiscardApprovalOnPlanFlag = "discard-approval-on-plan"
EmojiReaction = "emoji-reaction"
EnableDiffMarkdownFormat = "enable-diff-markdown-format"
EnablePolicyChecksFlag = "enable-policy-checks"
EnableRegExpCmdFlag = "enable-regexp-cmd"
ExecutableName = "executable-name"
FailOnPreWorkflowHookError = "fail-on-pre-workflow-hook-error"
HideUnchangedPlanComments = "hide-unchanged-plan-comments"
GHHostnameFlag = "gh-hostname"
GHTeamAllowlistFlag = "gh-team-allowlist"
GHTokenFlag = "gh-token"
GHUserFlag = "gh-user"
GHAppIDFlag = "gh-app-id"
GHAppKeyFlag = "gh-app-key"
GHAppKeyFileFlag = "gh-app-key-file"
GHAppSlugFlag = "gh-app-slug"
GHAppInstallationIDFlag = "gh-app-installation-id"
GHOrganizationFlag = "gh-org"
GHWebhookSecretFlag = "gh-webhook-secret" // nolint: gosec
GHAllowMergeableBypassApply = "gh-allow-mergeable-bypass-apply" // nolint: gosec
GiteaBaseURLFlag = "gitea-base-url"
GiteaTokenFlag = "gitea-token"
GiteaUserFlag = "gitea-user"
GiteaWebhookSecretFlag = "gitea-webhook-secret" // nolint: gosec
GiteaPageSizeFlag = "gitea-page-size"
GitlabHostnameFlag = "gitlab-hostname"
GitlabTokenFlag = "gitlab-token"
GitlabUserFlag = "gitlab-user"
GitlabWebhookSecretFlag = "gitlab-webhook-secret" // nolint: gosec
IncludeGitUntrackedFiles = "include-git-untracked-files"
APISecretFlag = "api-secret"
HidePrevPlanComments = "hide-prev-plan-comments"
QuietPolicyChecks = "quiet-policy-checks"
LockingDBType = "locking-db-type"
LogLevelFlag = "log-level"
MarkdownTemplateOverridesDirFlag = "markdown-template-overrides-dir"
MaxCommentsPerCommand = "max-comments-per-command"
ParallelPoolSize = "parallel-pool-size"
StatsNamespace = "stats-namespace"
AllowDraftPRs = "allow-draft-prs"
PortFlag = "port"
RedisDB = "redis-db"
RedisHost = "redis-host"
RedisPassword = "redis-password"
RedisPort = "redis-port"
RedisTLSEnabled = "redis-tls-enabled"
RedisInsecureSkipVerify = "redis-insecure-skip-verify"
RepoConfigFlag = "repo-config"
RepoConfigJSONFlag = "repo-config-json"
RepoAllowlistFlag = "repo-allowlist"
SilenceNoProjectsFlag = "silence-no-projects"
SilenceForkPRErrorsFlag = "silence-fork-pr-errors"
SilenceVCSStatusNoPlans = "silence-vcs-status-no-plans"
SilenceVCSStatusNoProjectsFlag = "silence-vcs-status-no-projects"
SilenceAllowlistErrorsFlag = "silence-allowlist-errors"
SkipCloneNoChanges = "skip-clone-no-changes"
SlackTokenFlag = "slack-token"
SSLCertFileFlag = "ssl-cert-file"
SSLKeyFileFlag = "ssl-key-file"
RestrictFileList = "restrict-file-list"
TFDownloadFlag = "tf-download"
TFDownloadURLFlag = "tf-download-url"
UseTFPluginCache = "use-tf-plugin-cache"
VarFileAllowlistFlag = "var-file-allowlist"
VCSStatusName = "vcs-status-name"
TFEHostnameFlag = "tfe-hostname"
TFELocalExecutionModeFlag = "tfe-local-execution-mode"
TFETokenFlag = "tfe-token"
WriteGitCredsFlag = "write-git-creds" // nolint: gosec
WebBasicAuthFlag = "web-basic-auth"
WebUsernameFlag = "web-username"
WebPasswordFlag = "web-password"
WebsocketCheckOrigin = "websocket-check-origin"
ADWebhookPasswordFlag = "azuredevops-webhook-password" // nolint: gosec
ADWebhookUserFlag = "azuredevops-webhook-user"
ADTokenFlag = "azuredevops-token" // nolint: gosec
ADUserFlag = "azuredevops-user"
ADHostnameFlag = "azuredevops-hostname"
AllowCommandsFlag = "allow-commands"
AllowForkPRsFlag = "allow-fork-prs"
AtlantisURLFlag = "atlantis-url"
AutoDiscoverModeFlag = "autodiscover-mode"
AutomergeFlag = "automerge"
ParallelPlanFlag = "parallel-plan"
ParallelApplyFlag = "parallel-apply"
AutoplanModules = "autoplan-modules"
AutoplanModulesFromProjects = "autoplan-modules-from-projects"
AutoplanFileListFlag = "autoplan-file-list"
BitbucketBaseURLFlag = "bitbucket-base-url"
BitbucketTokenFlag = "bitbucket-token"
BitbucketUserFlag = "bitbucket-user"
BitbucketWebhookSecretFlag = "bitbucket-webhook-secret"
CheckoutDepthFlag = "checkout-depth"
CheckoutStrategyFlag = "checkout-strategy"
ConfigFlag = "config"
DataDirFlag = "data-dir"
DefaultTFVersionFlag = "default-tf-version"
DisableApplyAllFlag = "disable-apply-all"
DisableAutoplanFlag = "disable-autoplan"
DisableAutoplanLabelFlag = "disable-autoplan-label"
DisableMarkdownFoldingFlag = "disable-markdown-folding"
DisableRepoLockingFlag = "disable-repo-locking"
DisableGlobalApplyLockFlag = "disable-global-apply-lock"
DisableUnlockLabelFlag = "disable-unlock-label"
DiscardApprovalOnPlanFlag = "discard-approval-on-plan"
EmojiReaction = "emoji-reaction"
EnableDiffMarkdownFormat = "enable-diff-markdown-format"
EnablePolicyChecksFlag = "enable-policy-checks"
EnableRegExpCmdFlag = "enable-regexp-cmd"
ExecutableName = "executable-name"
FailOnPreWorkflowHookError = "fail-on-pre-workflow-hook-error"
HideUnchangedPlanComments = "hide-unchanged-plan-comments"
GHHostnameFlag = "gh-hostname"
GHTeamAllowlistFlag = "gh-team-allowlist"
GHTokenFlag = "gh-token"
GHUserFlag = "gh-user"
GHAppIDFlag = "gh-app-id"
GHAppKeyFlag = "gh-app-key"
GHAppKeyFileFlag = "gh-app-key-file"
GHAppSlugFlag = "gh-app-slug"
GHAppInstallationIDFlag = "gh-app-installation-id"
GHOrganizationFlag = "gh-org"
GHWebhookSecretFlag = "gh-webhook-secret" // nolint: gosec
GHAllowMergeableBypassApply = "gh-allow-mergeable-bypass-apply" // nolint: gosec
GiteaBaseURLFlag = "gitea-base-url"
GiteaTokenFlag = "gitea-token"
GiteaUserFlag = "gitea-user"
GiteaWebhookSecretFlag = "gitea-webhook-secret" // nolint: gosec
GiteaPageSizeFlag = "gitea-page-size"
GitlabHostnameFlag = "gitlab-hostname"
GitlabTokenFlag = "gitlab-token"
GitlabUserFlag = "gitlab-user"
GitlabWebhookSecretFlag = "gitlab-webhook-secret" // nolint: gosec
IncludeGitUntrackedFiles = "include-git-untracked-files"
APISecretFlag = "api-secret"
HidePrevPlanComments = "hide-prev-plan-comments"
QuietPolicyChecks = "quiet-policy-checks"
LockingDBType = "locking-db-type"
LogLevelFlag = "log-level"
MarkdownTemplateOverridesDirFlag = "markdown-template-overrides-dir"
MaxCommentsPerCommand = "max-comments-per-command"
ParallelPoolSize = "parallel-pool-size"
StatsNamespace = "stats-namespace"
AllowDraftPRs = "allow-draft-prs"
PortFlag = "port"
RedisDB = "redis-db"
RedisHost = "redis-host"
RedisPassword = "redis-password"
RedisPort = "redis-port"
RedisTLSEnabled = "redis-tls-enabled"
RedisInsecureSkipVerify = "redis-insecure-skip-verify"
RepoConfigFlag = "repo-config"
RepoConfigJSONFlag = "repo-config-json"
RepoAllowlistFlag = "repo-allowlist"
SetAtlantisApplyCheckSuccessfulIfNoChangesFlag = "set-atlantis-apply-check-successful-if-no-changes"
SilenceNoProjectsFlag = "silence-no-projects"
SilenceForkPRErrorsFlag = "silence-fork-pr-errors"
SilenceVCSStatusNoPlans = "silence-vcs-status-no-plans"
SilenceVCSStatusNoProjectsFlag = "silence-vcs-status-no-projects"
SilenceAllowlistErrorsFlag = "silence-allowlist-errors"
SkipCloneNoChanges = "skip-clone-no-changes"
SlackTokenFlag = "slack-token"
SSLCertFileFlag = "ssl-cert-file"
SSLKeyFileFlag = "ssl-key-file"
RestrictFileList = "restrict-file-list"
TFDownloadFlag = "tf-download"
TFDownloadURLFlag = "tf-download-url"
UseTFPluginCache = "use-tf-plugin-cache"
VarFileAllowlistFlag = "var-file-allowlist"
VCSStatusName = "vcs-status-name"
TFEHostnameFlag = "tfe-hostname"
TFELocalExecutionModeFlag = "tfe-local-execution-mode"
TFETokenFlag = "tfe-token"
WriteGitCredsFlag = "write-git-creds" // nolint: gosec
WebBasicAuthFlag = "web-basic-auth"
WebUsernameFlag = "web-username"
WebPasswordFlag = "web-password"
WebsocketCheckOrigin = "websocket-check-origin"

// NOTE: Must manually set these as defaults in the setDefaults function.
DefaultADBasicUser = ""
Expand Down Expand Up @@ -526,6 +527,10 @@ var boolFlags = map[string]boolFlag{
description: "Controls whether the Redis client verifies the Redis server's certificate chain and host name. If true, accepts any certificate presented by the server and any host name in that certificate.",
defaultValue: DefaultRedisInsecureSkipVerify,
},
SetAtlantisApplyCheckSuccessfulIfNoChangesFlag: {
description: "Set the `atlantis/apply` pull request status check to \"passing\" if \"No Changes\" are detected.",
defaultValue: true,
},
SilenceNoProjectsFlag: {
description: "Silences Atlants from responding to PRs when it finds no projects.",
defaultValue: false,
Expand Down
59 changes: 30 additions & 29 deletions cmd/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,35 +126,36 @@ var testFlags = map[string]interface{}{
RepoAllowlistFlag: "github.com/runatlantis/atlantis",
RepoConfigFlag: "",
RepoConfigJSONFlag: "",
SilenceNoProjectsFlag: false,
SilenceVCSStatusNoProjectsFlag: false,
SilenceForkPRErrorsFlag: true,
SilenceAllowlistErrorsFlag: true,
SilenceVCSStatusNoPlans: true,
SkipCloneNoChanges: true,
SlackTokenFlag: "slack-token",
SSLCertFileFlag: "cert-file",
SSLKeyFileFlag: "key-file",
RestrictFileList: false,
TFDownloadFlag: true,
TFDownloadURLFlag: "https://my-hostname.com",
TFEHostnameFlag: "my-hostname",
TFELocalExecutionModeFlag: true,
TFETokenFlag: "my-token",
UseTFPluginCache: true,
VarFileAllowlistFlag: "/path",
VCSStatusName: "my-status",
WebBasicAuthFlag: false,
WebPasswordFlag: "atlantis",
WebUsernameFlag: "atlantis",
WebsocketCheckOrigin: false,
WriteGitCredsFlag: true,
DisableAutoplanFlag: true,
DisableAutoplanLabelFlag: "no-auto-plan",
DisableUnlockLabelFlag: "do-not-unlock",
EnablePolicyChecksFlag: false,
EnableRegExpCmdFlag: false,
EnableDiffMarkdownFormat: false,
SetAtlantisApplyCheckSuccessfulIfNoChangesFlag: true,
SilenceNoProjectsFlag: false,
SilenceVCSStatusNoProjectsFlag: false,
SilenceForkPRErrorsFlag: true,
SilenceAllowlistErrorsFlag: true,
SilenceVCSStatusNoPlans: true,
SkipCloneNoChanges: true,
SlackTokenFlag: "slack-token",
SSLCertFileFlag: "cert-file",
SSLKeyFileFlag: "key-file",
RestrictFileList: false,
TFDownloadFlag: true,
TFDownloadURLFlag: "https://my-hostname.com",
TFEHostnameFlag: "my-hostname",
TFELocalExecutionModeFlag: true,
TFETokenFlag: "my-token",
UseTFPluginCache: true,
VarFileAllowlistFlag: "/path",
VCSStatusName: "my-status",
WebBasicAuthFlag: false,
WebPasswordFlag: "atlantis",
WebUsernameFlag: "atlantis",
WebsocketCheckOrigin: false,
WriteGitCredsFlag: true,
DisableAutoplanFlag: true,
DisableAutoplanLabelFlag: "no-auto-plan",
DisableUnlockLabelFlag: "do-not-unlock",
EnablePolicyChecksFlag: false,
EnableRegExpCmdFlag: false,
EnableDiffMarkdownFormat: false,
}

func TestExecute_Defaults(t *testing.T) {
Expand Down
10 changes: 10 additions & 0 deletions runatlantis.io/docs/server-configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,16 @@ This is useful when you have many projects and want to keep the pull request cle
like `atlantis plan -p .*` will still work if used. normal commands will stil be blocked if necessary.
Defaults to `false`.

### `--set-atlantis-apply-check-successful-if-no-changes`
```bash
atlantis server --set-atlantis-apply-check-successful-if-no-changes
# or
ATLANTIS_SET_ATLANTIS_APPLY_CHECK_SUCCESSFUL_IF_NO_CHANGES=false
```
`--set-atlantis-apply-check-successful-if-no-changes` will set the `atlantis/apply` status check to "passing" on a VCS pull request if the `atlantis plan` command results in "No Changes".
This is useful, for example, when enabling auto-merge for pull requests that do not involve resource changes, such as automatic dependency updates.
Defaults to `true`.

### `--silence-allowlist-errors`

```bash
Expand Down
2 changes: 2 additions & 0 deletions server/controllers/events/events_controller_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1524,6 +1524,7 @@ func setupE2E(t *testing.T, repoDir string, opt setupOption) (events_controllers
lockingClient,
discardApprovalOnPlan,
e2ePullReqStatusFetcher,
true,
)

applyCommandRunner := events.NewApplyCommandRunner(
Expand All @@ -1541,6 +1542,7 @@ func setupE2E(t *testing.T, repoDir string, opt setupOption) (events_controllers
silenceNoProjects,
false,
e2ePullReqStatusFetcher,
true,
)

approvePoliciesCommandRunner := events.NewApprovePoliciesCommandRunner(
Expand Down
Loading