# Terraform CLI action

Run any Terraform command in a Buddy pipeline with the Terraform CLI action: fmt, validate, import, state, and output, with the same backends as Plan and Apply.

The **Terraform CLI** action (`TERRAFORM`) runs commands you write in the `hashicorp/terraform` image. Plan and Apply generate their commands for you. Here, you write every command yourself.

## When to use it

| Use the Terraform CLI action for | Use Plan and Apply for |
| :--- | :--- |
| `fmt -check`, `validate`, `test` | Changing infrastructure with a reviewed plan |
| `import`, `state mv`, `state rm`, `force-unlock` | A structured resource diff in the run view |
| `output` and passing outputs to later actions | [Output variables](/docs/terraform/output-variables.md) with change counts |
| Scripts mixing Terraform with other tools | OpenTofu |

The Terraform CLI action doesn't create a resource diff or `BUDDY_ACTION_TF_*` variables.

## Configuration

| Field | Description |
| :--- | :--- |
| `version` | Terraform version - the `hashicorp/terraform` image tag, for example `1.5.7`, or `latest`. Required. See [Versions](/docs/terraform/versions.md) |
| `commands` | Commands to run. Required |
| `setup_commands` | Commands to run before `commands`, for example to install tools |
| `shell` | `BASH` (default) or `SH` |
| `working_directory` | Directory the commands run in, relative to the repository root |
| `integration` | An AWS or Google Service Account integration. Its credentials are exported to the container |
| `backend` | `ARTIFACT`, `AMAZON`, `GOOGLE`, or `CUSTOM`. Required when `integration` is set, `CUSTOM` otherwise |
| `region` | AWS region, for the `AMAZON` backend |
| `artifact`, `artifact_version` | Artifact holding the state, for the `ARTIFACT` backend |
| `state_name` | State file name in the artifact - `<state_name>.tfstate`. Default: `tf.tfstate` |

The backends work like in the native actions. See [State backends](/docs/terraform/state.md). The difference is that in the Terraform CLI action, `region`, `artifact`, and `artifact_version` are fields of the action, not of `backend`.

## Examples

**Validate on every push:**

```yaml
- action: Validate
  type: TERRAFORM
  version: 1.5.7
  working_directory: infra
  commands: |-
    terraform fmt -check -recursive
    terraform init -backend=false
    terraform validate
```

**Import an existing resource** into a state kept in an artifact:

```yaml
- action: Import bucket
  type: TERRAFORM
  version: 1.5.7
  integration: my-aws
  backend: ARTIFACT
  artifact: infra-state
  artifact_version: prod
  working_directory: infra
  commands: |-
    terraform init -input=false
    terraform import aws_s3_bucket.assets my-assets-bucket
```

**Read outputs** and pass them to later actions:

```yaml
- action: Outputs
  type: TERRAFORM
  version: 1.5.7
  backend: ARTIFACT
  artifact: infra-state
  artifact_version: prod
  working_directory: infra
  commands: |-
    terraform init -input=false
    export APP_URL=$(terraform output -raw app_url)
```

A variable exported in `commands` is available in all later actions of the run, including their [trigger conditions](/docs/pipelines/conditional-executions.md). When `export` isn't an option - for example when a script sets the value in a subshell - append it to the file pointed to by `$BUDDY_VAR` instead, one `KEY=value` per line:

```bash
echo "APP_URL=$(terraform output -raw app_url)" >> $BUDDY_VAR
```

See [Passing variables](/docs/pipelines/variables/passing-variables.md).

For all fields, see the [Terraform CLI YAML reference](/docs/yaml/yaml-actions/terraform.md).


---
Original source: https://buddy.works/docs/terraform/terraform-cli