Skip to content

Fix CI Release-build analyzer errors#33

Merged
Chris-Wolfgang merged 1 commit into
developfrom
fix/release-build-ci-analyzer-errors
Apr 27, 2026
Merged

Fix CI Release-build analyzer errors#33
Chris-Wolfgang merged 1 commit into
developfrom
fix/release-build-ci-analyzer-errors

Conversation

@Chris-Wolfgang

Copy link
Copy Markdown
Owner

Summary

PR #32's CI (failed run) surfaced 5 distinct analyzer errors in Release that didn't fire locally. Cause: pr.yaml's "Fetch trusted configuration files from main branch" step writes .editorconfig with Out-File -Encoding UTF8, which prefixes a BOM that the .NET analyzer engine appears to ignore — so the project's severity overrides (e.g. MA0002 = suggestion) don't apply on CI. (Separate issue — flagging for a follow-up to switch to [System.IO.File]::WriteAllText(..., (Get-Content ... -Raw), $utf8NoBom).)

Rather than relying on .editorconfig overrides at all, this PR fixes the underlying findings.

src

  • MA0049InMemoryLogger and InMemoryLogger<T>: type name matches namespace. The package, namespace, and primary type intentionally share a name; suppressed via [SuppressMessage] with justification.
  • MA0158InMemoryLogger._lock: use System.Threading.Lock on net9.0+ via #if NET9_0_OR_GREATER; keep object lock on older TFMs.
  • S1066ScopeDisposable.Dispose: merge nested ifs with &&; preserve the comment.
  • S2365InMemoryLoggerProvider.LogEntries / Loggers: properties materialize a snapshot, which is the deliberate test-helper API. Suppressed via [SuppressMessage] with justification; cost documented in <remarks>.
  • MA0002InMemoryLoggerProvider.Loggers: pass StringComparer.Ordinal to the Dictionary copy constructor, matching the inner ConcurrentDictionary's comparer.

tests

  • S1481 / S2699InMemoryLoggerOfTTests.Ctor_when_default_parameters_creates_instance: Assert.NotNull(sut) instead of relying on a ReSharper comment to silence the unused-variable rule and the missing-assertion rule.
  • S2699InMemoryLoggerProviderTests.Dispose_does_not_throw: capture with Record.Exception and Assert.Null(ex) so the test has a real assertion.

Test plan

  • dotnet build "src/Wolfgang.Extensions.Logging.InMemoryLogger/Wolfgang.Extensions.Logging.InMemoryLogger.csproj" -c Release — 0 errors with .editorconfig present
  • Same build with .editorconfig temporarily renamed (simulating the CI BOM bug) — 0 errors
  • Same for the test csproj — 0 errors
  • dotnet test -c Release — 52/52 passing on net462, net47, net471, net472, net48, net481, net6.0, net7.0, net8.0, net9.0, net10.0
  • CI confirms

After this lands on develop, PR #32 (develop -> main) will re-run CI.

🤖 Generated with Claude Code

CI's pr.yaml fetches .editorconfig from main before building (the
'protected configuration files' guard). Locally, our .editorconfig sets
several rules to 'suggestion' so they don't fail the build, but on CI
the file appears to be ignored (the fetch step writes UTF-8 with BOM,
which can prevent the analyzer from picking it up). Either way, the
findings are real, so fix them at the source rather than leaning on
.editorconfig overrides.

src:
- InMemoryLogger / InMemoryLogger<T>: suppress MA0049 (type name matches
  containing namespace) on each class with a SuppressMessage attribute and
  justification - the package, namespace, and primary type intentionally
  share a name.
- InMemoryLogger: use System.Threading.Lock on net9+ (MA0158) via
  conditional compilation; keep object-based lock on older TFMs.
- InMemoryLogger.ScopeDisposable.Dispose: merge nested ifs (S1066).
- InMemoryLoggerProvider.LogEntries / Loggers: suppress S2365 (properties
  copying collections) - this is a deliberate test-helper API; cost is
  documented in <remarks>.
- InMemoryLoggerProvider.Loggers: pass StringComparer.Ordinal to the
  Dictionary copy constructor (MA0002), matching the inner
  ConcurrentDictionary.

tests:
- InMemoryLoggerOfTTests.Ctor_when_default_parameters_creates_instance:
  Assert.NotNull(sut) instead of relying on a ReSharper comment to silence
  S1481/S2699.
- InMemoryLoggerProviderTests.Dispose_does_not_throw: capture and assert
  on Record.Exception so the test has a real assertion (S2699).

Verified locally: build clean both with and without .editorconfig present
(simulating CI), 52/52 tests pass on net462, net47, net471, net472, net48,
net481, net6.0, net7.0, net8.0, net9.0, net10.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Chris-Wolfgang Chris-Wolfgang merged commit 4d2ea58 into develop Apr 27, 2026
@Chris-Wolfgang Chris-Wolfgang deleted the fix/release-build-ci-analyzer-errors branch April 27, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant