# CI Output Variables

The `ci.output` section configures output variables that are written for use in downstream CI jobs.
On GitHub Actions, these are written to `$GITHUB_OUTPUT`. On GitLab CI, they create dotenv artifacts.

> ⚠️ Experimental

## Configuration

**File:** `atmos.yaml`

```yaml
ci:
  output:
    enabled: true
    variables:
      - has_changes
      - has_additions
      - has_destructions
      - artifact_key
      - plan_summary
```

- **`ci.output.enabled`**

  Write plan/apply results as key-value pairs for use in downstream jobs.

  **Default:** `true`
- **`ci.output.variables`**

  List of native CI variables to output. This whitelist controls which built-in variables are written.
  Terraform outputs (prefixed with `output_`) are always included regardless of this setting.

  **Default:** All available variables

## Available Variables

### Plan Variables

| Variable | Type | Description |
|----------|------|-------------|
| `has_changes` | `true`/`false` | Whether the plan has any changes |
| `has_additions` | `true`/`false` | Whether the plan creates resources |
| `has_destructions` | `true`/`false` | Whether the plan destroys resources |
| `plan_summary` | string | Human-readable plan summary (e.g., "3 to add, 1 to change") |
| `artifact_key` | string | Planfile storage key (when storage is configured) |

### Aggregate Multi-component Plan Variables

Graph-backed multi-component `plan` runs in CI write aggregate output variables once after all
components finish. These variables are available for `--all`, `--components`, and `--query` plan
runs.

| Variable | Type | Description |
|----------|------|-------------|
| `has_changes` | `true`/`false` | Whether any component has changes |
| `has_errors` | `true`/`false` | Whether any component failed |
| `exit_code` | `0`, `1`, or `2` | Aggregate exit code: `1` for any failure, `2` for changes without failures, `0` for no changes |
| `resources_to_create` | number | Total resources to create across successful changed components |
| `resources_to_change` | number | Total resources to update across successful changed components |
| `resources_to_replace` | number | Total resources to replace across successful changed components |
| `resources_to_destroy` | number | Total resources to destroy across successful changed components |
| `components_total` | number | Total components in the graph run |
| `components_succeeded` | number | Components that completed without errors |
| `components_failed` | number | Components that failed |
| `components_changed` | number | Successful components with changes |
| `components_no_changes` | number | Successful components with no changes |
| `components_skipped` | number | Components skipped because dependencies failed or were skipped |
| `summary` | Markdown | Full aggregate job summary body |
| `command` | string | Always `plan` for aggregate plan output |
| `stack` | string | Requested stack, or `all` when not scoped to one stack |
| `component` | string | Always `aggregate` for aggregate plan output |

### Apply/Deploy Variables

| Variable | Type | Description |
|----------|------|-------------|
| `success` | `true`/`false` | Whether the operation succeeded |
| `output_*` | varies | All terraform outputs, prefixed with `output_` |

### Terraform Outputs

After a successful `apply` or `deploy`, all terraform outputs are exported with the `output_` prefix.
Nested outputs are flattened using dot notation.

For example, a terraform output `vpc_id = "vpc-123"` becomes `output_vpc_id=vpc-123`.

:::tip
Terraform `output_*` variables bypass the `ci.output.variables` whitelist — they are always included
when output is enabled.
:::

## Usage in GitHub Actions

```yaml
jobs:
  plan:
    runs-on: ubuntu-latest
    outputs:
      has_changes: ${{ steps.plan.outputs.has_changes }}
    steps:
      - name: Terraform Plan
        id: plan
        run: atmos terraform plan vpc -s prod

  apply:
    needs: plan
    if: ${{ needs.plan.outputs.has_changes == 'true' }}
    runs-on: ubuntu-latest
    steps:
      - run: atmos terraform deploy vpc -s prod
```

## Related

- [CI Configuration](/cli/configuration/ci) - Full configuration reference
- [Native CI Overview](/ci) - Feature overview
