mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-08-05 08:08:34 +00:00
feat: add silence_pr_comments on plan and apply (#4543)
This commit is contained in:
@@ -78,6 +78,7 @@ projects:
|
||||
plan_requirements: [mergeable, approved, undiverged]
|
||||
apply_requirements: [mergeable, approved, undiverged]
|
||||
import_requirements: [mergeable, approved, undiverged]
|
||||
silence_pr_comments: ["apply"]
|
||||
execution_order_group: 1
|
||||
depends_on:
|
||||
- project-1
|
||||
@@ -433,6 +434,7 @@ terraform_version: 0.11.0
|
||||
plan_requirements: ["approved"]
|
||||
apply_requirements: ["approved"]
|
||||
import_requirements: ["approved"]
|
||||
silence_pr_comments: ["apply"]
|
||||
workflow: myworkflow
|
||||
```
|
||||
|
||||
@@ -452,6 +454,7 @@ workflow: myworkflow
|
||||
| plan_requirements<br />*(restricted)* | array\[string\] | none | no | Requirements that must be satisfied before `atlantis plan` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](command-requirements.md) for more details. |
|
||||
| apply_requirements<br />*(restricted)* | array\[string\] | none | no | Requirements that must be satisfied before `atlantis apply` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](command-requirements.md) for more details. |
|
||||
| import_requirements<br />*(restricted)* | array\[string\] | none | no | Requirements that must be satisfied before `atlantis import` can be run. Currently the only supported requirements are `approved`, `mergeable`, and `undiverged`. See [Command Requirements](command-requirements.md) for more details. |
|
||||
| silence_pr_comments | array\[string\] | none | no | Silence PR comments from defined stages while preserving PR status checks. Supported values are: `plan`, `apply`. |
|
||||
| workflow <br />*(restricted)* | string | none | no | A custom workflow. If not specified, Atlantis will use its default workflow. |
|
||||
|
||||
::: tip
|
||||
|
||||
@@ -542,6 +542,7 @@ If you set a workflow with the key `default`, it will override this.
|
||||
| policy_check | bool | false | no | Whether or not to run policy checks on this repository. |
|
||||
| custom_policy_check | bool | false | no | Whether or not to enable custom policy check tools outside of Conftest on this repository. |
|
||||
| autodiscover | AutoDiscover | none | no | Auto discover settings for this repo |
|
||||
| silence_pr_comments | []string | none | no | Silence PR comments from defined stages while preserving PR status checks. Useful in large environments with many Atlantis instances and/or projects, when the comments are too big and too many, therefore it is preferable to rely solely on PR status checks. Supported values are: `plan`, `apply`. |
|
||||
|
||||
:::tip Notes
|
||||
|
||||
|
||||
@@ -1286,7 +1286,7 @@ func TestParseGlobalCfg(t *testing.T) {
|
||||
input: `repos:
|
||||
- id: /.*/
|
||||
allowed_overrides: [invalid]`,
|
||||
expErr: "repos: (0: (allowed_overrides: \"invalid\" is not a valid override, only \"plan_requirements\", \"apply_requirements\", \"import_requirements\", \"workflow\", \"delete_source_branch_on_merge\", \"repo_locking\", \"repo_locks\", \"policy_check\", and \"custom_policy_check\" are supported.).).",
|
||||
expErr: "repos: (0: (allowed_overrides: \"invalid\" is not a valid override, only \"plan_requirements\", \"apply_requirements\", \"import_requirements\", \"workflow\", \"delete_source_branch_on_merge\", \"repo_locking\", \"repo_locks\", \"policy_check\", \"custom_policy_check\", and \"silence_pr_comments\" are supported.).).",
|
||||
},
|
||||
"invalid plan_requirement": {
|
||||
input: `repos:
|
||||
@@ -1306,8 +1306,14 @@ func TestParseGlobalCfg(t *testing.T) {
|
||||
import_requirements: [invalid]`,
|
||||
expErr: "repos: (0: (import_requirements: \"invalid\" is not a valid import_requirement, only \"approved\", \"mergeable\" and \"undiverged\" are supported.).).",
|
||||
},
|
||||
"invalid silence_pr_comments": {
|
||||
input: `repos:
|
||||
- id: /.*/
|
||||
silence_pr_comments: [invalid]`,
|
||||
expErr: "server-side repo config 'silence_pr_comments' key value of 'invalid' is not supported, supported values are [plan, apply]",
|
||||
},
|
||||
"disable autodiscover": {
|
||||
input: `repos:
|
||||
input: `repos:
|
||||
- id: /.*/
|
||||
autodiscover:
|
||||
mode: disabled`,
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
validation "github.com/go-ozzo/ozzo-validation"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/runatlantis/atlantis/server/core/config/valid"
|
||||
"github.com/runatlantis/atlantis/server/utils"
|
||||
)
|
||||
|
||||
// GlobalCfg is the raw schema for server-side repo config.
|
||||
@@ -38,6 +39,7 @@ type Repo struct {
|
||||
PolicyCheck *bool `yaml:"policy_check,omitempty" json:"policy_check,omitempty"`
|
||||
CustomPolicyCheck *bool `yaml:"custom_policy_check,omitempty" json:"custom_policy_check,omitempty"`
|
||||
AutoDiscover *AutoDiscover `yaml:"autodiscover,omitempty" json:"autodiscover,omitempty"`
|
||||
SilencePRComments []string `yaml:"silence_pr_comments,omitempty" json:"silence_pr_comments,omitempty"`
|
||||
}
|
||||
|
||||
func (g GlobalCfg) Validate() error {
|
||||
@@ -94,6 +96,24 @@ func (g GlobalCfg) Validate() error {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate supported SilencePRComments values.
|
||||
for _, repo := range g.Repos {
|
||||
if repo.SilencePRComments == nil {
|
||||
continue
|
||||
}
|
||||
for _, silenceStage := range repo.SilencePRComments {
|
||||
if !utils.SlicesContains(valid.AllowedSilencePRComments, silenceStage) {
|
||||
return fmt.Errorf(
|
||||
"server-side repo config '%s' key value of '%s' is not supported, supported values are [%s]",
|
||||
valid.SilencePRCommentsKey,
|
||||
silenceStage,
|
||||
strings.Join(valid.AllowedSilencePRComments, ", "),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -195,8 +215,8 @@ func (r Repo) Validate() error {
|
||||
overridesValid := func(value interface{}) error {
|
||||
overrides := value.([]string)
|
||||
for _, o := range overrides {
|
||||
if o != valid.PlanRequirementsKey && o != valid.ApplyRequirementsKey && o != valid.ImportRequirementsKey && o != valid.WorkflowKey && o != valid.DeleteSourceBranchOnMergeKey && o != valid.RepoLockingKey && o != valid.RepoLocksKey && o != valid.PolicyCheckKey && o != valid.CustomPolicyCheckKey {
|
||||
return fmt.Errorf("%q is not a valid override, only %q, %q, %q, %q, %q, %q, %q, %q, and %q are supported", o, valid.PlanRequirementsKey, valid.ApplyRequirementsKey, valid.ImportRequirementsKey, valid.WorkflowKey, valid.DeleteSourceBranchOnMergeKey, valid.RepoLockingKey, valid.RepoLocksKey, valid.PolicyCheckKey, valid.CustomPolicyCheckKey)
|
||||
if o != valid.PlanRequirementsKey && o != valid.ApplyRequirementsKey && o != valid.ImportRequirementsKey && o != valid.WorkflowKey && o != valid.DeleteSourceBranchOnMergeKey && o != valid.RepoLockingKey && o != valid.RepoLocksKey && o != valid.PolicyCheckKey && o != valid.CustomPolicyCheckKey && o != valid.SilencePRCommentsKey {
|
||||
return fmt.Errorf("%q is not a valid override, only %q, %q, %q, %q, %q, %q, %q, %q, %q, and %q are supported", o, valid.PlanRequirementsKey, valid.ApplyRequirementsKey, valid.ImportRequirementsKey, valid.WorkflowKey, valid.DeleteSourceBranchOnMergeKey, valid.RepoLockingKey, valid.RepoLocksKey, valid.PolicyCheckKey, valid.CustomPolicyCheckKey, valid.SilencePRCommentsKey)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -365,5 +385,6 @@ OuterGlobalImportReqs:
|
||||
PolicyCheck: r.PolicyCheck,
|
||||
CustomPolicyCheck: r.CustomPolicyCheck,
|
||||
AutoDiscover: autoDiscover,
|
||||
SilencePRComments: r.SilencePRComments,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ type Project struct {
|
||||
ExecutionOrderGroup *int `yaml:"execution_order_group,omitempty"`
|
||||
PolicyCheck *bool `yaml:"policy_check,omitempty"`
|
||||
CustomPolicyCheck *bool `yaml:"custom_policy_check,omitempty"`
|
||||
SilencePRComments []string `yaml:"silence_pr_comments,omitempty"`
|
||||
}
|
||||
|
||||
func (p Project) Validate() error {
|
||||
@@ -156,6 +157,10 @@ func (p Project) ToValid() valid.Project {
|
||||
v.CustomPolicyCheck = p.CustomPolicyCheck
|
||||
}
|
||||
|
||||
if p.SilencePRComments != nil {
|
||||
v.SilencePRComments = p.SilencePRComments
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ type RepoCfg struct {
|
||||
AllowedRegexpPrefixes []string `yaml:"allowed_regexp_prefixes,omitempty"`
|
||||
AbortOnExcecutionOrderFail *bool `yaml:"abort_on_execution_order_fail,omitempty"`
|
||||
RepoLocks *RepoLocks `yaml:"repo_locks,omitempty"`
|
||||
SilencePRComments []string `yaml:"silence_pr_comments,omitempty"`
|
||||
}
|
||||
|
||||
func (r RepoCfg) Validate() error {
|
||||
@@ -96,5 +97,6 @@ func (r RepoCfg) ToValid() valid.RepoCfg {
|
||||
EmojiReaction: emojiReaction,
|
||||
AbortOnExcecutionOrderFail: abortOnExcecutionOrderFail,
|
||||
RepoLocks: repoLocks,
|
||||
SilencePRComments: r.SilencePRComments,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ const RepoLocksKey = "repo_locks"
|
||||
const PolicyCheckKey = "policy_check"
|
||||
const CustomPolicyCheckKey = "custom_policy_check"
|
||||
const AutoDiscoverKey = "autodiscover"
|
||||
const SilencePRCommentsKey = "silence_pr_comments"
|
||||
|
||||
var AllowedSilencePRComments = []string{"plan", "apply"}
|
||||
|
||||
// DefaultAtlantisFile is the default name of the config file for each repo.
|
||||
const DefaultAtlantisFile = "atlantis.yaml"
|
||||
@@ -85,6 +88,7 @@ type Repo struct {
|
||||
PolicyCheck *bool
|
||||
CustomPolicyCheck *bool
|
||||
AutoDiscover *AutoDiscover
|
||||
SilencePRComments []string
|
||||
}
|
||||
|
||||
type MergedProjectCfg struct {
|
||||
@@ -107,6 +111,7 @@ type MergedProjectCfg struct {
|
||||
RepoLocks RepoLocks
|
||||
PolicyCheck bool
|
||||
CustomPolicyCheck bool
|
||||
SilencePRComments []string
|
||||
}
|
||||
|
||||
// WorkflowHook is a map of custom run commands to run before or after workflows.
|
||||
@@ -212,8 +217,9 @@ func NewGlobalCfgFromArgs(args GlobalCfgArgs) GlobalCfg {
|
||||
repoLocks := DefaultRepoLocks
|
||||
customPolicyCheck := false
|
||||
autoDiscover := AutoDiscover{Mode: AutoDiscoverAutoMode}
|
||||
var silencePRComments []string
|
||||
if args.AllowAllRepoSettings {
|
||||
allowedOverrides = []string{PlanRequirementsKey, ApplyRequirementsKey, ImportRequirementsKey, WorkflowKey, DeleteSourceBranchOnMergeKey, RepoLockingKey, RepoLocksKey, PolicyCheckKey}
|
||||
allowedOverrides = []string{PlanRequirementsKey, ApplyRequirementsKey, ImportRequirementsKey, WorkflowKey, DeleteSourceBranchOnMergeKey, RepoLockingKey, RepoLocksKey, PolicyCheckKey, SilencePRCommentsKey}
|
||||
allowCustomWorkflows = true
|
||||
}
|
||||
|
||||
@@ -237,6 +243,7 @@ func NewGlobalCfgFromArgs(args GlobalCfgArgs) GlobalCfg {
|
||||
PolicyCheck: &policyCheck,
|
||||
CustomPolicyCheck: &customPolicyCheck,
|
||||
AutoDiscover: &autoDiscover,
|
||||
SilencePRComments: silencePRComments,
|
||||
},
|
||||
},
|
||||
Workflows: map[string]Workflow{
|
||||
@@ -273,7 +280,7 @@ func (r Repo) IDString() string {
|
||||
// final config. It assumes that all configs have been validated.
|
||||
func (g GlobalCfg) MergeProjectCfg(log logging.SimpleLogging, repoID string, proj Project, rCfg RepoCfg) MergedProjectCfg {
|
||||
log.Debug("MergeProjectCfg started")
|
||||
planReqs, applyReqs, importReqs, workflow, allowedOverrides, allowCustomWorkflows, deleteSourceBranchOnMerge, repoLocks, policyCheck, customPolicyCheck, _ := g.getMatchingCfg(log, repoID)
|
||||
planReqs, applyReqs, importReqs, workflow, allowedOverrides, allowCustomWorkflows, deleteSourceBranchOnMerge, repoLocks, policyCheck, customPolicyCheck, _, silencePRComments := g.getMatchingCfg(log, repoID)
|
||||
// If repos are allowed to override certain keys then override them.
|
||||
for _, key := range allowedOverrides {
|
||||
switch key {
|
||||
@@ -366,12 +373,29 @@ func (g GlobalCfg) MergeProjectCfg(log logging.SimpleLogging, repoID string, pro
|
||||
log.Debug("overriding server-defined %s with repo settings: [%t]", CustomPolicyCheckKey, *proj.CustomPolicyCheck)
|
||||
customPolicyCheck = *proj.CustomPolicyCheck
|
||||
}
|
||||
case SilencePRCommentsKey:
|
||||
if proj.SilencePRComments != nil {
|
||||
log.Debug("overriding repo-root-defined %s with repo settings: [%t]", SilencePRCommentsKey, strings.Join(proj.SilencePRComments, ","))
|
||||
silencePRComments = proj.SilencePRComments
|
||||
} else if rCfg.SilencePRComments != nil {
|
||||
log.Debug("overriding server-defined %s with repo settings: [%s]", SilencePRCommentsKey, strings.Join(rCfg.SilencePRComments, ","))
|
||||
silencePRComments = rCfg.SilencePRComments
|
||||
}
|
||||
}
|
||||
log.Debug("MergeProjectCfg completed")
|
||||
}
|
||||
|
||||
log.Debug("final settings: %s: [%s], %s: [%s], %s: [%s], %s: %s",
|
||||
PlanRequirementsKey, strings.Join(planReqs, ","), ApplyRequirementsKey, strings.Join(applyReqs, ","), ImportRequirementsKey, strings.Join(importReqs, ","), WorkflowKey, workflow.Name)
|
||||
log.Debug("final settings: %s: [%s], %s: [%s], %s: [%s], %s: %s, %s: %t, %s: %s, %s: %t, %s: %t, %s: [%s]",
|
||||
PlanRequirementsKey, strings.Join(planReqs, ","),
|
||||
ApplyRequirementsKey, strings.Join(applyReqs, ","),
|
||||
ImportRequirementsKey, strings.Join(importReqs, ","),
|
||||
WorkflowKey, workflow.Name,
|
||||
DeleteSourceBranchOnMergeKey, deleteSourceBranchOnMerge,
|
||||
RepoLockingKey, repoLocks.Mode,
|
||||
PolicyCheckKey, policyCheck,
|
||||
CustomPolicyCheckKey, policyCheck,
|
||||
SilencePRCommentsKey, strings.Join(silencePRComments, ","),
|
||||
)
|
||||
|
||||
return MergedProjectCfg{
|
||||
PlanRequirements: planReqs,
|
||||
@@ -391,6 +415,7 @@ func (g GlobalCfg) MergeProjectCfg(log logging.SimpleLogging, repoID string, pro
|
||||
RepoLocks: repoLocks,
|
||||
PolicyCheck: policyCheck,
|
||||
CustomPolicyCheck: customPolicyCheck,
|
||||
SilencePRComments: silencePRComments,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,7 +423,7 @@ func (g GlobalCfg) MergeProjectCfg(log logging.SimpleLogging, repoID string, pro
|
||||
// repo with id repoID. It is used when there is no repo config.
|
||||
func (g GlobalCfg) DefaultProjCfg(log logging.SimpleLogging, repoID string, repoRelDir string, workspace string) MergedProjectCfg {
|
||||
log.Debug("building config based on server-side config")
|
||||
planReqs, applyReqs, importReqs, workflow, _, _, deleteSourceBranchOnMerge, repoLocks, policyCheck, customPolicyCheck, _ := g.getMatchingCfg(log, repoID)
|
||||
planReqs, applyReqs, importReqs, workflow, _, _, deleteSourceBranchOnMerge, repoLocks, policyCheck, customPolicyCheck, _, silencePRComments := g.getMatchingCfg(log, repoID)
|
||||
return MergedProjectCfg{
|
||||
PlanRequirements: planReqs,
|
||||
ApplyRequirements: applyReqs,
|
||||
@@ -414,6 +439,7 @@ func (g GlobalCfg) DefaultProjCfg(log logging.SimpleLogging, repoID string, repo
|
||||
RepoLocks: repoLocks,
|
||||
PolicyCheck: policyCheck,
|
||||
CustomPolicyCheck: customPolicyCheck,
|
||||
SilencePRComments: silencePRComments,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,6 +500,26 @@ func (g GlobalCfg) ValidateRepoCfg(rCfg RepoCfg, repoID string) error {
|
||||
if p.CustomPolicyCheck != nil && !utils.SlicesContains(allowedOverrides, CustomPolicyCheckKey) {
|
||||
return fmt.Errorf("repo config not allowed to set '%s' key: server-side config needs '%s: [%s]'", CustomPolicyCheckKey, AllowedOverridesKey, CustomPolicyCheckKey)
|
||||
}
|
||||
if p.SilencePRComments != nil {
|
||||
if !utils.SlicesContains(allowedOverrides, SilencePRCommentsKey) {
|
||||
return fmt.Errorf(
|
||||
"repo config not allowed to set '%s' key: server-side config needs '%s: [%s]'",
|
||||
SilencePRCommentsKey,
|
||||
AllowedOverridesKey,
|
||||
SilencePRCommentsKey,
|
||||
)
|
||||
}
|
||||
for _, silenceStage := range p.SilencePRComments {
|
||||
if !utils.SlicesContains(AllowedSilencePRComments, silenceStage) {
|
||||
return fmt.Errorf(
|
||||
"repo config '%s' key value of '%s' is not supported, supported values are [%s]",
|
||||
SilencePRCommentsKey,
|
||||
silenceStage,
|
||||
strings.Join(AllowedSilencePRComments, ", "),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check custom workflows.
|
||||
@@ -532,7 +578,7 @@ func (g GlobalCfg) ValidateRepoCfg(rCfg RepoCfg, repoID string) error {
|
||||
}
|
||||
|
||||
// getMatchingCfg returns the key settings for repoID.
|
||||
func (g GlobalCfg) getMatchingCfg(log logging.SimpleLogging, repoID string) (planReqs []string, applyReqs []string, importReqs []string, workflow Workflow, allowedOverrides []string, allowCustomWorkflows bool, deleteSourceBranchOnMerge bool, repoLocks RepoLocks, policyCheck bool, customPolicyCheck bool, autoDiscover AutoDiscover) {
|
||||
func (g GlobalCfg) getMatchingCfg(log logging.SimpleLogging, repoID string) (planReqs []string, applyReqs []string, importReqs []string, workflow Workflow, allowedOverrides []string, allowCustomWorkflows bool, deleteSourceBranchOnMerge bool, repoLocks RepoLocks, policyCheck bool, customPolicyCheck bool, autoDiscover AutoDiscover, silencePRComments []string) {
|
||||
toLog := make(map[string]string)
|
||||
traceF := func(repoIdx int, repoID string, key string, val interface{}) string {
|
||||
from := "default server config"
|
||||
@@ -559,7 +605,7 @@ func (g GlobalCfg) getMatchingCfg(log logging.SimpleLogging, repoID string) (pla
|
||||
repoLocking := true
|
||||
repoLocks = DefaultRepoLocks
|
||||
|
||||
for _, key := range []string{PlanRequirementsKey, ApplyRequirementsKey, ImportRequirementsKey, WorkflowKey, AllowedOverridesKey, AllowCustomWorkflowsKey, DeleteSourceBranchOnMergeKey, RepoLockingKey, RepoLocksKey, PolicyCheckKey, CustomPolicyCheckKey} {
|
||||
for _, key := range []string{PlanRequirementsKey, ApplyRequirementsKey, ImportRequirementsKey, WorkflowKey, AllowedOverridesKey, AllowCustomWorkflowsKey, DeleteSourceBranchOnMergeKey, RepoLockingKey, RepoLocksKey, PolicyCheckKey, CustomPolicyCheckKey, SilencePRCommentsKey} {
|
||||
for i, repo := range g.Repos {
|
||||
if repo.IDMatches(repoID) {
|
||||
switch key {
|
||||
@@ -623,6 +669,11 @@ func (g GlobalCfg) getMatchingCfg(log logging.SimpleLogging, repoID string) (pla
|
||||
toLog[AutoDiscoverKey] = traceF(i, repo.IDString(), AutoDiscoverKey, repo.AutoDiscover.Mode)
|
||||
autoDiscover = *repo.AutoDiscover
|
||||
}
|
||||
case SilencePRCommentsKey:
|
||||
if repo.SilencePRComments != nil {
|
||||
toLog[SilencePRCommentsKey] = traceF(i, repo.IDString(), SilencePRCommentsKey, repo.SilencePRComments)
|
||||
silencePRComments = repo.SilencePRComments
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ func TestNewGlobalCfg(t *testing.T) {
|
||||
|
||||
if c.allowAllRepoSettings {
|
||||
exp.Repos[0].AllowCustomWorkflows = Bool(true)
|
||||
exp.Repos[0].AllowedOverrides = []string{"plan_requirements", "apply_requirements", "import_requirements", "workflow", "delete_source_branch_on_merge", "repo_locking", "repo_locks", "policy_check"}
|
||||
exp.Repos[0].AllowedOverrides = []string{"plan_requirements", "apply_requirements", "import_requirements", "workflow", "delete_source_branch_on_merge", "repo_locking", "repo_locks", "policy_check", "silence_pr_comments"}
|
||||
}
|
||||
if c.policyCheckEnabled {
|
||||
exp.Repos[0].PlanRequirements = append(exp.Repos[0].PlanRequirements, "policies_passed")
|
||||
|
||||
@@ -29,6 +29,7 @@ type RepoCfg struct {
|
||||
EmojiReaction string
|
||||
AllowedRegexpPrefixes []string
|
||||
AbortOnExcecutionOrderFail bool
|
||||
SilencePRComments []string
|
||||
}
|
||||
|
||||
func (r RepoCfg) FindProjectsByDirWorkspace(repoRelDir string, workspace string) []Project {
|
||||
@@ -158,6 +159,7 @@ type Project struct {
|
||||
ExecutionOrderGroup int
|
||||
PolicyCheck *bool
|
||||
CustomPolicyCheck *bool
|
||||
SilencePRComments []string
|
||||
}
|
||||
|
||||
// GetName returns the name of the project or an empty string if there is no
|
||||
|
||||
@@ -60,6 +60,7 @@ type ApplyCommandRunner struct {
|
||||
// SilenceVCSStatusNoPlans is whether any plan should set commit status if no projects
|
||||
// are found
|
||||
silenceVCSStatusNoProjects bool
|
||||
SilencePRComments []string
|
||||
}
|
||||
|
||||
func (a *ApplyCommandRunner) Run(ctx *command.Context, cmd *CommentCommand) {
|
||||
|
||||
@@ -125,6 +125,7 @@ type ProjectContext struct {
|
||||
AbortOnExcecutionOrderFail bool
|
||||
// Allows custom policy check tools outside of Conftest to run in checks
|
||||
CustomPolicyCheck bool
|
||||
SilencePRComments []string
|
||||
}
|
||||
|
||||
// SetProjectScopeTags adds ProjectContext tags to a new returned scope.
|
||||
|
||||
@@ -19,6 +19,7 @@ type ProjectResult struct {
|
||||
ImportSuccess *models.ImportSuccess
|
||||
StateRmSuccess *models.StateRmSuccess
|
||||
ProjectName string
|
||||
SilencePRComments []string
|
||||
}
|
||||
|
||||
// CommitStatus returns the vcs commit status of this project result.
|
||||
|
||||
@@ -76,6 +76,7 @@ type PlanCommandRunner struct {
|
||||
// a plan.
|
||||
DiscardApprovalOnPlan bool
|
||||
pullReqStatusFetcher vcs.PullReqStatusFetcher
|
||||
SilencePRComments []string
|
||||
}
|
||||
|
||||
func (p *PlanCommandRunner) runAutoplan(ctx *command.Context) {
|
||||
|
||||
@@ -276,8 +276,7 @@ func (p *DefaultProjectCommandBuilder) BuildPlanCommands(ctx *command.Context, c
|
||||
}
|
||||
ctx.Log.Debug("Building plan command for specific project with directory: '%v', workspace: '%v', project: '%v'",
|
||||
cmd.RepoRelDir, cmd.Workspace, cmd.ProjectName)
|
||||
pcc, err := p.buildProjectPlanCommand(ctx, cmd)
|
||||
return pcc, err
|
||||
return p.buildProjectPlanCommand(ctx, cmd)
|
||||
}
|
||||
|
||||
// See ProjectCommandBuilder.BuildApplyCommands.
|
||||
@@ -285,24 +284,21 @@ func (p *DefaultProjectCommandBuilder) BuildApplyCommands(ctx *command.Context,
|
||||
if !cmd.IsForSpecificProject() {
|
||||
return p.buildAllProjectCommandsByPlan(ctx, cmd)
|
||||
}
|
||||
pac, err := p.buildProjectCommand(ctx, cmd)
|
||||
return pac, err
|
||||
return p.buildProjectCommand(ctx, cmd)
|
||||
}
|
||||
|
||||
func (p *DefaultProjectCommandBuilder) BuildApprovePoliciesCommands(ctx *command.Context, cmd *CommentCommand) ([]command.ProjectContext, error) {
|
||||
if !cmd.IsForSpecificProject() {
|
||||
return p.buildAllProjectCommandsByPlan(ctx, cmd)
|
||||
}
|
||||
pac, err := p.buildProjectCommand(ctx, cmd)
|
||||
return pac, err
|
||||
return p.buildProjectCommand(ctx, cmd)
|
||||
}
|
||||
|
||||
func (p *DefaultProjectCommandBuilder) BuildVersionCommands(ctx *command.Context, cmd *CommentCommand) ([]command.ProjectContext, error) {
|
||||
if !cmd.IsForSpecificProject() {
|
||||
return p.buildAllProjectCommandsByPlan(ctx, cmd)
|
||||
}
|
||||
pac, err := p.buildProjectCommand(ctx, cmd)
|
||||
return pac, err
|
||||
return p.buildProjectCommand(ctx, cmd)
|
||||
}
|
||||
|
||||
func (p *DefaultProjectCommandBuilder) BuildImportCommands(ctx *command.Context, cmd *CommentCommand) ([]command.ProjectContext, error) {
|
||||
|
||||
@@ -306,6 +306,7 @@ func newProjectCommandContext(ctx *command.Context,
|
||||
JobID: uuid.New().String(),
|
||||
ExecutionOrderGroup: projCfg.ExecutionOrderGroup,
|
||||
AbortOnExcecutionOrderFail: abortOnExcecutionOrderFail,
|
||||
SilencePRComments: projCfg.SilencePRComments,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -225,13 +225,14 @@ type DefaultProjectCommandRunner struct {
|
||||
func (p *DefaultProjectCommandRunner) Plan(ctx command.ProjectContext) command.ProjectResult {
|
||||
planSuccess, failure, err := p.doPlan(ctx)
|
||||
return command.ProjectResult{
|
||||
Command: command.Plan,
|
||||
PlanSuccess: planSuccess,
|
||||
Error: err,
|
||||
Failure: failure,
|
||||
RepoRelDir: ctx.RepoRelDir,
|
||||
Workspace: ctx.Workspace,
|
||||
ProjectName: ctx.ProjectName,
|
||||
Command: command.Plan,
|
||||
PlanSuccess: planSuccess,
|
||||
Error: err,
|
||||
Failure: failure,
|
||||
RepoRelDir: ctx.RepoRelDir,
|
||||
Workspace: ctx.Workspace,
|
||||
ProjectName: ctx.ProjectName,
|
||||
SilencePRComments: ctx.SilencePRComments,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -253,13 +254,14 @@ func (p *DefaultProjectCommandRunner) PolicyCheck(ctx command.ProjectContext) co
|
||||
func (p *DefaultProjectCommandRunner) Apply(ctx command.ProjectContext) command.ProjectResult {
|
||||
applyOut, failure, err := p.doApply(ctx)
|
||||
return command.ProjectResult{
|
||||
Command: command.Apply,
|
||||
Failure: failure,
|
||||
Error: err,
|
||||
ApplySuccess: applyOut,
|
||||
RepoRelDir: ctx.RepoRelDir,
|
||||
Workspace: ctx.Workspace,
|
||||
ProjectName: ctx.ProjectName,
|
||||
Command: command.Apply,
|
||||
Failure: failure,
|
||||
Error: err,
|
||||
ApplySuccess: applyOut,
|
||||
RepoRelDir: ctx.RepoRelDir,
|
||||
Workspace: ctx.Workspace,
|
||||
ProjectName: ctx.ProjectName,
|
||||
SilencePRComments: ctx.SilencePRComments,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package events
|
||||
import (
|
||||
"github.com/runatlantis/atlantis/server/events/command"
|
||||
"github.com/runatlantis/atlantis/server/events/vcs"
|
||||
"github.com/runatlantis/atlantis/server/utils"
|
||||
)
|
||||
|
||||
type PullUpdater struct {
|
||||
@@ -23,12 +24,29 @@ func (c *PullUpdater) updatePull(ctx *command.Context, cmd PullCommand, res comm
|
||||
// clutter in a pull/merge request. This will not delete the comment, since the
|
||||
// comment trail may be useful in auditing or backtracing problems.
|
||||
if c.HidePrevPlanComments {
|
||||
ctx.Log.Debug("Hiding previous plan comments for command: '%v', directory: '%v'", cmd.CommandName().TitleString(), cmd.Dir())
|
||||
ctx.Log.Debug("hiding previous plan comments for command: '%v', directory: '%v'", cmd.CommandName().TitleString(), cmd.Dir())
|
||||
if err := c.VCSClient.HidePrevCommandComments(ctx.Log, ctx.Pull.BaseRepo, ctx.Pull.Num, cmd.CommandName().TitleString(), cmd.Dir()); err != nil {
|
||||
ctx.Log.Err("unable to hide old comments: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(res.ProjectResults) > 0 {
|
||||
var commentOnProjects []command.ProjectResult
|
||||
for _, result := range res.ProjectResults {
|
||||
if utils.SlicesContains(result.SilencePRComments, cmd.CommandName().String()) {
|
||||
ctx.Log.Debug("silenced command '%s' comment for project '%s'", cmd.CommandName().String(), result.ProjectName)
|
||||
continue
|
||||
}
|
||||
commentOnProjects = append(commentOnProjects, result)
|
||||
}
|
||||
|
||||
if len(commentOnProjects) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
res.ProjectResults = commentOnProjects
|
||||
}
|
||||
|
||||
comment := c.MarkdownRenderer.Render(ctx, res, cmd)
|
||||
if err := c.VCSClient.CreateComment(ctx.Log, ctx.Pull.BaseRepo, ctx.Pull.Num, comment, cmd.CommandName().String()); err != nil {
|
||||
ctx.Log.Err("unable to comment: %s", err)
|
||||
|
||||
Reference in New Issue
Block a user