Guides

GitHub Actions

Overview

Use the LevelFour API directly in GitHub Actions to:

  • Post cost summaries as PR comments
  • Generate daily cost reports
  • Monitor savings recommendations in CI

For Terraform-specific cost estimation using the l4 CLI, see CI/CD Integration.

Prerequisites

  1. A LevelFour API key (create one in the dashboard)
  2. Store the key as a GitHub Actions secret named LEVELFOUR_API_KEY

Cost Report via API

Post a cost summary as a PR comment using the REST API directly:

name: Cost Report
on:
  pull_request:
    types: [opened, synchronize]

jobs:
  cost-report:
    runs-on: ubuntu-latest
    permissions:
      pull-requests: write
    steps:
      - name: Get savings summary
        id: summary
        env:
          LEVELFOUR_API_KEY: ${{ secrets.LEVELFOUR_API_KEY }}
        run: |
          RESPONSE=$(curl -s \
            -H "Authorization: Bearer $LEVELFOUR_API_KEY" \
            https://api.levelfour.ai/api/v1/recommendations/savings-by-provider)
          echo "body<<EOF" >> $GITHUB_OUTPUT
          echo "## Cloud Cost Summary" >> $GITHUB_OUTPUT
          echo "" >> $GITHUB_OUTPUT
          echo '```json' >> $GITHUB_OUTPUT
          echo "$RESPONSE" | python3 -m json.tool >> $GITHUB_OUTPUT
          echo '```' >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT

      - name: Comment on PR
        uses: actions/github-script@v7
        with:
          script: |
            const body = process.env.BODY;
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: body,
            });
        env:
          BODY: ${{ steps.summary.outputs.body }}

Using the Python SDK

For richer output, install the SDK directly:

name: Cost Check (Python)
on:
  schedule:
    - cron: '0 9 * * 1-5'

jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - run: pip install levelfour

      - name: Run cost check
        env:
          LEVELFOUR_API_KEY: ${{ secrets.LEVELFOUR_API_KEY }}
        run: |
          python3 -c "
          from levelfour import LevelFour

          client = LevelFour()
          summary = client.recommendations.get_savings_by_provider()
          print(summary)

          overview = client.recommendations.get_overview()
          print(overview)

          spending = client.costs.get_summary()
          print(spending)
          "

Using the TypeScript SDK

name: Cost Check (TypeScript)
on:
  schedule:
    - cron: '0 9 * * 1-5'

jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/setup-node@v4
        with:
          node-version: '22'

      - run: npm install levelfour

      - name: Run cost check
        env:
          LEVELFOUR_API_KEY: ${{ secrets.LEVELFOUR_API_KEY }}
        run: |
          npx tsx -e "
          import { LevelFourClient } from 'levelfour';
          const client = new LevelFourClient();
          const summary = await client.recommendations.getSavingsByProvider();
          console.log(JSON.stringify(summary, null, 2));

          const spending = await client.costs.getSummary();
          console.log(JSON.stringify(spending, null, 2));
          "

Daily Cost Report as Artifact

name: Daily Cost Report
on:
  schedule:
    - cron: '0 9 * * 1-5'

jobs:
  report:
    runs-on: ubuntu-latest
    steps:
      - name: Fetch spending summary
        env:
          LEVELFOUR_API_KEY: ${{ secrets.LEVELFOUR_API_KEY }}
        run: |
          curl -s \
            -H "Authorization: Bearer $LEVELFOUR_API_KEY" \
            https://api.levelfour.ai/api/v1/costs/summary \
            | python3 -m json.tool > spending.json

      - name: Fetch recommendations
        env:
          LEVELFOUR_API_KEY: ${{ secrets.LEVELFOUR_API_KEY }}
        run: |
          curl -s \
            -H "Authorization: Bearer $LEVELFOUR_API_KEY" \
            "https://api.levelfour.ai/api/v1/recommendations?page=1&page_size=100" \
            | python3 -m json.tool > recommendations.json

      - name: Upload report
        uses: actions/upload-artifact@v4
        with:
          name: cost-report-${{ github.run_id }}
          path: |
            spending.json
            recommendations.json