go.chromium.org/luci@v0.0.0-20240309015107-7cdc2e660f33/lucicfg/starlark/stdlib/internal/luci/rules/notifier_template.star (about) 1 # Copyright 2019 The LUCI Authors. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 """Defines luci.notifier_template(...) rule.""" 16 17 load("@stdlib//internal/graph.star", "graph") 18 load("@stdlib//internal/lucicfg.star", "lucicfg") 19 load("@stdlib//internal/validate.star", "validate") 20 load("@stdlib//internal/luci/common.star", "keys") 21 22 def _notifier_template( 23 ctx, # @unused 24 *, 25 name = None, 26 body = None): 27 r"""Defines a template to use for notifications from LUCI. 28 29 Such template can be referenced by luci.notifier(...) and 30 luci.tree_closer(...) rules. 31 32 The main template body should have format `<subject>\n\n<body>` where 33 subject is one line of [text/template] and body is an [html/template]. The 34 body can either be specified inline right in the starlark script or loaded 35 from an external file via io.read_file(...). 36 37 [text/template]: https://godoc.org/text/template 38 [html/template]: https://godoc.org/html/template 39 40 #### Template input 41 42 The input to both templates is a 43 [TemplateInput](https://godoc.org/go.chromium.org/luci/luci_notify/api/config#TemplateInput) 44 Go struct derived from 45 [TemplateInput](https://cs.chromium.org/chromium/infra/go/src/go.chromium.org/luci/luci_notify/api/config/notify.proto?q=TemplateInput) 46 proto message. 47 48 #### Template functions 49 50 The following functions are available to templates in addition to the 51 [standard ones](https://godoc.org/text/template#hdr-Functions). 52 53 * `time`: converts a 54 [Timestamp](https://pkg.go.dev/google.golang.org/protobuf/types/known/timestamppb#Timestamp) 55 to [time.Time](https://godoc.org/time). 56 Example: `{{.Build.EndTime | time}}` 57 58 #### Template example 59 60 ```html 61 A {{.Build.Builder.Builder}} build completed 62 63 <a href="https://ci.chromium.org/b/{{.Build.Id}}">Build {{.Build.Number}}</a> 64 has completed with status {{.Build.Status}} 65 on `{{.Build.EndTime | time}}` 66 ``` 67 68 #### Template sharing 69 70 A template can "import" subtemplates defined in all other 71 luci.notifier_template(...). When rendering, *all* templates defined in the 72 project are merged into one. Example: 73 74 ```python 75 # The actual email template which uses subtemplates defined below. In the 76 # real life it might be better to load such large template from an external 77 # file using io.read_file. 78 luci.notifier_template( 79 name = 'default', 80 body = '\n'.join([ 81 'A {{.Build.Builder.Builder}} completed', 82 '', 83 'A <a href="https://ci.chromium.org/b/{{.Build.Id}}">build</a> has completed.', 84 '', 85 'Steps: {{template "steps" .}}', 86 '', 87 '{{template "footer"}}', 88 ]), 89 ) 90 91 # This template renders only steps. It is "executed" by other templates. 92 luci.notifier_template( 93 name = 'steps', 94 body = '{{range $step := .Build.Steps}}<li>{{$step.name}}</li>{{end}', 95 ) 96 97 # This template defines subtemplates used by other templates. 98 luci.notifier_template( 99 name = 'common', 100 body = '{{define "footer"}}Have a nice day!{{end}}', 101 ) 102 ``` 103 104 105 #### Email preview 106 107 [preview_email](http://godoc.org/go.chromium.org/luci/luci_notify/cmd/preview_email) 108 command can render a template file to stdout. 109 110 Example: 111 112 ```shell 113 bb get -json -A 8914184822697034512 | preview_email ./default.template 114 ``` 115 116 This example uses bb tool, available in 117 [depot_tools](https://chromium.googlesource.com/chromium/tools/depot_tools/). 118 119 Command `preview_email` is available in 120 [infra Go env](https://chromium.googlesource.com/infra/infra/+/main/go/README.md) 121 and as a 122 [CIPD package](https://chrome-infra-packages.appspot.com/p/infra/tools/preview_email). 123 124 #### Error handling 125 126 If a user-defined template fails to render, a built-in template is used to 127 generate a very short email with a link to the build and details about the 128 failure. 129 130 Args: 131 ctx: the implicit rule context, see lucicfg.rule(...). 132 name: name of this template to reference it from luci.notifier(...) or 133 luci.tree_closer(...) rules. Must match `^[a-z][a-z0-9\_]*$`. Required. 134 body: string with the template body. Use io.read_file(...) to load it from 135 an external file, if necessary. Required. 136 """ 137 name = validate.string("name", name, regexp = r"^[a-z][a-z0-9\_]*$") 138 key = keys.notifier_template(name) 139 graph.add_node(key, idempotent = True, props = { 140 "name": name, 141 "body": validate.string("body", body), 142 }) 143 graph.add_edge(keys.project(), key) 144 return graph.keyset(key) 145 146 notifier_template = lucicfg.rule(impl = _notifier_template)