How to Scope a Monorepo Build With git diff in GitHub Actions
A git diff against the base ref reveals which package directories changed, with no plugin required.
Check out full history, run git diff --name-only <base>..., reduce paths to package names, and loop the build over just those packages.
Steps
- Check out with
fetch-depth: 0. - Diff against
origin/<base>to list changed files. - Map paths to package dirs and build each.
Workflow
.github/workflows/ci.yml
jobs:
scoped:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: |
BASE="origin/${{ github.base_ref || 'main' }}"
PKGS=$(git diff --name-only "$BASE"... -- packages \
| cut -d/ -f2 | sort -u)
for p in $PKGS; do
echo "Building packages/$p"
pnpm --filter "./packages/$p" run build
doneGotchas
- Use three-dot
base...to diff against the merge base, not the literal base tip. - A shallow clone has no merge base;
fetch-depth: 0is required for a correct diff.
Related guides
How to Generate a Job Matrix From Changed Directories in GitHub ActionsBuild a GitHub Actions matrix at runtime from the directories a PR changed, emitting JSON to a job output and…
How to Sparse-Checkout One Package in a Monorepo With GitHub ActionsCheck out only one package directory from a large monorepo in GitHub Actions with the sparse-checkout input o…