Email templates

Users of luci-notify service can define custom email templates. A notifier configuration or a build can specify the template to be used when generating an email.

Directory/File structure

Templates live in a project configuration directory. You can locate your configuration directory in$LUCI_PROJECT. Browsing may also help.

A luci-notify service hosted at <appid> reads all files matching <appid>/email-templates/<template_name>.template. The prod app id is luci-notify. <template_name> must match regexp ^[a-z][a-z0-9\_]*$. Example:

  • luci-notify/email-templates/default.template
  • luci-notify/email-templates/fancy.template

Each file must be have format <subject>\n\n<body>, where subject is one line of text/template and body is an html/template.

Template default is used if template is not specified.

Note <appid>.cfg project config is still required, even if it does not define any notifiers.

Template input

The input to both templates is a TemplateInput Go struct derived from TemplateInput proto message.

Template functions

The following functions are available to templates in addition to the standard ones.

  • time: converts a Timestamp to time.Time. Example: {{.Build.EndTime | time}}
  • formatBuilderID: converts a BuilderID to a <project>/<bucket>/<builder> string. Example: {{.Build.Builder | formatBuilderID}}
  • markdown: converts a presumed Markdown string to safe HTML. Example: {{.Build.SummaryMarkdown | markdown}}
  • stepNames: converts a []*Step to a comma-separated list of quoted step names. Example: {{.MatchingFailedSteps | stepNames}}
  • buildUrl: converts the entire TemplateInput into a URL pointing to the milo page for the build in question. Example: {{. | buildUrl}}

Template example

A {{.Build.Builder | formatBuilderID}} build completed

<a href="https://{{.BuildbucketHostname}}/builds/{{.Build.Id}}">Build {{.Build.Number}}</a>
has completed with status {{.Build.Status}}
on `{{.Build.EndTime | time}}`

Template sharing

One file can define subtemplates and another file can reuse them. When rending, all template files are merged into one. Example:


A {{.Build.Builder | formatBuilderID}} completed

A <a href="https://{{.BuildbucketHostname}}/builds/{{.Build.Id}}">build</a> has completed.

Steps: {{template "steps" .}}

{{template "disclaimer"}}


This template renders only steps. It is used by other files.

{{range $step := .Build.Steps}}


This file defines subtemplates used by other files.

{{define "disclaimer"}}
  Disclaimer: luci-notify does not take any responsibility for the build result.

Email preview

preview_email command can render a template file to stdout.


  bb get -json -A 8914184822697034512 | preview_email ./default.template

This example uses bb tool, available in depot_tools.

Command preview_email is available in infra Go env and as a CIPD package.

Error handling

If a user-defined template fails to render, an built-in template is used to generate a very short email with a link to the build and details about the failure.