Skip to content

[ci-coach] ci: add per-component path filtering to skip unaffected build jobs #424

@github-actions

Description

@github-actions

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 changes job using dorny/paths-filter@v3.0.2 (pinned to commit SHA de90cc6) 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 builds
  • Bump @types/node from 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-sample
Show 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)

Metadata

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions