CI/CD Integration

Block deploys that violate FinOps policies. Run SOFE in your CI pipeline.

GitHub Actions

# .github/workflows/finops-check.yml
name: FinOps Policy Check

on: [push, pull_request]

jobs:
  sofe-evaluate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Install SOFE
        run: pip install sofe
      
      - name: Run evaluation
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: us-east-1
        run: |
          sofe evaluate \
            --policies ./policies/ \
            --fail-on high \
            --format json > findings.json
      
      - name: Upload findings
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: sofe-findings
          path: findings.json

--fail-on Flag

Exit with code 1 if findings meet or exceed the specified severity:

# Fail on critical only (most lenient)
sofe evaluate --policies ./policies/ --fail-on critical

# Fail on high or above (recommended for production)
sofe evaluate --policies ./policies/ --fail-on high

# Fail on any finding (strictest)
sofe evaluate --policies ./policies/ --fail-on low

Using the API (no AWS creds in CI)

# If you've connected your AWS account via platform.sofe.dev,
# you can call the API without local AWS credentials:

- name: SOFE Evaluate (via API)
  run: |
    RESULT=$(curl -s -X POST https://api.sofe.dev/evaluate \
      -H "X-API-Key: ${{ secrets.SOFE_API_KEY }}" \
      -H "Content-Type: application/json" \
      -d '{"policies": ["*"]}')
    
    HIGH=$(echo $RESULT | jq '.summary.high')
    if [ "$HIGH" -gt 0 ]; then
      echo "❌ Found $HIGH high-severity findings"
      exit 1
    fi

GitHub Action — sofe-action@v2

The official SOFE GitHub Action supports two modes: cloud (scan live AWS resources) and terraform (scan plan files pre-deploy).

Cloud Mode (scan live resources)

- uses: breakingthecloud/sofe-action@v2
  with:
    api-key: ${{ secrets.SOFE_API_KEY }}
    mode: cloud
    fail-on: high

Terraform Mode (pre-deploy scan)

- run: terraform plan -out=tfplan && terraform show -json tfplan > tfplan.json

- uses: breakingthecloud/sofe-action@v2
  with:
    api-key: ${{ secrets.SOFE_API_KEY }}
    mode: terraform
    plan-file: tfplan.json
    fail-on: high

Full Workflow (Terraform + PR Comment)

name: FinOps Pre-Deploy Gate
on: pull_request

jobs:
  terraform-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3

      - name: Terraform Plan
        run: |
          cd infra/
          terraform init && terraform plan -out=tfplan
          terraform show -json tfplan > tfplan.json

      - name: SOFE Pre-Deploy Scan
        uses: breakingthecloud/sofe-action@v2
        id: sofe
        with:
          api-key: ${{ secrets.SOFE_API_KEY }}
          mode: terraform
          plan-file: infra/tfplan.json
          fail-on: high

      - name: Comment on PR
        if: always()
        uses: actions/github-script@v7
        with:
          script: |
            const f = '${{ steps.sofe.outputs.findings-count }}';
            const r = '${{ steps.sofe.outputs.resources-scanned }}';
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `## SOFE Scan\n| Metric | Value |\n|--|--|\n| Findings | ${f} |\n| Resources | ${r} |`
            })

Terraform mode advantage: No CLI install needed — the action sends your tfplan.json directly to the API. Same 6 pre-deploy policies check tags, sizing, encryption before terraform apply.

Best Practices

  • Run on PRs (catch issues before merge)
  • Use --fail-on high for production branches
  • Store findings as artifacts (audit trail)
  • Use API key method if AWS creds rotation is complex
  • Start lenient (--fail-on critical), tighten over time