Skip to content

Versioning Phase 4 — create the Buildvana.Core.Versioning library #293

@rdeago

Description

@rdeago

Sub-issue of #267. Depends on Phase 1 (#268, config foundation). Lands before Phases 5–7; no live code is wired to it yet.

Scope

  • New src/Buildvana.Core.Versioning/ (replacing the empty leftover directory), targeting $(StandardTfm). Dependencies: Buildvana.Core.Abstractions, Buildvana.Core.Configuration, NuGet.Versioning, LibGit2Sharp. NuGet.Versioning and LibGit2Sharp stay internal — never surfaced in a public signature.
  • Definitions → Buildvana.Core.Abstractions (namespace Buildvana.Core.Versioning): VersionSpec(int Major, int Minor, bool Prerelease); the VersionSpecChange enum; any other simple enums. BCL-only. No Buildvana.Core.Versioning.Abstractions project — a single height impl plus a string-typed service surface means nothing trips a promotion trigger.
  • Machinery → Buildvana.Core.Versioning:
    • VersionSpec.Parse(string) as a static extension member (C# 14 extension block). Format MAJOR.MINOR[-[tag]] — no v prefix, tag optional, a bare - allowed without a tag; the presence of - after the minor sets Prerelease = true. Proposed regex (semver grammar minus patch/metadata, single loosened tag): ^(?<Major>0|[1-9][0-9]*)\.(?<Minor>0|[1-9][0-9]*)((?<Prerelease>\-)[0-9a-zA-Z]*)?(\s|$). ToString() emits M.m or M.m-prerelease, used only to round-trip the VERSION file.
    • Single LibGit2Sharp git-height calculator; version-file name is a constructor parameter. Height = commits from HEAD back to (and excluding) the last commit that modified the version file. Detached HEAD / empty branch handled per the non-public-release convention.
  • Main part → Buildvana.Core.Versioning (may depend on Buildvana.Core.Configuration):
    • VersioningSettings, mirroring DotNetSettings; surfaces release.branches, release.prereleaseTag, versioning.assemblyVersionPrecision.
    • VersioningService: constructor-injected dependencies (no DI container), uses IReporter, throws BuildFailedException. Reads the VERSION file (fail loudly if absent), computes the current version, and exposes it in the needed string forms (full semver, simple M.m.p, assembly version honoring precision, informational). IsPublicRelease = short branch name matches any release.branches regex (explicit ^…$ anchors, compiled, match timeout); IsPrerelease. Enforce: version is prerelease but release.prereleaseTag absent ⇒ fail.
  • The version value lives in a VERSION file (no extension) holding MAJOR.MINOR[-[tag]]; the file's tag text is informational (only the presence of - is read) — the effective prerelease tag comes from release.prereleaseTag.
  • Config keys: release.branches and release.prereleaseTag already exist; consider relocating them from ReleaseConfig to a VersioningConfig section if that better fits the new structure (config is unreleased, so no migration concern). Ensure versioning.assemblyVersionPrecision exists, adding it (model + generated schema) if not yet present.
  • Nothing else is touched: Buildvana.Tool keeps its own versioning types and nbgv; no wiring; no behavior change.

Acceptance criteria

  • Buildvana.Core.Versioning and the new Buildvana.Core.Abstractions types build cleanly; no Buildvana.Core.Versioning.Abstractions project exists; NuGet.Versioning/LibGit2Sharp appear in no public signature.
  • Unit tests (TUnit) pass in CI: VERSION parsing (1.0, 1.0-preview, 1.0-, malformed); branch-regex matching (match, no match, empty list, detached-HEAD/empty branch); assembly-version precision (major|minor|build|revision); height monotonicity and reset across a VERSION change on a temporary LibGit2Sharp repo; the version string formats.
  • bv behavior is unchanged (NBGV still in use; the tool is not yet wired to the library).
  • CHANGELOG: internal-only; no public entry (the library is not packaged standalone and not yet consumed).

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancement[issue/PR] requests / implements new or improved functionality.refactor[issue/PR] requests / implements a refactor of existing code without affecting functionality.
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions