Skip to main content

Templates

Tera template engine reference — variables, filters, and GoReleaser compatibility

Anodizer uses the Tera template engine (Jinja2/Django-like syntax). Templates can be used in most string fields throughout the configuration: name templates, tag templates, message templates, signing arguments, and more.

Syntax

Templates use {{ "{{ }}" }} for variable interpolation and {{ "{% %}" }} for control flow:

name_template: "{{ ProjectName }}-{{ Version }}-{{ Os }}-{{ Arch }}"

GoReleaser compatibility

For easier migration from GoReleaser, anodizer accepts Go-style templates with a leading dot. These are automatically preprocessed before rendering:

# Both forms are equivalent:
name_template: "{{ .ProjectName }}-{{ .Version }}"   # Go-style (compat)
name_template: "{{ ProjectName }}-{{ Version }}"       # Tera-style (native)

You can freely mix both styles in the same config file. The leading dot is stripped before the template is rendered.

Common GoReleaser idiom → Tera mapping

Anodizer preprocesses most Go-template constructs into their Tera equivalents, but a handful of idioms copied verbatim from a .goreleaser.yaml will produce confusing errors. Use this table when migrating.

GoReleaser idiomTera equivalentNotes
{{ if .IsRelease }}X{{ end }}{% if IsRelease %}X{% endif %}Statement tags use {% %}, not {{ }}
{{ if .IsRelease }}X{{ else }}Y{{ end }}{% if IsRelease %}X{% else %}Y{% endif %}{% else %}
{{ range .Tags }}...{{ end }}{% for t in Tags %}...{% endfor %}Tera names the loop variable explicitly
{{ range $k, $v := .Env }}...{{ end }}{% for k, v in Env %}...{% endfor %}Key/value loop
{{ with .Arm }}v{{ . }}{{ end }}{% if Arm %}v{{ Arm }}{% endif %}Tera has no with; reference the field by name
{{ tolower .Os }}{{ Os | lower }} — or {{ Os | tolower }}Filters use |; tolower/toupper aliases provided for parity
{{ replace .Tag "v" "" }}{{ Tag | replace(from="v", to="") }}Tera filters take named args
{{ trimprefix .Tag "v" }}{{ Tag | trimprefix(prefix="v") }}Alias filter registered for parity
{{ .Env.FOO }}{{ Env.FOO }} — or {{ .Env.FOO }}Dot-prefix form is preprocessed away
{{ default "x" .Tag }}{{ Tag | default(value="x") }}Tera pipes the value through a filter
{{ eq .Os "linux" }}{% if Os == "linux" %}...{% endif %}Equality is a normal operator, not a function
{{ printf "%s-%s" .Os .Arch }}{{ Os }}-{{ Arch }}Most printf formats can be inlined; use filters for padding/number formatting

If you hit a construct not covered here, open an issue with the failing template and the intended output.

Template variables

Project and version

VariableDescriptionExample
ProjectNameProject name from configmyapp
VersionSemantic version (without v prefix)1.2.3
RawVersionVersion string as-is from Cargo.toml1.2.3-rc.1
TagFull git tagv1.2.3
MajorMajor version component1
MinorMinor version component2
PatchPatch version component3
PrereleasePrerelease suffix (empty if none)rc.1

Git information

VariableDescriptionExample
FullCommitFull commit hashabc123def456...
ShortCommitShort commit hashabc1234
CommitAlias for FullCommitabc123def456...
BranchCurrent git branch namemain
CommitDateISO 8601 author date of HEAD2024-01-15T10:30:00Z
CommitTimestampUnix timestamp of HEAD1705312200
PreviousTagPrevious matching git tagv1.2.2
IsGitDirtytrue if working tree is dirtytrue
GitTreeStateWorking tree stateclean or dirty

Build context

VariableDescriptionExample
OsMapped OS namelinux, darwin, windows
ArchMapped architectureamd64, arm64
TargetFull target triplex86_64-unknown-linux-gnu
BinaryCurrent binary namemyapp
ArtifactNameCurrent artifact namemyapp-1.0.0-linux-amd64.tar.gz
ArtifactPathFull path to artifact/path/to/dist/myapp-1.0.0.tar.gz
ArtifactExtArtifact extension (compound-aware).tar.gz, .exe, .deb
ChecksumsCombined checksum file contentsabc123 myapp.tar.gz\n...

Release state

VariableDescriptionExample
IsSnapshottrue in snapshot modetrue
IsDrafttrue if draft releasefalse
IsNightlytrue in nightly modefalse
ReleaseURLURL of created GitHub releasehttps://github.com/...

Time

VariableDescriptionExample
DateCurrent date2024-01-15
TimestampCurrent Unix timestamp1705312200
NowCurrent UTC time (ISO 8601)2024-01-15T10:30:00Z

Environment variables

Access environment variables via Env:

name_template: "{{ ProjectName }}-{{ Env.CUSTOM_SUFFIX }}"

You can define custom environment variables in the config:

env:
  CUSTOM_SUFFIX: "special"
  BUILD_MODE: "production"

Pipeline outputs

Stages can write values to the Outputs map, and templates can read them:

# Tera-style
body_template: "Build ID: {{ Outputs.build_id }}"
# Go-style (also supported)
body_template: "Build ID: {{ .Outputs.build_id }}"

Similar to Var.* but for pipeline outputs rather than user config values.

Note: Only reference keys that are actually set by stages. For optional keys, use the | default guard:

body_template: "Build: {{ Outputs.build_id | default(value=\"unknown\") }}"

Filters

Tera provides many built-in filters. Common ones:

FilterExampleResult
lower{{ "HELLO" | lower }}hello
upper{{ "hello" | upper }}HELLO
title{{ "hello world" | title }}Hello World
trim{{ " hello " | trim }}hello
replace{{ Version | replace(from=".", to="_") }}1_2_3
default{{ Branch | default(value="main") }}main

GoReleaser-compatible aliases

AliasTera equivalent
tolowerlower
toupperupper

Custom filters

FilterDescriptionExample
trimprefixRemove prefix{{ Tag | trimprefix(prefix="v") }}1.2.3
trimsuffixRemove suffix{{ File | trimsuffix(suffix=".tar.gz") }}

Control flow

Tera supports conditionals and loops:

header: |
  {% if IsSnapshot %}
  **This is a snapshot build — not for production use.**
  {% else %}
  ## {{ ProjectName }} {{ Version }}
  {% endif %}
# Loops (less common in config, but available)
message_template: |
  New release: {{ Tag }}
  {% for crate in crates %}
  - {{ crate.name }}: {{ crate.version }}
  {% endfor %}