DEV Community

Haripriya Veluchamy
Haripriya Veluchamy

Posted on

A Monorepo Success Story: Path-Based Pipeline Triggering in Azure DevOps

Introduction

Managing CI/CD pipelines for a monorepo can quickly become challenging as your project grows. What starts as a simple, single pipeline can evolve into a resource-intensive process that slows down development and increases costs. Here's how I implemented path-based pipeline triggering to solve these challenges.

The Challenge: Monorepo Growing Pains

Our project started with a single pipeline managing all components (frontend, backend, database, infrastructure). As we grew, several issues emerged:

  • Inefficient Resource Usage: Every code change triggered a full pipeline run
  • Slow Feedback: Developers waited too long for build results
  • Agent Pool Congestion: Our Azure DevOps agents were constantly busy
  • Increased Costs: Unnecessary pipeline runs consumed build minutes
  • Poor Developer Experience: Waiting for pipelines slowed development

We needed to run pipelines only for components that changed, reduce build times, and optimize resources.

The Solution: Path-Based Triggering

I implemented a path-based pipeline triggering strategy with these key components:

1. Component-Specific Pipelines

I created separate pipelines for each major component (frontend, backend, database, infrastructure).

2. Strategic Path-Based Triggers

For each pipeline, I configured path-based triggers:

trigger:
  batch: true
  branches:
    include:
    - main
  paths:
    include:
    - component-directory/**
    - .azure-pipelines/component-pipeline.yaml
Enter fullscreen mode Exit fullscreen mode

Key elements:

  • Path Patterns: Using /** to match directories recursively
  • Self-Referential Inclusion: Including the pipeline file itself
  • Batch Processing: Combining rapid commits with batch: true

3. Consistent PR Triggers

I applied identical path filtering to PR validations:

pr:
  branches:
    include:
    - main
  paths:
    include:
    - component-directory/**
    - .azure-pipelines/component-pipeline.yaml
Enter fullscreen mode Exit fullscreen mode

4. Precise Path Matching

Success required attention to:

  • Directory structure alignment
  • File extension accuracy (.yaml vs .yml)
  • Comprehensive path coverage

Implementation Challenges

My initial attempts had issues:

  • I forgot to configure PR triggers, causing PR validations to run all pipelines
  • Azure DevOps requires exact path matching, so precision matters
  • Finding the right balance of path patterns took iteration

The Results

After implementation, we achieved:

  • 70% reduction in pipeline runs
  • 3-4x faster feedback cycles for developers
  • Improved agent availability for other projects
  • Significant cost savings in build minutes
  • Better developer experience with faster turnaround

Key Lessons Learned

  1. Path-Based Triggers Need Precision: Patterns must exactly match your repository structure
  2. Configure Both CI and PR Triggers: Missing either causes unnecessary pipeline runs
  3. Include Pipeline Files in Triggers: Ensures pipeline changes trigger validation
  4. Use Batch Processing: Optimizes performance for busy repositories

Best Practices

  • Map Component Boundaries: Understand which directories belong to which components
  • Start Broad, Then Refine: Monitor and adjust path patterns based on observations
  • Test on a Development Branch First: Avoid disrupting your main branch
  • Document Your Approach: Help team members understand the pipeline organization

Conclusion

Path-based pipeline triggering transformed our monorepo CI/CD process from a bottleneck to an efficient system. The approach saved time and resources while enhancing developer productivity.

If you're managing a growing monorepo in Azure DevOps, I recommend exploring path-based triggers. The initial setup requires attention to detail, but the benefits in efficiency, cost savings, and developer satisfaction make it worthwhile.

# Sample Configuration Template
trigger:
  batch: true
  branches:
    include:
    - main
  paths:
    include:
    - your-component-directory/**
    - .azure-pipelines/your-component-pipeline.yaml

pr:
  branches:
    include:
    - main
  paths:
    include:
    - your-component-directory/**
    - .azure-pipelines/your-component-pipeline.yaml
Enter fullscreen mode Exit fullscreen mode

Have you implemented path-based triggering in your DevOps setup? I'd love to hear your experiences!

Top comments (0)