Action — detect-changes
Detects which subdirectories under apps/ (or a custom directory) have changed since the last commit, and outputs a JSON matrix for use in downstream matrix jobs.
Usage
yaml
jobs:
detect:
runs-on: ubuntu-latest
outputs:
changed-apps: ${{ steps.changes.outputs.changed-apps }}
has-changes: ${{ steps.changes.outputs.has-changes }}
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
- uses: KevinDeBenedetti/github-workflows/.github/actions/detect-changes@main
id: changes
with:
apps-directory: apps
build:
needs: detect
if: needs.detect.outputs.has-changes == 'true'
strategy:
matrix:
app: ${{ fromJson(needs.detect.outputs.changed-apps) }}
runs-on: ubuntu-latest
steps:
- run: echo "Building ${{ matrix.app }}"Inputs
| Input | Type | Default | Description |
|---|---|---|---|
apps-directory | string | apps | Root directory containing app subdirectories |
base-ref | string | '' | Base git ref to compare against (auto-detected if empty) |
Outputs
| Output | Description |
|---|---|
changed-apps | JSON array of changed app names, e.g. ["api","web"] |
has-changes | "true" or "false" — whether any app changed |
changed-api | "true" or "false" — whether apps/api changed |
changed-web | "true" or "false" — whether apps/web changed |
changed-client | "true" or "false" — whether apps/client changed |
Base ref resolution
- Uses
base-refinput if provided - Falls back to
github.event.pull_request.base.shaon pull requests - Falls back to
github.event.beforeon push events - Falls back to
HEAD~1if the before SHA is empty or all zeros (e.g. first push to branch)
Notes
- Requires
fetch-depth: 0(or at least enough history to compare against the base ref) in your checkout step. When the base commit is missing from the clone the action fails with an explicit error instead of reporting "no change" (which used to skip every downstream job). - Per-app boolean outputs (
changed-api,changed-web,changed-client) are useful forif:conditions when you don't need a matrix. Composite actions cannot declare outputs dynamically, so only these three names exist; for any other app testchanged-apps, e.g.contains(fromJson(steps.changes.outputs.changed-apps), 'admin'). - App names are sanitized (lowercased, non-alphanumeric characters replaced with
_) in the output key names.