Files
atlantis/server/pull_closed_executor.go
Luke Kysow 57e18399d7 Delete plan on successful apply (#46)
* Return locks when they're deleted

* Implement DeletePlan and DeletePlanByPull

* Clean up data from pull request on close

* Delete plan on successful apply
2017-06-25 10:11:51 -07:00

80 lines
2.2 KiB
Go

package server
import (
"github.com/hootsuite/atlantis/locking"
"github.com/hootsuite/atlantis/models"
"github.com/pkg/errors"
"github.com/hootsuite/atlantis/plan"
"fmt"
"strings"
"text/template"
"bytes"
)
type PullClosedExecutor struct {
locking *locking.Client
github *GithubClient
planBackend plan.Backend
}
type templatedProject struct {
Path string
Envs string
}
var pullClosedTemplate = template.Must(template.New("").Parse("Locks and plans deleted for the projects and environments modified in this pull request:\n" +
"{{ range . }}\n" +
"- path: `{{ .Path }}` {{ .Envs }}{{ end }}"))
func (p *PullClosedExecutor) CleanUpPull(repo models.Repo, pull models.PullRequest) error {
locks, err := p.locking.UnlockByPull(repo.FullName, pull.Num)
if err != nil {
return errors.Wrap(err, "cleaning up locks")
}
// if there are no locks then there's no need to comment
if len(locks) == 0 {
return nil
}
err = p.planBackend.DeletePlansByPull(repo.FullName, pull.Num)
if err != nil {
return errors.Wrap(err, "cleaning up plans")
}
templateData := p.buildTemplateData(locks)
var buf bytes.Buffer
if err = pullClosedTemplate.Execute(&buf, templateData); err != nil {
return errors.Wrap(err, "rendering template for comment")
}
return p.github.CreateComment(repo, pull, buf.String())
}
// buildTemplateData formats the lock data into a slice that can easily be templated
// for the GitHub comment. We organize all the environments by their respective project paths
// so the comment can look like: path: {path}, environments: {all-envs}
func (p *PullClosedExecutor) buildTemplateData(locks []models.ProjectLock) []templatedProject {
envsByPath := make(map[string][]string)
for _, l := range locks {
path := l.Project.RepoFullName + "/" + l.Project.Path
envsByPath[path] = append(envsByPath[path], l.Env)
}
var projects []templatedProject
for p, e := range envsByPath {
envsStr := fmt.Sprintf("`%s`", strings.Join(e, "`, `"))
if len(e) == 1 {
projects = append(projects, templatedProject{
Path: p,
Envs: "environment: " + envsStr,
})
} else {
projects = append(projects, templatedProject{
Path: p,
Envs: "environments: " + envsStr,
})
}
}
return projects
}