Skip to content

Templates

Fábio Luciano edited this page Jun 22, 2026 · 6 revisions

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/template only, no Sprig. Use printf for truncation (printf "%.200s" .Description) instead of trunc.

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; use printf for truncation.
  • Teams — Adaptive Card TextBlock subset (bold, italic, lists, links). No tables, no code blocks.
  • Discord — Discord Markdown. No Sprig; use printf for 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
email subject email-subject.tmpl
email 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's configmapRef form 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 }}

Clone this wiki locally