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
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"rollForward": false
},
"csharpier": {
"version": "1.2.6",
"version": "1.3.0",
"commands": [
"csharpier"
],
Expand Down
48 changes: 40 additions & 8 deletions .github/workflows/build-test-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,47 @@ jobs:
- name: Build
run: dotnet build Scribe.slnx --configuration Release --no-restore

# Microsoft.Testing.Platform: tests are self-hosting executables driven by the MTP
# `dotnet test` (opted in via global.json `test.runner`). xUnit's built-in reporter
# emits CTRF test results (no extra package); the CodeCoverage extension emits
# Cobertura. Both are rendered below; the report steps run on always() so a test
# failure still publishes results while the Test step's exit code fails the job.
- name: Test
run: dotnet test Scribe.slnx --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=test-results.trx"
run: >-
dotnet test --solution Scribe.slnx --configuration Release --no-build --verbosity normal
--
--report-ctrf --report-ctrf-filename test-results.ctrf.json
--coverage --coverage-output-format cobertura --coverage-output coverage.cobertura.xml

- name: Publish test report
if: always()
continue-on-error: true
uses: ctrf-io/github-test-reporter@v1
with:
report-path: '**/test-results.ctrf.json'

- name: Generate coverage report
if: always()
continue-on-error: true
uses: danielpalme/ReportGenerator-GitHub-Action@5
with:
reports: '**/coverage.cobertura.xml'
targetdir: coveragereport
reporttypes: MarkdownSummaryGithub;Html

- name: Publish coverage summary
if: always()
run: |
if [ -f coveragereport/SummaryGithub.md ]; then
cat coveragereport/SummaryGithub.md >> "$GITHUB_STEP_SUMMARY"
fi

- name: Upload coverage report
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: coveragereport

- name: Pack core packages
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
Expand All @@ -86,13 +125,6 @@ jobs:
dotnet pack Scribe.Ink/Scribe.Ink.csproj --configuration Release --no-build --output .artifacts/packages
dotnet pack Scribe.Scriptorium/Scribe.Scriptorium.csproj --configuration Release --no-build --output .artifacts/packages

- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-core
path: "**/test-results.trx"

- name: Upload packages
if: github.event_name == 'push' || github.event_name == 'workflow_dispatch'
uses: actions/upload-artifact@v4
Expand Down
2 changes: 2 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<PropertyGroup Condition="$(MSBuildProjectName.EndsWith('.Tests'))">
<IsTestProject>true</IsTestProject>
<IsPackable>false</IsPackable>
<!-- Microsoft.Testing.Platform test projects are executables (they host the in-proc runner). -->
<OutputType>Exe</OutputType>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>preview</LangVersion>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down
13 changes: 6 additions & 7 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,19 @@
<!-- Versioning — applied globally to all Scribe projects. -->
<GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.9.50" PrivateAssets="all" />
<!-- SourceLink — embeds GitHub source pointers in PDBs so consumers can step through source. -->
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.201" PrivateAssets="all" />
<GlobalPackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.300" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<!-- Roslyn SDK — used by Scribe. -->
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="5.3.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.3.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="5.3.0" />
<!-- Test dependencies -->
<!-- Test dependencies. xunit.v3.mtp-v2 hosts on Microsoft.Testing.Platform v2 (no VSTest SDK
or runner.visualstudio); CodeCoverage is the native MTP coverage collector. -->
<PackageVersion Include="Bogus" Version="35.6.5" />
<PackageVersion Include="coverlet.collector" Version="8.0.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageVersion Include="Microsoft.Testing.Extensions.CodeCoverage" Version="18.8.0" />
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="xunit.v3" Version="3.2.2" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5" />
<PackageVersion Include="xunit.v3.mtp-v2" Version="3.2.2" />
</ItemGroup>
</Project>
</Project>
45 changes: 45 additions & 0 deletions Scribe.Tests/OutputDirectoryAssemblyResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Runtime.Loader;
using Xunit.v3;

[assembly: TestPipelineStartup(typeof(Scribe.Tests.OutputDirectoryAssemblyResolver))]

namespace Scribe.Tests;

/// <summary>
/// Microsoft.Testing.Platform runs this test project as a self-hosted executable that
/// resolves runtime assemblies strictly from its <c>.deps.json</c>. Scribe is consumed
/// here via a <c>ProjectReference</c> to a Scribe.Sdk <c>Library</c> project, whose output
/// is intentionally kept out of consumers' runtime dependency graph — in production it
/// ships embedded as an analyzer, loaded by the Roslyn host, never as an application
/// runtime dependency. VSTest's <c>testhost</c> masked this by probing the output
/// directory; MTP does not, so a test that instantiates a generator touching Scribe throws
/// <see cref="System.IO.FileNotFoundException"/>.
///
/// Installed via xUnit's pipeline-startup hook rather than a <c>[ModuleInitializer]</c>:
/// the Scribe.Sdk injects polyfilled <c>ModuleInitializerAttribute</c> types into both
/// <c>Scribe</c> and <c>Scribe.Ink</c>, which collide here via <c>InternalsVisibleTo</c>.
/// The assemblies sit in the output directory regardless; this teaches the default load
/// context to probe there for anything missing from the deps.json graph.
/// </summary>
public sealed class OutputDirectoryAssemblyResolver : ITestPipelineStartup
{
public ValueTask StartAsync(Xunit.Sdk.IMessageSink diagnosticMessageSink)
{
AssemblyLoadContext.Default.Resolving += static (context, assemblyName) =>
{
if (assemblyName.Name is not { } name)
{
return null;
}

var candidate = Path.Combine(AppContext.BaseDirectory, name + ".dll");
return File.Exists(candidate)
? context.LoadFromAssemblyPath(candidate)
: null;
};

return default;
}

public ValueTask StopAsync() => default;
}
29 changes: 25 additions & 4 deletions Scribe.Tests/Scribe.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<ItemGroup>
<ProjectReference Include="..\Scribe\Scribe.csproj" />
<ProjectReference Include="..\Scribe.Ink\Scribe.Ink.csproj" />
Expand All @@ -7,9 +7,30 @@
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
<PackageReference Include="Microsoft.NET.Test.Sdk" />
<PackageReference Include="Microsoft.Testing.Extensions.CodeCoverage" />
<PackageReference Include="Shouldly" />
<PackageReference Include="xunit.v3" />
<PackageReference Include="xunit.runner.visualstudio" />
<PackageReference Include="xunit.v3.mtp-v2" />
</ItemGroup>

<!--
Microsoft.CodeAnalysis.CSharp 5.x (netstandard2.0) transitively pulls in the netstandard2.0
builds of several system libraries (System.Threading.Tasks.Extensions, System.Collections.Immutable,
System.Memory, …). The .NET 10 framework also provides 10.x versions, so any type present in both
— e.g. ValueTask, used by xUnit's ITestPipelineStartup in OutputDirectoryAssemblyResolver — raises a
CS0433 ambiguous-type error. All listed assemblies are binary-compatible and the framework copy wins at
runtime. Strip the .nuget-cached netstandard2.0 copies from ReferencePath, keeping the framework copies.
(Same workaround as Hermetic.Logos.Tests.)
-->
<PropertyGroup>
<_AmbiguousNetStandardSystemRefs>;System.Buffers.dll;System.Collections.Immutable.dll;System.Memory.dll;System.Numerics.Vectors.dll;System.Reflection.Metadata.dll;System.Runtime.CompilerServices.Unsafe.dll;System.Text.Encoding.CodePages.dll;System.Threading.Tasks.Extensions.dll;</_AmbiguousNetStandardSystemRefs>
</PropertyGroup>
<Target Name="RemoveAmbiguousNetStandardSystemRefs" AfterTargets="ResolveAssemblyReferences">
<ItemGroup>
<ReferencePath
Remove="@(ReferencePath)"
Condition="$(_AmbiguousNetStandardSystemRefs.Contains(';%(FileName)%(Extension);'))
and $([System.String]::Copy('%(Identity)').Contains('.nuget'))"
/>
</ItemGroup>
</Target>
</Project>
5 changes: 5 additions & 0 deletions Scribe.slnx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
<Solution>
<Project Path="Scribe/Scribe.csproj" />
<Folder Name="/Solution Items/">
<File Path=".config/dotnet-tools.json" />
<File Path="Directory.Build.props" />
<File Path="Directory.Build.targets" />
<File Path="Directory.Packages.props" />
<File Path="global.json" />
<File Path="version.json" />
</Folder>
<Project Path="Scribe.Ink/Scribe.Ink.csproj" />
Expand Down
5 changes: 4 additions & 1 deletion global.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
"allowPrerelease": false
},
"msbuild-sdks": {
"BulletsForHumanity.Scribe.Sdk": "0.6.4"
"BulletsForHumanity.Scribe.Sdk": "0.6.6"
},
"test": {
"runner": "Microsoft.Testing.Platform"
}
}
Loading