Skip to main content

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

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

atmos.yaml
settings:
pro:
workspace_id: "your-workspace-id"

Configuration Reference

settings.pro.base_url

Base URL for the Atmos Pro API.

  • Type: string
  • Default: https://app.cloudposse.com
  • Environment Variable: ATMOS_PRO_BASE_URL
settings.pro.endpoint

API endpoint path appended to the base URL.

  • Type: string
  • Default: api/v1
  • Environment Variable: ATMOS_PRO_ENDPOINT
settings.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
settings.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
settings.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)
settings.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
settings.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

Environment Variables

ATMOS_PRO_BASE_URL
Override the Atmos Pro API base URL. Maps to settings.pro.base_url.
ATMOS_PRO_ENDPOINT
Override the API endpoint path. Maps to settings.pro.endpoint.
ATMOS_PRO_WORKSPACE_ID
Workspace identifier for authentication. Not a secret. Maps to settings.pro.workspace_id.
ATMOS_PRO_TOKEN
Bearer token obtained via OIDC token exchange (advanced). Maps to settings.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.

atmos.yaml
settings:
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:

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@v4

- 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.

atmos.yaml
settings:
pro:
token: !env ATMOS_PRO_TOKEN

Pass the bearer token via environment variable:

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 settings.pro on each stack (or component): for every event activity you want Atmos Pro to handle, declare which workflow file to dispatch and which inputs to pass.

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

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

settings.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.

stacks/mixins/atmos-pro.yaml
settings:
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 }}"
settings.pro.pull_request.opened
Activity fired when a pull request is opened.
settings.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).
settings.pro.pull_request.reopened
Activity fired when a closed pull request is reopened.
settings.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.

settings.pro.release

Configure workflow dispatch for GitHub release activities.

atmos.yaml
settings:
pro:
enabled: true
release:
published:
workflows:
atmos-terraform-apply.yaml:
inputs:
component: "{{ .atmos_component }}"
stack: "{{ .atmos_stack }}"
settings.pro.release.published
Activity fired when a GitHub release is published. Typically wired to an apply workflow scoped to a production stack.

settings.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.

stacks/deploy/_defaults.yaml
settings:
pro:
enabled: true
drift_detection:
enabled: true
settings.pro.drift_detection.enabled

Enable Atmos Pro drift detection for this stack.

  • Type: boolean
  • Default: false

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 settings.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.):

stacks/mixins/atmos-pro.yaml
settings:
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"
settings.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. settings.pro.merge_group.checks_requested.workflows if defined — this is the recommended path.
  2. Otherwise, settings.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 settings.pro.merge_group block to every stack mixin that already has settings.pro.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

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.