Skip to content

Commit

Permalink
Merge pull request #457 from runatlantis/automerge
Browse files Browse the repository at this point in the history
Add automerge capability
  • Loading branch information
lkysow authored Feb 7, 2019
2 parents 2c6b87d + 74e9bbb commit 102addc
Show file tree
Hide file tree
Showing 67 changed files with 2,480 additions and 648 deletions.
9 changes: 5 additions & 4 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
- checkout
- run: make test-coverage
- run: make check-fmt
- run: make check-gometalint
- run: make check-lint
- run:
name: post coverage to codecov.io
command: bash <(curl -s https://codecov.io/bash)
Expand Down Expand Up @@ -42,9 +42,10 @@ jobs:
# We use dockerize -wait here to wait until the server is up.
- run: |
dockerize -wait tcp://localhost:8080 -- \
muffet -e 'https://github\\.com/runatlantis/atlantis/edit/master/.*' \
-e 'https://github.com/helm/charts/tree/master/stable/atlantis#customization' \
http://localhost:8080/
muffet \
-e 'https://github\.com/runatlantis/atlantis/edit/master/.*' \
-e 'https://github.com/helm/charts/tree/master/stable/atlantis#customization' \
http://localhost:8080/
# Build and push 'latest' Docker tag.
docker_master:
Expand Down
21 changes: 21 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
linters:
enable:
- deadcode
- errcheck
- gochecknoinits
# We don't use goconst because it gives false positives in the tests.
# - goconst
- gofmt
- golint
- gosec
- gosimple
- ineffassign
- interfacer
- staticcheck
- structcheck
- typecheck
- unconvert
- unused
- varcheck
- vet
- vetshadow
44 changes: 0 additions & 44 deletions .gometalinter.json

This file was deleted.

19 changes: 6 additions & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,19 +60,12 @@ release: ## Create packages for a release
fmt: ## Run goimports (which also formats)
goimports -w $$(find . -type f -name '*.go' ! -path "./vendor/*" ! -path "./server/static/bindata_assetfs.go" ! -path "**/mocks/*")

gometalint: ## Run every linter ever
# gotype and gotypex are disabled because they don't pass on CI and https://github.com/alecthomas/gometalinter/issues/206
# maligned is disabled because I'd rather have alphabetical struct fields than save a few bytes
# gocyclo is temporarily disabled because we don't pass it right now
# golint is temporarily disabled because we need to add comments everywhere first
# CGO_ENABLED=0 is attempted workaround for https://github.com/alecthomas/gometalinter/issues/149
CGO_ENABLED=0 gometalinter --config=.gometalinter.json ./...

gometalint-install: ## Install gometalint
go get -u github.com/alecthomas/gometalinter
gometalinter --install

check-gometalint: gometalint-install gometalint
lint: ## Run linter
golangci-lint run

check-lint:
curl -sfL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b ./bin v1.13.2
./bin/golangci-lint run

check-fmt: ## Fail if not formatted
go get golang.org/x/tools/cmd/goimports
Expand Down
6 changes: 6 additions & 0 deletions cmd/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const (
AllowForkPRsFlag = "allow-fork-prs"
AllowRepoConfigFlag = "allow-repo-config"
AtlantisURLFlag = "atlantis-url"
AutomergeFlag = "automerge"
BitbucketBaseURLFlag = "bitbucket-base-url"
BitbucketTokenFlag = "bitbucket-token"
BitbucketUserFlag = "bitbucket-user"
Expand Down Expand Up @@ -205,6 +206,11 @@ var boolFlags = []boolFlag{
" on the Atlantis server.",
defaultValue: false,
},
{
name: AutomergeFlag,
description: "Automatically merge pull requests when all plans are successfully applied.",
defaultValue: false,
},
{
name: RequireApprovalFlag,
description: "Require pull requests to be \"Approved\" before allowing the apply command to be run.",
Expand Down
14 changes: 14 additions & 0 deletions cmd/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ func TestExecute_Defaults(t *testing.T) {
Equals(t, "http://"+hostname+":4141", passedConfig.AtlantisURL)
Equals(t, false, passedConfig.AllowForkPRs)
Equals(t, false, passedConfig.AllowRepoConfig)
Equals(t, false, passedConfig.Automerge)

// Get our home dir since that's what gets defaulted to
dataDir, err := homedir.Expand("~/.atlantis")
Expand Down Expand Up @@ -438,6 +439,7 @@ func TestExecute_Flags(t *testing.T) {
cmd.AtlantisURLFlag: "url",
cmd.AllowForkPRsFlag: true,
cmd.AllowRepoConfigFlag: true,
cmd.AutomergeFlag: true,
cmd.BitbucketBaseURLFlag: "https://bitbucket-base-url.com",
cmd.BitbucketTokenFlag: "bitbucket-token",
cmd.BitbucketUserFlag: "bitbucket-user",
Expand Down Expand Up @@ -468,6 +470,7 @@ func TestExecute_Flags(t *testing.T) {
Equals(t, "url", passedConfig.AtlantisURL)
Equals(t, true, passedConfig.AllowForkPRs)
Equals(t, true, passedConfig.AllowRepoConfig)
Equals(t, true, passedConfig.Automerge)
Equals(t, "https://bitbucket-base-url.com", passedConfig.BitbucketBaseURL)
Equals(t, "bitbucket-token", passedConfig.BitbucketToken)
Equals(t, "bitbucket-user", passedConfig.BitbucketUser)
Expand Down Expand Up @@ -499,6 +502,7 @@ func TestExecute_ConfigFile(t *testing.T) {
atlantis-url: "url"
allow-fork-prs: true
allow-repo-config: true
automerge: true
bitbucket-base-url: "https://mydomain.com"
bitbucket-token: "bitbucket-token"
bitbucket-user: "bitbucket-user"
Expand Down Expand Up @@ -533,6 +537,7 @@ tfe-token: my-token
Equals(t, "url", passedConfig.AtlantisURL)
Equals(t, true, passedConfig.AllowForkPRs)
Equals(t, true, passedConfig.AllowRepoConfig)
Equals(t, true, passedConfig.Automerge)
Equals(t, "https://mydomain.com", passedConfig.BitbucketBaseURL)
Equals(t, "bitbucket-token", passedConfig.BitbucketToken)
Equals(t, "bitbucket-user", passedConfig.BitbucketUser)
Expand Down Expand Up @@ -564,6 +569,7 @@ func TestExecute_EnvironmentOverride(t *testing.T) {
atlantis-url: "url"
allow-fork-prs: true
allow-repo-config: true
automerge: true
bitbucket-base-url: "https://mydomain.com"
bitbucket-token: "bitbucket-token"
bitbucket-user: "bitbucket-user"
Expand Down Expand Up @@ -594,6 +600,7 @@ tfe-token: my-token
"ATLANTIS_URL": "override-url",
"ALLOW_FORK_PRS": "false",
"ALLOW_REPO_CONFIG": "false",
"AUTOMERGE": "false",
"BITBUCKET_BASE_URL": "https://override-bitbucket-base-url",
"BITBUCKET_TOKEN": "override-bitbucket-token",
"BITBUCKET_USER": "override-bitbucket-user",
Expand Down Expand Up @@ -628,6 +635,7 @@ tfe-token: my-token
Equals(t, "override-url", passedConfig.AtlantisURL)
Equals(t, false, passedConfig.AllowForkPRs)
Equals(t, false, passedConfig.AllowRepoConfig)
Equals(t, false, passedConfig.Automerge)
Equals(t, "https://override-bitbucket-base-url", passedConfig.BitbucketBaseURL)
Equals(t, "override-bitbucket-token", passedConfig.BitbucketToken)
Equals(t, "override-bitbucket-user", passedConfig.BitbucketUser)
Expand Down Expand Up @@ -659,6 +667,7 @@ func TestExecute_FlagConfigOverride(t *testing.T) {
atlantis-url: "url"
allow-fork-prs: true
allow-repo-config: true
automerge: true
bitbucket-base-url: "https://bitbucket-base-url"
bitbucket-token: "bitbucket-token"
bitbucket-user: "bitbucket-user"
Expand Down Expand Up @@ -689,6 +698,7 @@ tfe-token: my-token
cmd.AtlantisURLFlag: "override-url",
cmd.AllowForkPRsFlag: false,
cmd.AllowRepoConfigFlag: false,
cmd.AutomergeFlag: false,
cmd.BitbucketBaseURLFlag: "https://override-bitbucket-base-url",
cmd.BitbucketTokenFlag: "override-bitbucket-token",
cmd.BitbucketUserFlag: "override-bitbucket-user",
Expand Down Expand Up @@ -717,6 +727,7 @@ tfe-token: my-token
Ok(t, err)
Equals(t, "override-url", passedConfig.AtlantisURL)
Equals(t, false, passedConfig.AllowForkPRs)
Equals(t, false, passedConfig.Automerge)
Equals(t, "https://override-bitbucket-base-url", passedConfig.BitbucketBaseURL)
Equals(t, "override-bitbucket-token", passedConfig.BitbucketToken)
Equals(t, "override-bitbucket-user", passedConfig.BitbucketUser)
Expand Down Expand Up @@ -750,6 +761,7 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
"ATLANTIS_URL": "url",
"ALLOW_FORK_PRS": "true",
"ALLOW_REPO_CONFIG": "true",
"AUTOMERGE": "true",
"BITBUCKET_BASE_URL": "https://bitbucket-base-url",
"BITBUCKET_TOKEN": "bitbucket-token",
"BITBUCKET_USER": "bitbucket-user",
Expand Down Expand Up @@ -788,6 +800,7 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
cmd.AtlantisURLFlag: "override-url",
cmd.AllowForkPRsFlag: false,
cmd.AllowRepoConfigFlag: false,
cmd.AutomergeFlag: false,
cmd.BitbucketBaseURLFlag: "https://override-bitbucket-base-url",
cmd.BitbucketTokenFlag: "override-bitbucket-token",
cmd.BitbucketUserFlag: "override-bitbucket-user",
Expand Down Expand Up @@ -818,6 +831,7 @@ func TestExecute_FlagEnvVarOverride(t *testing.T) {
Equals(t, "override-url", passedConfig.AtlantisURL)
Equals(t, false, passedConfig.AllowForkPRs)
Equals(t, false, passedConfig.AllowRepoConfig)
Equals(t, false, passedConfig.Automerge)
Equals(t, "https://override-bitbucket-base-url", passedConfig.BitbucketBaseURL)
Equals(t, "override-bitbucket-token", passedConfig.BitbucketToken)
Equals(t, "override-bitbucket-user", passedConfig.BitbucketUser)
Expand Down
1 change: 1 addition & 0 deletions runatlantis.io/.vuepress/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ module.exports = {
['how-atlantis-works', 'Overview'],
'locking',
'autoplanning',
'automerging',
'checkout-strategy',
'security'
]
Expand Down
13 changes: 8 additions & 5 deletions runatlantis.io/docs/atlantis-yaml-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ to use `atlantis.yaml` files.
## Example Using All Keys
```yaml
version: 2
automerge: true
projects:
- name: my-project-name
dir: .
Expand Down Expand Up @@ -67,14 +68,16 @@ It should be noted that `atlantis apply` itself could be exploited if run on a m
### Top-Level Keys
```yaml
version:
automerge:
projects:
workflows:
```
| Key | Type | Default | Required | Description |
| --------- | ---------------------------------------------------------------- | ------- | -------- | ------------------------------------------- |
| version | int | none | yes | This key is required and must be set to `2` |
| projects | array[[Project](atlantis-yaml-reference.html#project)] | [] | no | Lists the projects in this repo |
| workflows | map[string -> [Workflow](atlantis-yaml-reference.html#workflow)] | {} | no | Custom workflows |
| Key | Type | Default | Required | Description |
| --------- | ---------------------------------------------------------------- | ------- | -------- | ----------------------------------------------------------- |
| version | int | none | yes | This key is required and must be set to `2` |
| automerge | bool | false | no | Automatically merge pull request when all plans are applied |
| projects | array[[Project](atlantis-yaml-reference.html#project)] | [] | no | Lists the projects in this repo |
| workflows | map[string -> [Workflow](atlantis-yaml-reference.html#workflow)] | {} | no | Custom workflows |

### Project
```yaml
Expand Down
44 changes: 44 additions & 0 deletions runatlantis.io/docs/automerging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Automerging
Atlantis can be configured to automatically merge a pull request after all plans have
been successfully applied.


![Automerge](./images/automerge.png)

## How To Enable
Automerging can be enabled either by:
1. Passing the `--automerge` flag to `atlantis server`. This will cause all
pull requests to be automerged and any repo config will be ignored.
1. Setting `automerge: true` in the repo's `atlantis.yaml` file:
```yaml
version: 2
automerge: true
projects:
- dir: .
```
:::tip NOTE
If a repo has an `atlantis.yaml` file, then each project in the repo needs
to be configured under the `projects` key.
:::

## All Plans Must Succeed
When automerge is enabled, **all plans** in a pull request **must succeed** before
**any** plans can be applied.

For example, imagine this scenario:
1. I open a pull request that makes changes to two Terraform projects, in `dir1/`
and `dir2/`.
1. The plan for `dir2/` fails because my Terraform syntax is wrong.

In this scenario, I can't run
```
atlantis apply -d dir1
```
Even though that plan succeeded, because **all** plans must succeed for **any** plans
to be saved.
Once I fix the issue in `dir2`, I can push a new commit which will trigger an
autoplan. Then I will be able to apply both plans.
## Permissions
The Atlantis VCS user must have the ability to merge pull requests.
Binary file added runatlantis.io/docs/images/automerge.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
22 changes: 21 additions & 1 deletion server/events/command_result.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,29 @@

package events

import "github.com/runatlantis/atlantis/server/events/models"

// CommandResult is the result of running a Command.
type CommandResult struct {
Error error
Failure string
ProjectResults []ProjectResult
ProjectResults []models.ProjectResult
// PlansDeleted is true if all plans created during this command were
// deleted. This happens if automerging is enabled and one project has an
// error since automerging requires all plans to succeed.
PlansDeleted bool
}

// HasErrors returns true if there were any errors during the execution,
// even if it was only in one project.
func (c CommandResult) HasErrors() bool {
if c.Error != nil || c.Failure != "" {
return true
}
for _, r := range c.ProjectResults {
if !r.IsSuccessful() {
return true
}
}
return false
}
Loading

0 comments on commit 102addc

Please sign in to comment.