Workspaces and environments
Most teams run one configuration against several environments - dev, staging, prod. In Buddy, you separate their states in one of three ways.
Terraform workspaces
tf_workspace selects a Terraform workspace. Buddy exports it as TF_WORKSPACE before init, so Terraform selects the workspace, or creates it if needed.
yaml- action: Plan type: TERRAFORM_PLAN tool: OPENTOFU version: 1.12.6 tf_workspace: staging
- When
tf_workspaceis empty, the action uses theTF_WORKSPACEvariable if it is set, anddefaultotherwise. - The workspace that actually ran is exported as
BUDDY_ACTION_TF_PLAN_WORKSPACE. - Use the same
tf_workspacein Plan and Apply. Otherwise, Apply runs against a different state.
To use one pipeline for all environments, set tf_workspace: $ENVIRONMENT and pass ENVIRONMENT when you run the pipeline.
default workspace. With the artifact backend, separate environments with artifact versions instead (see below).
Separate backends
You can give each environment its own state instead:
- Artifact backend: one artifact version per environment -
artifact_version: $ENVIRONMENT. - S3 or GCS: a different
keyorprefixper environment.additional_argsis only added toplanandapply, notinit, so pass backend settings in theTF_CLI_ARGS_initvariable, for example-backend-config=key=staging/terraform.tfstate.
Keep each environment's variables in a separate .tfvars file and pick it with additional_args: -var-file=env/$ENVIRONMENT.tfvars.
Several directories in one repository
When one repository holds several root modules - network/, database/, app/ - each one needs its own working_directory:
- One pipeline per directory. Trigger each pipeline only on changes in its directory, so a change to
app/doesn't plannetwork/. - Several Plan and Apply pairs in one pipeline. Give each Apply an explicit
plan_file_path, because by default Apply picks up the plan from the most recent Plan action. See The plan file.
Promoting a change between environments
A common setup is one pipeline per environment, run in order:
- A push to
mainruns thestagingpipeline: Plan → Apply. - When it succeeds, it triggers the
prodpipeline: Plan → Approve Run → Apply.
Each pipeline plans against its own state, so the production plan always reflects what's actually deployed in production.
Last modified on Oct 19, 2026