Test Project Exists + .NET Collector
Enforce Test Project Exists using data collected by .NET Collector. Automatically check devex build and ci standards on every PR.
How .NET Collector Powers This Guardrail
The .NET Collector gathers metadata from your languages, build systems. This data flows into Lunar's Component JSON, where the Test Project Exists guardrail evaluates it against your standards.
When enabled, this check runs automatically on every PR and in AI coding workflows, providing real-time enforcement with actionable feedback.
Quick Start Configuration
Add both the collector and policy to your lunar-config.yml to enable this guardrail.
# Step 1: Enable the .NET Collector
collectors:
- uses: github://earthly/lunar-lib/collectors/dotnet@v1.0.0
# with: ...
# Step 2: Enable the .NET Project Guardrails
policies:
- uses: github://earthly/lunar-lib/policies/dotnet@v1.0.0
include: [test-project-exists]
# with: ...
What .NET Collector Collects
This collector gathers the following data that the Test Project Exists guardrail evaluates.
project
Detects .NET project structure including project files (.csproj, .fsproj, .vbproj), solution files (.sln), SDK configuration (global.json), MSBuild properties (Directory.Build.props), target frameworks, project types, and SDK versions. Writes project metadata to .lang.dotnet.
dependencies
Extracts NuGet dependencies from project files, including direct dependencies, project references, and dependency locking status (packages.lock.json). Writes dependency data to .lang.dotnet.dependencies.
cicd
Records every dotnet command executed in CI pipelines along with the .NET SDK version. Writes command strings and version info to .lang.dotnet.cicd for audit trails and build reproducibility analysis.
Example Data Flow
Here's an example of the data that .NET Collector writes to the Component JSON, which Test Project Exists then evaluates.
{
"lang": {
"dotnet": {
"sdk_version": "8.0.100",
"target_frameworks": ["net8.0"],
"project_files": [
{
"path": "MyApp/MyApp.csproj",
"type": "csharp",
"output_type": "Exe",
"target_framework": "net8.0"
}
],
"solution_files": ["MyApp.sln"],
"global_json_exists": true,
"directory_build_props_exists": false,
"packages_lock_exists": true,
"test_projects": [
{
"path": "MyApp.Tests/MyApp.Tests.csproj",
"type": "csharp",
"test_framework": "xunit"
}
],
"source": { "tool": "dotnet", "integration": "code" },
"dependencies": {
"direct": [
{
"name": "Microsoft.Extensions.Hosting",
"version": "8.0.0",
"type": "package"
}
],
"project_references": [
{
"path": "MyLibrary/MyLibrary.csproj"
}
],
"source": { "tool": "dotnet", "integration": "code" }
},
"cicd": {
"cmds": [
{"cmd": "dotnet restore", "version": "8.0.100"},
{"cmd": "dotnet build --configuration Release", "version": "8.0.100"},
{"cmd": "dotnet test --no-build", "version": "8.0.100"}
],
"source": {"tool": "dotnet", "integration": "ci"}
}
}
}
}
Configuration Options
.NET Project Guardrails Inputs
| Input | Required | Default | Description |
|---|---|---|---|
min_sdk_version |
Optional |
8.0
|
Minimum .NET SDK version required for the project |
min_sdk_version_cicd |
Optional |
8.0
|
Minimum .NET SDK version required for CI/CD pipelines |
Ready to Automate Your Standards?
See how Lunar can turn your engineering wiki, compliance docs, or postmortem action items into automated guardrails with our 100+ built-in guardrails.