What happened?
.github/scripts/inspect-packed-nupkgs.sh validates each publishable package's packed .nuspec third-party dependency range against a hardcoded expected-string literal, via assert_dependency_range() (line 123). The check is a plain string equality between the packed <dependency version="..."> and a literal passed at the call site — it has no mechanism to derive or cross-check that literal from Directory.Packages.props, the actual source of truth for the version range that ends up in the packed nuspec.
Five packages currently carry this pattern, each with its own independent hardcoded literal:
xunit.v3.extensibility.core → Compono.XunitV3 (line 176)
NSubstitute → Compono.NSubstitute (line 181)
Bogus → Compono.Bogus (line 186)
TUnit.Core → Compono.TUnit (line 191)
MSTest.TestFramework → Compono.MSTest (line 214)
Whenever Dependabot (the dotnet-minor-patch group) bumps one of these packages' PackageVersion in Directory.Packages.props, the packed nuspec's dependency range legitimately changes to match — but the corresponding literal in inspect-packed-nupkgs.sh doesn't move with it, since Dependabot has no awareness of that separate, hand-maintained string. The next package-validation CI run then fails on a correctly-packed package, because the validator is stale, not the package.
This isn't specific to any one package — it's a structural property of all five call sites, since they all follow the identical hardcoded-literal pattern with no synchronization to Directory.Packages.props.
Concrete occurrence
Dependabot PR #121 bumped TUnit.Core/TUnit in Directory.Packages.props from [1.65.38, 2.0.0) to [1.65.63, 2.0.0) and merged to main. PR #120's package-validation job then failed because inspect-packed-nupkgs.sh still asserted the old [1.65.38, 2.0.0) literal against Compono.TUnit's packed nuspec. Reproduced directly against a clean origin/main worktree (no PR #120 changes involved) — confirming main itself independently failed the same assertion, i.e. the packed output was correct and the validator was stale. Fixed for this one occurrence in commit 5cfe446 (a one-line literal update), but that only addresses this single instance — the four other call sites remain equally exposed to the same drift the next time Dependabot touches any of those ranges.
Searched repo history (git log, PR history) for earlier instances of this same drift pattern — found none prior to this occurrence, so this is the first time it's surfaced, not a repeat failure. It is nonetheless a recurring class of failure by construction: any future Dependabot bump to any of the five tracked dependencies will reproduce it identically.
Desired outcome
package-validation should stay green on a correctly-packed package without requiring someone to manually notice and hand-edit a separate literal every time Dependabot moves one of these five ranges. How to achieve that (e.g. some form of synchronization between Directory.Packages.props and the validator) is an implementation question for whoever picks this up — not prescribed here. Any fix should preserve the existing intent of assert_dependency_range() (a deliberate, reviewed, tested range per ADR-0031 Amendment 1 — not a bare unbounded floor, not a blanket exact pin) rather than weakening the check or removing it.
Steps to reproduce
- On
main, pick any of the five tracked dependencies (e.g. NSubstitute in Directory.Packages.props).
- Bump its
PackageVersion range (simulating a Dependabot update), e.g. [6.2.0, 7.0.0) → [6.3.0, 7.0.0).
dotnet pack src/Compono.NSubstitute/Compono.NSubstitute.csproj -c Release -o /tmp/pack-out
bash .github/scripts/inspect-packed-nupkgs.sh /tmp/pack-out
- Observe
FAIL: Compono.NSubstitute's .nuspec dependency on NSubstitute is '[6.3.0, 7.0.0)', expected the intended tested range '[6.2.0, 7.0.0)' — the packed nuspec is correct; the validator's hardcoded literal is what's wrong.
Environment
Repo tooling / CI (package-validation GitHub Actions workflow, .github/scripts/inspect-packed-nupkgs.sh). Not a runtime/consumer-facing issue.
What happened?
.github/scripts/inspect-packed-nupkgs.shvalidates each publishable package's packed.nuspecthird-party dependency range against a hardcoded expected-string literal, viaassert_dependency_range()(line 123). The check is a plain string equality between the packed<dependency version="...">and a literal passed at the call site — it has no mechanism to derive or cross-check that literal fromDirectory.Packages.props, the actual source of truth for the version range that ends up in the packed nuspec.Five packages currently carry this pattern, each with its own independent hardcoded literal:
xunit.v3.extensibility.core→Compono.XunitV3(line 176)NSubstitute→Compono.NSubstitute(line 181)Bogus→Compono.Bogus(line 186)TUnit.Core→Compono.TUnit(line 191)MSTest.TestFramework→Compono.MSTest(line 214)Whenever Dependabot (the
dotnet-minor-patchgroup) bumps one of these packages'PackageVersioninDirectory.Packages.props, the packed nuspec's dependency range legitimately changes to match — but the corresponding literal ininspect-packed-nupkgs.shdoesn't move with it, since Dependabot has no awareness of that separate, hand-maintained string. The nextpackage-validationCI run then fails on a correctly-packed package, because the validator is stale, not the package.This isn't specific to any one package — it's a structural property of all five call sites, since they all follow the identical hardcoded-literal pattern with no synchronization to
Directory.Packages.props.Concrete occurrence
Dependabot PR #121 bumped
TUnit.Core/TUnitinDirectory.Packages.propsfrom[1.65.38, 2.0.0)to[1.65.63, 2.0.0)and merged tomain. PR #120'spackage-validationjob then failed becauseinspect-packed-nupkgs.shstill asserted the old[1.65.38, 2.0.0)literal againstCompono.TUnit's packed nuspec. Reproduced directly against a cleanorigin/mainworktree (no PR #120 changes involved) — confirmingmainitself independently failed the same assertion, i.e. the packed output was correct and the validator was stale. Fixed for this one occurrence in commit5cfe446(a one-line literal update), but that only addresses this single instance — the four other call sites remain equally exposed to the same drift the next time Dependabot touches any of those ranges.Searched repo history (
git log, PR history) for earlier instances of this same drift pattern — found none prior to this occurrence, so this is the first time it's surfaced, not a repeat failure. It is nonetheless a recurring class of failure by construction: any future Dependabot bump to any of the five tracked dependencies will reproduce it identically.Desired outcome
package-validationshould stay green on a correctly-packed package without requiring someone to manually notice and hand-edit a separate literal every time Dependabot moves one of these five ranges. How to achieve that (e.g. some form of synchronization betweenDirectory.Packages.propsand the validator) is an implementation question for whoever picks this up — not prescribed here. Any fix should preserve the existing intent ofassert_dependency_range()(a deliberate, reviewed, tested range per ADR-0031 Amendment 1 — not a bare unbounded floor, not a blanket exact pin) rather than weakening the check or removing it.Steps to reproduce
main, pick any of the five tracked dependencies (e.g.NSubstituteinDirectory.Packages.props).PackageVersionrange (simulating a Dependabot update), e.g.[6.2.0, 7.0.0)→[6.3.0, 7.0.0).dotnet pack src/Compono.NSubstitute/Compono.NSubstitute.csproj -c Release -o /tmp/pack-outbash .github/scripts/inspect-packed-nupkgs.sh /tmp/pack-outFAIL: Compono.NSubstitute's .nuspec dependency on NSubstitute is '[6.3.0, 7.0.0)', expected the intended tested range '[6.2.0, 7.0.0)'— the packed nuspec is correct; the validator's hardcoded literal is what's wrong.Environment
Repo tooling / CI (
package-validationGitHub Actions workflow,.github/scripts/inspect-packed-nupkgs.sh). Not a runtime/consumer-facing issue.