Skip to content

fix(build): restore multi-TFM compatibility for Release pack#194

Draft
ottobolyos wants to merge 6 commits into
TrakHound:masterfrom
ottobolyos:fix/multi-tfm-compat
Draft

fix(build): restore multi-TFM compatibility for Release pack#194
ottobolyos wants to merge 6 commits into
TrakHound:masterfrom
ottobolyos:fix/multi-tfm-compat

Conversation

@ottobolyos

Copy link
Copy Markdown
Contributor

Summary

Commit dd2eb424 chore(warnings): annotate Windows-only service + socket APIs with SupportedOSPlatform (2026-05-22) landed [SupportedOSPlatform("windows")] decorations on six Service / HTTP-server types/methods to silence CA1416 on net8.0. The decoration's type lives in System.Runtime.Versioning on .NET 5.0+ but is absent / inaccessible on net4x and netstandard2.0, so the multi-TFM Release pack has been failing CS0122 / CS0246 on every commit since. CI runs only Debug / net8.0 and never exercises the Release multi-TFM matrix, which is how the regression slipped through.

This PR restores Release pack-ability across the full TFM matrix by wrapping each affected site in #if NET5_0_OR_GREATER. The matrix-spanning CI gate that prevents the next slip ships in the follow-up PR (warnings cleanup + Release-pack gate) — see § Follow-up below.

Behaviour change

None at runtime. The [SupportedOSPlatform("windows")] decoration remains in effect under .NET 5.0+; the only difference is that net4x and netstandard2.0 no longer try to reference a type that doesn't ship there.

Bug classes covered

Class Diagnostic Site count Root-cause fix
Multi-TFM attribute compat CS0122 / CS0246 — SupportedOSPlatformAttribute absent on net4x / netstandard2.0 6 files Wrap using System.Runtime.Versioning; + attribute usages in #if NET5_0_OR_GREATER.
LangVersion fallback on netstandard2.0 CS8370 — using declarations require C# 8.0 1 csproj (MTConnect.NET-XML) Add <LangVersion>8.0</LangVersion> to the project's <PropertyGroup>.
Shadowed local variable CS0136 — inner var observation shadows outer on net4x 1 site (MqttRelay/Module.cs) Rename the inner declaration to condObservation.

Tests

  • tests/MTConnect.NET-Common-Tests/Platform/SupportedOSPlatformAttributePresenceTests.cs — for each of the six wrapped Service / HTTP-server members, reflection asserts the [SupportedOSPlatform("windows")] attribute is present with PlatformName == "windows" when running under net8.0. Pins the API surface so a future "someone removes the attribute" regression is caught.
  • tests/MTConnect.NET-XML-Tests/Xml/UsingDeclarationsTests.cs — exercises the C# 8.0 using declaration code path in MTConnect.NET-XML via XsdPreprocessor.StripXsd11Constructs. Pins the path against regression.
  • tests/MTConnect.NET-AgentModule-MqttRelay-Tests/ConditionObservationVariableScopeTests.cs — scans Module.cs for the shadowing foreach (var observation in ...) declaration that triggered CS0136 under net4x. Goes from RED to GREEN as the rename lands; pins against future re-introduction of the shadow.

Files touched

  • libraries/MTConnect.NET-HTTP/Ceen/Httpd/HttpServer.cs
  • libraries/MTConnect.NET-Services/{WindowsService,MTConnectAgentService,MTConnectAdapterService}.cs
  • agent/MTConnect.NET-Applications-Agents/Service.cs
  • adapter/MTConnect.NET-Applications-Adapter/Service.cs
  • libraries/MTConnect.NET-XML/MTConnect.NET-XML.csproj
  • agent/Modules/MTConnect.NET-AgentModule-MqttRelay/Module.cs
  • Test files listed above.

Follow-up

PR #195 (warnings cleanup) ships:

  • Root-cause fixes for CS0162 (4 sites), SYSLIB0057 (5 sites), CS0809 (HTTP), CA2022 (HTTP), CS1574 (2 App projects), NU5017 (SysML) — every diagnostic that the Release pack also surfaces on master today.
  • A new CI job release-pack running dotnet pack -c Release across the full TFM matrix as the regression-prevention gate. Without that gate the same class of slip recurs.
  • Tests per fix where the diagnostic has a meaningful runtime semantic.

Adds a reflection-based fixture under
tests/MTConnect.NET-Common-Tests/Platform/ that asserts every site
PR TrakHound#194 wraps in `#if NET5_0_OR_GREATER` still carries the
`[SupportedOSPlatform("windows")]` decoration when the build path
yields net8.0. The fixture covers the six sites from the May-22
warnings sweep — WindowsService, MTConnectAgentService,
MTConnectAdapterService, both `MTConnect.Applications.Service`
types (agent + adapter), and the
`Ceen.Httpd.HttpServer.AppDomainBridge.HandleRequest(SocketInformation,...)`
plus `HttpServer.RunClient(SocketInformation,...)` HTTP-server
sites — and pins the API surface so a future contributor who
removes the attribute or narrows the wrap fails the test.

The fixture runs only under net8.0 (the only TFM every test project
targets), so cannot directly fail under the pre-fix code. Its
value is regression-preventive against future removal, matching the
TDD shape the brief specifies for sites whose pre-fix surface is
already correct on the test TFM.

Extends the test csproj with reflection-only references to
MTConnect.NET-Services, MTConnect.NET-HTTP,
MTConnect.NET-Applications-Agents, and
MTConnect.NET-Applications-Adapter so the fixture can locate the
six annotated members.
Adds a fixture under tests/MTConnect.NET-XML-Tests/Xml/ that
exercises XsdPreprocessor.StripXsd11Constructs — the production site
that uses the C# 8.0 `using var reader = ...;` declaration. On
netstandard2.0 the compiler's default LangVersion is 7.3, which
rejects the using-declaration form with CS8370; PR TrakHound#194 pins the
project's LangVersion to 8.0. The fixture runs only under net8.0
(the only test TFM), so it passes regardless of LangVersion; its
value is keeping the path exercised so a regression that breaks the
preprocessor's load step surfaces as a failure rather than only as a
build break.
Adds a structural test under
tests/MTConnect.NET-AgentModule-MqttRelay-Tests/ that scans
Module.cs for the shadowing `foreach (var observation in ...)`
declaration inside AgentObservationAdded. The test fails before the
PR TrakHound#194 rename (the file still contains the shadow) and passes
after — pinning the rename and catching any future re-introduction
of the shadow under net8.0, which is the only TFM the CI matrix
exercises directly.

The brief allowed either a unit-level pin or an E2E condition-path
workflow test. The rename is the only correctness concern (the
condition path is otherwise covered by MqttRelayWorkflowTests),
so the lighter unit-level pin is the right shape — no Docker
dependency, runs in the standard filtered test pass.
Restores Release pack-ability across the full TFM matrix
(net461..net9.0 + netstandard2.0). Commit dd2eb42 (2026-05-22)
landed `[SupportedOSPlatform("windows")]` decorations on six
Service / HTTP-server types/methods to silence the CA1416
platform-compatibility analyser on net8.0. The attribute type
ships in System.Runtime on .NET 5.0+ but is absent from net4x and
netstandard2.0, so the multi-TFM Release pack has been failing
CS0122 / CS0246 on every commit since. The CA1416 analyser only
fires on net5+ too, so the attribute serves no purpose on older
TFMs.

Wraps each `using System.Runtime.Versioning;` directive and each
`[SupportedOSPlatform("windows")]` attribute usage in
`#if NET5_0_OR_GREATER ... #endif` so the older TFMs see neither.
No runtime behaviour change on .NET 5.0+ — the decoration remains
in effect — and net4x / netstandard2.0 stop referencing a type
that does not ship there.

Sites covered:
  * libraries/MTConnect.NET-Services/WindowsService.cs
  * libraries/MTConnect.NET-Services/MTConnectAgentService.cs
  * libraries/MTConnect.NET-Services/MTConnectAdapterService.cs
  * libraries/MTConnect.NET-HTTP/Ceen/Httpd/HttpServer.cs (two
    attribute sites — AppDomainBridge.HandleRequest and
    HttpServer.RunClient overloads that take SocketInformation)
  * agent/MTConnect.NET-Applications-Agents/Service.cs
  * adapter/MTConnect.NET-Applications-Adapter/Service.cs

The SupportedOSPlatformAttributePresenceTests fixture added in
the preceding test commit goes from RED on net8.0 (it asserted
the attribute was present, so the assert held even pre-fix) to
GREEN — the attribute remains visible under the test TFM.
XsdPreprocessor.StripXsd11Constructs uses a C# 8.0 `using var`
declaration:

    using var reader = new StringReader(xsdSourceXml);

The Roslyn default LangVersion on netstandard2.0 / net4x falls back
to 7.3, which rejects the using-declaration syntax with CS8370 and
breaks the multi-TFM Release pack. Pinning LangVersion to 8.0 — the
lowest version that accepts the syntax — restores Release
pack-ability across the full TFM matrix without dragging in the
behavioural changes of later C# versions.

Directory.Build.props sets no LangVersion globally, so the
per-csproj fix is the right scope; the project's Description
already advertises support for the same TFM matrix the fix
restores.
The async-void AgentObservationAdded handler took `observation` as
its outer parameter, and the inner durable-relay branch declared
the same name in a `foreach (var observation in conditionObservations)`
loop. The shadow fails CS0136 under net4x and breaks the multi-TFM
Release pack.

Renames the loop variable to `condObservation` and updates the
single usage inside the loop body. The handler's behaviour is
unchanged — the rename is a pure scope correction. The
non-durable-relay branch a few lines below uses a different
variable name (`conditionObservations`) and never shadowed.

The ConditionObservationVariableScopeTests fixture added in the
preceding test commit scans Module.cs for the shadowing
`foreach (var observation in ...)` declaration; it goes from RED
to GREEN as this commit lands.
@ottobolyos

Copy link
Copy Markdown
Contributor Author

Follow-up PR for the remaining Release-pack diagnostic classes is now open as draft: #195 — six bug classes (CS0162, SYSLIB0057, CS0809, CA2022, CS1574, NU5017) cleaned at root cause, plus a new release-pack CI job that runs dotnet pack -c Release across the full multi-TFM matrix on every push and every non-draft PR to prevent the regression class recurring.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In Progress

Development

Successfully merging this pull request may close these issues.

2 participants