forked from hootsuite/atlantis
/
github_comment_renderer.go
120 lines (109 loc) · 3.51 KB
/
github_comment_renderer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
package server
import (
"bytes"
"fmt"
"strings"
"text/template"
)
var singleProjectTmpl = template.Must(template.New("").Parse("{{ range $result := .Results }}{{$result}}{{end}}\n" + logTmpl))
var multiProjectTmpl = template.Must(template.New("").Parse(
"Ran {{.Command}} in {{ len .Results }} directories:\n" +
"{{ range $path, $result := .Results }}" +
" * `{{$path}}`\n" +
"{{end}}\n" +
"{{ range $path, $result := .Results }}" +
"##{{$path}}/\n" +
"{{$result}}\n" +
"---{{end}}" +
logTmpl))
var planSuccessTmpl = template.Must(template.New("").Parse(
"```diff\n" +
"{{.TerraformOutput}}\n" +
"```\n\n" +
"* To **discard** this plan click [here]({{.LockURL}})."))
var applySuccessTmpl = template.Must(template.New("").Parse(
"```diff\n" +
"{{.Output}}\n" +
"```"))
var errTmplText = "**{{.Command}} Error**\n" +
"```\n" +
"{{.Error}}\n" +
"```\n"
var errTmpl = template.Must(template.New("").Parse(errTmplText))
var errWithLogTmpl = template.Must(template.New("").Parse(errTmplText + logTmpl))
var failureTmplText = "**{{.Command}} Failed**: {{.Failure}}\n"
var failureTmpl = template.Must(template.New("").Parse(failureTmplText))
var failureWithLogTmpl = template.Must(template.New("").Parse(failureTmplText + logTmpl))
var logTmpl = "{{if .Verbose}}\n<details><summary>Log</summary>\n <p>\n\n```\n{{.Log}}```\n</p></details>{{end}}\n"
// GithubCommentRenderer renders responses as GitHub comments
type GithubCommentRenderer struct{}
type CommonData struct {
Command string
Verbose bool
Log string
}
type ErrData struct {
Error string
CommonData
}
type FailureData struct {
Failure string
CommonData
}
type ResultData struct {
Results map[string]string
CommonData
}
func (g *GithubCommentRenderer) render(res CommandResponse, log string, verbose bool) string {
commandStr := strings.Title(res.Command.String())
common := CommonData{commandStr, verbose, log}
if res.Error != nil {
return g.renderTemplate(errWithLogTmpl, ErrData{res.Error.Error(), common})
}
if res.Failure != "" {
return g.renderTemplate(failureWithLogTmpl, FailureData{res.Failure, common})
}
return g.renderProjectResults(res.ProjectResults, common)
}
func (g *GithubCommentRenderer) renderProjectResults(pathResults []ProjectResult, common CommonData) string {
results := make(map[string]string)
for _, result := range pathResults {
if result.Error != nil {
results[result.Path] = g.renderTemplate(errTmpl, struct {
Command string
Error string
}{
Command: common.Command,
Error: result.Error.Error(),
})
} else if result.Failure != "" {
results[result.Path] = g.renderTemplate(failureTmpl, struct {
Command string
Failure string
}{
Command: common.Command,
Failure: result.Failure,
})
} else if result.PlanSuccess != nil {
results[result.Path] = g.renderTemplate(planSuccessTmpl, *result.PlanSuccess)
} else if result.ApplySuccess != "" {
results[result.Path] = g.renderTemplate(applySuccessTmpl, struct{ Output string }{result.ApplySuccess})
} else {
results[result.Path] = "Found no template. This is a bug!"
}
}
var tmpl *template.Template
if len(results) == 1 {
tmpl = singleProjectTmpl
} else {
tmpl = multiProjectTmpl
}
return g.renderTemplate(tmpl, ResultData{results, common})
}
func (g *GithubCommentRenderer) renderTemplate(tmpl *template.Template, data interface{}) string {
buf := &bytes.Buffer{}
if err := tmpl.Execute(buf, data); err != nil {
return fmt.Sprintf("Failed to render template, this is a bug: %v", err)
}
return buf.String()
}