dotnet-quality-ci
Set up or refine open-source .NET code-quality gates for CI: formatting, `.editorconfig`, SDK analyzers, third-party analyzers, coverage, mutation testing, architecture tests, and security scanning. Use when a .NET repo needs an explicit quality stack in `AGENTS.md`, docs, or pip
Install
npx skills add https://github.com/Postpartum-genushyacinthus29/dotnet-skills/tree/main/skills/dotnet-quality-ci
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install postpartum-genushyacinthus29-dotnet-skills@llmmart
git clone https://github.com/Postpartum-genushyacinthus29/dotnet-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole postpartum-genushyacinthus29/dotnet-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
.NET Quality CI
Trigger On
- adding or tightening .NET code-quality gates in CI
- choosing analyzers, coverage, mutation, or architecture-test tooling for a .NET repo
- standardizing
.editorconfig,dotnet format, and warning policy
Value
- produce a concrete project delta: code, docs, config, tests, CI, or review artifact
- reduce ambiguity through explicit planning, verification, and final validation skills
- leave reusable project context so future tasks are faster and safer
Do Not Use For
- non-.NET repositories
- generic CI/CD guidance with no .NET quality stack decisions
- framework-specific test authoring with no quality-gate change
Inputs
- the nearest
AGENTS.md - the current repo-root
.editorconfigand MSBuild props - the current CI workflow and package references
- the active test runner model: VSTest or Microsoft.Testing.Platform
Quick Start
- Read the nearest
AGENTS.mdand confirm scope and constraints. - Run this skill's
Workflowthrough theRalph Loopuntil outcomes are acceptable. - Return the
Required Result Formatwith concrete artifacts and verification evidence.
Workflow
- Start with the repo-native baseline:
- repo-root
.editorconfig dotnet format --verify-no-changes- SDK analyzers with explicit
EnableNETAnalyzers,AnalysisLevel, and warning policy
- repo-root
- Add third-party analyzers only where they close a real gap:
StyleCopAnalyzersRoslynatorMeziantou.Analyzer- framework analyzers such as xUnit, MSTest, or TUnit analyzers
- Separate quality gates by purpose:
- formatting and style
- correctness and static analysis
- coverage and reports
- architecture rules
- security scanning
- mutation testing
- For complexity, use a composite approach:
- CA1502 thresholding
- maintainability limits in
AGENTS.md - architecture tests
- coverage and mutation where risk justifies it
- Make ownership explicit in
AGENTS.mdand CI:- which command formats
- which command analyzes
- which command measures coverage
- which runner model the tests use
- After any .NET code change, the repo's quality pass must be runnable by agents:
- format
- build
- analyze
- focused tests
- broader tests
- coverage and report generation when configured
- extra configured gates only when the repo actually enabled them
- Route tool-specific setup through dedicated skills where possible:
dotnet-formatdotnet-code-analysisdotnet-analyzer-config- analyzer-pack skills such as
dotnet-stylecop-analyzers,dotnet-roslynator, anddotnet-meziantou-analyzer - frontend asset quality skills in mixed
.NETplus Node repos such asdotnet-eslint,dotnet-stylelint,dotnet-htmlhint,dotnet-webhint,dotnet-biome,dotnet-sonarjs,dotnet-metalint, anddotnet-chous - coverage/reporting skills such as
dotnet-coverletanddotnet-reportgenerator - architecture/security skills such as
dotnet-netarchtest,dotnet-archunitnet, anddotnet-codeql
- Avoid overlapping tools with conflicting ownership. If you add an opinionated formatter, define whether it replaces or complements
dotnet format.
Bootstrap When Missing
If a quality gate is requested but not configured, use this activation path:
- Detect current state in
.csproj,Directory.Build.*,.editorconfig, tool manifests, and CI workflow files. - Choose exactly one owner command per gate category (format, analyze, test, coverage, architecture, security, mutation).
- Install the minimal required package or tool and commit checked-in config files.
- Wire the gate into both
AGENTS.mdand CI with explicit commands. - Run a first verify pass, fix actionable failures, and rerun.
- Return
status: configuredif newly enabled and passing, orstatus: improvedif issues remain but baseline improved. - Return
status: not_applicableonly when the gate is explicitly out of scope for this repo.
Deliver
- a documented .NET quality baseline
- CI commands that are explicit and reproducible
- analyzer and coverage choices that match the repo's runner model
- a documented post-change quality pass for agents and CI
- tool selection that stays open-source and free by default, with caveats called out explicitly
Validate
- repo-root
.editorconfigis the default source of truth for per-rule severity - formatting, analyzer, and coverage commands are runner-compatible
- added tools cover distinct gaps instead of duplicating each other
- complexity and architecture policy are explicit, not implied
- .NET code changes are expected to pass more than tests alone when quality gates are configured
- any licensing or hosting caveat is documented before the tool becomes a default gate
Ralph Loop
Use the Ralph Loop for every task, including docs, architecture, testing, and tooling work.
- Plan first (mandatory):
- analyze current state
- define target outcome, constraints, and risks
- write a detailed execution plan
- list final validation skills to run at the end, with order and reason
- Execute one planned step and produce a concrete delta.
- Review the result and capture findings with actionable next fixes.
- Apply fixes in small batches and rerun the relevant checks or review steps.
- Update the plan after each iteration.
- Repeat until outcomes are acceptable or only explicit exceptions remain.
- If a dependency is missing, bootstrap it or return
status: not_applicablewith explicit reason and fallback path.
Required Result Format
status:complete|clean|improved|configured|not_applicable|blockedplan: concise plan and current iteration stepactions_taken: concrete changes madevalidation_skills: final skills run, or skipped with reasonsverification: commands, checks, or review evidence summaryremaining: top unresolved items ornone
For setup-only requests with no execution, return status: configured and exact next commands.
Load References
references/editorconfig-and-ci.mdreferences/quality-toolchain.mdreferences/workflows.mdreferences/checklist.md
Example Requests
- "Define the best OSS CI stack for this .NET repo."
- "Add .NET analyzers, coverage, and mutation testing guidance."
- "Make
.editorconfigand CI agree in our .NET solution."
Files (dotnet-skills)
-
references
-
checklist.md 7.6 KB
# .NET CI Quality Checklist Use this checklist when setting up or auditing quality gates for a .NET repository. ## Foundation Checklist ### Repository Configuration - [ ] Repo-root `.editorconfig` exists and owns formatting, naming, and analyzer severity - [ ] `Directory.Build.props` exists for shared MSBuild properties - [ ] `EnableNETAnalyzers` is explicitly set to `true` - [ ] `AnalysisLevel` is set to `latest` or a specific version - [ ] `TreatWarningsAsErrors` policy is documented and applied consistently - [ ] `.config/dotnet-tools.json` tracks local tool versions if tools are used ### Build Configuration - [ ] Solution builds with `dotnet build -warnaserror` - [ ] Build uses deterministic output settings for reproducibility - [ ] SDK version is pinned in `global.json` if consistency is required - [ ] Build logs no analyzer suppressions without documented reason ## Formatting and Style ### dotnet format - [ ] `dotnet format --verify-no-changes` runs in CI - [ ] Format failures block PR merge - [ ] Format rules are in `.editorconfig`, not scattered across IDE settings - [ ] Whitespace, indentation, and naming rules are explicit ### Optional Formatter - [ ] If CSharpier is used, ownership split with `dotnet format` is documented - [ ] Formatter choice is documented in `AGENTS.md` - [ ] Pre-commit hooks or CI enforce the chosen formatter ## Static Analysis ### SDK Analyzers - [ ] `Microsoft.CodeAnalysis.NetAnalyzers` is enabled (default in .NET 5+) - [ ] CA rules are configured in `.editorconfig` with explicit severity - [ ] `CA1502` (cyclomatic complexity) threshold is set if complexity matters - [ ] `CA1505` (maintainability index) is enabled for maintainability gates - [ ] `CA1506` (class coupling) is enabled for architecture guidance ### Third-Party Analyzers - [ ] Analyzer packages serve distinct purposes (no redundant overlap) - [ ] `StyleCopAnalyzers` configured if naming/documentation rules needed - [ ] `Roslynator` configured if broader Roslyn rules needed - [ ] `Meziantou.Analyzer` configured if security/performance rules needed - [ ] Framework-specific analyzers installed (xUnit, MSTest, or TUnit) ### Analyzer Configuration - [ ] All analyzer rules have explicit severity in `.editorconfig` - [ ] Suppressed rules are documented with reason - [ ] `stylecop.json` is minimal and does not duplicate `.editorconfig` - [ ] No analyzer warnings are silently ignored ## Testing ### Test Runner - [ ] Test runner model is documented: VSTest or Microsoft.Testing.Platform - [ ] Test command is explicit in `AGENTS.md` and CI - [ ] Tests pass locally and in CI with same command - [ ] Test filters work correctly for focused and broad test runs ### Test Quality - [ ] Unit tests exist for business logic - [ ] Integration tests exist for external dependencies - [ ] Test naming follows consistent convention - [ ] Test organization matches production code structure ## Code Coverage ### Coverage Collection - [ ] Coverage driver matches test runner: - VSTest: `coverlet.collector` or `--collect:"XPlat Code Coverage"` - MTP: `coverlet.MTP` or MSTest SDK coverage extensions - [ ] Coverage output format is specified (Cobertura recommended) - [ ] Coverage artifacts are generated in CI ### Coverage Reporting - [ ] ReportGenerator or equivalent produces human-readable reports - [ ] Coverage report is uploaded as CI artifact - [ ] Coverage thresholds are documented if enforced - [ ] Coverage badge is generated if displayed in README ## Architecture and Security ### Architecture Tests - [ ] Architecture test project exists if layer boundaries matter - [ ] NetArchTest or ArchUnitNET is configured - [ ] Dependency rules are explicit and tested - [ ] Architecture tests run in CI ### Security Scanning - [ ] CodeQL is configured for GitHub repositories (with hosting caveat noted) - [ ] Security advisories are monitored via Dependabot or equivalent - [ ] Secrets scanning is enabled - [ ] Container scanning if Docker is used ## Advanced Quality Gates ### Mutation Testing - [ ] Stryker.NET is configured for critical libraries - [ ] Mutation testing runs on schedule (not every PR) - [ ] Mutation score threshold is documented - [ ] Mutation reports are reviewed periodically ### Complexity Management - [ ] `CA1502` threshold is set for max cyclomatic complexity - [ ] `AGENTS.md` documents: - `file_max_loc` - `type_max_loc` - `function_max_loc` - `max_nesting_depth` - [ ] Complex methods are flagged in code review - [ ] Refactoring is prioritized for high-complexity code ## CI Workflow ### Workflow Structure - [ ] Quality workflow triggers on push to main and PRs - [ ] Jobs are ordered logically: restore, build, test, format, analyze - [ ] Independent jobs run in parallel where possible - [ ] Dependent jobs use `needs` to express dependencies - [ ] Workflow uses caching for NuGet packages ### Workflow Reliability - [ ] Workflow uses pinned action versions (not `@main` or `@latest`) - [ ] .NET SDK version is explicit in `setup-dotnet` - [ ] Environment variables reduce CLI noise (`DOTNET_NOLOGO`, `DOTNET_CLI_TELEMETRY_OPTOUT`) - [ ] Timeouts are set for long-running jobs - [ ] Artifacts are uploaded for reports and coverage ### Workflow Maintenance - [ ] Workflow files are reviewed in PRs - [ ] Workflow changes are tested in feature branches - [ ] Deprecated actions are updated promptly - [ ] Workflow documentation exists in `AGENTS.md` or `CONTRIBUTING.md` ## Documentation ### AGENTS.md Quality Section - [ ] Exact `build` command is documented - [ ] Exact `test` command is documented - [ ] Exact `format` command is documented - [ ] Exact `analyze` command is documented - [ ] Exact `coverage` command is documented (if enabled) - [ ] Test runner model is stated: VSTest or Microsoft.Testing.Platform - [ ] Quality gate ownership is clear for each category ### Contributor Documentation - [ ] Quality gate setup is documented in `CONTRIBUTING.md` - [ ] Local quality check commands are documented - [ ] Pre-commit hook setup is documented (if used) - [ ] IDE configuration recommendations exist ## Verification Commands Run these commands to verify quality gate setup: ```bash # Verify formatting dotnet format --verify-no-changes # Verify build with warnings as errors dotnet build -warnaserror # Verify tests pass dotnet test # Verify coverage collection (VSTest) dotnet test --collect:"XPlat Code Coverage" # Verify analyzers run dotnet build -p:EnforceCodeStyleInBuild=true # Verify architecture tests (if configured) dotnet test --filter "Category=Architecture" ``` ## Common Issues Checklist - [ ] No conflicting ownership between `dotnet format` and CSharpier - [ ] No VSTest switches in Microsoft.Testing.Platform projects - [ ] No `.runsettings` assumptions that break on MTP - [ ] No analyzer packages that duplicate SDK analyzer rules - [ ] No coverage drivers mismatched with test runner - [ ] No hand-edited generated files that drift from source - [ ] No quality gates that only run locally and skip CI - [ ] No suppressed warnings without documented justification ## Sources - [Overview of .NET source code analysis](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview) - [Configuration files for code analysis rules](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files) - [dotnet format command](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format) - [Code metrics values](https://learn.microsoft.com/en-us/visualstudio/code-quality/code-metrics-values?view=vs-2022) - [GitHub Actions for .NET](https://docs.github.com/en/actions/use-cases-and-examples/building-and-testing/building-and-testing-net) -
editorconfig-and-ci.md 2.5 KB
# .NET EditorConfig and CI Ownership Use this reference when the repository needs one durable source of truth for formatting, naming, style, and analyzer severity. ## Ownership Rules - repo-root lowercase `.editorconfig` is the default source of truth for .NET formatting, naming, code-style, and analyzer severity. - nested `.editorconfig` files are allowed when they serve a clear subtree-specific purpose. - `.globalconfig` is an exceptional fallback, not the normal repo setup. - `Directory.Build.props`, `Directory.Build.targets`, or project files should own bulk switches such as: - `EnableNETAnalyzers` - `AnalysisLevel` - `TreatWarningsAsErrors` - runner selection such as `UseVSTest` - the root `.editorconfig` should own per-rule severity and code-style detail. ## CI Rules - `dotnet format` reads `.editorconfig`; use `dotnet format --verify-no-changes` in CI. - `dotnet build -warnaserror` or the repo's equivalent should enforce analyzer severity. - Coverage driver must match the runner: - VSTest: `coverlet.collector` or `--collect:"XPlat Code Coverage"` - Microsoft.Testing.Platform: `coverlet.MTP` or MSTest SDK coverage extensions - Report generation is a separate step. Use ReportGenerator after coverage collection if humans need HTML, Markdown, or badges. ## Conflict Rules - Do not let IDE-only settings, CI-only flags, and repo config disagree about the same rule. - Do not write inline comments in `.editorconfig` values; they are not part of the current EditorConfig spec. - Do not let `CSharpier` and `dotnet format` both own formatting unless the split is explicit and documented. - Do not mix VSTest-only switches, filters, or `.runsettings` assumptions into Microsoft.Testing.Platform jobs. - Keep `stylecop.json` for StyleCop behavior only; do not treat it as the repo-wide severity owner. ## Good AGENTS.md Signals for .NET - exact `build`, `test`, `format`, `analyze`, and `coverage` commands - exact test runner model: `VSTest` or `Microsoft.Testing.Platform` - exact framework skill: `dotnet-xunit`, `dotnet-tunit`, or `dotnet-mstest` - explicit statement that the repo-root `.editorconfig` is the analyzer source of truth ## Sources - [dotnet format command](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format) - [Configuration files for code analysis rules](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files) - [Overview of .NET source code analysis](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview) -
quality-toolchain.md 7.1 KB
# Recommended OSS .NET Quality Toolchain Use this reference when a .NET repository needs an explicit, open-source-first quality stack for CI. Each listed tool now has a dedicated skill folder, so use this page for selection and use the matching tool skill for installation and detailed setup. Open/free policy for this catalog: - everything listed here is open source or free to adopt locally - `CodeQL` stays in the catalog with an explicit caveat because the hosted GitHub private-repo experience is not universally free Install policy for this catalog: - always verify first whether the tool is already present in `*.csproj`, `Directory.Build.*`, `.config/dotnet-tools.json`, or CI workflows - prefer the repo's existing installation path over adding a second package, tool, or runner ## Baseline Stack Use this baseline for most .NET repositories before adding anything exotic: | Area | Tool | Skill | Why | | --- | --- | --- | --- | | Format and style | `dotnet format` | `dotnet-format` | Native CLI support, reads `.editorconfig`, supports verify-only mode in CI | | Built-in static analysis | SDK analyzers / `Microsoft.CodeAnalysis.NetAnalyzers` | `dotnet-code-analysis` | First-party CA and IDE rules, enabled by default on modern .NET | | Complexity and maintainability | `CA1502`/`CA1505`/`CA1506` | `dotnet-complexity` | Finds overly complex methods, low maintainability index, and excessive coupling | | Analyzer config | repo-root `.editorconfig` | `dotnet-analyzer-config` | One durable source of truth for style and rule severity | | Style and conventions | `StyleCopAnalyzers` | `dotnet-stylecop-analyzers` | Strong naming, layout, documentation, and consistency checks | | General code quality | `Roslynator` | `dotnet-roslynator` | Broad Roslyn analyzer set and optional CLI | | General code quality | `Meziantou.Analyzer` | `dotnet-meziantou-analyzer` | Design, usage, security, performance, and style rules | | Coverage collection | `coverlet` | `dotnet-coverlet` | Cross-platform line, branch, and method coverage | | Coverage reporting | `ReportGenerator` | `dotnet-reportgenerator` | Converts coverage artifacts into HTML, Markdown, Cobertura, badges, and more | ## Framework-Specific Additions Pick the test-framework add-on that matches the repo: | Framework | Tool | Skill | Why | | --- | --- | --- | --- | | xUnit | `xunit.analyzers` | `dotnet-xunit` | xUnit-specific correctness and usage rules | | TUnit | built-in TUnit analyzers | `dotnet-tunit` | Compile-time guidance for signatures, attributes, and usage | | MSTest | `MSTest.Analyzers` via `MSTest` / `MSTest.Sdk` | `dotnet-mstest` | MSTest-specific correctness and usage rules | ## High-Value Optional Gates These tools are worth adding once the baseline is stable: | Area | Tool | Skill | Why | Notes | | --- | --- | --- | --- | --- | | Mutation testing | `Stryker.NET` | `dotnet-stryker` | Verifies that tests actually catch faults | Best on libraries and critical domains, not every PR path | | Architecture tests | `NetArchTest.Rules` | `dotnet-netarchtest` | Simple, fluent architectural rules in tests | Good for layered or clean architecture policies | | Architecture tests | `ArchUnitNET` | `dotnet-archunitnet` | Richer architecture assertions across xUnit, MSTest, and TUnit | Heavier than NetArchTest but more expressive | | Deep inspections and cleanup | `JetBrains ReSharper Command Line Tools` | `dotnet-resharper-clt` | Powerful ReSharper inspections plus cleanup profiles in CI or local runs | Free official JetBrains CLI package; keep shared policy in solution `.DotSettings` | | Security scanning | `CodeQL` | `dotnet-codeql` | Deep GitHub-native query-based analysis | Open ecosystem with private-repo hosting caveats | | Opinionated formatter | `CSharpier` | `dotnet-csharpier` | Fast one-style formatter for C# and XML | Use only if the repo wants a formatter owner beyond `dotnet format` | ## Complexity Strategy There is no dominant open-source, CI-native .NET complexity suite that cleanly replaces NDepend. For OSS-first repos, use a composite gate: 1. `CA1502` with an explicit threshold for excessive cyclomatic complexity. 2. Maintainability limits in `AGENTS.md`: - `file_max_loc` - `type_max_loc` - `function_max_loc` - `max_nesting_depth` 3. Architecture tests with NetArchTest or ArchUnitNET. 4. Coverage and mutation testing on critical paths. For complex methods specifically, the primary built-in analyzer is `CA1502`. If the repo later chooses a commercial metric product, treat it as an additional gate, not a replacement for the design and analyzer baseline. ## Suggested CI Order ```bash dotnet restore dotnet build MySolution.sln -warnaserror dotnet test MySolution.sln --no-build dotnet format MySolution.sln --verify-no-changes ``` ## Agent Post-Change Flow When an agent writes or refactors `.NET` code, do not stop after `dotnet test`. Use the exact commands from `AGENTS.md`. The usual checked-in flow is: 1. `format` 2. `build` 3. `analyze` 4. focused `test` 5. broader `test` 6. `coverage` and report generation when configured 7. extra configured gates such as Roslynator, StyleCop, Meziantou, ReSharper CLT, architecture tests, CodeQL, CSharpier, or Stryker Run only the gates the repo actually enabled. Then add the runner-specific extras: - VSTest coverage: ```bash dotnet test MySolution.sln --collect:"XPlat Code Coverage" ``` - Microsoft.Testing.Platform coverage: ```bash dotnet test MySolution.sln --coverlet ``` - Report generation: ```bash reportgenerator -reports:"**/coverage.cobertura.xml" -targetdir:"artifacts/coverage" -reporttypes:"HtmlSummary;Cobertura" ``` - Mutation testing: ```bash dotnet stryker ``` ## Sources - [dotnet format command](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format) - [Overview of .NET source code analysis](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/overview) - [Configuration files for code analysis rules](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/configuration-files) - [CA1502: Avoid excessive complexity](https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1502) - [Code metrics values](https://learn.microsoft.com/en-us/visualstudio/code-quality/code-metrics-values?view=vs-2022) - [StyleCopAnalyzers](https://github.com/DotNetAnalyzers/StyleCopAnalyzers) - [Roslynator](https://github.com/JosefPihrt/Roslynator) - [Meziantou.Analyzer](https://github.com/meziantou/Meziantou.Analyzer) - [Coverlet](https://github.com/coverlet-coverage/coverlet) - [ReportGenerator](https://github.com/danielpalme/ReportGenerator) - [Stryker.NET](https://github.com/stryker-mutator/stryker-net) - [NetArchTest](https://github.com/BenMorris/NetArchTest) - [ArchUnitNET](https://github.com/TNG/ArchUnitNET) - [ReSharper command line tools](https://www.jetbrains.com/help/resharper/ReSharper_Command_Line_Tools.html) - [CleanupCode](https://www.jetbrains.com/help/resharper/CleanupCode.html) - [InspectCode](https://www.jetbrains.com/help/resharper/InspectCode.html) - [CodeQL code scanning](https://docs.github.com/en/code-security/code-scanning/introduction-to-code-scanning/about-code-scanning-with-codeql) - [CSharpier](https://github.com/belav/csharpier) -
workflows.md 9.7 KB
# GitHub Actions Workflows for .NET Quality Gates Use this reference when setting up or refining GitHub Actions CI pipelines for .NET quality enforcement. ## Minimal Quality Workflow Start with this baseline workflow for most .NET repositories: ```yaml name: .NET Quality on: push: branches: [main] pull_request: branches: [main] jobs: quality: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - name: Restore run: dotnet restore - name: Build run: dotnet build --no-restore -warnaserror - name: Test run: dotnet test --no-build --verbosity normal - name: Format check run: dotnet format --verify-no-changes --verbosity diagnostic ``` ## Full Quality Pipeline with Coverage Extend the baseline with coverage collection and reporting: ```yaml name: .NET Quality Full on: push: branches: [main] pull_request: branches: [main] env: DOTNET_NOLOGO: true DOTNET_CLI_TELEMETRY_OPTOUT: true jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - name: Restore run: dotnet restore - name: Build run: dotnet build --no-restore --configuration Release -warnaserror - name: Test with coverage run: | dotnet test --no-build --configuration Release \ --collect:"XPlat Code Coverage" \ --results-directory ./coverage - name: Generate coverage report run: | dotnet tool install -g dotnet-reportgenerator-globaltool reportgenerator \ -reports:"coverage/**/coverage.cobertura.xml" \ -targetdir:"coverage/report" \ -reporttypes:"HtmlSummary;Cobertura;MarkdownSummaryGithub" - name: Upload coverage report uses: actions/upload-artifact@v4 with: name: coverage-report path: coverage/report - name: Format check run: dotnet format --verify-no-changes analyze: runs-on: ubuntu-latest needs: build-and-test steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - name: Restore run: dotnet restore - name: Build with analysis run: | dotnet build --no-restore --configuration Release \ -p:EnforceCodeStyleInBuild=true \ -p:TreatWarningsAsErrors=true ``` ## Separate Jobs Pattern For larger repositories, split quality gates into parallel jobs: ```yaml name: .NET Quality Gates on: push: branches: [main] pull_request: branches: [main] env: DOTNET_NOLOGO: true jobs: format: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - run: dotnet restore - run: dotnet format --verify-no-changes build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - run: dotnet restore - run: dotnet build --no-restore -warnaserror test: runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - run: dotnet restore - run: dotnet build --no-restore - run: dotnet test --no-build analyze: runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v4 - uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - run: dotnet restore - name: Run analyzers run: | dotnet build --no-restore \ -p:EnforceCodeStyleInBuild=true \ -p:TreatWarningsAsErrors=true ``` ## Coverage with Microsoft.Testing.Platform For projects using Microsoft.Testing.Platform instead of VSTest: ```yaml name: .NET MTP Coverage on: push: branches: [main] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - name: Restore run: dotnet restore - name: Build run: dotnet build --no-restore - name: Test with MTP coverage run: | dotnet test --no-build \ --coverlet-coverage \ --coverlet-output-format cobertura \ --coverlet-output ./coverage/ - name: Generate report run: | dotnet tool install -g dotnet-reportgenerator-globaltool reportgenerator \ -reports:"coverage/**/*.cobertura.xml" \ -targetdir:"coverage/report" \ -reporttypes:"HtmlSummary;Cobertura" - name: Upload coverage uses: actions/upload-artifact@v4 with: name: coverage path: coverage/report ``` ## Matrix Build for Multiple .NET Versions Test against multiple .NET versions: ```yaml name: .NET Multi-Version on: push: branches: [main] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest strategy: matrix: dotnet-version: ['8.x', '9.x'] steps: - uses: actions/checkout@v4 - name: Setup .NET ${{ matrix.dotnet-version }} uses: actions/setup-dotnet@v4 with: dotnet-version: ${{ matrix.dotnet-version }} - run: dotnet restore - run: dotnet build --no-restore - run: dotnet test --no-build ``` ## CodeQL Security Scanning Add GitHub CodeQL for security analysis: ```yaml name: CodeQL on: push: branches: [main] pull_request: branches: [main] schedule: - cron: '0 6 * * 1' jobs: analyze: runs-on: ubuntu-latest permissions: security-events: write actions: read contents: read steps: - uses: actions/checkout@v4 - name: Initialize CodeQL uses: github/codeql-action/init@v3 with: languages: csharp - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - name: Build run: | dotnet restore dotnet build --no-restore - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v3 ``` ## Mutation Testing with Stryker Add mutation testing for critical libraries: ```yaml name: Mutation Testing on: push: branches: [main] schedule: - cron: '0 4 * * 0' jobs: mutate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - name: Install Stryker run: dotnet tool install -g dotnet-stryker - name: Restore run: dotnet restore - name: Run Stryker run: dotnet stryker --reporter html --reporter progress working-directory: ./tests/MyProject.Tests - name: Upload mutation report uses: actions/upload-artifact@v4 with: name: stryker-report path: '**/StrykerOutput/**' ``` ## Architecture Tests Integration Run architecture tests as part of the test job: ```yaml name: Architecture Tests on: push: branches: [main] pull_request: branches: [main] jobs: architecture: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - name: Restore run: dotnet restore - name: Build run: dotnet build --no-restore - name: Run architecture tests run: dotnet test --no-build --filter "Category=Architecture" ``` ## ReSharper Command Line Tools Use JetBrains InspectCode for deep analysis: ```yaml name: ReSharper Inspection on: push: branches: [main] pull_request: branches: [main] jobs: inspect: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: '9.x' - name: Install ReSharper CLT run: dotnet tool install -g JetBrains.ReSharper.GlobalTools - name: Restore run: dotnet restore - name: Run InspectCode run: | jb inspectcode MySolution.sln \ --output=inspectcode-report.xml \ --format=Xml \ --severity=WARNING - name: Upload inspection report uses: actions/upload-artifact@v4 with: name: inspectcode-report path: inspectcode-report.xml ``` ## Caching Dependencies Add caching to speed up workflow runs: ```yaml - name: Cache NuGet packages uses: actions/cache@v4 with: path: ~/.nuget/packages key: ${{ runner.os }}-nuget-${{ hashFiles('**/*.csproj', '**/Directory.Build.props') }} restore-keys: | ${{ runner.os }}-nuget- ``` ## Sources - [actions/setup-dotnet](https://github.com/actions/setup-dotnet) - [actions/cache](https://github.com/actions/cache) - [github/codeql-action](https://github.com/github/codeql-action) - [dotnet test command](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-test) - [dotnet format command](https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-format) - [ReportGenerator](https://github.com/danielpalme/ReportGenerator) - [Stryker.NET](https://github.com/stryker-mutator/stryker-net) - [ReSharper command line tools](https://www.jetbrains.com/help/resharper/ReSharper_Command_Line_Tools.html)
-
-
SKILL.md 6.8 KB
--- name: dotnet-quality-ci version: "1.0.0" category: "Code Quality" description: "Set up or refine open-source .NET code-quality gates for CI: formatting, `.editorconfig`, SDK analyzers, third-party analyzers, coverage, mutation testing, architecture tests, and security scanning. Use when a .NET repo needs an explicit quality stack in `AGENTS.md`, docs, or pipeline YAML." compatibility: "Requires a .NET solution or project; may update `AGENTS.md`, CI workflows, a repo-root `.editorconfig`, `Directory.Build.props`, or analyzer package references." --- # .NET Quality CI ## Trigger On - adding or tightening .NET code-quality gates in CI - choosing analyzers, coverage, mutation, or architecture-test tooling for a .NET repo - standardizing `.editorconfig`, `dotnet format`, and warning policy ## Value - produce a concrete project delta: code, docs, config, tests, CI, or review artifact - reduce ambiguity through explicit planning, verification, and final validation skills - leave reusable project context so future tasks are faster and safer ## Do Not Use For - non-.NET repositories - generic CI/CD guidance with no .NET quality stack decisions - framework-specific test authoring with no quality-gate change ## Inputs - the nearest `AGENTS.md` - the current repo-root `.editorconfig` and MSBuild props - the current CI workflow and package references - the active test runner model: VSTest or Microsoft.Testing.Platform ## Quick Start 1. Read the nearest `AGENTS.md` and confirm scope and constraints. 2. Run this skill's `Workflow` through the `Ralph Loop` until outcomes are acceptable. 3. Return the `Required Result Format` with concrete artifacts and verification evidence. ## Workflow 1. Start with the repo-native baseline: - repo-root `.editorconfig` - `dotnet format --verify-no-changes` - SDK analyzers with explicit `EnableNETAnalyzers`, `AnalysisLevel`, and warning policy 2. Add third-party analyzers only where they close a real gap: - `StyleCopAnalyzers` - `Roslynator` - `Meziantou.Analyzer` - framework analyzers such as xUnit, MSTest, or TUnit analyzers 3. Separate quality gates by purpose: - formatting and style - correctness and static analysis - coverage and reports - architecture rules - security scanning - mutation testing 4. For complexity, use a composite approach: - CA1502 thresholding - maintainability limits in `AGENTS.md` - architecture tests - coverage and mutation where risk justifies it 5. Make ownership explicit in `AGENTS.md` and CI: - which command formats - which command analyzes - which command measures coverage - which runner model the tests use 6. After any .NET code change, the repo's quality pass must be runnable by agents: - format - build - analyze - focused tests - broader tests - coverage and report generation when configured - extra configured gates only when the repo actually enabled them 7. Route tool-specific setup through dedicated skills where possible: - `dotnet-format` - `dotnet-code-analysis` - `dotnet-analyzer-config` - analyzer-pack skills such as `dotnet-stylecop-analyzers`, `dotnet-roslynator`, and `dotnet-meziantou-analyzer` - frontend asset quality skills in mixed `.NET` plus Node repos such as `dotnet-eslint`, `dotnet-stylelint`, `dotnet-htmlhint`, `dotnet-webhint`, `dotnet-biome`, `dotnet-sonarjs`, `dotnet-metalint`, and `dotnet-chous` - coverage/reporting skills such as `dotnet-coverlet` and `dotnet-reportgenerator` - architecture/security skills such as `dotnet-netarchtest`, `dotnet-archunitnet`, and `dotnet-codeql` 8. Avoid overlapping tools with conflicting ownership. If you add an opinionated formatter, define whether it replaces or complements `dotnet format`. ## Bootstrap When Missing If a quality gate is requested but not configured, use this activation path: 1. Detect current state in `.csproj`, `Directory.Build.*`, `.editorconfig`, tool manifests, and CI workflow files. 2. Choose exactly one owner command per gate category (format, analyze, test, coverage, architecture, security, mutation). 3. Install the minimal required package or tool and commit checked-in config files. 4. Wire the gate into both `AGENTS.md` and CI with explicit commands. 5. Run a first verify pass, fix actionable failures, and rerun. 6. Return `status: configured` if newly enabled and passing, or `status: improved` if issues remain but baseline improved. 7. Return `status: not_applicable` only when the gate is explicitly out of scope for this repo. ## Deliver - a documented .NET quality baseline - CI commands that are explicit and reproducible - analyzer and coverage choices that match the repo's runner model - a documented post-change quality pass for agents and CI - tool selection that stays open-source and free by default, with caveats called out explicitly ## Validate - repo-root `.editorconfig` is the default source of truth for per-rule severity - formatting, analyzer, and coverage commands are runner-compatible - added tools cover distinct gaps instead of duplicating each other - complexity and architecture policy are explicit, not implied - .NET code changes are expected to pass more than tests alone when quality gates are configured - any licensing or hosting caveat is documented before the tool becomes a default gate ## Ralph Loop Use the Ralph Loop for every task, including docs, architecture, testing, and tooling work. 1. Plan first (mandatory): - analyze current state - define target outcome, constraints, and risks - write a detailed execution plan - list final validation skills to run at the end, with order and reason 2. Execute one planned step and produce a concrete delta. 3. Review the result and capture findings with actionable next fixes. 4. Apply fixes in small batches and rerun the relevant checks or review steps. 5. Update the plan after each iteration. 6. Repeat until outcomes are acceptable or only explicit exceptions remain. 7. If a dependency is missing, bootstrap it or return `status: not_applicable` with explicit reason and fallback path. ### Required Result Format - `status`: `complete` | `clean` | `improved` | `configured` | `not_applicable` | `blocked` - `plan`: concise plan and current iteration step - `actions_taken`: concrete changes made - `validation_skills`: final skills run, or skipped with reasons - `verification`: commands, checks, or review evidence summary - `remaining`: top unresolved items or `none` For setup-only requests with no execution, return `status: configured` and exact next commands. ## Load References - `references/editorconfig-and-ci.md` - `references/quality-toolchain.md` - `references/workflows.md` - `references/checklist.md` ## Example Requests - "Define the best OSS CI stack for this .NET repo." - "Add .NET analyzers, coverage, and mutation testing guidance." - "Make `.editorconfig` and CI agree in our .NET solution."
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.