Build only what changed, not the entire solution!
Features • Problem • Solution • Setup • Documentation
This PowerShell script revolutionizes CI/CD pipelines for large .NET solutions by implementing intelligent selective building. Instead of rebuilding hundreds of projects for a single file change, it analyzes Git diff and builds only affected projects.
Perfect for:
- 🏢 Enterprise legacy applications with 100+ projects
- 🔧 Teams without Docker or modern containerization
- ⏰ Projects with 20+ minute build times
- 💰 Organizations with limited CI/CD budget
❌ Solution with 150+ projects
❌ Every PR triggers a full solution build
❌ 20-30 minutes waiting for a single line change
❌ Legacy codebase without Docker support
❌ No budget for proper CI/CD refactoring
Traditional MSBuild approach:
<MSBuild Projects="EntireSolution.sln" />☝️ Rebuilds EVERYTHING, even if you changed one CSS file!
graph LR
A[Feature Branch] -->|Git Diff| B[Changed Files]
B --> C[Extract Projects]
C --> D[Build Only Changed]
D --> E[20 min saved! ⚡]
Our approach:
<MSBuild Projects="$(projects)" />☝️ Builds only changed projects + their dependencies!
| Feature | Description |
|---|---|
| 🎯 Selective Building | Analyzes Git changes and builds only affected projects |
| 🔍 Dependency Tracking | Automatically includes referenced projects |
| 🌿 Branch Comparison | Compares feature branches against master/develop |
| 🔄 PR Support | Native Azure DevOps Pull Request integration |
| 📊 Frontend Detection | Separate tracking for frontend changes |
| ⚙️ Customizable | Adapt to your project structure |
| 📈 Pipeline Variables | Sets Azure DevOps variables for next steps |
| Technology | Purpose | Documentation |
|---|---|---|
| Script Engine | Learn More | |
| Build System | Learn More | |
| CI/CD Platform | Learn More | |
| Version Control | Learn More |
|
Full solution build
|
Only changed projects
|
# Required
- Azure DevOps account
- Git repository
- MSBuild installed
- PowerShell 5.1+-
Clone the repository
git clone https://github.com/damianczer/azure-devops-msbuild-auto.git
-
Add script to your pipeline
steps: - task: PowerShell@2 inputs: filePath: 'script.ps1' arguments: > -CompareSourceBranch "master" -BranchName "$(Build.SourceBranch)" -Repository "$(Build.SourcesDirectory)" -TargetBranch "$(System.PullRequest.TargetBranch)"
-
Configure MSBuild task
- task: MSBuild@1 condition: eq(variables['isBuildable'], 'True') inputs: solution: '$(projects)'
Parameters:
CompareSourceBranch: Base branch (e.g.,master,develop)BranchName: Current branch from pipeline variableRepository: Source directory pathTargetBranch: PR target branch (for PR builds)
Output Variables:
projects: Space-separated list of.csprojfileshasFrontendChanged: Boolean flag for frontend changesisBuildable: Boolean flag if build is needed
Build.proj Example:
<Project>
<Target Name="BuildChanged">
<MSBuild Projects="$(projects)"
Properties="Configuration=Release;Platform=Any CPU"
BuildInParallel="true" />
</Target>
</Project># 1️⃣ Compare branches
git diff --name-only feature-branch..master
# 2️⃣ Extract changed files
src/Feature/Authentication/code/Models/User.cs
src/Feature/Catalog/code/Services/ProductService.cs
src/Frontend/App/components/Header.tsx
# 3️⃣ Find related .csproj files
src/Feature/Authentication/Authentication.csproj
src/Feature/Catalog/Catalog.csproj
# 4️⃣ Set pipeline variables
projects = "Auth.csproj Catalog.csproj"
hasFrontendChanged = true
isBuildable = true
# 5️⃣ MSBuild uses variables
<MSBuild Projects="$(projects)" />The script looks for /code directory by default. Modify for your structure:
# Current structure: src/Feature/FeatureName/code/
if ($element.Contains("/code")) {
# Extract project path
}
# Your structure: src/Modules/ModuleName/
if ($element.Contains("/Modules/")) {
$index = $element.IndexOf("/Modules/")
# Custom logic
}# Track database changes
if ($element.Contains("/Database/")) {
$hasDatabaseChanged = $true
}
# Track API changes
if ($element.Contains("/API/")) {
$hasAPIChanged = $true
}| Parameter | Required | Description | Example |
|---|---|---|---|
CompareSourceBranch |
✅ | Branch to compare against | master, develop |
BranchName |
✅ | Current branch name | feature/new-feature |
Repository |
✅ | Repository path | C:\Repos\MyProject |
TargetBranch |
❌ | PR target branch | refs/heads/develop |
variables:
projects: 'Project1.csproj Project2.csproj'
hasFrontendChanged: 'true'
isBuildable: 'true'Contributions are welcome! Here's how:
- 🍴 Fork the repository
- 🌿 Create feature branch (
git checkout -b feature/AmazingFeature) - 💾 Commit changes (
git commit -m 'Add AmazingFeature') - 📤 Push to branch (
git push origin feature/AmazingFeature) - 🔀 Open Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License - Copyright (c) 2025 Damian Czerwiński




