Skip to content

Commit

Permalink
Use template for email bodies
Browse files Browse the repository at this point in the history
  • Loading branch information
richvdh committed Mar 15, 2024
1 parent 28d9c63 commit 575d259
Show file tree
Hide file tree
Showing 7 changed files with 40 additions and 32 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,8 @@ Optional parameters:

## Issue template

It is possible to specify a template in the configuration file which will be used to build the
body of any issues created on Github or Gitlab, via the `issue_body_template_file` setting. See
[templates/README.md](templates/README.md) for more information.
It is possible to override the templates used to construct emails, and Github and Gitlab issues.
See [templates/README.md](templates/README.md) for more information.

## HTTP endpoints

Expand Down
7 changes: 7 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ import _ "embed"
//go:embed templates/issue_body.tmpl
var DefaultIssueBodyTemplate string

// DefaultEmailBodyTemplate is the default template used for `email_body_template_file` in the config.
//
//go:embed templates/email_body.tmpl
var DefaultEmailBodyTemplate string

var configPath = flag.String("config", "rageshake.yaml", "The path to the config file. For more information, see the config file in this repository.")
var bindAddr = flag.String("listen", ":9110", "The port to listen on.")

Expand Down Expand Up @@ -71,6 +76,7 @@ type config struct {
GitlabIssueConfidential bool `yaml:"gitlab_issue_confidential"`

IssueBodyTemplateFile string `yaml:"issue_body_template_file"`
EmailBodyTemplateFile string `yaml:"email_body_template_file"`

SlackWebhookURL string `yaml:"slack_webhook_url"`

Expand Down Expand Up @@ -169,6 +175,7 @@ func main() {
rand.Seed(time.Now().UnixNano())
http.Handle("/api/submit", &submitServer{
issueTemplate: parseTemplate(DefaultIssueBodyTemplate, cfg.IssueBodyTemplateFile, "issue"),
emailTemplate: parseTemplate(DefaultEmailBodyTemplate, cfg.EmailBodyTemplateFile, "email"),
ghClient: ghClient,
glClient: glClient,
apiPrefix: apiPrefix,
Expand Down
9 changes: 5 additions & 4 deletions rageshake.sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ github_token: secrettoken
github_project_mappings:
my-app: octocat/HelloWorld

# The path of a template for the body of Github and Gitlab issues. See `templates/README.md` for more information on
# the templates.
issue_body_template_file: path/to/issue_body.tmpl

# a GitLab personal access token (https://gitlab.com/-/profile/personal_access_tokens), which
# will be used to create a GitLab issue for each report. It requires
# `api` scope. If omitted, no issues will be created.
Expand Down Expand Up @@ -63,3 +59,8 @@ smtp_password: myemailpass
generic_webhook_urls:
- https://server.example.com/your-server/api
- http://another-server.com/api

# The paths of template files for the body of Github and Gitlab issues, and emails.
# See `templates/README.md` for more information.
issue_body_template_file: path/to/issue_body.tmpl
email_body_template_file: path/to/email_body.tmpl
39 changes: 15 additions & 24 deletions submit.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ type submitServer struct {
// Template for building github and gitlab issues
issueTemplate *template.Template

// Template for building emails
emailTemplate *template.Template

// github client for reporting bugs. may be nil, in which case,
// reporting is disabled.
ghClient *github.Client
Expand Down Expand Up @@ -82,7 +85,8 @@ type jsonLogEntry struct {
Lines string `json:"lines"`
}

// `issueBodyTemplatePayload` contains the data made available to the `issue_body_template`.
// `issueBodyTemplatePayload` contains the data made available to the `issue_body_template` and
// `email_body_template`.
//
// !!! Keep in step with the documentation in `templates/README.md` !!!
type issueBodyTemplatePayload struct {
Expand Down Expand Up @@ -521,7 +525,7 @@ func (s *submitServer) saveReport(ctx context.Context, p payload, reportDir, lis
return nil, err
}

if err := s.sendEmail(p, reportDir); err != nil {
if err := s.sendEmail(p, reportDir, listingURL); err != nil {
return nil, err
}

Expand Down Expand Up @@ -671,22 +675,6 @@ func buildReportTitle(p payload) string {
return trimmedUserText
}

func buildReportBody(p payload, newline, quoteChar string) *bytes.Buffer {
var bodyBuf bytes.Buffer
fmt.Fprintf(&bodyBuf, "User message:\n\n%s\n\n", p.UserText)
var dataKeys []string
for k := range p.Data {
dataKeys = append(dataKeys, k)
}
sort.Strings(dataKeys)
for _, k := range dataKeys {
v := p.Data[k]
fmt.Fprintf(&bodyBuf, "%s: %s%s%s%s", k, quoteChar, v, quoteChar, newline)
}

return &bodyBuf
}

func buildGenericIssueRequest(p payload, listingURL string, bodyTemplate *template.Template) (title string, body []byte, err error) {
var bodyBuf bytes.Buffer

Expand Down Expand Up @@ -743,11 +731,16 @@ func buildGitlabIssueRequest(p payload, listingURL string, bodyTemplate *templat
}, nil
}

func (s *submitServer) sendEmail(p payload, reportDir string) error {
func (s *submitServer) sendEmail(p payload, reportDir string, listingURL string) error {
if len(s.cfg.EmailAddresses) == 0 {
return nil
}

title, body, err := buildGenericIssueRequest(p, listingURL, s.emailTemplate)
if err != nil {
return err
}

e := email.NewEmail()

e.From = "Rageshake <[email protected]>"
Expand All @@ -756,10 +749,8 @@ func (s *submitServer) sendEmail(p payload, reportDir string) error {
}

e.To = s.cfg.EmailAddresses

e.Subject = fmt.Sprintf("[%s] %s", p.AppName, buildReportTitle(p))

e.Text = buildReportBody(p, "\n", "\"").Bytes()
e.Subject = fmt.Sprintf("[%s] %s", p.AppName, title)
e.Text = body

allFiles := append(p.Files, p.Logs...)
for _, file := range allFiles {
Expand All @@ -771,7 +762,7 @@ func (s *submitServer) sendEmail(p payload, reportDir string) error {
if s.cfg.SMTPPassword != "" || s.cfg.SMTPUsername != "" {
auth = smtp.PlainAuth("", s.cfg.SMTPUsername, s.cfg.SMTPPassword, s.cfg.SMTPServer)
}
err := e.Send(s.cfg.SMTPServer, auth)
err = e.Send(s.cfg.SMTPServer, auth)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion submit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func submitSimpleRequestToServer(t *testing.T, allowedAppNameMap map[string]bool
w := httptest.NewRecorder()

var cfg config
s := &submitServer{nil, nil, nil, "/", nil, nil, allowedAppNameMap, &cfg}
s := &submitServer{nil, nil, nil, nil, "/", nil, nil, allowedAppNameMap, &cfg}

s.ServeHTTP(w, req)
rsp := w.Result()
Expand Down
1 change: 1 addition & 0 deletions templates/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ The templates are as follows:

* `issue_body.tmpl`: Used when filing an issue at Github or Gitlab, and gives the issue description. Override via
the `issue_body_template_file` setting in the configuration file.
* `email_body.tmpl`: Used when sending an email. Override via the `email_body_template_file` configuration setting.

See https://pkg.go.dev/text/template#pkg-overview for documentation of the template language.

Expand Down
9 changes: 9 additions & 0 deletions templates/email_body.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
User message:
{{ .UserText }}

{{ range $key, $val := .Data -}}
{{ $key }}: "{{ $val }}"
{{ end }}
[Logs]({{ .ListingURL }}) ([archive]({{ .ListingURL }}?format=tar.gz))
{{- range $file := .Files}} / [{{ $file }}]({{ $.ListingURL }}/{{ $file }})
{{- end }}

0 comments on commit 575d259

Please sign in to comment.