---
name: dotnet-dev
description: 'Expert guidance for .NET development in this repository. Use this skill for building, testing, debugging, and understanding project structure, coding conventions, dependency injection patterns, and testing practices.'
---
# .NET Development Skills
Expert guidance for .NET development in this repository.
## Build & Test Commands
```bash
# Build the solution
dotnet build ./src/GitVersion.slnx
# Build a single project
dotnet build --project ./src/GitVersion.Core/GitVersion.Core.csproj
# Run all tests
dotnet test --solution ./src/GitVersion.slnx
# Run tests for a specific project
dotnet test --project ./src/GitVersion.Core.Tests/GitVersion.Core.Tests.csproj
# Run tests with specific framework
dotnet test --project ./src/GitVersion.Core.Tests/GitVersion.Core.Tests.csproj --framework net10.0
# Run specific test by filter
dotnet test --project ./src/GitVersion.Core.Tests/GitVersion.Core.Tests.csproj --filter "FullyQualifiedName~TestClassName"
# Format code
dotnet format ./src/GitVersion.slnx
# Verify formatting (CI-friendly)
dotnet format --verify-no-changes ./src/GitVersion.slnx
```
## Package Management
This repository uses **Central Package Management** via `Directory.Packages.props`.
### Adding/Updating Packages
```bash
# Add a package (version managed centrally)
dotnet add ./src/ProjectName/ProjectName.csproj package PackageName
# Update central package version in src/Directory.Packages.props
```
**Important**: Always update versions in `src/Directory.Packages.props`, not in individual `.csproj` files.
### Directory.Packages.props Structure
```xml
true
```
## Project Structure
- `src/` - Main solution with production code and tests
- `new-cli/` - New CLI implementation (separate solution)
- `build/` - Build automation (Cake-based)
- `docs/` - Documentation
### Key Projects
| Project | Purpose |
|----------------------------|---------------------------------------|
| `GitVersion.Core` | Core version calculation logic |
| `GitVersion.App` | CLI application |
| `GitVersion.Configuration` | Configuration file handling |
| `GitVersion.Output` | Output formatters (JSON, BuildServer) |
| `GitVersion.BuildAgents` | CI/CD platform integrations |
| `GitVersion.MsBuild` | MSBuild task integration |
| `GitVersion.LibGit2Sharp` | Git repository abstraction |
## Coding Conventions
### Primary Constructors
Prefer primary constructors with readonly field assignments:
```csharp
internal class BuildAgentResolver(IEnumerable buildAgents, ILogger logger) : IBuildAgentResolver
{
private readonly IEnumerable buildAgents = buildAgents.NotNull();
private readonly ILogger logger = logger.NotNull();
public IBuildAgent? Resolve()
{
// Use this.buildAgents and this.logger
}
}
```
### Dependency Injection
Use constructor injection with `ILogger` for logging:
```csharp
public class MyService
{
private readonly ILogger logger;
public MyService(ILogger logger)
{
this.logger = logger;
}
}
```
### Logging
Use Microsoft.Extensions.Logging with Serilog:
```csharp
// Information level
this.logger.LogInformation("Processing {BranchName}", branch.Name);
// Warning level
this.logger.LogWarning("Configuration not found, using defaults");
// Error level
this.logger.LogError(ex, "Failed to calculate version");
// Debug level (verbose)
this.logger.LogDebug("Cache hit for {CacheKey}", key);
```
### Nullable Reference Types
All projects use nullable reference types. Handle nullability explicitly:
```csharp
public string? OptionalProperty { get; set; }
public string RequiredProperty { get; set; } = string.Empty;
```
### File-Scoped Namespaces
Use file-scoped namespaces:
```csharp
namespace GitVersion;
public class MyClass
{
// ...
}
```
## Testing
### Test Project Naming
- Test projects mirror source projects: `GitVersion.Core` → `GitVersion.Core.Tests`
### Test Frameworks
- **NUnit** - Primary test framework
- **NSubstitute** - Mocking framework
- **Shouldly** - Assertion library
### Test Patterns
```csharp
[TestFixture]
public class MyServiceTests
{
[Test]
public void MethodName_Scenario_ExpectedResult()
{
// Arrange
var service = new MyService();
// Act
var result = service.DoSomething();
// Assert
result.ShouldBe(expected);
}
[TestCase("input1", "expected1")]
[TestCase("input2", "expected2")]
public void MethodName_WithParameters_ReturnsExpected(string input, string expected)
{
var result = service.Process(input);
result.ShouldBe(expected);
}
}
```
## Configuration Files
### Supported Names
- `GitVersion.yml`
- `GitVersion.yaml`
- `.GitVersion.yml`
- `.GitVersion.yaml`
### Schema Location
JSON schemas are in `schemas/` directory for validation.
## Build Agents
Build agent integrations write environment variables with `GitVersion_` prefix:
```csharp
// Example: GitHub Actions
Environment.SetEnvironmentVariable($"GitVersion_{name}", value);
```
## Common Tasks
### Running the CLI Locally
```bash
dotnet run --project src/GitVersion.App
```
### Debugging Tests
```bash
# Run with detailed output
dotnet test --project ./src/GitVersion.Core.Tests/GitVersion.Core.Tests.csproj -v detailed
# Run specific test
dotnet test --filter "FullyQualifiedName=GitVersion.Core.Tests.MyTest"
```
### Checking for Errors
```bash
# Build with warnings as errors
dotnet build ./src/GitVersion.slnx -warnaserror
```
## Public API Management
This repository
uses [Microsoft.CodeAnalysis.PublicApiAnalyzers](https://github.com/dotnet/roslyn-analyzers/blob/main/src/PublicApiAnalyzers/PublicApiAnalyzers.Help.md)
to track public API surface.
### Rules
- **`PublicAPI.Unshipped.txt`**: All new or modified public APIs go here
- **`PublicAPI.Shipped.txt`**: Only deletions are allowed; never add or modify entries directly
### Workflow
1. When adding new public APIs, they automatically get flagged and should be added to `PublicAPI.Unshipped.txt`
2. When modifying existing APIs, move the old entry from `PublicAPI.Shipped.txt` to `PublicAPI.Unshipped.txt` (marked as
removed) and add the new signature to `PublicAPI.Unshipped.txt`
3. Only remove entries from `PublicAPI.Shipped.txt` when an API is being deleted
4. During release, unshipped APIs get moved to shipped via the `mark-shipped.ps1` script