--- 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