mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-08-05 08:58:29 +00:00
feat: selfapprove flag for approving policies (#4794)
Co-authored-by: PePe Amengual <jose.amengual@gmail.com>
This commit is contained in:
@@ -71,6 +71,7 @@ policies:
|
||||
- `source` - Tells atlantis where to fetch the policies from. Currently you can only host policies locally by using `local`.
|
||||
- `owners` - Defines the users/teams which are able to approve a specific policy set.
|
||||
- `approve_count` - Defines the number of approvals needed to bypass policy checks. Defaults to the top-level policies configuration, if not specified.
|
||||
- `prevent_self_approve` - Defines whether the PR author can approve policies
|
||||
|
||||
By default conftest is configured to only run the `main` package. If you wish to run specific/multiple policies consider passing `--namespace` or `--all-namespaces` to conftest with [`extra_args`](custom-workflows.md#adding-extra-arguments-to-terraform-commands) via a custom workflow as shown in the below example.
|
||||
|
||||
|
||||
@@ -607,11 +607,12 @@ mode: on_apply
|
||||
|
||||
### PolicySet
|
||||
|
||||
| Key | Type | Default | Required | Description |
|
||||
| ------ | ------ | ------- | -------- | -------------------------------------- |
|
||||
| name | string | none | yes | unique name for the policy set |
|
||||
| path | string | none | yes | path to the rego policies directory |
|
||||
| source | string | none | yes | only `local` is supported at this time |
|
||||
| Key | Type | Default | Required | Description |
|
||||
| ------ | ------ | ------- | -------- | --------------------------------------------------------------------------------------------------------------|
|
||||
| name | string | none | yes | unique name for the policy set |
|
||||
| path | string | none | yes | path to the rego policies directory |
|
||||
| source | string | none | yes | only `local` is supported at this time |
|
||||
| prevent_self_approve | bool | false | no | Whether or not the author of PR can approve policies. Defaults to `false` (the author must also be in owners) |
|
||||
|
||||
### Metrics
|
||||
|
||||
|
||||
@@ -70,11 +70,12 @@ func (o PolicyOwners) ToValid() valid.PolicyOwners {
|
||||
}
|
||||
|
||||
type PolicySet struct {
|
||||
Path string `yaml:"path" json:"path"`
|
||||
Source string `yaml:"source" json:"source"`
|
||||
Name string `yaml:"name" json:"name"`
|
||||
Owners PolicyOwners `yaml:"owners,omitempty" json:"owners,omitempty"`
|
||||
ApproveCount int `yaml:"approve_count,omitempty" json:"approve_count,omitempty"`
|
||||
Path string `yaml:"path" json:"path"`
|
||||
Source string `yaml:"source" json:"source"`
|
||||
Name string `yaml:"name" json:"name"`
|
||||
Owners PolicyOwners `yaml:"owners,omitempty" json:"owners,omitempty"`
|
||||
ApproveCount int `yaml:"approve_count,omitempty" json:"approve_count,omitempty"`
|
||||
PreventSelfApprove bool `yaml:"self_approve,omitempty" json:"prevent_self_approve,omitempty"`
|
||||
}
|
||||
|
||||
func (p PolicySet) Validate() error {
|
||||
@@ -94,6 +95,7 @@ func (p PolicySet) ToValid() valid.PolicySet {
|
||||
policySet.Path = p.Path
|
||||
policySet.Source = p.Source
|
||||
policySet.ApproveCount = p.ApproveCount
|
||||
policySet.PreventSelfApprove = p.PreventSelfApprove
|
||||
policySet.Owners = p.Owners.ToValid()
|
||||
|
||||
return policySet
|
||||
|
||||
@@ -27,11 +27,12 @@ type PolicyOwners struct {
|
||||
}
|
||||
|
||||
type PolicySet struct {
|
||||
Source string
|
||||
Path string
|
||||
Name string
|
||||
ApproveCount int
|
||||
Owners PolicyOwners
|
||||
Source string
|
||||
Path string
|
||||
Name string
|
||||
ApproveCount int
|
||||
Owners PolicyOwners
|
||||
PreventSelfApprove bool
|
||||
}
|
||||
|
||||
func (p *PolicySets) HasPolicies() bool {
|
||||
|
||||
@@ -377,7 +377,7 @@ func (p *DefaultProjectCommandRunner) doApprovePolicies(ctx command.ProjectConte
|
||||
ignorePolicy = true
|
||||
}
|
||||
// Increment approval if user is owner.
|
||||
if isOwner && !ignorePolicy {
|
||||
if isOwner && !ignorePolicy && (ctx.User.Username != ctx.Pull.Author || !policySet.PreventSelfApprove) {
|
||||
if !ctx.ClearPolicyApproval {
|
||||
prjPolicyStatus[i].Approvals = policyStatus.Approvals + 1
|
||||
} else {
|
||||
@@ -391,6 +391,7 @@ func (p *DefaultProjectCommandRunner) doApprovePolicies(ctx command.ProjectConte
|
||||
if !policyStatus.Passed && (prjPolicyStatus[i].Approvals != policySet.ApproveCount) {
|
||||
allPassed = false
|
||||
}
|
||||
|
||||
prjPolicySetResults = append(prjPolicySetResults, models.PolicySetResult{
|
||||
PolicySetName: policySet.Name,
|
||||
Passed: policyStatus.Passed,
|
||||
|
||||
@@ -1168,6 +1168,56 @@ func TestDefaultProjectCommandRunner_ApprovePolicies(t *testing.T) {
|
||||
expFailure: `One or more policy sets require additional approval.`,
|
||||
hasErr: false,
|
||||
},
|
||||
{
|
||||
description: "Policy Approval should not be the Author of the PR",
|
||||
userTeams: []string{"someuserteam"},
|
||||
clearPolicyApproval: false,
|
||||
policySetCfg: valid.PolicySets{
|
||||
PolicySets: []valid.PolicySet{
|
||||
{
|
||||
Owners: valid.PolicyOwners{
|
||||
Users: []string{"lkysow"},
|
||||
},
|
||||
Name: "policy1",
|
||||
ApproveCount: 1,
|
||||
},
|
||||
{
|
||||
Owners: valid.PolicyOwners{
|
||||
Users: []string{"lkysow"},
|
||||
},
|
||||
Name: "policy2",
|
||||
ApproveCount: 1,
|
||||
PreventSelfApprove: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
policySetStatus: []models.PolicySetStatus{
|
||||
{
|
||||
PolicySetName: "policy1",
|
||||
Approvals: 0,
|
||||
Passed: false,
|
||||
},
|
||||
{
|
||||
PolicySetName: "policy2",
|
||||
Approvals: 0,
|
||||
Passed: false,
|
||||
},
|
||||
},
|
||||
expOut: []models.PolicySetResult{
|
||||
{
|
||||
PolicySetName: "policy1",
|
||||
ReqApprovals: 1,
|
||||
CurApprovals: 1,
|
||||
},
|
||||
{
|
||||
PolicySetName: "policy2",
|
||||
ReqApprovals: 1,
|
||||
CurApprovals: 0,
|
||||
},
|
||||
},
|
||||
expFailure: `One or more policy sets require additional approval.`,
|
||||
hasErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
@@ -1225,7 +1275,7 @@ func TestDefaultProjectCommandRunner_ApprovePolicies(t *testing.T) {
|
||||
projPolicyStatus = c.policySetStatus
|
||||
}
|
||||
|
||||
modelPull := models.PullRequest{BaseRepo: testdata.GithubRepo, State: models.OpenPullState, Num: testdata.Pull.Num}
|
||||
modelPull := models.PullRequest{BaseRepo: testdata.GithubRepo, State: models.OpenPullState, Num: testdata.Pull.Num, Author: testdata.User.Username}
|
||||
When(runner.VcsClient.GetTeamNamesForUser(testdata.GithubRepo, testdata.User)).ThenReturn(c.userTeams, nil)
|
||||
ctx := command.ProjectContext{
|
||||
User: testdata.User,
|
||||
|
||||
Reference in New Issue
Block a user