Templates
Templates help you remove repetition in qp.yaml. qp supports both string snippets and parameterized task templates.
1. String Snippet Templates
Use snippet templates for repeated command fragments.
templates:
docker_login: aws ecr get-login-password | docker login --username AWS --password-stdin {{vars.registry}}
common_flags: --log-level info --color always
tasks:
publish:
desc: Publish container image
cmd: "{{template.docker_login}} && docker push {{vars.registry}}/{{vars.service}}:{{vars.git_sha}} {{template.common_flags}}"This keeps tasks readable when shared fragments grow.
2. Parameterized Task Templates
Task templates generate task families from one blueprint.
templates:
go-service:
params:
service:
type: string
required: true
package:
type: string
required: true
tasks:
build:
desc: Build service
cmd: go build -o bin/{{param.service}} ./cmd/{{param.service}}
test:
desc: Test service package
cmd: go test ./{{param.package}}/...
check:
desc: Verify service
steps: [build, test]Instantiate with use:
tasks:
auth:
desc: Auth service workflow
use: go-service
params:
service: auth
package: internal/auth
payments:
desc: Payments service workflow
use: go-service
params:
service: payments
package: internal/paymentsGenerated tasks include namespaced children such as:
auth:buildauth:testauth:checkpayments:buildpayments:testpayments:check
The parent task (auth, payments) becomes a pipeline entrypoint over generated children.
Template Task Overrides
You can customize generated tasks per instance via override.tasks.
tasks:
auth:
desc: Auth service workflow
use: go-service
params:
service: auth
package: internal/auth
override:
tasks:
test:
when: branch() == "main"
timeout: 10m
env:
GOFLAGS: -raceCurrent override fields are intentionally narrow:
whentimeoutenv
Expansion Model
Template expansion happens at config load time, before execution.
Practical implications:
qp listandqp helpshow generated task names.needsreferences inside templates are namespaced to the instance.- Validation runs against expanded concrete tasks.
Worked Multi-Service Example
vars:
registry: ghcr.io/acme
git_sha:
sh: git rev-parse --short HEAD
templates:
service-release:
params:
service:
type: string
required: true
tasks:
build:
desc: Build image
cmd: docker build -t {{vars.registry}}/{{param.service}}:{{vars.git_sha}} ./services/{{param.service}}
push:
desc: Push image
needs: [build]
cmd: docker push {{vars.registry}}/{{param.service}}:{{vars.git_sha}}
tasks:
api:
desc: API release workflow
use: service-release
params:
service: api
worker:
desc: Worker release workflow
use: service-release
params:
service: workerqp api
qp worker:pushWhen To Use Templates
Use templates when:
- the same task pattern repeats across packages/services
- naming consistency matters
- you want one place to evolve standard build/test/release behavior
Avoid templates when only one task uses the pattern and readability would decrease.
Next Step
To apply environment-specific overlays on top of variables and templates, continue to Profiles.