Templates
Comment bodies, chat messages and check-run output are rendered with Go text/template, executed against the event. Label entries (labels.add/remove) use the same engine.
template: |
## Pipeline {{.State}}{{if eq .State "success"}} β
{{else}} β{{end}}
**Pipeline:** {{.PipelineName}} Β· **Run:** {{.RunName}}
**Commit:** `{{ .CommitSHA | trunc 8 }}`
{{- if .TargetURL }}
[View logs]({{.TargetURL}})
{{- end }}
The relay ships 15 pre-built templates in the tekton-events-relay-templates ConfigMap. Each is tuned for a specific surface (GitHub PR comments, Slack messages, email bodies, etc.) with the right Markdown dialect, emoji, and layout for that destination.
Further reading
| Page | What youβll find |
|---|---|
| Template-Field-Reference | Every available field, its type, and when itβs populated |
| Template-Function-Reference | Sprig functions plus the domain helpers (Truncate, PRRef, IssueRef, UserMention) |
| Template-Markdown-Capabilities | What Markdown features each surface supports (tables, <details>, emoji, etc.) |
| Template-Customization-Guide | Step-by-step guide to writing and shipping your own templates |
| Notifier-Format-Requirements | Per-notifier format rules (Slack mrkdwn, Teams Adaptive Cards, Discord embeds, etc.) |
Available fields
The template context is the same event the CEL layer sees β identical names, accessed with a leading dot:
{{.State}}, {{.Resource}}, {{.Provider}}, {{.RunName}}, {{.RunID}}, {{.Namespace}}, {{.PipelineName}}, {{.TaskName}}, {{.PipelineTaskName}}, {{.PipelineDisplayName}}, {{.TaskDisplayName}}, {{.TriggerName}}, {{.EventListenerName}}, {{.TaskCount}}, {{.CommitSHA}}, {{.Context}}, {{.Description}}, {{.TargetURL}}, {{.APIBaseURL}}, {{.Repo.Owner}}, {{.Repo.Name}}, {{.Repo.ID}}, {{.Repo.Workspace}}, {{.Repo.Project}}, {{.Repo.Org}}, {{.IsFinallyTask}}, {{.SCMEventType}}, {{.StartedAt}}, {{.FinishedAt}}.
Pointer fields β guard before dereferencing:
{{ if .PRNumber }}PR #{{ .PRNumber }}{{ end }}
Tekton results (slice of {Name, Value}):
{{ range .Results }}{{ if eq .Name "IMAGE_DIGEST" }}Image: `{{ .Value }}`{{ end }}{{ end }}
Functions
Sprig
The full Sprig function library is available in SCM comment, check-run, Grafana, email, Jira, and accumulator templates: upper, lower, title, trim, trunc, replace, default, now, date, add, printf, join, ternary, regexReplaceAll, β¦
{{ .CommitSHA | trunc 8 }}
{{ .Description | default "no description" }}
{{ ternary "β
" "β" (eq .State "success") }}
{{ regexReplaceAll "[.][0-9]+s" (toString (.FinishedAt.Sub .StartedAt)) "s" }}
Slack, Teams, and Discord use plain Go
text/templateonly, no Sprig. Useprintffor truncation (printf "%.200s" .Description) instead oftrunc.
Domain helpers
Provider-aware helpers that override any Sprig equivalent:
| Function | Example | Renders |
|---|---|---|
IssueRef provider n | {{ IssueRef .Provider .IssueNumber }} | #42 in the providerβs linking syntax |
PRRef provider n | {{ PRRef .Provider .PRNumber }} | PR/MR reference (#42, !42 on GitLab) |
UserMention provider user | {{ UserMention .Provider "alice" }} | @alice in the providerβs syntax |
Truncate s n | {{ Truncate .Description 200 }} | Rune-aware truncation with ellipsis |
Shipped templates
The chart ships 15 templates in configmap-templates.yaml, mounted at /etc/templates. Each is tuned for its destinationβs Markdown dialect.
GitHub PR comment (github-pr-comment.tmpl)
Full GFM with <details> for results. Designed for mode: upsert so a single comment is updated as the run progresses.
## β
Pipeline `build-and-test` β **success**
| | |
|---|---|
| **Run** | `build-and-test-abc123` |
| **Namespace** | `ci` |
| **Commit** | `a1b2c3d4` |
| **Context** | `tekton/build` |
| **Tasks** | 6 |
| **Duration** | 42s |
> Build passed all checks
<details><summary>π¦ Results (3)</summary>
| Name | Value |
|---|---|
| `IMAGE_DIGEST` | `sha256:abc123...` |
| `COVERAGE` | `87.3%` |
| `ARTIFACT_URL` | `https://...` |
</details>
π [View logs in Tekton Dashboard](https://tekton.example.com/#/namespaces/ci/pipelineruns/build-and-test-abc123)
GitHub check run (github-checkrun.tmpl)
Shown in the Checks tab. Results stay expanded instead of collapsed.
## β
Build result: **success**
| | |
|---|---|
| **Run** | `build-and-test-abc123` |
| **Pipeline** | `build-and-test` |
| **Namespace** | `ci` |
| **Tasks executed** | 6 |
| **Duration** | 42s |
### Summary
Build passed all checks
### Results
| Name | Value |
|---|---|
| `IMAGE_DIGEST` | `sha256:abc123...` |
| `COVERAGE` | `87.3%` |
π [View logs in Tekton Dashboard](https://tekton.example.com/#/namespaces/ci/pipelineruns/build-and-test-abc123)
GitLab MR note (gitlab-note.tmpl)
GitLab Flavored Markdown with tables and <details>.
## β
Pipeline `deploy-staging` β **success**
| | |
|---|---|
| **Run** | `deploy-staging-xyz789` |
| **Namespace** | `staging` |
| **Commit** | `f0e1d2c3` |
| **Context** | `tekton/build` |
| **Duration** | 1m23s |
<details><summary>π¦ Results (2)</summary>
| Name | Value |
|---|---|
| `DEPLOY_URL` | `https://staging.example.com` |
| `IMAGE_TAG` | `v1.2.3-abc123` |
</details>
π [View logs in Tekton Dashboard](https://tekton.example.com/#/namespaces/staging/pipelineruns/deploy-staging-xyz789)
Slack default (slack-default.tmpl)
Slack mrkdwn syntax. No Sprig, uses printf for truncation.
:white_check_mark: *deploy-staging* β *success*
> *Run:* `deploy-staging-xyz789` *Namespace:* `staging`
> *Commit:* `f0e1d2c3`
> *Duration:* 83s
> Deployed to staging environment
<https://tekton.example.com/#/namespaces/staging/pipelineruns/deploy-staging-xyz789|:mag: View logs>
Slack failure alert (slack-failure-rich.tmpl)
Rotating light for failures only. Designed for when: 'stateIn("failure", "error")'.
:rotating_light: *deploy-production* failed in *production*
> *Run:* `deploy-production-abc123` *Commit:* `a1b2c3d4`
> *Duration:* 45s
> Error: image pull backoff for gcr.io/my-project/app:v1.2.3
<https://tekton.example.com/#/namespaces/production/pipelineruns/deploy-production-abc123|:mag: View logs>
Discord default (discord-default.tmpl)
Discord Markdown with code block for structured data.
β
**Pipeline success** in `ci`
Run: deploy-staging-xyz789 Pipeline: deploy-staging Commit: f0e1d2c3 Duration: 83s
> Deployed to staging environment
π [View in Dashboard](https://tekton.example.com/#/namespaces/ci/pipelineruns/deploy-staging-xyz789)
Teams default (teams-default.tmpl)
Adaptive Card TextBlock subset: bold, italic, lists, links only. No tables, no code blocks.
β
**deploy-staging** β **success**
- **Run:** deploy-staging-xyz789
- **Namespace:** staging
- **Commit:** f0e1d2c3
- **Duration:** 83s
Deployed to staging environment
[View logs](https://tekton.example.com/#/namespaces/ci/pipelineruns/deploy-staging-xyz789)
Email default (email-default.tmpl)
Plain text. Used for both subject and body.
Pipeline success: deploy-staging
Run: deploy-staging-xyz789
Namespace: staging
Commit: f0e1d2c3
Deployed to staging environment
View logs: https://tekton.example.com/#/namespaces/ci/pipelineruns/deploy-staging-xyz789
Grafana deploy marker (deploy-marker.tmpl)
Short one-line annotation correlatable with dashboards.
deploy-staging success (deploy-staging-xyz789) β f0e1d2c3
Provider-agnostic rich PR summary (pr-summary-rich.tmpl)
Works across GitHub, GitLab, Gitea, Bitbucket, Azure DevOps. Designed for mode: upsert.
## β
Pipeline `deploy-staging` β **success**
| | |
|---|---|
| **Run** | `deploy-staging-xyz789` |
| **Commit** | `f0e1d2c3` |
| **Namespace** | `staging` |
| **Started** | 2026-06-19 14:30:00 UTC |
<details><summary>π¦ Pipeline results</summary>
| Name | Value |
|---|---|
| `DEPLOY_URL` | `https://staging.example.com` |
</details>
π [View logs in Tekton Dashboard](https://tekton.example.com/#/namespaces/staging/pipelineruns/deploy-staging-xyz789)
Gitea issue comment (gitea-issue-comment.tmpl)
GFM with tables. Used for issue-level notifications.
## β οΈ Pipeline `deploy-staging` β **failure**
| | |
|---|---|
| **Run** | `deploy-staging-xyz789` |
| **Namespace** | `staging` |
| **Context** | `tekton/build` |
| **Duration** | 45s |
> Error: image pull backoff
π [View logs in Tekton Dashboard](https://tekton.example.com/#/namespaces/staging/pipelineruns/deploy-staging-xyz789)
Jira comment (jira-comment.tmpl)
Minimal plain text for Jiraβs wiki-markup renderer.
Pipeline success: deploy-staging
Run: deploy-staging-xyz789
Commit: f0e1d2c3
Logs: https://tekton.example.com/#/namespaces/staging/pipelineruns/deploy-staging-xyz789
Bitbucket PR comment (bitbucket-comment.tmpl)
Limited Markdown (no <details>, unreliable tables). Uses bold lists instead.
## β
Pipeline `deploy-staging` β **success**
- **Run:** `deploy-staging-xyz789`
- **Namespace:** `staging`
- **Commit:** `f0e1d2c3`
- **Duration:** 83s
> Deployed to staging environment
π [View logs in Tekton Dashboard](https://tekton.example.com/#/namespaces/staging/pipelineruns/deploy-staging-xyz789)
Azure DevOps PR comment (azuredevops-comment.tmpl)
GFM tables, no <details>.
## β
Pipeline `deploy-staging` β **success**
| | |
|---|---|
| **Run** | `deploy-staging-xyz789` |
| **Namespace** | `staging` |
| **Commit** | `f0e1d2c3` |
| **Tasks** | 6 |
| **Duration** | 83s |
> Deployed to staging environment
**Results**
| Name | Value |
|---|---|
| `DEPLOY_URL` | `https://staging.example.com` |
π [View logs in Tekton Dashboard](https://tekton.example.com/#/namespaces/staging/pipelineruns/deploy-staging-xyz789)
Accumulator default (accumulator-default.tmpl)
Summary context with task-level breakdown. Sprig available.
β
Pipeline success β deploy-staging
Run: deploy-staging-xyz789
Namespace: staging
Commit: f0e1d2c3
Tasks: 6
Duration: 42s
Results:
- IMAGE_DIGEST: sha256:abc123...
- COVERAGE: 87.3%
URL: https://tekton.example.com/#/namespaces/staging/pipelineruns/deploy-staging-xyz789
Per-surface notes
- GitHub / Gitea / GitLab comments β full Markdown (tables, details/summary, emoji).
- Slack β Slack mrkdwn:
*bold*,<url|text>links,:emoji:. No Sprig; useprintffor truncation. - Teams β Adaptive Card TextBlock subset (bold, italic, lists, links). No tables, no code blocks.
- Discord β Discord Markdown. No Sprig; use
printffor truncation. - Email β plain text or HTML (set
html: true). - Grafana β short annotation text, one line.
- Jira β wiki-markup subset. Keep it minimal.
- Webhook β no template; shape the JSON with the
transform(gojq) expression instead, see Notifiers. - Datadog / PagerDuty β events built natively by the notifier; no templates.
See Template-Markdown-Capabilities for a detailed comparison of what each surface supports.
Accumulator summary template
The accumulator renders a different context, SummaryData:
{{.PipelineName}} {{.RunName}} {{.State}}
{{ range .Tasks }}{{ .Emoji }} {{ .Name }} β {{ .State }} ({{ .Duration }})
{{ end }}
Fields: .PipelineName, .RunName, .State, and .Tasks[] with .Name, .State, .Emoji, .Duration. Without a custom template you get the shipped accumulator-default.tmpl.
Supplying a template
Every templatable field (template, and emailβs subject) accepts up to three forms in the Helm chart. There are no hardcoded template defaults in the application code. For the required-template notifiers (email, grafana, and the jira comment action), omitting the field makes the chart wire in a shipped default from its tekton-events-relay-templates ConfigMap (configmap-templates.yaml). For optional-template handlers (slack, teams, discord, webhook, and all SCM comment actions), omitting the field is valid and uses the handlerβs built-in fallback β no shipped default is wired. See the category breakdown below.
1. Inline β short templates, written directly in values.yaml:
template: |
Pipeline {{.State}}: {{.RunName}}
Commit: {{.CommitSHA}}
2. ConfigMap reference β long templates, kept in a ConfigMap and mounted at /etc/templates:
template:
configmapRef:
name: my-custom-templates # optional; defaults to tekton-events-relay-templates
key: slack.tpl
3. Omitted β leave the field out and the chart points at the shipped default:
| Notifier | Field | Default key |
|---|---|---|
subject | email-subject.tmpl | |
template | email-default.tmpl | |
| grafana | template | deploy-marker.tmpl |
| jira (comment) | template | jira-comment.tmpl |
| slack | template | slack-default.tmpl |
| teams | template | teams-default.tmpl |
| discord | template | discord-default.tmpl |
| accumulator | template | accumulator-default.tmpl |
| GitHub PR comment | template | github-pr-comment.tmpl |
| GitHub check run | template | github-checkrun.tmpl |
| GitHub issue comment | template | github-issue-comment.tmpl |
| GitHub discussion comment | template | github-discussion-comment.tmpl |
| GitLab MR/issue note | template | gitlab-note.tmpl |
| Gitea PR comment | template | gitea-pr-comment.tmpl |
| Gitea issue comment | template | gitea-issue-comment.tmpl |
| Bitbucket PR comment | template | bitbucket-comment.tmpl |
| Azure DevOps PR comment | template | azuredevops-comment.tmpl |
For the rich PR summary that works across providers, use pr-summary-rich.tmpl with any SCM comment action.
Raw app config (non-Helm): if you run the binary with a hand-written config (see examples/config.yaml), a template field is either an inline string or an absolute file path beginning with
/(e.g./etc/templates/slack.tmpl). The chartβsconfigmapRefform is sugar that resolves to such a path. There are no in-code defaults, so the field is required β mount the templates ConfigMap and point at it.
Custom templates
To write your own templates, see Template-Customization-Guide for a step-by-step walkthrough. The Template-Function-Reference covers every available function, and Template-Field-Reference lists every field you can use.
Common patterns:
Conditional sections:
{{- if .CommitSHA }}
| **Commit** | `{{ .CommitSHA | trunc 8 }}` |
{{- end }}
Duration calculation:
{{- if and (not .StartedAt.IsZero) (not .FinishedAt.IsZero) }}
| **Duration** | {{ regexReplaceAll "[.][0-9]+s" (toString (.FinishedAt.Sub .StartedAt)) "s" }} |
{{- end }}
Collapsible results:
<details><summary>π¦ Results ({{ len .Results }})</summary>
| Name | Value |
|---|---|
{{ range .Results }}
| `{{ .Name }}` | `{{ Truncate .Value 120 }}` |
{{ end }}
</details>
State-dependent emoji:
{{- if eq .State "success" }}β
{{- else if eq .State "failure" }}β
{{- else if eq .State "error" }}β οΈ
{{- else if eq .State "canceled" }}π«
{{- else }}β³
{{- end }}