Skip to main content

GitHub Actions

Integrate Cloud Cost Analyzer into your GitHub Actions workflows.

Use the official GitHub Action for the simplest setup:

# .github/workflows/cost-analysis.yml
name: Cost Analysis

on:
pull_request:
branches: [main]

permissions:
id-token: write
contents: read
pull-requests: write

jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1

- uses: dragonfractal/cca-scan-action@v1
with:
api-key: ${{ secrets.CCA_API_KEY }}

That's it — 3 steps. The action runs CCA (via its container image), scans your account, and posts results as a PR comment.

Scanning Azure

Set provider: azure and give the job Azure credentials — the action forwards the standard AZURE_* variables into the scan container. Two options:

OIDC (recommended, no stored secret)azure/login provides a federated token that the action mounts into the container:

permissions:
id-token: write
contents: read
pull-requests: write

jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

- uses: dragonfractal/cca-scan-action@v1
with:
api-key: ${{ secrets.CCA_API_KEY }}
provider: azure

Service principal secret — pass the credentials as env on the action step:

      - uses: dragonfractal/cca-scan-action@v1
env:
AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
with:
api-key: ${{ secrets.CCA_API_KEY }}
provider: azure

The scan needs only the Reader role (plus Cost Management Reader for cost data) on the subscription.

Action Inputs

InputRequiredDefaultDescription
api-keyYesCCA API key (get one here)
providerNoawsCloud provider (aws, azure)
regionsNoComma-separated regions (e.g. us-east-1,us-west-2)
versionNolatestCCA Docker image version
output-fileNocca-scan-results.jsonPath to save the JSON scan results
comment-on-prNotruePost summary as PR comment
fail-on-findingsNo0Fail if findings exceed threshold (0 = never)

Action Outputs

OutputDescription
findings-countNumber of findings detected
total-savingsTotal potential monthly savings (USD)

Required Secrets

Add these in Settings > Secrets and variables > Actions:

SecretDescription
CCA_API_KEYCCA API key (sign up here)
AWS_ROLE_ARNIAM role ARN for OIDC authentication (recommended)

Or use static credentials:

SecretDescription
AWS_ACCESS_KEY_IDAWS access key
AWS_SECRET_ACCESS_KEYAWS secret key

For Azure (see Scanning Azure above):

SecretDescription
AZURE_CLIENT_IDService principal client ID
AZURE_TENANT_IDAzure AD tenant ID
AZURE_SUBSCRIPTION_IDSubscription to scan
AZURE_CLIENT_SECRETService principal secret (only for the non-OIDC path)

Use Cases

Weekly Scheduled Scan

name: Weekly Cost Scan

on:
schedule:
- cron: '0 9 * * 1' # Monday 9am UTC
workflow_dispatch:

permissions:
id-token: write
contents: read

jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1

- uses: dragonfractal/cca-scan-action@v1
with:
api-key: ${{ secrets.CCA_API_KEY }}
comment-on-pr: 'false'

PR Cost Impact Check

name: Cost Impact Check

on:
pull_request:
branches: [main]
paths:
- 'terraform/**'
- 'infrastructure/**'

permissions:
id-token: write
contents: read
pull-requests: write

jobs:
cost-check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1

- uses: dragonfractal/cca-scan-action@v1
with:
api-key: ${{ secrets.CCA_API_KEY }}
comment-on-pr: 'true'

Upload findings to code scanning (SARIF)

Emit SARIF and upload it so findings show up in the repo's Security > Code scanning tab. Note the security-events: write permission, required to upload.

name: Cost Findings (Code Scanning)

on:
schedule:
- cron: '0 6 * * 1'
workflow_dispatch:

permissions:
id-token: write
contents: read
security-events: write # required to upload SARIF

jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1

- name: Install CCA
run: curl -sSL https://releases.dragonfractal.com/install.sh | sh

- name: Scan to SARIF
env:
CCA_API_KEY: ${{ secrets.CCA_API_KEY }}
run: cca scan --provider aws --output sarif --output-file cca.sarif

- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: cca.sarif

Multi-Region Scan

name: Multi-Region Scan

on:
schedule:
- cron: '0 6 * * *'

permissions:
id-token: write
contents: read

jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1

- uses: dragonfractal/cca-scan-action@v1
with:
api-key: ${{ secrets.CCA_API_KEY }}
regions: us-east-1,us-west-2,eu-west-1
comment-on-pr: 'false'

Fail on Too Many Findings

- uses: dragonfractal/cca-scan-action@v1
with:
api-key: ${{ secrets.CCA_API_KEY }}
fail-on-findings: '20' # Fail if more than 20 findings

Use Outputs in Subsequent Steps

- uses: dragonfractal/cca-scan-action@v1
id: cca
with:
api-key: ${{ secrets.CCA_API_KEY }}

- name: Check results
run: |
echo "Found ${{ steps.cca.outputs.findings-count }} findings"
echo "Potential savings: $${{ steps.cca.outputs.total-savings }}/mo"

Alternative: Docker Image

If you prefer to run CCA directly without the action:

- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: us-east-1

- name: Run CCA
run: |
docker run --rm \
-e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN \
dragonfractal/cca:latest \
scan --api-key ${{ secrets.CCA_API_KEY }} -r us-east-1

Alternative: Install Script

- name: Install CCA
run: curl -sSL https://releases.dragonfractal.com/install.sh | sh

- name: Scan
env:
CCA_API_KEY: ${{ secrets.CCA_API_KEY }}
run: cca scan -r us-east-1

Next Steps