> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agno.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CI/CD Automation

> Automate builds with GitHub Actions

## Choose Your Method

| Method             | When to Use                      | Setup Effort |
| ------------------ | -------------------------------- | ------------ |
| Manual builds      | Small teams, infrequent deploys  | Low          |
| DockerHub + GitHub | Using DockerHub, simpler setup   | Medium       |
| ECR + GitHub OIDC  | Using ECR, no stored credentials | Higher       |

<Note>
  For manual builds, see [Deploy - AWS
  Setup](/deploy/templates/aws/deploy#step-1-aws-setup). ECR
  tokens expire after 12 hours.
</Note>

## PR Validation

Every PR runs automatic validation. The workflow is in `.github/workflows/validate.yml`:

```yaml theme={null}
# Runs on every PR
on:
  pull_request:
```

This checks formatting, tests, and types before merging.

<img src="https://mintcdn.com/agno-v2/yeT29TzCG5roT0hQ/images/validate-cicd.png?fit=max&auto=format&n=yeT29TzCG5roT0hQ&q=85&s=01d9c697e3f87a8248fa8daa6fac3922" alt="PR validation workflow" width="940" height="353" data-path="images/validate-cicd.png" />

## DockerHub with GitHub

Build and push images on GitHub release. Workflow: `.github/workflows/docker-images.yml`

<Steps>
  <Step title="Create Docker Access Token">
    Go to [Docker Hub Settings → Security](https://hub.docker.com/settings/security) and create an access token.

    <img src="https://mintcdn.com/agno-v2/Y7twezR0wF2re1xh/images/docker-access-token.png?fit=max&auto=format&n=Y7twezR0wF2re1xh&q=85&s=870118e1906c093108643eceaaf577e6" alt="Docker Hub access token" width="742" height="568" data-path="images/docker-access-token.png" />
  </Step>

  <Step title="Add GitHub Secrets">
    In your GitHub repo, go to **Settings → Secrets and variables → Actions**.

    Add these secrets:

    | Name                 | Value                        |
    | -------------------- | ---------------------------- |
    | `DOCKERHUB_USERNAME` | Your Docker Hub username     |
    | `DOCKERHUB_TOKEN`    | The access token from Step 1 |

    Add this variable:

    | Name                  | Value                                             |
    | --------------------- | ------------------------------------------------- |
    | `DOCKERHUB_NAMESPACE` | Your Docker Hub namespace (usually your username) |

    <img src="https://mintcdn.com/agno-v2/Y7twezR0wF2re1xh/images/github-actions-docker-secrets.png?fit=max&auto=format&n=Y7twezR0wF2re1xh&q=85&s=70015ffb61a3816c45806f85c8c44877" alt="GitHub Actions secrets configuration" width="1143" height="822" data-path="images/github-actions-docker-secrets.png" />
  </Step>

  <Step title="Trigger a Release">
    ```bash theme={null}
    gh release create v0.1.0 --title "v0.1.0" -n ""
    ```

    The workflow builds and pushes `your-namespace/agentos-template:dev` and `:prd` tags.

    <img src="https://mintcdn.com/agno-v2/Y7twezR0wF2re1xh/images/github-actions-build-docker.png?fit=max&auto=format&n=Y7twezR0wF2re1xh&q=85&s=2f96812f7b12f8e1f9d831152556c5d7" alt="GitHub Actions Docker build workflow" width="1042" height="732" data-path="images/github-actions-build-docker.png" />
  </Step>
</Steps>

## ECR with GitHub OIDC

Build and push to ECR using OpenID Connect. No IAM access keys stored in GitHub.

Workflow: `.github/workflows/ecr-images.yml`

### Set Up OIDC Provider

<Steps>
  <Step title="Add OIDC Identity Provider">
    1. Open IAM Console → **Identity providers** → **Add provider**
    2. Provider type: **OpenID Connect**
    3. Provider URL: `https://token.actions.githubusercontent.com`
    4. Click **Get thumbprint**
    5. Audience: `sts.amazonaws.com`

    <img src="https://mintcdn.com/agno-v2/Y7twezR0wF2re1xh/images/github-oidc-provider.png?fit=max&auto=format&n=Y7twezR0wF2re1xh&q=85&s=3eda54501351859a9afc8a041dc82139" alt="AWS IAM OIDC Provider configuration" width="1125" height="799" data-path="images/github-oidc-provider.png" />
  </Step>

  <Step title="Create IAM Role">
    1. After adding the provider, click **Assign role** → **Create a new role**

    <img src="https://mintcdn.com/agno-v2/Y7twezR0wF2re1xh/images/github-oidc-provider-assign-role.png?fit=max&auto=format&n=Y7twezR0wF2re1xh&q=85&s=dbd84c74dc15c2dd74311e69afd6a6cd" alt="Assign role to OIDC provider" width="1347" height="587" data-path="images/github-oidc-provider-assign-role.png" />

    2. Select **Create a new role**

    <img src="https://mintcdn.com/agno-v2/Y7twezR0wF2re1xh/images/github-oidc-provider-create-new-role.png?fit=max&auto=format&n=Y7twezR0wF2re1xh&q=85&s=e7b3d4a069f97ba3dbfe8bc08e8a534f" alt="Create new IAM role" width="604" height="278" data-path="images/github-oidc-provider-create-new-role.png" />

    3. Confirm **Web identity** is selected as trusted entity, Identity provider shows GitHub, and Audience is `sts.amazonaws.com`

    <img src="https://mintcdn.com/agno-v2/Y7twezR0wF2re1xh/images/github-oidc-provider-trusted-entity.png?fit=max&auto=format&n=Y7twezR0wF2re1xh&q=85&s=3fe69db526ec7276382189d8d063561f" alt="Configure trusted entity" width="1300" height="934" data-path="images/github-oidc-provider-trusted-entity.png" />

    4. Add permission: `AmazonEC2ContainerRegistryPowerUser`
    5. Role name: `GithubActionsRole`
    6. Copy the Role ARN (format: `arn:aws:iam::[ACCOUNT_ID]:role/GithubActionsRole`)

    <img src="https://mintcdn.com/agno-v2/Y7twezR0wF2re1xh/images/github-oidc-role.png?fit=max&auto=format&n=Y7twezR0wF2re1xh&q=85&s=ff1efeba61931aa435c13062d91a8f0b" alt="GitHub Actions IAM Role" width="1389" height="710" data-path="images/github-oidc-role.png" />
  </Step>

  <Step title="Update Workflow File">
    Edit `.github/workflows/ecr-images.yml`:

    ```yaml theme={null}
    env:
      ECR_REPO: [ACCOUNT_ID].dkr.ecr.us-east-1.amazonaws.com
      AWS_ROLE: arn:aws:iam::[ACCOUNT_ID]:role/GithubActionsRole
      AWS_REGION: us-east-1
    ```
  </Step>

  <Step title="Change Trigger to Release">
    The workflow defaults to `workflow_dispatch` (manual trigger). To trigger on release:

    ```yaml theme={null}
    on:
      release:
        types: [published]
    ```

    If using ECR, disable the DockerHub workflow by changing its trigger:

    ```yaml theme={null}
    # In docker-images.yml
    on: workflow_dispatch
    ```
  </Step>

  <Step title="Trigger Build">
    ```bash theme={null}
    gh release create v0.1.0 --title "v0.1.0" -n ""
    ```

    Or trigger manually:

    ```bash theme={null}
    gh workflow run ecr-images.yml
    ```

    <img src="https://mintcdn.com/agno-v2/Y7twezR0wF2re1xh/images/github-actions-build-ecr.png?fit=max&auto=format&n=Y7twezR0wF2re1xh&q=85&s=aff1bdde8baea8591770b0f6b5ac036b" alt="GitHub Actions ECR build workflow" width="1389" height="710" data-path="images/github-actions-build-ecr.png" />
  </Step>
</Steps>

<Note>
  **Why OIDC?** GitHub Actions requests a temporary token from AWS instead of
  using stored credentials. More secure, no credential rotation needed.
</Note>

## After CI/CD Builds

After a new image is pushed, update your ECS deployment:

<CodeGroup>
  ```bash Full Options theme={null}
  ag infra patch --env prd --infra aws --name service
  ```

  ```bash Shorthand theme={null}
  ag infra patch prd:aws::service
  ```
</CodeGroup>

This triggers a new deployment with the latest image.
