Local development environments#
Goal. New engineers clone the repo, run one command, and have a working local database with enough data to develop against. No “ask Slack for a SQL dump.”
Why Orchard. A single authoritative scenario replaces the tribal-knowledge approach. The scenario lives in the repo and evolves with the schema.
Pattern: one “dev” scenario per service#
scenarios/
└── dev.hcldev.hcl is the canonical “everything you need to boot up locally.” Engineers
run it after applying migrations.
Example#
scenario "dev" {
required_providers {
postgres = { source = "builtin/postgres" }
exec = { source = "builtin/exec" }
}
variable "dsn" {
default = "postgres://localhost:5432/myapp_dev?sslmode=disable"
}
provider "postgres" {
dsn = var.dsn
}
provider "exec" {}
# Confirm the database is reachable before we try to seed it.
action "exec_run" "check_db" {
command = "psql"
args = [var.dsn, "-c", "SELECT 1"]
}
component "admin" "seed_admin" {
source = "../components/user.hcl"
inputs = {
email = "admin@local.dev"
role = "admin"
}
}
component "fixtures" "dev_data" {
source = "../components/dev_fixtures.hcl"
inputs = {
admin_id = component.admin.seed_admin.id
}
}
output "admin_email" { value = component.admin.seed_admin.email }
output "login_url" { value = "http://localhost:3000/login" }
}The engineer runs:
make db-setup # runs migrations
orchard run scenarios/dev.hclAnd sees:
admin_email = admin@local.dev
login_url = http://localhost:3000/loginPattern: idempotent vs destructive#
Local dev scenarios are typically destructive — they assume a fresh
database. That’s fine; document it. The alternative is writing idempotent SQL
(INSERT ... ON CONFLICT DO UPDATE), which works but complicates the scenario.
For most teams: “blow it away and re-seed” is the right default. Add a
make db-reset that drops and recreates the database, then runs the dev
scenario.
Tips#
- Keep it fast. Local dev is a daily ritual — the scenario should finish in seconds, not minutes. Pare down the data to what’s needed for day-to-day work.
- Split heavy data into opt-in scenarios. Keep
dev.hclminimal and lean; offerdev_heavy.hclfor engineers working on reporting or perf. - Document required env vars in one place. If the scenario uses
--var stripe_api_key=..., say so in the repo’s README — Orchard will tell you about the missing variable, but a pointer up front is kinder.