chore: adopt Central Package Management and collect coverage - #27
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
STANDARD.md §1.2, §1.3, §2.6 — the last three machine-checkable clauses SelfUpdate was failing.
Directory.Packages.propsadded; versions leave all three project files.CentralPackageVersionOverrideEnabled=false.Directory.Build.props.Microsoft.Testing.Extensions.CodeCoverageadded and invoked by CI, with a per-platform artifact upload.Why
CentralPackageVersionOverrideEnabled=falseis the half that matters: without it MSBuild silently ignores a stray inlineVersion=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.coveragefile per target framework.The demo project opts
GenerateDocumentationFileback off. It is not shipped, so its types are not public surface, and demanding XML docs on sample code would fail the build underTreatWarningsAsErrors— 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, sonet8.0still floors at 8.0.2 / 8.0.1 andnet10.0at 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:.nuspec(nupkg and snupkg)lib/net8.0/*.dll,lib/net10.0/*.dlllib/net8.0/*.xml,lib/net10.0/*.xmllib/net8.0/*.pdb,lib/net10.0/*.pdbREADME.md,icon.png,[Content_Types].xml*.psmdcp_rels/.relsTarget=/Idnaming that psmdcpThat is exactly the bar
ADOPTING.mdsets — the.psmdcpfilename 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…vs9caf8240…). Rebuilding both from cleanobj/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
TreatWarningsAsErrorsis on)CHANGELOG.mdupdated under[Unreleased]Consumer impact
None, demonstrated rather than asserted.
<Version>is untouched and no tag is pushed.🤖 Generated with Claude Code