Skip to content

chore: adopt Central Package Management and collect coverage - #27

Merged
StuartMeeks merged 1 commit into
mainfrom
chore/standards-cpm
Aug 20, 2026
Merged

chore: adopt Central Package Management and collect coverage#27
StuartMeeks merged 1 commit into
mainfrom
chore/standards-cpm

Conversation

@StuartMeeks

Copy link
Copy Markdown
Owner

What changed

STANDARD.md §1.2, §1.3, §2.6 — the last three machine-checkable clauses SelfUpdate was failing.

  • Directory.Packages.props added; versions leave all three project files. CentralPackageVersionOverrideEnabled=false.
  • Thirteen properties restated in every csproj move to Directory.Build.props.
  • Microsoft.Testing.Extensions.CodeCoverage added and invoked by CI, with a per-platform artifact upload.

Why

CentralPackageVersionOverrideEnabled=false is the half that matters: without it MSBuild silently ignores a stray inline Version= and uses the central one, which is exactly the drift the file exists to prevent.

Coverage: §2.6 exists because a referenced-but-never-invoked collector is worse than none — it reads as coverage in the dependency list while producing no data. So this adds the package and dotnet test … -- --coverage. Verified locally: one .coverage file per target framework.

The demo project opts GenerateDocumentationFile back off. It is not shipped, so its types are not public surface, and demanding XML docs on sample code would fail the build under TreatWarningsAsErrors — the same reasoning §2.7 applies to the test project.

No dependency floor was raised. Per-TFM floors survive intact — CPM re-evaluates the conditional ItemGroups per target framework during the inner build, so net8.0 still floors at 8.0.2 / 8.0.1 and net10.0 at 10.0.11. Raising a floor is consumer-visible and belongs in its own reviewed commit.

Proof that the package is unchanged

Packed before and after from clean obj/ at the same commit, then extracted and compared file by file:

File Result
.nuspec (nupkg and snupkg) byte-identical
lib/net8.0/*.dll, lib/net10.0/*.dll byte-identical
lib/net8.0/*.xml, lib/net10.0/*.xml byte-identical
lib/net8.0/*.pdb, lib/net10.0/*.pdb byte-identical
README.md, icon.png, [Content_Types].xml byte-identical
*.psmdcp filename differs, content identical
_rels/.rels differs only in the Target=/Id naming that psmdcp

That is exactly the bar ADOPTING.md sets — the .psmdcp filename is regenerated by NuGet on every pack.

A false positive worth recording

A first attempt appeared to show both assemblies differing. It did not. The "before" pack had reused a stale obj/, so the two builds embedded different git commit SHAs via SourceLink, which moved the MVID and the deterministic PE stamp with them. Decoding the differing byte runs showed the two SHAs as ASCII directly (1acc08c3… vs 9caf8240…). Rebuilding both from clean obj/ removed the difference entirely.

Recording it because that failure mode looks precisely like a real packaging regression, and 46 differing byte-runs in a shipped assembly is not something to wave through.

Checklist

  • Build is clean — no new warnings (TreatWarningsAsErrors is on)
  • Tests pass on every shipped target framework — 392 tests, 196 × net8.0/net10.0, coverage collected on both
  • Public API changes carry XML docs — n/a, no code change
  • CHANGELOG.md updated under [Unreleased]
  • Dependency floors unchanged — proven above

Consumer impact

None, demonstrated rather than asserted. <Version> is untouched and no tag is pushed.

🤖 Generated with Claude Code

STANDARD.md sections 1.2, 1.3 and 2.6.

Versions move from the three project files into Directory.Packages.props with
CentralPackageVersionOverrideEnabled=false, so a stray inline Version= is a hard
build error instead of being silently ignored — which is the drift the file
exists to prevent. The per-TFM floors survive: CPM re-evaluates the conditional
ItemGroups per target framework during the inner build, so net8.0 still floors
at 8.0.2 / 8.0.1 and net10.0 at 10.0.11. No floor was raised; that is
consumer-visible and belongs in its own reviewed commit.

Proven behaviour-preserving rather than asserted. Packed before and after from
clean obj/ at the same commit (9caf824): the .nuspec, both lib/ assemblies, both
XML doc files, both symbol PDBs, README and icon are byte-identical. The only
differences anywhere in either package are the .psmdcp filename, which NuGet
regenerates per pack, and the _rels/.rels entry that names it — the psmdcp
*content* is identical too.

A first attempt appeared to show the assemblies differing. It did not: the
"before" pack had reused a stale obj/, so the two builds embedded different git
commit SHAs via SourceLink, which moved the MVID and the deterministic PE stamp
with them. Decoding the differing bytes showed the two SHAs directly. Rebuilding
both from clean obj/ removed the difference entirely — worth recording, because
that failure mode looks exactly like a real packaging regression.

Thirteen properties restated in every csproj move to Directory.Build.props
(1.2). The demo project opts GenerateDocumentationFile back off: it is not
shipped, so its types are not public surface, and demanding XML docs on sample
code would fail the build under TreatWarningsAsErrors. Same reasoning as 2.7
gives the test project.

Coverage (2.6) adds Microsoft.Testing.Extensions.CodeCoverage AND has CI invoke
it, with a per-platform artifact upload. A referenced-but-never-invoked
collector is worse than none — it reads as coverage in the dependency list while
producing no data. Verified locally: one .coverage file per TFM.

Also corrects a comment in dependabot.yml that pointed at "the csproj" for the
floor rationale, which moved to Directory.Packages.props in this change.

Verified: Release build 0 warnings, 392 tests passing across net8.0 and net10.0,
coverage collected on both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@StuartMeeks
StuartMeeks merged commit ad260dd into main Aug 20, 2026
9 checks passed
@StuartMeeks
StuartMeeks deleted the chore/standards-cpm branch August 20, 2026 08:11
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