# Native CI

Atmos integrates CI/CD directly into the CLI. Run Terraform commands in GitHub Actions to
publish job summaries, status checks, output variables, and pull-request plan comments.
Use stored planfiles to verify changes before applying, and Git-aware commands to plan
and deploy only the components affected by a change.

:::note Native CI replaces legacy Terraform actions
Atmos now handles Terraform CI directly, replacing the
[legacy Terraform GitHub Actions](/deprecated/github-actions).
Use native Atmos commands for new workflows.

Existing workflows that use the legacy actions continue to work.
See [GitHub Actions Workflows](#github-actions-workflows) for examples and setup requirements.
:::

## Quick Start

To use GitHub event data in CEL rules, see [Policy CI Context](/policies/ci).
To require plan checks or lifecycle hooks, see [Policies](/policies).

**File:** `atmos.yaml`

```yaml
ci:
  enabled: true
  summary:
    enabled: true
  output:
    enabled: true
    variables:
      - has_changes
      - has_additions
      - has_destructions
      - plan_summary
  checks:
    enabled: true
  comments:
    enabled: true
    behavior: upsert
```

Use this configuration with the [GitHub Actions workflows](#github-actions-workflows) below.

**CI Configuration**

Configure CI providers, job summaries, output variables, status checks, pull-request plan comments, planfile storage, and templates in your `atmos.yaml`.

Configuration Reference[Read more](/cli/configuration/ci)

## GitHub Actions Workflows

Atmos provides CI features directly in the CLI; GitHub Actions runs the workflows. Browse the [GitHub Actions overview](/integrations/github-actions) for setup and runnable examples.

### Plan on Pull Request

Review infrastructure changes before merging a pull request. Run an Atmos plan in GitHub Actions and publish the results as job summaries, checks, and pull request comments.

[Read the Plan on Pull Request guide](/integrations/github-actions/plan-on-pull-request).

### Apply on Merge

Deploy infrastructure after a change merges. Atmos can compare the new plan against the plan reviewed in the pull request before applying it.

[Read the Apply on Merge guide](/integrations/github-actions/apply-on-merge).

### Deploy Affected

Run CI jobs only for component instances affected by a change. Atmos produces the GitHub Actions matrix from your stacks and Git changes.

[Read the Deploy Affected Components guide](/integrations/github-actions/deploy-affected).

### Deploy All

Run a workflow across every component instance in your stacks. Generate the job matrix from Atmos instead of maintaining a separate inventory in your workflow.

[Read the Deploy All Components guide](/integrations/github-actions/deploy-all).

### Choosing Which Components Run in CI

Some components require privileged credentials or manual execution. Others need access to a private VPC, a peering
connection, or an internal service that the CI runner cannot reach. Use [labels](/stacks/components/component-metadata#labels)
to select the components this workflow can run. Native CI does not read the legacy Atmos GitHub Actions setting
`settings.github.actions_enabled`.

Set a default label, then override it on components excluded from the workflow:

**File:** `stacks/orgs/acme/_defaults.yaml`

```yaml
metadata:
  labels:
    ci: auto
```

**File:** `stacks/catalog/private-service.yaml`

```yaml
components:
  terraform:
    private-service:
      metadata:
        labels:
          ci: manual
```

Build the matrix with `--labels=ci:auto` (equivalent to `--labels=ci=auto`):

```yaml
- id: affected
  run: atmos describe affected --format=matrix --labels=ci:auto
```

The labels are user-defined: `ci: manual` excludes a component from this workflow. Run excluded components manually or
through a separate workflow with appropriate credentials and connectivity, selecting `--labels=ci:manual`. Labels do not
detect network access or enforce permissions. Matching is positive only, so use defaults and overrides to express exclusions.

To plan the selection directly, run `atmos terraform plan --affected --labels=ci:auto`. To include matching dependents
as separate matrix entries, use:

```shell
atmos describe affected --format=matrix --include-dependents --flatten --labels=ci:auto
```

Matching dependents remain selected even when their parent is excluded. See the
[selector reference](/cli/commands/describe/affected#filtering-by-tags-and-labels) for matching rules and dependent behavior,
and [Deploy Affected](/integrations/github-actions/deploy-affected) for a workflow that skips empty matrices.

:::caution Empty selectors disable filtering
`--labels=` or an empty `ATMOS_LABELS` applies no label filter. When using a workflow variable, reject an empty value
with `--labels="ci=${CI_LABEL:?}"` or validate it in an earlier step.
:::

Set selector environment variables on the steps that need them. See
[environment variables and uploads](/cli/commands/describe/affected#selector-environment-and-uploads) for their scope and
[template processing](/cli/commands/describe/affected#selector-matching-rules) for templated labels.

### Keeping Privileged Components Out of CI with OPA

For components prohibited from running in GitHub Actions, optionally attach an [OPA policy](/validation/opa) that rejects
execution there. This policy also blocks manually triggered GitHub Actions workflows. A component that only needs a runner
with different network access does not need this prohibition.

**File:** `stacks/schemas/opa/ci/privileged-component.rego`

```
package atmos

errors[message] {
  input.process_env.GITHUB_ACTIONS == "true"
  input.metadata.labels.ci == "manual"
  message := sprintf("%s is a privileged component and can't run in GitHub Actions", [input.atmos_component])
}
```

Attach the policy and label to the privileged component:

**File:** `stacks/catalog/iam.yaml`

```yaml
components:
  terraform:
    iam:
      metadata:
        labels:
          ci: manual
      settings:
        validation:
          ci-guard:
            schema_type: opa
            schema_path: "ci/privileged-component.rego"
            description: Block privileged components from running in GitHub Actions
```

Set `schemas.opa.base_path` so Atmos can resolve the relative `schema_path`:

**File:** `atmos.yaml`

```yaml
schemas:
  opa:
    base_path: "stacks/schemas/opa"
```

The policy fails validation if the component runs in GitHub Actions; it does not skip the job. See
[OPA validation](/validation/opa#configure-component-validation) for configuration details.

### Gating Production with Environments

Require approval before deploying production infrastructure. GitHub environments provide approval gates and environment-specific credentials while Atmos selects and deploys the stack.

[Read the Deployment Approvals guide](/integrations/github-actions/deployment-approvals).

## Workflow Setup and Reference

### Permissions

See the GitHub Actions guide for [GitHub permissions](/integrations/github-actions/authentication#permissions).

### Authentication

See the GitHub Actions guide for [cloud authentication](/integrations/github-actions/authentication#authentication).

### Caching the Toolchain

See the GitHub Actions guide for [toolchain caching](/integrations/github-actions#caching-the-toolchain).

### SBOM Artifacts

See the GitHub Actions guide for [SBOM artifacts](/integrations/github-actions#sbom-artifacts).

### Validate Workflows

See the GitHub Actions guide for [workflow validation](/integrations/github-actions/validate-workflows).

## Features

Terraform commands support the full native CI feature set below. Kubernetes, Helm, and Helmfile
commands produce job summaries only; CloudFormation commands produce summaries and output
variables. These commands do not emit status checks, PR comments, or stored artifacts.

### [Job Summaries](/ci/job-summaries)

Rich Markdown summaries with resource counts, inline badges, collapsible diffs, and captured
command output written to `$GITHUB_STEP_SUMMARY`. Terraform includes plan/apply summaries plus
the broader native CI features below. Helm and Helmfile currently write summaries only, and
CloudFormation writes summaries plus output variables. Templates are fully customizable with Go template syntax.

Kubernetes summaries are intentionally compact: `plan`/`diff` show created, changed, and
no-change objects; `apply`/`deploy` show applied or delivered objects; `delete` shows deleted
and not-found objects; `validate` shows valid and invalid objects plus errors.

CloudFormation summaries cover changesets, stack operations, and drift results. See
[Job Summaries](/ci/job-summaries#cloudformation-summaries) for the command-specific details.

### [Outputs](/cli/configuration/ci/output)

Terraform plan and apply results exported as CI output variables for use in downstream jobs.
On GitHub Actions, these are written to `$GITHUB_OUTPUT`. Kubernetes commands do not emit output
variables.

CloudFormation commands emit these variables, following the same `ci.output.enabled` and
`ci.output.variables` settings as Terraform:

- `stack`, `component`, `command` (the verb you ran, for example `plan`), `stack_name`, and `exit_code`
- `changeset_name`, when the operation created a changeset
- `has_changes` (`diff`/`plan`, `apply`/`deploy`): `false` for a no-op changeset
- `stack_status`, when the operation observed a final status (`delete`)
- `drifted`, `drift_status`, and `drifted_resource_count` (`drift detect`, `drift describe`)
- `output_<Key>` for each stack Output after `apply`/`deploy`. These bypass the `ci.output.variables`
  allow-list and carry masked values by default. `--mask=false` disables presentation masking and may
  export NoEcho-dependent outputs in clear text.

### [Checks](/cli/configuration/ci/checks)

Live commit status checks showing real-time operation progress — "Plan in progress" while
running and "3 to add, 1 to change, 0 to destroy" when complete.

### [PR Comments](/cli/configuration/ci/comments)

When `ci.comments.enabled: true`, Terraform plans running in a pull-request context can post their
rendered plan summary as a PR comment. The comment uses the same template as the job summary and,
with the default `upsert` behavior, updates one comment per command, component, and stack on later
runs. This requires GitHub Actions `pull-requests: write`; comments are not posted for non-PR runs,
when no summary is available, or by apply, deploy, Kubernetes, Helm, Helmfile, or CloudFormation
commands.

### [Planfile Storage](/ci/planfile-storage)

Store and retrieve planfiles across CI pipeline stages using S3, GitHub Artifacts, or local
filesystem. The `deploy` command downloads stored planfiles, generates a fresh plan, and
performs a semantic comparison to detect drift before applying.

### [Build Cache](/cli/configuration/ci/cache)

Warm-start the toolchain across CI jobs by restoring and saving the Atmos cache root via the
CI provider's cache store — the same store `actions/cache` uses. Runs automatically with
`ci.cache.auto: both`, or explicitly with the [`atmos ci cache`](/cli/commands/ci/cache)
subcommands.

### [GitOps](/cli/configuration/git)

Atmos is **git-aware**, which is what makes true GitOps possible: the repository is the source of
truth, and the pipeline reconciles only what changed.

- **Plan what's affected**
  [`atmos describe affected`](/cli/commands/describe/affected)
   diffs two Git commits and reports exactly which components and stacks changed — including changes that ripple through dependencies, imports, and remote state. See 
  [Deploy Affected](#deploy-affected)
   for the matrix workflow.
- **Apply only what changed**
  Fan out across just the affected components, so a PR plans — and a merge applies — only the work that actually changed, instead of re-running the entire estate on every commit.
- **Reusable across repositories**
  Publish service catalogs and module libraries once and 
  [vendor](/vendor/)
   them into every workload repository, so many repos share one versioned source of truth instead of copy-pasting configuration.
- **Automate workload repositories**
  Commit generated artifacts back to a source-of-truth repository as part of the pipeline. Define managed repositories once under 
  `git.repositories`
  , then have Atmos commit and push automatically — with signed commits, a bot author identity, and bounded non-fast-forward retries — from 
  [`kind: git` hooks](/stacks/hooks#kind-git)
  , the 
  [`atmos git`](/cli/commands/git/usage)
   commands, or CI workflows. This is the foundation for GitOps with Argo CD, Flux, or downstream CI consuming the committed output.

## Commands

CI features are activated with the `--ci` flag on supported commands or automatically when running in a CI environment (e.g. GitHub Actions):

- **[`atmos terraform plan [--ci]`](/cli/commands/terraform/plan)**
  Run plan with job summary, output variables, status checks, and planfile upload.
- **[`atmos terraform apply [--ci]`](/cli/commands/terraform/apply)**
  Run apply with job summary, output variables, and status checks.
- **[`atmos terraform deploy [--ci]`](/cli/commands/terraform/deploy)**
  Deploy with stored planfile verification, drift detection, and full CI reporting.
- **[`atmos helm template|diff|apply|deploy|delete [--ci]`](/cli/commands/helm/usage)**
  Run native Helm components with job summaries for rendered/applied object metadata.
- **[`atmos helmfile template|diff|apply|sync|deploy|destroy [--ci]`](/cli/commands/helmfile/usage)**
  Run Helmfile components with job summaries that include captured masked command output.
- **[`atmos terraform planfile`](/cli/commands/terraform/planfile)**
  Manage stored planfiles: upload, download, list, delete, and show.
- **[`atmos describe affected --format=matrix`](/cli/commands/describe/affected)**
  Generate GitHub Actions matrix strategy from affected components.
- **[`atmos kubernetes render|plan|diff|apply|deploy|delete|validate [--ci]`](/cli/commands/kubernetes/usage)**
  Run Kubernetes operations with a native job summary only. No output variables, status checks, comments, or artifacts are emitted.
- **[`atmos vendor update --pull-request`](/cli/commands/vendor/vendor-update)**
  Open (or update) a pull request with available vendored-component updates directly from CI — replaces the deprecated Component Updater action.
- **[`atmos aws cloudformation diff|apply|delete [--ci]`](/cli/commands/aws/cloudformation)**
  Run CloudFormation diff, apply, and delete with a native job summary and output variables. No status checks, comments, or artifacts are emitted.
- **[`atmos aws cloudformation drift detect|describe [--ci]`](/cli/commands/aws/cloudformation/drift)**
  Run CloudFormation drift detection and description with a native job summary and output variables.

## Providers

Atmos auto-detects the CI environment and selects the appropriate provider:

- ****GitHub Actions****
  Integrates with GitHub job summaries, commit status checks, and output variables. Requires 
  `GITHUB_TOKEN`
   for checks and PR features.
- ****Generic CI****
  Prints summaries, checks, and outputs to stdout. Useful for local development and testing, or any CI provider without native integration.

## Related

- [CI Configuration](/cli/configuration/ci) - Configure CI integration in `atmos.yaml`
- [CI Commands](/cli/commands/ci) - CI command reference
- [Profiles](/cli/configuration/profiles) - Configure CI-specific profiles
- [`atmos vendor update`](/cli/commands/vendor/vendor-update) - Update vendored components and open pull requests from CI
- [Deprecated GitHub Actions](/deprecated/github-actions) - Full list of legacy actions and their native replacements
- [Auth](/stacks/auth) - Configure OIDC authentication for CI
