Skip to content

feat: Implement nbgv path-filters command for monorepo pathFilters automation#1397

Merged
AArnott merged 8 commits into
mainfrom
aarnott-nbgv-path-filters-command
Jun 23, 2026
Merged

feat: Implement nbgv path-filters command for monorepo pathFilters automation#1397
AArnott merged 8 commits into
mainfrom
aarnott-nbgv-path-filters-command

Conversation

@AArnott

@AArnott AArnott commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements the nbgv path-filters command to automate discovery and maintenance of pathFilters in monorepo scenarios. This addresses #1396 by leveraging MSBuild's ProjectGraph API to efficiently compute transitive closure of project dependencies.

What's New

Two new subcommands:

  • nbgv path-filters check - Validates that pathFilters in all version.json files are complete and correct
  • nbgv path-filters update - Automatically computes and updates pathFilters based on actual project structure

Key Design Decisions

MSBuild ProjectGraph for Dependency Discovery

  • Uses the standard MSBuild ProjectGraph API to find transitive closure of project references
  • Efficient single-pass analysis for monorepos of any size
  • Naturally handles multi-framework projects and complex dependency graphs

Respects version.json Boundaries

  • When searching for projects under a version.json, stops at any subdirectory that has its own version.json
  • Prevents root-level version.json from incorrectly claiming nested projects
  • Allows independent versioning of different monorepo components

Includes Entire Project Directories

  • pathFilters specify project directories (e.g., /ProjectA) rather than individual .csproj files
  • Cleaner, more intuitive filters: any source change under the directory triggers versioning
  • Shared build files like Directory.Build.props are included as specific file paths

Respects .gitignore Rules

  • Uses Repository.Ignore.IsPathIgnored() to exclude all ignored files (including generated directories like bin/, obj/, packages/)
  • Prevents build artifacts and NuGet cache files from being treated as source code
  • Respects all .gitignore patterns configured in the repository

Transitive Dependency Inclusion

  • If project B references project A, B's pathFilters includes files imported by A
  • This is correct: if A's build changes, B is affected via the project reference
  • Ensures downstream projects version-bump when upstream dependencies change

Documentation

Added comprehensive documentation in docfx/docs/path-filters.md covering:

  • When to use these commands
  • How the analysis works
  • Important behaviors and edge cases
  • Real-world examples showing monorepo scenarios
  • CI integration recommendations

Testing

Verified with a test directory containing:

  • Root version.json (left untouched as it has no direct projects)
  • Two nested components (A and B) with their own version.json files
  • B depends on A; A imports shared .props files
  • Both check and update subcommands produce correct results
  • Shared imports are included in both components' pathFilters
  • Generated files are properly excluded

Closes #1396

AArnott and others added 8 commits June 23, 2026 11:59
- Register MSBuildLocator at application startup (MainInner) instead of per-command
- MSBuildLocator must be registered before any MSBuild code is loaded
- Add Microsoft.Build.Locator package reference
- Filter out obj/ and bin/ directory files from pathFilters (these are generated)
- Fix StyleCop warning SA1507 (multiple blank lines)

This ensures the path-filters command correctly uses the installed MSBuild
and SDK resolvers when evaluating projects, and includes only source files
in the computed pathFilters.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…ual project files

- Include the directory containing each project (e.g., /A) instead of the .csproj file
- Keep individual files for MSBuild imports like Directory.Build.props since these
  are shared build files not contained in project directories
- This makes pathFilters cleaner and more intuitive

For example, B's pathFilters now includes /A and /B (directories) plus
/Directory.Build.props (shared file) instead of /A/A.csproj and /B/B.csproj.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…n files

- Only process version.json files that have at least one MSBuild project
- When searching for projects, stop at directories containing other version.json files
- This prevents root version.json files with no direct projects from being processed
- Each version.json boundary is respected, ensuring clean separation of concerns

Example: In a directory structure with root/A/version.json and root/B/version.json,
the root version.json is left untouched because all its projects are in subdirectories
with their own version.json files. Only A and B are processed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Add comprehensive documentation to path-filters.md covering:
  - When to use path-filters command (monorepos, complex dependencies)
  - How it works (project discovery, transitive dependencies, shared files)
  - Important behaviors (orphan skipping, boundary respect, directory inclusion)
  - Usage examples (check, update commands with options)
  - Real-world example with multiple projects
  - CI integration guidance

- Add reference in nbgv-cli.md command list linking to path-filters documentation

The path-filters command automates computation and validation of pathFilters
based on MSBuild project structure, making it easy to maintain correct
filters in monorepos with multiple versioned projects.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…paths

- Added virtual IsIgnored(path) method to GitContext base class
- Implemented in LibGit2Context to check against common .gitignore patterns (bin/, obj/, packages/, .vs/, .vscode/, node_modules/)
- This ensures generated files are excluded from pathFilters more comprehensively
- Simplistic but effective approach that covers the most common use cases

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…hecking

- Replaced manual pattern matching with LibGit2Sharp's built-in ignore checking
- This respects all .gitignore patterns in the repository, not just hardcoded directories
- Cleaner, more maintainable, and handles all ignore rules correctly
- Properly converts absolute paths to repo-relative paths before checking

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@AArnott AArnott added this pull request to the merge queue Jun 23, 2026
Merged via the queue into main with commit 0347da5 Jun 23, 2026
12 checks passed
@AArnott AArnott deleted the aarnott-nbgv-path-filters-command branch June 23, 2026 20:48
@AArnott AArnott added this to the v3.10 milestone Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Automatic increase of version when transitively included project changes

1 participant