# Atmos Pro

Configure Atmos Pro integration for stack locking, status reporting, and workspace management across your organization.

## Overview

Atmos Pro provides centralized management capabilities for teams using Atmos at scale:

- **Stack Locking** — Prevent concurrent modifications to the same stack
- **Status Reporting** — Track deployment status and history
- **Workspace Management** — Organize teams and projects

## Configuration

`atmos pro` is a top-level CLI command group, so its connection config lives at the top-level
`pro:` key in `atmos.yaml` — a sibling of `auth:`, `docs:`, and `ci:`.

> **Note**
>
> `settings.pro` is a **deprecated alias** for the same config. Atmos still reads it, resolving
> each field independently: a field set at the top level always wins; a field only set under
> `settings.pro` still falls back to that value. New configs should use the top-level `pro:` form.

The only required setting is your `workspace_id`. All other settings have sensible defaults and can be left unset.

### Minimal

**File:** `atmos.yaml`

```yaml
pro:
  workspace_id: "your-workspace-id"
```

### Advanced

Override defaults only if needed. All fields shown below are optional except `workspace_id`.

**File:** `atmos.yaml`

```yaml
pro:
  base_url: "https://app.cloudposse.com"
  endpoint: "api/v1"
  workspace_id: "your-workspace-id"
  max_payload_bytes: 4194304
  github_oidc:
    request_url: ""
    request_token: ""
  git_sts:
    git_config_mode: "env"
    revoke_on_exit: true
```

## Configuration Reference

- **`pro.base_url`**

  Base URL for the Atmos Pro API.
  - **Type:** `string`
  - **Default:** `https://app.cloudposse.com`
  - **Environment Variable:** `ATMOS_PRO_BASE_URL`
- **`pro.endpoint`**

  API endpoint path appended to the base URL.
  - **Type:** `string`
  - **Default:** `api/v1`
  - **Environment Variable:** `ATMOS_PRO_ENDPOINT`
- **`pro.workspace_id`**

  Atmos Pro workspace identifier. Required for authentication. This value is not a secret and is safe to commit to version control.
  - **Type:** `string`
  - **Default:** (none)
  - **Environment Variable:** `ATMOS_PRO_WORKSPACE_ID`
- **`pro.token`**

  Bearer token for Atmos Pro API authentication. Atmos Pro does not issue API keys or personal access tokens — the only way to obtain a bearer token is by performing an OIDC token exchange against the Atmos Pro API. This is intended for advanced integrations outside of GitHub Actions.
  - **Type:** `string`
  - **Default:** (none)
  - **Environment Variable:** `ATMOS_PRO_TOKEN`
- **`pro.max_payload_bytes`**

  Maximum payload size (in bytes) before Atmos automatically chunks upload requests to Atmos Pro. When `atmos describe affected --upload` or `atmos list instances --upload` produces a payload larger than this threshold, it is split into multiple smaller requests with batch metadata for server-side reassembly.
  - **Type:** `integer`
  - **Default:** `4194304` (4 MB)
- **`pro.github_oidc.request_url`**

  GitHub Actions OIDC token request URL. Automatically set in GitHub Actions via the `ACTIONS_ID_TOKEN_REQUEST_URL` environment variable.
  - **Type:** `string`
- **`pro.github_oidc.request_token`**

  GitHub Actions OIDC request token. Automatically set in GitHub Actions via the `ACTIONS_ID_TOKEN_REQUEST_TOKEN` environment variable.
  - **Type:** `string`
- **`pro.git_sts.git_config_mode`**

  Global default for how the [`github/sts`](/cli/configuration/auth#github-sts-atmos-pro) auth integration
  delivers minted tokens to child `git` processes: `env` (default) injects inline
  `GIT_CONFIG_KEY_n`/`GIT_CONFIG_VALUE_n` rewrites; `file` writes a `0600` gitconfig and emits an
  additive `include.path` so token values stay off the environment. Per-integration
  `git_config_mode` in a `github/sts` integration `spec` overrides this default.
  - **Type:** `string`
  - **Default:** `env`
- **`pro.git_sts.revoke_on_exit`**

  Global default for whether minted `github/sts` tokens are auto-revoked at command-end in CI.
  Set `false` to keep credentials alive for a separate CI step. Per-integration
  `revoke_on_exit` in a `github/sts` integration `spec` overrides this default.
  - **Type:** `boolean`
  - **Default:** `true`

## Environment Variables

- **`ATMOS_PRO_BASE_URL`**
  Override the Atmos Pro API base URL. Maps to 
  `pro.base_url`
  .
- **`ATMOS_PRO_ENDPOINT`**
  Override the API endpoint path. Maps to 
  `pro.endpoint`
  .
- **`ATMOS_PRO_WORKSPACE_ID`**
  Workspace identifier for authentication. Not a secret. Maps to 
  `pro.workspace_id`
  .
- **`ATMOS_PRO_TOKEN`**
  Bearer token obtained via OIDC token exchange (advanced). Maps to 
  `pro.token`
  .
- **`ATMOS_PRO_RUN_ID`**
  CI/CD run identifier. Set automatically in CI environments for tracking.

## Authentication

### GitHub OIDC Token Exchange

For GitHub Actions workflows, use OIDC token exchange for secure, token-less authentication. This is the recommended approach.

**File:** `atmos.yaml`

```yaml
pro:
  workspace_id: "your-workspace-id"
  github_oidc:
    request_url: !env ACTIONS_ID_TOKEN_REQUEST_URL
    request_token: !env ACTIONS_ID_TOKEN_REQUEST_TOKEN
```

In your GitHub Actions workflow:

```yaml
name: Deploy Infrastructure
on: push

permissions:
  id-token: write  # Required for OIDC token request
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v6

      - name: Deploy with Atmos
        run: |
          atmos pro lock vpc -s prod/us-east-1
          atmos terraform apply vpc -s prod/us-east-1
          atmos pro unlock vpc -s prod/us-east-1
```

Advanced: Bearer Token Authentication

Atmos Pro does not issue API keys or personal access tokens. The only way to obtain a bearer token is by
performing your own OIDC token exchange against the Atmos Pro API. This is intended for advanced integrations
outside of GitHub Actions, such as custom CI/CD pipelines that handle OIDC flows independently.

**File:** `atmos.yaml`

```yaml
pro:
  token: !env ATMOS_PRO_TOKEN
```

Pass the bearer token via environment variable:

```bash
export ATMOS_PRO_TOKEN="<bearer-token-from-oidc-exchange>"
atmos pro lock vpc -s prod/us-east-1
```

## Event Integration

Atmos Pro reacts to GitHub webhook events on your repositories and dispatches
workflows on a per-stack, per-event basis. The contract is defined under the
top-level `pro:` section on each stack (or component) — a sibling of `vars:`,
`metadata:`, and `settings:` — for every event activity you want Atmos Pro to
handle, declare which workflow file to dispatch and which inputs to pass.

> **Note**
>
> `settings.pro` is a **deprecated alias** for this same per-component/stack config. An explicit
> `pro:` block takes whole-block precedence over `settings.pro:` when both are set on the same
> component (they are not merged together field-by-field). New stack configs should use the
> top-level `pro:` form.

The CLI does not interpret these blocks — they are passed through unchanged in
the payload uploaded by `atmos describe affected --upload` (and `atmos list
instances --upload`). Atmos Pro reads the blocks server-side when the matching
GitHub webhook arrives and dispatches the configured workflow against the
correct SHA.

### Supported events

- **`pro.pull_request`**
  Plan and apply workflows for pull-request lifecycle activities (
  `opened`
  , 
  `synchronize`
  , 
  `reopened`
  , 
  `merged`
  ).
- **`pro.release`**
  Workflows triggered when a GitHub release is published.
- **`pro.drift_detection`**
  Per-stack opt-in for drift detection. Atmos Pro periodically inspects enabled stacks and surfaces drift.
- **`pro.merge_group`**
  Workflows for GitHub merge-queue checks. New in this release — see 
  [Merge Queue Support](#merge-queue-support)
  .

### `pro.pull_request`

Configure workflow dispatch for pull-request activities. Each activity maps a
GitHub PR action to a list of workflows to dispatch. The `merged` activity is
synthesized by Atmos Pro from `pull_request.closed` events with `merged: true`
and is the conventional place to wire your apply workflow.

**File:** `stacks/mixins/atmos-pro.yaml`

```yaml
pro:
  enabled: true
  pull_request:
    opened:
      workflows:
        atmos-terraform-plan.yaml:
          inputs:
            component: "{{ .atmos_component }}"
            stack: "{{ .atmos_stack }}"
    synchronize:
      workflows:
        atmos-terraform-plan.yaml:
          inputs:
            component: "{{ .atmos_component }}"
            stack: "{{ .atmos_stack }}"
    reopened:
      workflows:
        atmos-terraform-plan.yaml:
          inputs:
            component: "{{ .atmos_component }}"
            stack: "{{ .atmos_stack }}"
    # `merged` is synthesized from pull_request.closed{merged:true}.
    merged:
      workflows:
        atmos-terraform-apply.yaml:
          inputs:
            component: "{{ .atmos_component }}"
            stack: "{{ .atmos_stack }}"
```

- **`pro.pull_request.opened`**
  Activity fired when a pull request is opened.
- **`pro.pull_request.synchronize`**
  Activity fired when new commits are pushed to a pull request. This is the canonical "plan on every push" trigger and is also the fallback target for merge-queue checks (see 
  [Resolution order](#resolution-order)
  ).
- **`pro.pull_request.reopened`**
  Activity fired when a closed pull request is reopened.
- **`pro.pull_request.merged`**
  Activity fired when a pull request is closed with 
  `merged: true`
  . This is the conventional place to wire the apply workflow. Apply continues to fire here even when the PR is merged through a merge queue.

### `pro.release`

Configure workflow dispatch for GitHub release activities.

**File:** `atmos.yaml`

```yaml
pro:
  enabled: true
  release:
    published:
      workflows:
        atmos-terraform-apply.yaml:
          inputs:
            component: "{{ .atmos_component }}"
            stack: "{{ .atmos_stack }}"
```

- **`pro.release.published`**
  Activity fired when a GitHub release is published. Typically wired to an apply workflow scoped to a production stack.

### `pro.drift_detection`

Per-stack opt-in for Atmos Pro's drift detection. Configure once per stack
(usually in `_defaults.yaml`) and override per environment as needed.

**File:** `stacks/deploy/_defaults.yaml`

```yaml
pro:
  enabled: true
  drift_detection:
    enabled: true
```

- **`pro.drift_detection.enabled`**

  Enable Atmos Pro drift detection for this stack.

  Effective drift detection also requires the component to be effectively Pro-enabled. An outer
  [`metadata.enabled: false`](/stacks/components/component-metadata#enabled) or
  `pro.enabled: false` disables drift detection regardless of this value — Atmos
  collapses the hierarchy (`metadata.enabled` > `pro.enabled` > `drift_detection.enabled`)
  before upload so a disabled component is never dispatched for drift.
  - **Type:** `boolean`
  - **Default:** `false`

### CI PR-comment badge

Native CI's `plan`/`apply`/`test` PR comments include a Pro status badge in the same row as the
result badges, reflecting this same effective enabled state:

- **Green (`PRO-ENABLED`)** — the component is effectively Pro-enabled (`metadata.enabled` and
  `pro.enabled` both true or defaulted). Links to your [Atmos Pro dashboard](https://atmos-pro.com/dashboard).
- **Silver (`PRO-DISABLED`)** — the component is not Pro-enabled. Links to
  [atmos-pro.com](https://atmos-pro.com).

### Merge Queue Support

Atmos Pro reports check status on GitHub merge-queue synthetic commits the same way it does on regular pull-request commits. When a PR enters the merge queue, GitHub creates a synthetic merge commit on a temporary `gh-readonly-queue/<base>/pr-<N>-<sha>` branch and re-runs all required status checks against that new SHA. Atmos Pro creates an "Atmos Pro" check run on that synthetic SHA, watches for the configured workflow to complete, and concludes the check (success / failure / no-affected-stacks neutral). Comment updates are posted to the originating PR so the queue check resolution appears on the same thread.

> **Note**
>
> **Prerequisites.** Full merge-queue support requires **Atmos CLI ≥ 1.218.0**. Earlier CLI versions still work for the empty-diff case (Atmos Pro concludes the check as "No affected stacks workflow detected"), but PRs that actually touch stacks will be reported incorrectly until the CLI is upgraded.

#### How it works

1. **PR opened or synchronized** → Atmos Pro dispatches `pull_request.synchronize.workflows` against the PR head SHA.
2. **PR added to the merge queue** → GitHub creates a synthetic merge commit on `gh-readonly-queue/<base>/pr-<N>-<sha>`. Atmos Pro creates a check run on that synthetic SHA and dispatches the workflow resolved from `merge_group` (see below).
3. **Queue ultimately merges the PR** → GitHub fires `pull_request.closed` with `merged: true` on the originating PR. The existing `pull_request.merged.workflows` (apply) flow runs unchanged. Apply does **not** fire on `merge_group` events.

#### Configure `pro.merge_group`

To get the right outcome on merge-queue synthetic commits, declare a
`merge_group` block alongside `pull_request` and `release` and point it at the
workflow you want dispatched in the queue. Workflow filenames are arbitrary —
Atmos Pro has no way to tell from the filename whether a workflow plans,
applies, or does something else — so the recommended pattern is to be
explicit about which workflow runs in the queue rather than relying on Atmos
Pro to infer one from your `pull_request.synchronize` config.

In most cases the queue should run the **same plan workflow** as
`pull_request.synchronize`, optionally with stricter inputs (fail-on-drift,
required approvals, etc.):

**File:** `stacks/mixins/atmos-pro.yaml`

```yaml
pro:
  enabled: true
  pull_request:
    synchronize:
      workflows:
        atmos-terraform-plan.yaml:
          inputs:
            component: "{{ .atmos_component }}"
            stack: "{{ .atmos_stack }}"
  merge_group:
    checks_requested:
      workflows:
        atmos-terraform-plan.yaml:
          inputs:
            component: "{{ .atmos_component }}"
            stack: "{{ .atmos_stack }}"
            # Example: stricter inputs in the queue.
            fail_on_drift: "true"
```

- **`pro.merge_group.checks_requested`**

  Activity fired when GitHub requests checks on a merge-queue synthetic
  commit (the only meaningful merge\_group activity for Atmos Pro). The
  `workflows` map has the same shape as `pull_request.<activity>.workflows`.

#### Resolution order

When Atmos Pro receives a merge-queue trigger for a stack, it resolves the
workflow to dispatch in this order:

1. `pro.merge_group.checks_requested.workflows` if defined — **this
   is the recommended path.**
2. Otherwise, `pro.pull_request.synchronize.workflows` is used as a
   backstop so existing customers do not regress when a queue is enabled.
   Because workflow filenames are arbitrary, this backstop can dispatch a
   workflow that is not appropriate for the queue (e.g. an apply step). Treat
   it as a transitional behavior, not a recommended configuration.
3. Otherwise, no workflow is dispatched (same null behavior as a stack with no
   per-event configuration).

#### Schema notes

- `merge_group` is a **sibling** of `pull_request` / `release` /
  `drift_detection`, not nested under `pull_request`. The events fire on
  different SHAs and have a different action vocabulary, matching GitHub's
  webhook event model.
- The only valid activity under `merge_group` today is `checks_requested`.
  GitHub also fires `merge_group.destroyed`, but Atmos Pro relies on its
  existing stale-uploads reconciler for cleanup, so users do not configure
  anything for it.

#### Migration note

If you are enabling GitHub merge queue on a repository that already uses
Atmos Pro, the right migration is to add a `pro.merge_group` block
(or `settings.pro.merge_group` if the repository is still on the deprecated form)
to every stack mixin that already has `pull_request`. In most
cases the queue should dispatch the same plan workflow as
`pull_request.synchronize` — declare it explicitly so the queue's check
outcome is deterministic and reviewable from your stack config rather than
inferred from a backstop.

#### See also

- [Managing a merge queue](https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue) — GitHub documentation
- [`atmos describe affected --upload`](/cli/commands/describe/affected) — uploads affected stacks under `pull_request`, `pull_request_target`, and `merge_group` events

### Workflow input templating

Inputs to dispatched workflows are rendered as Go templates against the
component context. The most common variables:

- `{{ .atmos_component }}` — the affected component name
- `{{ .atmos_stack }}` — the affected stack name
- `{{ .vars.<name> }}` — any value from the component's `vars` section
- `{{ .settings.<name> }}` — any value from the component's `settings` section

Use these to keep workflow definitions DRY across stacks.

## Related Commands
