Tutorials
Learn how to write your own templates for Vela.
A template is a pipeline with one to many defined steps that can be sourced into another pipeline. Templates can live in any repository in a source control system and are expanded at compile time to create the final executable pipeline.
Templates can take the form of generalized workflows across repositories or complex workflows like matrices in a single build.
render_inline: true
syntax.Check out the YAML reference documentation for templates.
By default, templates utilize the Go template language unless otherwise specified. You may opt to specify the format
key to switch the template language to one of the following:
format: go
format: golang
format: ""
format: starlark
Go Templates is the default formatter for building out template pipelines. We extend Go’s built-in template functions by utilizing the sprig library in the engine to allow for more options on top of the Go template syntax.
Let’s take a look at a basic template:
build.yml
but the YAML does not have a required name.metadata:
template: true
steps:
- name: Test and Build
commands:
- go test ./...
- go build
image: {{ .image }}
pull: always
ruleset:
event: [ push, pull_request ]
The caller of this template could look like:
version: "1"
templates:
- name: go
source: github.com/octocat/hello-world/.vela/build.yml
format: go
type: github
steps:
- name: sample
template:
name: go
vars:
image: golang:latest
Starlark is a configuration language that was designed for the Bazel build system. The language is a Python dialect that exists for advanced configuration management that can require complex structures. The language is dynamically typed and allows for all sorts of language-esque primitives to make writing large configuration files more manageable.
It is recommended users read the Starlark Spec to understand the syntax differences between Python and Starlark. Python IDE tools are compatible with Starlark to assist users in writing their .star
or .py
template pipelines.
Let’s take a look at a basic template:
build.star
but the file does not have a required name.def main(ctx):
return {
'version': '1',
'steps': [
{
'name': 'build',
'image': ctx["vars"]["image"],
'commands': [
'go build',
'go test',
]
},
],
}
The caller of this template could look like:
version: "1"
templates:
- name: starlark
source: github.com/octocat/hello-world/.vela/build.star
format: starlark
type: github
steps:
- name: sample
template:
name: starlark
vars:
image: golang:latest
As of v0.19.0
, users can leverage step rulesets
for steps that call a template:
version: "1"
templates:
- name: pr_flow
source: pr_flow.yml
type: file
steps:
- name: always run
image: alpine:latest
commands:
- echo "always run"
- name: pr template
ruleset:
event: pull_request
template:
name: pr_flow
NOTE: Only compile-time rules are supported for template rulesets. Runtime rules, such as status
, will not work, as the template has already been merged into the parent pipeline at that time. Any rulesets within the template will still be valid provided the template itself passes the ruleset.
.vela.yml
As of 0.9.0
Vela allows using Starlark and Go templates directly in the .vela.yml
given you select the desired template language in the pipeline settings https://vela.company.com/<org>/<repo>/settings
.
NOTE: When Starlark is chosen in the pipeline settings, Vela will look for any of the following files for the pipeline instructions
.vela.yml
, .vela.py
or .vela.star
.vela.yml
using Golangversion: "1"
# The trailing dash trims any whitespace to the right of the closing }} tag. See
# https://pkg.go.dev/text/template#hdr-Text_and_spaces
{{$stageList := list "foo" "bar" "star" -}}
stages:
{{range $stage := $stageList -}}
{{ $stage }}:
steps:
- name: {{ $stage }}
image: alpine
commands:
- echo hello from {{ $stage }}
{{ end }}
.vela.yml
, .vela.py
or .vela.star
using Starlark
def main(ctx):
stageNames = ["foo", "bar", "star"]
stages = {}
for name in stageNames:
stages[name] = stage(name)
return {
'version': '1',
'stages': stages
}
def stage(word):
return {
"steps": [
{
"name": "build_%s" % word,
"image": "alpine:latest",
'commands': [
"echo hello from %s" % word
]
}
]
}
.vela.yml
Rendering a template inline gives you the power of:
Using this feat unlocks powerful pipelines that allow you to use templates with:
To use this feature all you need to do is add render_inline: true
in the metadata block of your pipeline and you can start compiling templates without the need of the stages and steps blocks. This feature does work with both Go templates and Starlark.
This example is for injecting a stages into an external calling pipeline.
metadata:
template: true
stages:
test:
steps:
- name: Test
commands:
- go test ./...
image: {{ .image }}
pull: always
ruleset:
event: [ push, pull_request ]
build:
steps:
- name: Build
commands:
- go build
image: {{ .image }}
pull: always
ruleset:
event: [ push, pull_request ]
The caller of this template could look like:
version: "1"
metadata:
render_inline: true
templates:
- name: go
source: github.com/octocat/hello-world/.vela/build.yml
format: go
type: github
vars:
image: golang:latest
This example is for combing stages from an external template into the calling pipeline.
metadata:
template: true
stages:
test:
steps:
- name: Test
commands:
- go test ./...
image: {{ .image }}
pull: always
ruleset:
event: [ push, pull_request ]
The caller of this template could look like:
version: "1"
metadata:
render_inline: true
templates:
- name: go
source: github.com/octocat/hello-world/.vela/build.yml
format: go
type: github
vars:
image: golang:latest
stages:
build:
steps:
- name: Build
commands:
- go build
image: {{ .image }}
pull: always
ruleset:
event: [ push, pull_request ]
As of version 0.20.0
, Vela supports templates calling templates. This can be useful for cases where a portable and repeatable process exists within a larger template. Let’s take a look at an example:
version: "1"
templates:
- name: test_and_build
source: github.com/octocat/hello-world/.vela/test_and_build.yml
format: go
type: github
# in this example, this project uses a redis service to test, whereas perhaps other projects do not
steps:
- name: redis
image: redis:latest
pull: always
detach: true
- name: check status
image: redis:latest
pull: always
commands:
- sleep 15
- redis-cli -h redis ping\
# call the portable go test and build template
- name: test_and_build
template:
name: test_and_build
metadata:
template: true
templates:
- name: tag
source: github.com/octocat/hello-world/.vela/tag.yml
format: go
type: github
steps:
- name: install
image: golang:latest
pull: always
environment:
CGO_ENABLED: '0'
GOOS: linux
commands:
- go get ./...
- name: test
image: golang:latest
pull: always
environment:
CGO_ENABLED: '0'
GOOS: linux
commands:
- go test ./...
- name: build
image: golang:latest
pull: always
environment:
CGO_ENABLED: '0'
GOOS: linux
commands:
- go build
# in this example, the tag template is expanded within this go test_and_build template
- name: tag
# leveraging rulesets to control template call
ruleset:
event: [ tag ]
template:
name: tag
In the above example, the test and build template will call the tag template on tag events. This style of template composition can help organize pipeline tasks, limit redundant code, and make editing/improving pipelines an easier endeavor.
The limitation on how many nested templates can be called is determined by the VELA_MAX_TEMPLATE_DEPTH
flag set by platform administrators.
render_inline: true
, all templates that are called must also have render_inline: true
in the metadata
block.Learn how to write your own templates for Vela.
Methods of validation and ways to improve template development