Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Use the most recent .NET LTS as the base image
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS base
# Use .NET 11 as the base image
FROM mcr.microsoft.com/dotnet/sdk:11.0 AS base

# Install .NET 9 SDK and shared frameworks side-by-side
COPY --from=mcr.microsoft.com/dotnet/sdk:9.0 /usr/share/dotnet/sdk /usr/share/dotnet/sdk
COPY --from=mcr.microsoft.com/dotnet/sdk:9.0 /usr/share/dotnet/shared /usr/share/dotnet/shared
# Install .NET 10 SDK and shared frameworks side-by-side
COPY --from=mcr.microsoft.com/dotnet/sdk:10.0 /usr/share/dotnet/sdk /usr/share/dotnet/sdk
COPY --from=mcr.microsoft.com/dotnet/sdk:10.0 /usr/share/dotnet/shared /usr/share/dotnet/shared
7 changes: 6 additions & 1 deletion .github/workflows/ci-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jobs:
with:
projects: coverlet.slnx
configuration: Release
include-preview: true
upload-build-artifact-name: build-release
timeout-minutes: 45

Expand Down Expand Up @@ -65,6 +66,7 @@ jobs:
configuration: Release
build: true
restore: true
include-preview: true
download-pattern: build-release
timeout-minutes: 45

Expand All @@ -76,6 +78,7 @@ jobs:
projects: src/coverlet.MTP/coverlet.MTP.csproj
configuration: Release
version: ${{ needs.build.outputs.version }}
include-preview: true
download-build-artifact-pattern: build-release
upload-packed-artifact-name: NuGet-Release
timeout-minutes: 30
Expand All @@ -89,7 +92,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-26.04, windows-2025, macos-26]
framework: [net9.0, net10.0]
framework: [net10.0, net11.0]
permissions:
contents: read
steps:
Expand All @@ -98,6 +101,8 @@ jobs:

- name: Install .NET
uses: codebeltnet/install-dotnet@v3
with:
includePreview: true

- name: Download validated package
uses: actions/download-artifact@v8
Expand Down
11 changes: 7 additions & 4 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ This fork is intentionally narrower than `coverlet-coverage/coverlet`. Preserve

When synchronizing from `coverlet-coverage/coverlet`, keep the sync selective:

1. Fetch upstream without tags to avoid importing upstream release tags into this fork:
1. Read `UPSTREAM.md` before selecting changes. It records the reviewed upstream snapshot, completed ports, exclusions, and intentional fork differences. Fetch upstream without tags to avoid importing upstream release tags into this fork:

```powershell
git fetch --no-tags https://github.com/coverlet-coverage/coverlet.git master:refs/remotes/coverlet-upstream/master
Expand All @@ -21,10 +21,13 @@ When synchronizing from `coverlet-coverage/coverlet`, keep the sync selective:

3. Port only changes that apply to the retained package surface: `src\coverlet.core`, `src\coverlet.MTP`, and the directly related tests.
4. Do not reintroduce upstream surfaces removed by this fork, including legacy console, collector, msbuild packages, legacy Azure Pipelines, broad upstream documentation, or `version.json`.
5. Preserve `Codebelt.Coverlet.MTP` package identity, `Coverlet.MTP` assembly identity, and the multi-targeted `netstandard2.0;net9.0;net10.0` layout.
5. Preserve `Codebelt.Coverlet.MTP` package identity, `Coverlet.MTP` assembly identity, and the multi-targeted `netstandard2.0;net10.0;net11.0` layout.
6. Keep versioning on MinVer `v*` tags and the existing release workflow guards. Do not restore upstream Nerdbank.GitVersioning files.
7. Adapt release notes to this fork's root `CHANGELOG.md`; describe only changes that were actually ported.
8. If an upstream tag was accidentally fetched and points at an upstream commit, delete that local tag before release preparation:
7. Update `UPSTREAM.md` in the same change set as every upstream sync, including a no-change review. Record the operation date (`YYYY-MM-DD`), upstream repository/branch and exact reviewed commit, comparison base, source commits or PRs, what was ported or adapted, what was already present, and what was omitted or deferred with reasons. Link destination commits or the PR when available. Record validation actually performed, its target frameworks and outcomes, and any unresolved work. Distinguish reviewed, ported, tested, and released states; a reviewed upstream tip does not mean every preceding commit was merged. Update the entry when validation or integration completes, and preserve earlier entries.
When reconstructing earlier operations, verify release-tag targets and distinguish inherited upstream ancestry, selective ports, and Codebelt-only maintenance. Keep the original upstream marker (`v10.0.1-coverlet`) distinct from the later shared comparison base. State whether a date comes from a source commit, integration commit, or recorded operation; do not invent tag creation dates, synchronization dates, or validation results. Do not move tags to make the history appear aligned.
8. Keep meaningful production behavior differences from upstream documented in `UPSTREAM.md`, with a reason and source or regression-test link. Preserve upstream behavior by default; the target-framework focus and Codebelt packaging/tooling do not authorize unrelated features or silent coverage-semantic changes.
9. Adapt release notes to this fork's root `CHANGELOG.md`; describe only changes that were actually ported. Keep `README.md` focused on orientation and usage, with a link to `UPSTREAM.md`; keep the detailed sync ledger in `UPSTREAM.md` and the maintenance rules here.
10. If an upstream tag was accidentally fetched and points at an upstream commit, delete that local tag before release preparation:

```powershell
git tag -d v<version>
Expand Down
23 changes: 20 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,37 @@ All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [vNext] - 2026-10-30
## [11.0.0] - 2026-11-10

This is a patch release that makes the MTP package-validation tests prepare their own Codebelt.Coverlet.MTP package during local builds, including Visual Studio Test Explorer runs, with no runtime or package behavior changes.
This major release adds .NET 11 support, removes the dedicated .NET 9 target, and incorporates upstream improvements to branch coverage and local-function instrumentation. MTP package-validation tests also prepare their own Codebelt.Coverlet.MTP package during local builds, including Visual Studio Test Explorer runs.

### Added

- Add control-flow analysis that identifies branches unreachable from method entry, including through exception handlers, with compatibility for existing serialized instrumentation state,
- Add regression coverage for MTP central configuration files, report formats, coverage thresholds, shared-framework resolution, and branch reachability,
- Add automatic preparation of the Codebelt.Coverlet.MTP package for the MTP package-validation tests during local builds, skipped for IDE design-time builds, with isolated output under `artifacts/validation` per configuration and framework.

### Changed

- Target .NET 10 and .NET 11 alongside .NET Standard 2.0, with runtime dependency versions selected per target framework,
- Exclude unreachable branches from branch coverage totals and from Cobertura, LCOV, and OpenCover branch details,
- Update Microsoft Testing Platform to 2.5.1, Microsoft.NET.Test.Sdk to 18.11.0, xunit.v3.mtp-v2 to 4.0.2, xunit.runner.visualstudio to 4.0.1, Moq to 4.21.0, and LinqKit.Microsoft.EntityFrameworkCore to 10.1.1,
- Update NuGet.Packaging and NuGet.Versioning to 7.9.0, retaining a NuGet.Versioning 6.14.3 override for .NET Standard 2.0,
- Change the validation tests to read the package folder from MSBuild metadata instead of a hard-coded `artifacts/package/<configuration>` path, with missing-package guidance that points to `-p:PrepareValidationPackage=true` or an existing package,
- Disable automatic package preparation in GitHub Actions so validation consumes the downloaded release package, while allowing opt-out outside GitHub Actions with `-p:PrepareValidationPackage=false`,
- Document the automatic packing behavior and opt-out in `CONTRIBUTING.md`, replacing the manual `dotnet pack` step.

### Removed

- Remove the dedicated .NET 9 target,
- Remove the direct System.Reflection.Metadata reference from the core test project, which uses the framework-provided assembly.

### Fixed

- Instrument local functions when CompilerGeneratedAttribute or GeneratedCodeAttribute is excluded, while continuing to honor other configured exclusion attributes,
- Resolve shared-framework assemblies when runtime directory names contain version suffixes,
- Align pattern-matching branch assertions with the selected SDK's compiled output.

## [10.1.1] - 2026-10-20

This is a patch release that fixes module unload mutex collisions between unrelated coverage sessions and updates the Microsoft runtime pins and the `System.Security.Cryptography.Pkcs` override used by coverlet.core, with no new capabilities.
Expand Down Expand Up @@ -111,7 +128,7 @@ This is a minor release focused on the Codebelt.Coverlet.MTP fork with narrowed
- .vscode/settings.json configuration,
- .devcontainer legacy configuration.

[10.1.2]: https://github.com/codebeltnet/coverlet/compare/v10.1.1...vNext
[11.0.0]: https://github.com/codebeltnet/coverlet/compare/v10.1.1...v11.0.0
[10.1.1]: https://github.com/codebeltnet/coverlet/compare/v10.1.0...v10.1.1
[10.1.0]: https://github.com/codebeltnet/coverlet/compare/v10.0.1...v10.1.0
[10.0.1]: https://github.com/codebeltnet/coverlet/compare/v10.0.0...v10.0.1
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Contributions are welcome. This repository is a deliberately narrow Codebelt-mai

## Requirements

Use the .NET SDK pinned by `global.json`. The retained production matrix is `netstandard2.0`, `net9.0`, and `net10.0`; tests execute on `net9.0` and `net10.0`.
Use the .NET SDK pinned by `global.json`. The retained production matrix is `netstandard2.0`, `net10.0`, and `net11.0`; tests execute on `net10.0` and `net11.0`.

## Building, testing, and packing

Expand Down Expand Up @@ -36,7 +36,7 @@ Examples:

```bash
dotnet test test/coverlet.MTP.tests/coverlet.MTP.tests.csproj -c Release -f net10.0 -- --filter-class Coverlet.MTP.Collector.Tests.CollectorExtensionTests
dotnet test test/coverlet.core.tests/coverlet.core.tests.csproj -c Release -f net9.0 -- --filter-method PatternMatchingOr_Should_Report_100_Percent_Branch_Coverage
dotnet test test/coverlet.core.tests/coverlet.core.tests.csproj -c Release -f net11.0 -- --filter-method PatternMatchingOr_Should_Report_100_Percent_Branch_Coverage
```

## Debugging isolated coverage tests
Expand Down
64 changes: 36 additions & 28 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,34 +4,20 @@
<CentralPackageTransitivePinningEnabled>true</CentralPackageTransitivePinningEnabled>
</PropertyGroup>
<PropertyGroup>
<!--
Framework-aligned runtime package versions: shipping projects consume the Microsoft.Extensions.*/System.* packages
of their own .NET generation (net10.0 -> 10.0.x, net9.0 -> 9.0.x) so the package never carries newer generation
assets in an older TFM group. netstandard2.0 keeps explicit 8.0.x overrides in the project files because those
versions are not uniform across packages. Test projects stay on the newest generation for every TFM because their
tooling (Microsoft.CodeAnalysis, ReportGenerator.Core) already requires the 10.0.x packages.
-->
<MicrosoftNet10RuntimeVersion>10.0.13</MicrosoftNet10RuntimeVersion>
<MicrosoftNet9RuntimeVersion>9.0.21</MicrosoftNet9RuntimeVersion>
<MicrosoftNet10RuntimeVersion>10.0.14</MicrosoftNet10RuntimeVersion>
<MicrosoftNet11RuntimeVersion>11.0.0-rc.3.26522.148</MicrosoftNet11RuntimeVersion>
<MicrosoftNetRuntimeVersion>$(MicrosoftNet10RuntimeVersion)</MicrosoftNetRuntimeVersion>
<MicrosoftNetRuntimeVersion Condition="'$(TargetFramework)' == 'net9.0' AND '$(IsTestProject)' != 'true'">$(MicrosoftNet9RuntimeVersion)</MicrosoftNetRuntimeVersion>
<MicrosoftNETTestSdkVersion>18.10.1</MicrosoftNETTestSdkVersion>
<MicrosoftTestingPlatformVersion>2.4.1</MicrosoftTestingPlatformVersion>
<MoqVersion>4.20.72</MoqVersion>
<NugetPackageVersion>7.6.0</NugetPackageVersion>
<XunitV3Version>4.0.1</XunitV3Version>
<XunitRunnerVisualstudioVersion>4.0.0</XunitRunnerVisualstudioVersion>
<MicrosoftNetRuntimeVersion Condition="'$(TargetFramework)' == 'net11.0'">$(MicrosoftNet11RuntimeVersion)</MicrosoftNetRuntimeVersion>
<MicrosoftNETTestSdkVersion>18.11.0</MicrosoftNETTestSdkVersion>
<MicrosoftTestingPlatformVersion>2.5.1</MicrosoftTestingPlatformVersion>
<MoqVersion>4.21.0</MoqVersion>
<NugetPackageVersion>7.9.0</NugetPackageVersion>
<XunitV3Version>4.0.2</XunitV3Version>
<XunitRunnerVisualstudioVersion>4.0.1</XunitRunnerVisualstudioVersion>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="LinqKit.Microsoft.EntityFrameworkCore" Version="10.0.11" />
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="LinqKit.Microsoft.EntityFrameworkCore" Version="10.1.1" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.9.0" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="$(MicrosoftNETTestSdkVersion)" />
<PackageVersion Include="Microsoft.Testing.Extensions.AzureDevOpsReport" Version="$(MicrosoftTestingPlatformVersion)" />
<PackageVersion Include="Microsoft.Testing.Extensions.HangDump" Version="$(MicrosoftTestingPlatformVersion)" />
Expand All @@ -46,14 +32,36 @@
<PackageVersion Include="NuGet.Versioning" Version="$(NugetPackageVersion)" />
<PackageVersion Include="ReportGenerator.Core" Version="5.5.11" />
<PackageVersion Include="System.Buffers" Version="4.6.1" />
<PackageVersion Include="System.Collections.Immutable" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="System.Linq.Async" Version="7.0.1" />
<PackageVersion Include="System.Memory" Version="4.6.3" />
<PackageVersion Include="System.Reflection.Metadata" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="System.Text.Json" Version="$(MicrosoftNetRuntimeVersion)" />
<PackageVersion Include="System.Threading.Tasks.Extensions" Version="4.6.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="$(XunitRunnerVisualstudioVersion)" />
<PackageVersion Include="xunit.v3.mtp-v2" Version="$(XunitV3Version)" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0' Or '$(TargetFramework)' == 'netstandard2.0'">
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="System.Collections.Immutable" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="System.Reflection.Metadata" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="$(MicrosoftNet10RuntimeVersion)" />
<PackageVersion Include="System.Text.Json" Version="$(MicrosoftNet10RuntimeVersion)" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net11.0'">
<PackageVersion Include="Microsoft.Bcl.AsyncInterfaces" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.DependencyModel" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.FileSystemGlobbing" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="System.Collections.Immutable" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="System.Reflection.Metadata" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="System.Security.Cryptography.Pkcs" Version="$(MicrosoftNet11RuntimeVersion)" />
<PackageVersion Include="System.Text.Json" Version="$(MicrosoftNet11RuntimeVersion)" />
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions Documentation/Coverlet.MTP.Integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ More information is available here:
This package provides explicit dependency groups for:

- `netstandard2.0`
- `net9.0`
- `net10.0`
- `net11.0`

## Quick Start

Expand Down Expand Up @@ -641,6 +641,6 @@ dotnet test --coverlet --diagnostic --diagnostic-verbosity Trace

## Requirements

- .NET 9.0 SDK or newer for `net9.0` projects; .NET 10.0 SDK or newer for `net10.0` projects
- .NET 10.0 SDK or newer for `net10.0` projects; .NET 11.0 SDK or newer for `net11.0` projects
- Microsoft.Testing.Platform 2.0.0 or newer
- Test framework with MTP support (e.g., xUnit v3 (xunit.v3.mtp-v2), MSTest v3, NUnit with MTP adapter)
Loading
Loading