# Terraform Apply

Run `terraform`/`tofu` apply on a plan file produced by a preceding Terraform Plan action in the same pipeline run.

## YAML Parameters

```typescript
interface YAMLParameters {
  /** The Terraform tool to run: `OPENTOFU`, `TERRAFORM` (FOSS, up to 1.5.7) or `CUSTOM`. */
  tool: "OPENTOFU" | "TERRAFORM" | "CUSTOM";
  type: "TERRAFORM_APPLY";
  /** Unique identifier for the action within the pipeline. */
  action: string;
  /** Path to the plan file. Defaults to `$BUDDY_ACTION_TF_PLAN_OUTPUT_FILE` (output of the preceding Terraform Plan action). */
  plan_file_path?: string;
  /** Tool version, e.g. `1.9.0` or `latest`. Required unless `tool` is `CUSTOM`. */
  version?: string;
  /** Path to the binary inside the Docker image, e.g. `/usr/local/bin/tofu`. Required when `tool` is `CUSTOM`. */
  custom_binary_path?: string;
  /** Custom Docker image to run in. Required when `tool` is `CUSTOM`. */
  docker_image_name?: string;
  /** Tag of the custom Docker image. */
  docker_image_tag?: string;
  /** The location of the image used by the action. */
  image_location?: "PUBLIC_REGISTRY" | "PRIVATE_REGISTRY" | "ACTION" | "ARTIFACT_REGISTRY";
  /** The type of registry from which the image is retrieved. */
  docker_registry?: "NONE" | "DOCKER_HUB" | "AMAZON_ECR" | "GOOGLE_GCR" | "GOOGLE_ARTIFACT_REGISTRY" | "OTHER" | "GIT_HUB_CONTAINER_REGISTRY" | "ARTIFACT_REGISTRY" | "DIGITAL_OCEAN_CONTAINER_REGISTRY";
  /** The URL of the Docker registry. Required when `docker_registry` is `OTHER`. */
  registry?: string;
  /** Username for Docker registry authentication. Used with `password` when `docker_registry` is `OTHER`. */
  login?: string;
  /** Password for Docker registry authentication. Used with `login` when `docker_registry` is `OTHER`. */
  password?: string;
  /** The region of the Docker registry (for Amazon ECR). */
  region?: string;
  /** Docker registry integration used to pull the custom image. */
  integration?: string;
  /** Path relative to the repository root. Defaults to `.`. */
  working_directory?: string;
  /** Extra CLI arguments appended to the command, as a single space-separated string. Example: `-var-file=prod.tfvars -parallelism=20`. */
  additional_args?: string;
  /** Terraform workspace to run in, exported to the tool as `TF_WORKSPACE`. Set the same value in the Plan and Apply actions, otherwise Apply runs against a different state. Defaults to `default`, or to `TF_WORKSPACE` set as a pipeline variable. */
  tf_workspace?: string;
  /** State backend configuration: `type` (`CUSTOM`, `AMAZON`, `GOOGLE`, `ARTIFACT`), `integration`, `region`, `artifact` and `artifact_version`. Defaults to `CUSTOM`, which means the backend is declared in the Terraform code. The backend `integration` is separate from the action `integration` pulling the custom runner image. */
  backend?: TerraformRunBackendYaml;
  /** Specifies when the action should be executed. */
  trigger_time?: "ON_EVERY_EXECUTION" | "ON_FAILURE" | "ON_BACK_TO_SUCCESS" | "ON_WARNING" | "ON_WAIT_FOR_APPROVE" | "ON_TERMINATE";
  /** The list of variables for dynamic action execution. The action runs once for each value. */
  loop?: string[];
  /** Defines whether the action should be executed on each failure. Restricted to and required if the trigger_time is ON_FAILURE. */
  run_only_on_first_failure?: boolean;
  /** When set to true the action is disabled. By default it is set to false. */
  disabled?: boolean;
  /** The timeout in seconds. */
  timeout?: number;
  /** If set to true the execution will proceed, mark action as a warning and jump to the next action. Doesn't apply to deployment actions. */
  ignore_errors?: boolean;
  /** Delay time between auto retries in seconds. */
  retry_interval?: number;
  /** Number of retries if the action fails. */
  retry_count?: number;
  /** Defines whether the action should run in parallel with the next one. */
  run_next?: "WAIT_ON_SUCCESS" | "IN_SOFT_PARALLEL" | "IN_HARD_PARALLEL";
  /** The list of trigger conditions to meet so that the action can be triggered. */
  trigger_conditions?: TriggerConditionYaml[];
  /** The list of variables you can use in the action. */
  variables?: VariableYaml[];
}
```

## Type Definitions

```typescript
interface TerraformRunBackendYaml {
  type?: "CUSTOM" | "AMAZON" | "GOOGLE" | "ARTIFACT";
  integration?: string;
  region?: string;
  artifact?: string;
  artifact_version?: string;
}

interface TriggerConditionYaml {
  /** The type of trigger condition */
  trigger_condition: "ALWAYS" | "ON_CHANGE" | "ON_CHANGE_AT_PATH" | "VAR_IS" | "VAR_IS_NOT" | "VAR_CONTAINS" | "VAR_NOT_CONTAINS" | "DATETIME" | "SUCCESS_PIPELINE" | "DAY" | "HOUR" | "OR" | "VAR_LESS_THAN" | "VAR_LESS_THAN_OR_EQUAL" | "VAR_GREATER_THAN" | "VAR_GREATER_THAN_OR_EQUAL" | "ACTION_STATUS_IS" | "ACTION_STATUS_IS_NOT" | "TRIGGERING_USER_IS" | "TRIGGERING_USER_IS_NOT" | "TRIGGERING_USER_IS_IN_GROUP" | "TRIGGERING_USER_IS_NOT_IN_GROUP";
  /** The value to compare the trigger variable against */
  trigger_variable_value?: string;
  /** The name of the variable to check in the trigger condition */
  trigger_variable_key?: string;
  /** The timezone for datetime trigger conditions (e.g., 'UTC', 'Europe/Warsaw') */
  timezone?: string;
  /** The hours when the datetime trigger should activate (0-23) */
  trigger_hours?: number[];
  /** The days when the datetime trigger should activate (1-7, where 1 is Monday) */
  trigger_days?: number[];
  /** The project name for cross-project pipeline triggers */
  project?: string;
  /** The pipeline name for cross-pipeline triggers */
  pipeline?: string;
  /** The username or email of the user who can trigger the pipeline */
  trigger_user?: string;
  /** The name of the group that can trigger the pipeline */
  trigger_group?: string;
  /** The file paths that must change to trigger the pipeline */
  trigger_condition_paths?: string[];
  /** The action status to check for action status triggers */
  trigger_status?: "SUCCESSFUL" | "FAILED" | "SKIPPED" | "SUPPRESSED";
  /** The name of the action to check status for */
  trigger_action_name?: string;
  /** The list of nested trigger conditions for OR/AND operators */
  trigger_operands?: TriggerConditionYaml[];
}

interface VariableYaml {
  /** The name of the variable */
  key: string;
  /** The value of the variable */
  value?: string;
  /** The type of the added variable */
  type?: "VAR" | "FILE" | "SSH_KEY" | "IOS_KEYCHAIN" | "IOS_PROVISION_PROFILES" | "SSH_PUBLIC_KEY" | "GPG_KEY";
  /** If set to true the variable value will be encrypted and hidden */
  encrypted?: boolean;
  /** Initial path for the variable */
  init_path?: string;
  /** Default value for the variable */
  defaults?: string;
  /** Specifies where to copy the file on each run. Set if type is FILE, SSH_KEY, IOS_KEYCHAIN, or IOS_PROVISION_PROFILES. */
  file_path?: string;
  /** File permission set on copy to a container on each run. Set if type is FILE, SSH_KEY, IOS_KEYCHAIN, or IOS_PROVISION_PROFILES. */
  file_chmod?: string;
  /** Set if type is FILE, SSH_KEY, IOS_KEYCHAIN, or IOS_PROVISION_PROFILES. If it's NONE, the variable can be used as a parameter in an action. For CONTAINER, the given key is additionally copied to an action container on each run */
  file_place?: "NONE" | "CONTAINER";
  /** Password for certificates */
  password?: string;
  /** Passphrase for encrypted SSH keys */
  passphrase?: string;
  /** Key identifier for iOS certificates, provisioning profiles, or GPG keys */
  key_identifier?: string;
  /** If set to true the variable value can be set by Buddy actions */
  settable?: string;
  /** If set to true the variable is disabled and will not be injected anywhere */
  disabled?: boolean;
  /** Encoding of the variable value. Use `b64` for binary files (certificates, images, compiled blobs) where the value is already base64-encoded. Omit or set to `text` for plain text files (JSON, XML, config) — the system will handle encoding automatically. Only applies to non-encrypted asset variables (FILE, SSH_KEY, SSH_PUBLIC_KEY, IOS_KEYCHAIN, IOS_PROVISION_PROFILES). */
  encoding?: "text" | "b64";
  /** Note for this resource */
  note?: string;
  /** YAML note for AI agents operating on this resource */
  agent_note?: string;
}

```

## YAML Examples

### Terraform Apply

```yaml
- action: "Terraform Apply"
  type: "TERRAFORM_APPLY"
  tool: "OPENTOFU"
  version: "1.9.0"

```

### Terraform Apply with explicit plan file

```yaml
- action: "Terraform Apply"
  type: "TERRAFORM_APPLY"
  tool: "OPENTOFU"
  version: "1.9.0"
  working_directory: "./infrastructure/prod"
  tf_workspace: "production"
  plan_file_path: "$BUDDY_ACTION_TF_PLAN_OUTPUT_FILE"
  additional_args: "-parallelism=20"

```

### Terraform Apply with state in a Buddy artifact

```yaml
- action: "Terraform Apply"
  type: "TERRAFORM_APPLY"
  tool: "OPENTOFU"
  version: "1.9.0"
  working_directory: "./infrastructure/prod"
  backend:
    type: "ARTIFACT"
    artifact: "terraform-state"
    artifact_version: "1.0.0"

```

### Terraform Apply with custom image from a private registry

```yaml
- action: "Terraform Apply"
  type: "TERRAFORM_APPLY"
  tool: "CUSTOM"
  custom_binary_path: "/usr/local/bin/tofu"
  docker_image_name: "mycompany/terraform-runner"
  docker_image_tag: "1.9.5"
  image_location: "PRIVATE_REGISTRY"
  docker_registry: "OTHER"
  registry: "my.registry.com"
  login: "buddyworks"
  password: "${top_secret_password}"
  working_directory: "./infrastructure/prod"

```


---
Original source: https://buddy.works/docs/yaml/yaml-actions/terraform-apply