Skip to content

How Recipes Work

Recipes are the heart of Pilum. They define deployment workflows as ordered steps, along with validation rules for service configuration.

What is a Recipe?

A recipe is a YAML file that defines:

  1. Required fields — What a pilum.yaml must contain
  2. Optional fields — Additional configuration with defaults
  3. Steps — Ordered commands to execute
name: gcp-cloud-run
description: Deploy to GCP Cloud Run
provider: gcp
service: cloud-run
required_fields:
- name: project
description: GCP project ID
type: string
- name: region
description: GCP region
type: string
optional_fields:
- name: min_instances
description: Minimum number of instances
type: int
default: "0"
steps:
- name: build binary
execution_mode: service_dir
timeout: 300
- name: build docker image
execution_mode: service_dir
timeout: 300
- name: push to registry
execution_mode: root
timeout: 180
- name: deploy to cloud run
execution_mode: root
timeout: 300
tags:
- deploy

Recipe-Driven Validation

When you run pilum check, Pilum:

  1. Finds all pilum.yaml files
  2. Looks up the recipe for each service’s provider
  3. Validates that all required fields (without defaults) are present

This means no Go code per provider — just add a YAML file.

Terminal window
$ pilum check
api-gateway: validated against gcp-cloud-run
worker-service: validated against gcp-cloud-run
payment-api: missing required field 'region'

Required vs Optional Fields

Required Fields

Fields that must be in pilum.yaml:

required_fields:
- name: project
description: GCP project ID
type: string
- name: region
description: GCP region (e.g., us-central1)
type: string

If a required field has a default, it becomes optional:

required_fields:
- name: stack_name
description: CloudFormation stack name
type: string
default: ${name}-stack # Uses service name if not specified

Optional Fields

Additional configuration shown during pilum init:

optional_fields:
- name: min_instances
description: Minimum number of instances
type: int
default: "0"
- name: memory
description: Memory allocation
type: string
default: "512Mi"

Optional fields are not validated — they provide suggestions during setup.

Field Types

TypeDescriptionExample
stringText value"us-central1"
intInteger value10
booltrue/falsetrue
listArray of values["a", "b"]

Steps

Steps define the deployment workflow:

steps:
- name: build binary
execution_mode: service_dir
timeout: 300
env_vars:
CGO_ENABLED: "0"
- name: deploy
command: ["gcloud", "run", "deploy", "${name}"]
execution_mode: root
timeout: 300
retries: 2
tags:
- deploy

Step Options

FieldTypeDescription
namestringStep name (used for handler lookup)
commandstring/listExplicit command (overrides handler)
execution_modestringroot or service_dir
timeoutintMax seconds to wait
retriesintRetry count on failure
env_varsmapEnvironment variables
tagslistLabels for filtering

Execution Mode

  • root — Run from project root directory
  • service_dir — Run from the service’s directory

Tags

Tags enable filtering with --only-tags and --exclude-tags:

steps:
- name: build
tags: [build]
- name: deploy
tags: [deploy]
Terminal window
# Run only deploy steps
pilum deploy --only-tags=deploy --tag=v1.0.0
# Skip build steps
pilum deploy --exclude-tags=build --tag=v1.0.0

Handler vs Explicit Commands

Steps can use:

  1. Handlers — Auto-generated commands based on step name
  2. Explicit commands — Shell commands defined in the recipe

Using Handlers

When no command is specified, Pilum looks up a registered handler:

steps:
- name: build binary
execution_mode: service_dir
# Handler generates: go build -o ./dist ...

Using Explicit Commands

Define the exact command to run:

steps:
- name: sync to s3
command: aws s3 sync ./dist s3://${project}-bucket
execution_mode: service_dir

Available variables: ${name}, ${tag}, ${provider}, ${region}, ${project}

Built-in Recipes

Pilum includes recipes for:

RecipeProviderService
gcp-cloud-rungcpcloud-run
aws-lambdaawslambda
homebrewhomebrewpackage

Next Steps