Reference version
2.1.41-preview
Background and motivation
bv, Buildvana.Sdk, and Buildvana.Runtime are released in lockstep and designed as a matched group. The SDK forces the referenced version of Buildvana.Runtime for hooks, but nothing checks that the repo's pinned SDK version (global.json, msbuild-sdks) matches the running bv. A mismatch — a half-updated repo, a globally installed newer tool against an older pin — currently produces silent behavior drift instead of a clear message.
A typical situation where this can bite is a hook trying to load a Buildvana configuration, just validated by bv version X upon startup, using the loader from Buildvana.Runtime version Y, where X and Y have incompatible configuration shapes.
Proposed enhancement
bv subcommands declare, via a usesSdk boolean parameter in ImplementsCommandAttribute (default: false), whether they use the SDK. "Using the SDK" means, of course, invoking a dotnet, msbuild, or nuget command, or anything that executes any MSBuild target on any project in the solution. As a general rule, build pipeline commands (with the possible exception of clean) and release have usesSdk = true.
- Before invoking a subcommand that has
usesSdk = true, bv reads the Buildvana.Sdk entry from global.json msbuild-sdks and compares it to its own version. A missing entry counts as a mismatch.
- On mismatch,
bv fails with a message naming both versions and the fix for each direction (dotnet tool update vs. editing the pin).
- A new
sync-sdk subcommand (name provisional) rewrites the pin to bv's own version if the latter is more recent (a missing entry counts as less recent than any version); if the inverse is true (bv version predates the SDK version), the tools.bv.version property is rewritten in .config/dotnet-tools.json if present and if equal to the currently running bv version (a dnx bv invocation should not touch dotnet-tools.json). If the two versions are equal, the command modifies neither. If global.json is missing entirely, it is created with only an msbuild-sdks section.
Acceptance criteria:
- Check runs before every subcommand that uses Buildvana SDK.
- Clear failure message naming both versions and mentioning the
bv sync-sdk command.
- Tests for match, mismatch (both directions), and missing-pin handling.
- Changelog entry under
## Unreleased changes.
Non-goals
Edge cases triggered by the user by pinning versions in the wrong places (e.g., a version-suffixed Sdk attribute in a project file, or a pinned Buildvana.Sdk in either Directory.Build.props or Directory.Build.targets) are not a concern. Developers usually know what they are doing; when they don't, let them have a learning experience.
Implementation proposals
- A
SelfVersionService (name provisional) doing checks and JSON edits via the existing JSON helpers (for global.json) or dotnet tool (for .config/dotnet-tools.json).
- Versions are compared according to SemVer, i.e., preview < stable. A missing pin counts as less recent than any version. SemVer metadata don't participate in comparisons and are never written to pins.
- A global
--skip-sdk-check option disables the check, for scenarios that require a deliberate mismatch (e.g., bisecting an SDK regression in CI).
Risks
None in sight.
🤖 Edited with Claude Code
Reference version
2.1.41-preview
Background and motivation
bv,Buildvana.Sdk, andBuildvana.Runtimeare released in lockstep and designed as a matched group. The SDK forces the referenced version ofBuildvana.Runtimefor hooks, but nothing checks that the repo's pinned SDK version (global.json,msbuild-sdks) matches the runningbv. A mismatch — a half-updated repo, a globally installed newer tool against an older pin — currently produces silent behavior drift instead of a clear message.A typical situation where this can bite is a hook trying to load a Buildvana configuration, just validated by
bvversion X upon startup, using the loader fromBuildvana.Runtimeversion Y, where X and Y have incompatible configuration shapes.Proposed enhancement
bvsubcommands declare, via ausesSdkboolean parameter inImplementsCommandAttribute(default:false), whether they use the SDK. "Using the SDK" means, of course, invoking adotnet,msbuild, ornugetcommand, or anything that executes any MSBuild target on any project in the solution. As a general rule, build pipeline commands (with the possible exception ofclean) andreleasehaveusesSdk = true.usesSdk = true,bvreads theBuildvana.Sdkentry fromglobal.jsonmsbuild-sdksand compares it to its own version. A missing entry counts as a mismatch.bvfails with a message naming both versions and the fix for each direction (dotnet tool updatevs. editing the pin).sync-sdksubcommand (name provisional) rewrites the pin tobv's own version if the latter is more recent (a missing entry counts as less recent than any version); if the inverse is true (bvversion predates the SDK version), thetools.bv.versionproperty is rewritten in.config/dotnet-tools.jsonif present and if equal to the currently runningbvversion (adnx bvinvocation should not touchdotnet-tools.json). If the two versions are equal, the command modifies neither. Ifglobal.jsonis missing entirely, it is created with only anmsbuild-sdkssection.Acceptance criteria:
bv sync-sdkcommand.## Unreleased changes.Non-goals
Edge cases triggered by the user by pinning versions in the wrong places (e.g., a version-suffixed
Sdkattribute in a project file, or a pinnedBuildvana.Sdkin eitherDirectory.Build.propsorDirectory.Build.targets) are not a concern. Developers usually know what they are doing; when they don't, let them have a learning experience.Implementation proposals
SelfVersionService(name provisional) doing checks and JSON edits via the existing JSON helpers (forglobal.json) ordotnet tool(for.config/dotnet-tools.json).--skip-sdk-checkoption disables the check, for scenarios that require a deliberate mismatch (e.g., bisecting an SDK regression in CI).Risks
None in sight.
🤖 Edited with Claude Code