-
Notifications
You must be signed in to change notification settings - Fork 0
[ci-coach] ci: add per-component path filtering to skip unaffected build jobs #424
Description
Summary
Adds per-component change detection to the CI workflow so that only the relevant build job(s) run when a PR touches a single component. This is particularly impactful for the many Dependabot PRs this polyglot repo receives — a frontend npm bump no longer triggers the .NET, Go, and Python builds.
Optimizations
1. Per-Component Path Filtering
Type: Conditional Execution
Impact: Estimated ~75% reduction in CI minutes for single-component changes (3 of 4 jobs skipped)
Risk: Low
Changes:
- Added a new
changesjob usingdorny/paths-filter@v3.0.2(pinned to commit SHAde90cc6) that detects which component directories were modified - Each build job (
build-dotnet,build-go,build-python,build-web) now has:needs: [changes]— waits for the filter job (~5s)if: needs.changes.outputs.(component) == 'true'— skips unless relevant files changed
- Filter paths are scoped precisely per component, with
'.github/workflows/ci.yml'included in all filters so CI workflow changes still trigger a full matrix run
Rationale: The existing src/** path filter at the workflow level correctly gates the workflow trigger, but every triggered run executes all 4 independent jobs regardless of which component changed. In this polyglot repo, Dependabot raises separate PRs per ecosystem (npm, pip, Go modules, NuGet) — each was running all 4 builds unnecessarily.
Detailed Analysis
Observed Dependabot PR pattern (recent commits):
Bump globals from 17.3.0 to 17.4.0 in /src/Garage.Web→ previously triggered dotnet + go + python + web buildsBump@types/nodefrom 25.3.2 to 25.3.3 in /src/Garage.Web→ same
With this change, both of those PRs would only run changes + build-web.
Filter path mappings:
| Component | Trigger paths |
|---|---|
dotnet |
src/Garage.{ApiService,ApiDatabaseSeeder,ApiModel,AppHost,ServiceDefaults,Shared}/**, **/*.csproj, **/*.props, *.slnx, global.json |
go |
src/Garage.FeatureFlags/** |
python |
src/Garage.ChatService/** |
web |
src/Garage.Web/** |
| all | .github/workflows/ci.yml |
Trade-off: The changes job adds ~5–10s overhead per run. For single-component changes the net saving is the full runtime of the 3 skipped builds (easily 3–5 minutes saved per run).
Expected Impact
- Time Savings: ~3–5 minutes per single-component PR run (3 builds skipped)
- Cost Reduction: ~75% fewer runner-minutes on Dependabot PRs
- Risk Level: Low — worst case is a build job is incorrectly skipped if paths are misconfigured, which is easy to detect and fix
Testing Recommendations
- Review workflow syntax (YAML is valid)
- Monitor first few Dependabot PRs after merge to confirm correct jobs are selected
- Verify a multi-component change (e.g., shared .props file) still triggers all builds
Generated by CI Optimization Coach
To install this agentic workflow, run
gh aw add githubnext/agentics/workflows/ci-coach.md@da02dddebe71d9a937665abdcd1f5214dab852a7
- expires on Mar 4, 2026, 11:26 AM UTC
Note
This was originally intended as a pull request, but the git push operation failed.
Workflow Run: View run details and download patch artifact
The patch file is available in the agent-artifacts artifact in the workflow run linked above.
To create a pull request with the changes:
# Download the artifact from the workflow run
gh run download 22573672290 -n agent-artifacts -D /tmp/agent-artifacts-22573672290
# Create a new branch
git checkout -b ci/per-component-path-filtering-6656db231dbcbed8
# Apply the patch (--3way handles cross-repo patches where files may already exist)
git am --3way /tmp/agent-artifacts-22573672290/aw-ci-per-component-path-filtering.patch
# Push the branch to origin
git push origin ci/per-component-path-filtering-6656db231dbcbed8
# Create the pull request
gh pr create --title '[ci-coach] ci: add per-component path filtering to skip unaffected build jobs' --base main --head ci/per-component-path-filtering-6656db231dbcbed8 --repo askpt/openfeature-aspire-sampleShow patch preview (103 of 103 lines)
From a451f94c51a4ddd90edc58d96687c732b631a098 Mon Sep 17 00:00:00 2001
From: Copilot <223556219+Copilot@users.noreply.github.com>
Date: Mon, 2 Mar 2026 11:24:48 +0000
Subject: [PATCH] ci: add per-component path filtering to skip unaffected build
jobs
Add a 'changes' detection job using dorny/paths-filter that identifies
which components (dotnet/go/python/web) were modified. Each build job
now only runs when its relevant source files change.
This avoids running all 4 build jobs for component-isolated changes
such as Dependabot npm/pip/go bumps, which previously triggered all
builds due to the broad 'src/**' path filter.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.github/workflows/ci.yml | 47 ++++++++++++++++++++++++++++++++++++++++
1 file changed, 47 insertions(+)
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index ee25a3a..2a89773 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -23,7 +23,48 @@ concurrency:
cancel-in-progress: ${{ github.ref != 'refs/heads/main' }}
jobs:
+ # Detect which components changed to skip unaffected build jobs
+ changes:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ pull-requests: read
+ outputs:
+ dotnet: ${{ steps.filter.outputs.dotnet }}
+ go: ${{ steps.filter.outputs.go }}
+ python: ${{ steps.filter.outputs.python }}
+ web: ${{ steps.filter.outputs.web }}
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
+ - uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36 # v3.0.2
+ id: filter
+ with:
+ filters: |
+ dotnet:
+ - 'src/Garage.ApiService/**'
+ - 'src/Garage.ApiDatabaseSeeder/**'
+ - 'src/Garage.ApiModel/**'
+ - 'src/Garage.AppHost/**'
+ - 'src/Garage.ServiceDefaults/**'
+ - 'src/Garage.Shared/**'
+ - '**/*.csproj'
+
... (truncated)