build: adopt static-analysis packs at suggestion (#15, increment 1)
Build ErsatzTV Image / Build & test (.NET) (push) Successful in 2m19s
Build ErsatzTV Image / Build & push image (amd64) (push) Successful in 4m31s

Add Roslynator, SonarAnalyzer.CSharp, Meziantou.Analyzer, and AsyncFixer as central
analyzer references (Directory.Build.targets, CPM-versioned, guarded on
ManagePackageVersionsCentrally so the gitignored .mcp tool isn't affected).
.editorconfig defaults dotnet_analyzer_diagnostic.severity to `suggestion` so the packs
surface findings without failing the TreatWarningsAsErrors (TWAE) build; rules are
promoted to warning/error incrementally (promotion = enforcement via the existing TWAE
build, so no separate lint step is needed).

StyleCop.Analyzers is intentionally excluded: its latest stable (1.1.118) crashes
(AD0001) on C# records and overlaps the existing .editorconfig/Roslynator.

Blazor .razor: editorconfig severity overrides don't reach analyzer diagnostics in Razor
@code (source-generator limitation; dotnet format can't fix them either), so the
currently-firing SonarAnalyzer rules are temporarily NoWarn-ed in ErsatzTV.csproj and
burned down rule-by-rule in #25. The same rules run at suggestion on .cs.

Formatting normalization (mixed UTF-8 BOM + whitespace) is deferred to its own PR.

Full-solution Release build green (0 errors, 0 warnings).

Refs #15

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit was merged in pull request #26.
This commit is contained in:
2026-06-27 07:37:15 +00:00
committed by timothy
co-authored by Claude Opus 4.8
parent f1ff39954f
commit f2d0a36ed6
5 changed files with 77 additions and 0 deletions
+16
View File
@@ -104,3 +104,19 @@ ij_json_wrap_long_lines = false
[*.cs]
# disable CA1848: Use the LoggerMessage delegates`
dotnet_diagnostic.ca1848.severity = none
# --- Static-analysis pack adoption (ersatztv#15) ---
# Roslynator / SonarAnalyzer / Meziantou / AsyncFixer are referenced centrally
# (Directory.Build.targets). Default every analyzer diagnostic to `suggestion` so the new
# packs don't fail the TreatWarningsAsErrors build; high-value rules get promoted to
# warning/error one at a time (see ersatztv#15 / docs/contributing.md). Explicit per-rule
# severities (e.g. ca1848 above) still take precedence over this bulk default.
dotnet_analyzer_diagnostic.severity = suggestion
# Blazor components: analyzers run on .razor/.cshtml @code too, and TWAE would otherwise
# turn their default-severity findings into build errors — keep them at suggestion as well.
[*.razor]
dotnet_analyzer_diagnostic.severity = suggestion
[*.cshtml]
dotnet_analyzer_diagnostic.severity = suggestion
+27
View File
@@ -11,4 +11,31 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<!-- Curated static-analysis packs (ersatztv#15), applied to every project. Versions are
central (Directory.Packages.props / CPM). Guarded on CPM so the gitignored .mcp tool
(which opts out of CPM) doesn't pull versionless references. They start at `suggestion`
severity in .editorconfig so they don't fail the TreatWarningsAsErrors build; high-value
rules are promoted to warning/error incrementally. -->
<ItemGroup Condition="'$(ManagePackageVersionsCentrally)' == 'true'">
<PackageReference Include="Roslynator.Analyzers">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Meziantou.Analyzer">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<!-- StyleCop.Analyzers intentionally omitted: its latest stable (1.1.118) crashes
(AD0001) on C# records and its rules overlap the existing .editorconfig/Roslynator.
Revisit via the record-compatible 1.2.0-beta if StyleCop is specifically wanted. (#15) -->
<PackageReference Include="AsyncFixer">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
+4
View File
@@ -4,6 +4,7 @@
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AsyncFixer" Version="2.1.0" />
<PackageVersion Include="Blazored.FluentValidation" Version="2.2.0" />
<PackageVersion Include="BlazorSortable" Version="5.2.1" />
<PackageVersion Include="Blurhash.SkiaSharp" Version="2.0.0" />
@@ -35,6 +36,7 @@
<PackageVersion Include="Markdig" Version="0.44.0" />
<PackageVersion Include="MediatR" Version="[12.5.0]" />
<PackageVersion Include="MediatR.Courier.DependencyInjection" Version="5.0.0" />
<PackageVersion Include="Meziantou.Analyzer" Version="3.0.115" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Authentication.OpenIdConnect" Version="10.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="10.0.2" />
@@ -74,6 +76,7 @@
<PackageVersion Include="Refit.Newtonsoft.Json" Version="9.0.2" />
<PackageVersion Include="Refit.Xml" Version="9.0.2" />
<PackageVersion Include="RichTextKit.Stbear" Version="0.4.167.3" />
<PackageVersion Include="Roslynator.Analyzers" Version="4.15.0" />
<PackageVersion Include="Scalar.AspNetCore" Version="2.12.32" />
<PackageVersion Include="Scriban.Signed" Version="6.5.2" />
<PackageVersion Include="Serilog" Version="4.3.0" />
@@ -90,6 +93,7 @@
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.12" />
<PackageVersion Include="SkiaSharp" Version="3.119.1" />
<PackageVersion Include="SkiaSharp.NativeAssets.Linux.NoDependencies" Version="3.119.1" />
<PackageVersion Include="SonarAnalyzer.CSharp" Version="10.27.0.140913" />
<!-- Direct pin to override EF Core 9's transitive SQLitePCLRaw 2.1.10 (vulnerable
bundled SQLite, GHSA-2m69-gcr7-jv3q). The 3.x line ships the patched native
(lib.e_sqlite3 3.50.3); core 3.0.3 satisfies Microsoft.Data.Sqlite's `>= 2.1.10`. (#8) -->
+6
View File
@@ -7,6 +7,12 @@
<IsPackable>false</IsPackable>
<ImplicitUsings>enable</ImplicitUsings>
<NoWarn>VSTHRD200,CA1873</NoWarn>
<!-- ersatztv#25: SonarAnalyzer findings in Blazor .razor @code can't be downgraded via
.editorconfig (Razor source-generator limitation), so under TreatWarningsAsErrors they
would break the build. Temporarily suppressed here; the #25 burn-down removes each ID
as its .razor findings are fixed. (These same rules run at `suggestion` on .cs via
.editorconfig — visible, non-blocking.) -->
<NoWarn>$(NoWarn);S6966;S3267;S2325;S3260;S2094;S3458;S3358;S6667;S125;S1135;S1751;S1125;S1066;S127;S927;S6610;S6580;S5693;S3440;S2933;S1871</NoWarn>
<IncludeAllContentForSelfExtract>true</IncludeAllContentForSelfExtract>
<Configurations>Debug;Release;Debug No Sync</Configurations>
<Platforms>AnyCPU</Platforms>
+24
View File
@@ -137,6 +137,30 @@ Core `[9.0.x,10)`) are respected — no v10 jump. PR volume is throttled (`prCon
to drain faster. `workflow_dispatch` defaults to a safe **dry run**. Cross-repo rollout
tracked in server-management#484. (server-management#484)
## Static analysis & formatting
**Analyzer packs**`Directory.Build.targets` references **Roslynator**, **SonarAnalyzer.CSharp**,
**Meziantou.Analyzer**, and **AsyncFixer** for every project (versions central via CPM; guarded on
`ManagePackageVersionsCentrally` so the gitignored `.mcp` tool isn't pulled in). They are introduced
**incrementally** (ersatztv#15): `.editorconfig` sets `dotnet_analyzer_diagnostic.severity = suggestion`
so the packs surface findings without failing the `TreatWarningsAsErrors` (TWAE) build. **Promotion is
the enforcement** — raising a rule to `warning` makes it a CI-blocking error via the existing TWAE
build, so no separate lint step is needed.
- **StyleCop.Analyzers is intentionally excluded**: its latest stable (1.1.118) crashes (`AD0001`) on
C# `record` declarations, and its rules overlap the existing `.editorconfig`/Roslynator. Revisit via
the record-compatible `1.2.0-beta` only if specifically wanted.
- **Blazor `.razor` caveat**: editorconfig severity overrides don't reach analyzer diagnostics in Razor
`@code` (source-generator limitation — `dotnet format` can't fix them either), so the currently-firing
SonarAnalyzer rules are temporarily `NoWarn`-ed in `ErsatzTV.csproj` and burned down rule-by-rule in
**ersatztv#25**. The same rules run at `suggestion` on `.cs`.
**Formatting** — the tree isn't yet `dotnet format`-clean (mixed UTF-8 BOM + whitespace inherited from
upstream: ~1,500 BOM files + ~480 whitespace). A one-time normalization lands as its **own dedicated
PR** (kept out of the analyzer work to stay reviewable); afterwards `dotnet format whitespace
--verify-no-changes` (+ `style`) joins the `test` job so drift can't return. `.gitattributes` already
pins line endings.
## Registry
Gitea Packages, HTTP-only at `192.168.1.95:3000`. jazz's Docker daemon has it as an