Add buildvana.json configuration foundation - #277
Conversation
Introduce the shared, host-agnostic Buildvana.Core.Configuration library (System.Text.Json + BCL only): the typed BuildvanaConfig model, a loader that discovers buildvana.json xor buildvana.jsonc in the home directory, and validation that fails via BuildFailedException on malformed input, unknown members, unknown dictionary keys, or both file variants being present. The committed JSON schema (schemas/buildvana.schema.json) is generated from the model via JsonSchemaExporter, reusing [Description] attributes for hover docs; tools/generate-config-schema.cs regenerates and verifies it, enforced in CI. Home-directory discovery now treats buildvana.json/.jsonc as a marker and stops at the nearest directory (the start directory included) containing any marker. The rule is mirrored in HomeDirectoryDiscovery and Sdk.props, with new diagnostic BVSDK1005 when both file variants are present. The configuration is registered as a singleton in the bv tool but stays inert: nothing reads it yet, so there is no behavior change. Phase 1 of Tenacom#267, implementing Tenacom#268. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
@claude please review this PR. |
|
Claude finished @rdeago's task in 6m 5s —— View job PR Review
Overall this is a clean, well-structured implementation. The design decisions are sound — separating model from loader, sharing serialization options between the loader and schema generator so they stay in sync, the CI staleness check. Below are the findings, roughly in priority order. 🟡 Schema/loader divergence on constrained dictionary keysFile: The JSON schema uses This is a DX gap — the two layers disagree. The root cause is that Fixing it requires a post-generation patch in 🟢 Schema permits null where the loader rejects itFile: "type": ["object", "null"]The root type includes // BuildvanaConfigLoader.cs:73
return config ?? throw new BuildFailedException($"{path} was parsed as JSON null.");Minor inconsistency — the schema advertises a superset of what the loader accepts. Since 🟢 Schema allows null items in array propertiesFile: "items": { "type": ["string", "null"] }
🟢 DI registration is lazy — Phase 1 does not actually validate the configFile: .AddSingleton(static sp => BuildvanaConfigLoader.Load(sp.GetRequiredService<IHomeDirectoryProvider>().HomeDirectory))
🟢
|
CountLines split on '\n' and reported Length, but Generate() always emits a trailing newline, so the count was one higher than the actual number of lines. Subtract one to report the true line count. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The BuildvanaConfig singleton uses a factory, so discovery/parse/validation only run when the service is first resolved. No Phase 1 command resolves it, so a malformed buildvana.json stays inert until a Phase 2 consumer reads it. Add a comment making that intent explicit at the registration site. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The schema exporter marked the document root as ["object", "null"], so a buildvana.json containing just `null` validated against the schema even though the loader rejects it. Force the root type to "object" after export so the schema matches what the loader accepts. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Collection element types in the model are non-nullable, but the schema exporter emitted nullable item schemas (["string", "null"]) for release.branches, release.generateDocsFrom, and dotnet.args value lists. Strip null from array item types during schema generation so the schema matches the model, and reject null list items in the loader so the two layers stay in agreement instead of diverging in the opposite direction. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The schema left these dictionaries open-ended (additionalProperties), so an editor validated keys the loader then rejected at runtime. Generate explicit properties for the allowed keys with additionalProperties: false, mirroring the loader's validation. The allowed-key lists now live on DotNetConfig and NuGetConfig as a single source shared by the loader and the schema generator, so the two layers cannot drift apart. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
|
@claude thanks for the review — all five findings addressed, one commit each:
Verified with @claude please review again. |
|
Claude finished @rdeago's task in 2m 31s —— View job PR Re-Review
All five findings have been addressed cleanly. Here's a pass on each fix and a note on one new observation. 🟡 → ✅ Schema/loader dict key divergence (
|
Summary
Phase 1 of #267 (implements #268): the shared configuration foundation. Introduces
Buildvana.Core.Configuration, a host-agnostic Core-tier library (System.Text.Json+ BCL only) holding the full typedBuildvanaConfigmodel and a loader, consumed bybvnow andBuildvana.Sdk.Tasksin a later phase. The configuration is inert: discovered, parsed, validated, and registered in the tool's DI, but nothing reads it yet — no behavior changes.Closes #268.
What's included
BuildvanaConfigshape (release,versioning,dotnet,nuget,github,git), everything optional. Discovery isbuildvana.jsonxorbuildvana.jsoncin the home directory; parse usesSkipcomments, trailing commas, andDisallowunmapped members, with$schemawhitelisted. Dictionary sections get explicit key validation (dotnet.args: all/restore/build/test/pack;nuget.feeds: prerelease/release). Failures surface asBuildFailedException.schemas/buildvana.schema.jsongenerated from the model viaJsonSchemaExporter(reusing[Description]s for hover docs).tools/generate-config-schema.csregenerates (--update) / verifies (--check) it; CI fails on drift..buildvana-home, or a Git marker. Behaviour mirrored betweenHomeDirectoryDiscoveryandSdk.props; newBVSDK1005when both config variants are present.BuildvanaConfigregistered as a singleton (inert).Acceptance criteria
Buildvana.Tool; absent file ⇒ defaults, no behavior change.buildvana.json/.jsoncand still recognizes.buildvana-home/.git*, in both tool and SDK.Notes / decisions
tools/, not a unit-test project (the repo has none yet).nuget.feedskeys areprerelease/releaseonly (privatedropped from the older spec).BVESDK003→BVSDK1003indocs/Diagnostics.md.[UsedImplicitly(…WithMembers)]so ReSharper doesn't flag serializer-onlyinitaccessors.Test plan
dotnet bv packclean (both packages produced).inspectcode --severity=WARNING— 0 results.🤖 Generated with Claude Code