In this tutorial, you will set up Digger to automate Terragrunt pull requests using Github Actions

Prerequisites

Step 1: create your Digger account

Head to ui.digger.dev and sign up using your preferred method. You should see an empty dashboard after you sign up.

Step 2: install the Digger GitHub App

Install the Digger GitHub App into your repository.
Digger GitHub App does not need access to your cloud account, it just starts jobs in your CI. All sensitive data stays in your CI job.You can also self-host Digger orchestrator with a private GiHub app and issue your own token

Step 3: Create Action Secrets with cloud credentials

In GitHub repository settings, go to Secrets and Variables - Actions. Create the following secrets:
  • AWS_ACCESS_KEY_ID
  • AWS_SECRET_ACCESS_KEY
You can also use OIDC for AWS authentication.

Step 4: Create digger.yml

Terragrunt projects can be configured in two ways:

Option A: Individual projects (for smaller setups)

If you have a few Terragrunt modules, you can list them individually:
projects:
- name: dev
  dir: dev
  terragrunt: true
- name: prod
  dir: prod
  terragrunt: true
For Terragrunt monorepos with many modules, use the blocks syntax to automatically generate projects:
generate_projects:
  blocks:
    - block_name: dev
      terragrunt: true
      root_dir: "dev/"
      workflow: default
    - block_name: staging
      terragrunt: true
      root_dir: "staging/"
      workflow: default
    - block_name: prod
      terragrunt: true
      root_dir: "prod/"
      workflow: default

workflows:
  default:
    plan:
      steps:
        - init
        - plan
    apply:
      steps:
        - init
        - apply
This approach automatically discovers all Terragrunt modules under each directory and creates projects for them. Digger will also handle dependencies between modules.
For more advanced configurations and performance optimization for large monorepos, see Using Terragrunt and Generate Projects.

Step 5: Create Github Actions workflow file

Place it at .github/workflows/digger_workflow.yml (name is important!)
name: Digger Workflow

on:
  workflow_dispatch:
    inputs:
      spec:
        required: true
      run_name:
        required: false

run-name: '${{inputs.run_name}}'

jobs:
  digger-job:
    runs-on: ubuntu-latest
    permissions:
      contents: write      # required to merge PRs
      actions: write       # required for plan persistence
      id-token: write      # required for workload-identity-federation
      pull-requests: write # required to post PR comments
      issues: read         # required to check if PR number is an issue or not
      statuses: write      # required to validate combined PR status

    steps:
      - uses: actions/checkout@v4
      - name: ${{ fromJSON(github.event.inputs.spec).job_id }}
        run: echo "job id ${{ fromJSON(github.event.inputs.spec).job_id }}"
      - uses: diggerhq/digger@vLatest
        with:
          digger-spec: ${{ inputs.spec }}
          setup-aws: true
          setup-terragrunt: true
          terragrunt-version: 0.44.1
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        env:
          GITHUB_CONTEXT: ${{ toJson(github) }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Notice that we use setup-terragrunt: true instead of setup-terraform. Terragrunt will handle the Terraform binary installation internally.

Step 6: Create a PR to verify that it works

Terragrunt will run an existing plan against your code. Make any change to your Terragrunt code e.g. add a blank line. An action run should start (you can see log output in Actions). After some time you should see output of Terragrunt Plan added as a comment to your PR. Then you can add a comment like digger apply and shortly after apply output will be added as comment too.

Demo repositories

Important notes

SOPS integration

If you use sops_decrypt_file in your terragrunt.hcl, you need to handle the case when Digger generates projects in the backend. Use the DIGGER_GENERATE_PROJECT environment variable:
locals {
  secrets = get_env("DIGGER_GENERATE_PROJECT", "false") == "true" ? {} : yamldecode(sops_decrypt_file("secrets.yaml"))
}
This prevents SOPS decryption errors during project generation.

Performance optimization

For very large Terragrunt monorepos, consider:
  • Using the blocks syntax to segment your repository
  • Implementing config caching for faster PR processing
  • Organizing modules by environment or provider to minimize traversal time