Monorepo with Path-Based Filtering

Configure GitHub Actions for monorepos using path filtering to run specific jobs only when relevant directories change. Covers dorny/paths-filter and built-in path triggers.

Advanced

Detailed Explanation

Path-Based Workflow Filtering for Monorepos

Monorepos contain multiple projects in a single repository. Without path filtering, every push triggers CI for all projects — wasting time and compute. Path filtering ensures only affected projects are tested.

Built-in Path Filtering

name: Frontend CI

on:
  push:
    paths:
      - 'packages/frontend/**'
      - 'packages/shared/**'
      - 'package.json'
  pull_request:
    paths:
      - 'packages/frontend/**'
      - 'packages/shared/**'

jobs:
  test-frontend:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run test --workspace=packages/frontend

Advanced: Dynamic Path Detection

For more complex scenarios, use dorny/paths-filter to detect changes and conditionally run jobs:

name: Monorepo CI

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  detect-changes:
    runs-on: ubuntu-latest
    outputs:
      frontend: ${{ steps.filter.outputs.frontend }}
      backend: ${{ steps.filter.outputs.backend }}
      shared: ${{ steps.filter.outputs.shared }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            frontend:
              - 'packages/frontend/**'
            backend:
              - 'packages/backend/**'
            shared:
              - 'packages/shared/**'

  test-frontend:
    needs: detect-changes
    if: needs.detect-changes.outputs.frontend == 'true' || needs.detect-changes.outputs.shared == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run test --workspace=packages/frontend

  test-backend:
    needs: detect-changes
    if: needs.detect-changes.outputs.backend == 'true' || needs.detect-changes.outputs.shared == 'true'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm ci
      - run: npm run test --workspace=packages/backend

Key Benefits

  • Reduced CI time: Only test what changed
  • Shared dependency tracking: The shared filter triggers both frontend and backend tests when common code changes
  • Dynamic workflows: Job-level conditionals skip entire jobs (shown as "skipped" in the UI, still count as passed for required checks)

Path Syntax

Pattern Matches
src/** Any file under src/
*.js JS files in root directory only
**/*.test.ts Test files anywhere in the repo
!docs/** Exclude docs directory (negation)

Use Case

Managing CI/CD for monorepos with multiple packages, services, or applications in a single repository. Common in organizations using tools like Turborepo, Nx, Lerna, or npm/pnpm workspaces.

Try It — GitHub Actions Workflow Builder

Open full tool