Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Buildvana.slnx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
<Project Path="src/Buildvana.Core.Json/Buildvana.Core.Json.csproj" />
<Project Path="src/Buildvana.Core.JsonSchema/Buildvana.Core.JsonSchema.csproj" />
<Project Path="src/Buildvana.Core.Process/Buildvana.Core.Process.csproj" />
<Project Path="src/Buildvana.Core.Testing/Buildvana.Core.Testing.csproj" />
<Project Path="src/Buildvana.Core.Versioning/Buildvana.Core.Versioning.csproj" />
<Project Path="src/Buildvana.Sdk.SourceGenerators/Buildvana.Sdk.SourceGenerators.csproj" />
<Project Path="src/Buildvana.Sdk.Tasks/Buildvana.Sdk.Tasks.csproj" />
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- the GitHub token (`github.tokenEnv`, default `GITHUB_TOKEN`): names the environment variable that holds the token used for release operations.
- `buildvana.json` accepts a `git.identity` (`{ name, email }`) section describing the author/committer for automated commits. It is validated and exposed, but not yet wired to release commits.
- The `ThisAssemblyClass` SDK module, removed along with code generation tasks after v1.0.0-alpha.20, has been reintroduced. Setting the `GenerateThisAssemblyClass` property to `true` (default: `false`) in a C# project generates a `ThisAssembly` static class containing constants defined via `ThisAssemblyConstant` items, using the syntax documented in [docs/ConstantsSyntax.md](docs/ConstantsSyntax.md). A set of default constants (assembly version, company, product, etc.) is defined unless the `EnableDefaultThisAssemblyConstants` property is set to `false`; the class name and namespace can be customized via the `ThisAssemblyClassName` and `ThisAssemblyClassNamespace` properties. Unlike its previous incarnation, the feature is implemented as a Roslyn incremental source generator, and supports C# projects only: setting `GenerateThisAssemblyClass` to `true` in a project in any other language raises warning BVSDK2300.
- Buildvana now computes project versions natively, replacing Nerdbank.GitVersioning end-to-end (see the corresponding breaking change below). The single source of truth for the version is a plain-text `VERSION` file at the repository root, holding a `MAJOR.MINOR[-[tag]]` specification; the patch number is the Git height of the version line, i.e. the number of commits since the last change of `MAJOR.MINOR`, computed with the same rules as Nerdbank.GitVersioning (counting from 1 at the bump commit, longest path across merges; prerelease-only edits to `VERSION` do not reset the height). Versioning policy lives in `buildvana.json`:
- `release.branches`: regular expressions (matched against the short branch name) identifying branches that produce public releases. On other branches, and in detached-HEAD state, the build is a non-public release, and the informational version carries a short commit ID (`1.2.3-preview.g0123456789` on prereleases, `1.2.3-g0123456789` on stable versions);
- `versioning.prereleaseTag`: the effective prerelease tag (e.g. `preview`), required when `VERSION` marks a prerelease line (the tag text in `VERSION` itself is informational only);
- `versioning.assemblyVersionPrecision` (`major` | `minor` | `build`, default `major`): how much of the computed version goes into `AssemblyVersion`.

With a `VERSION` file present, every project built with Buildvana SDK gets `$(Version)`, `$(PackageVersion)`, `$(AssemblyVersion)` (precision-controlled), `$(FileVersion)` (`MAJOR.MINOR.HEIGHT.0`), and `$(InformationalVersion)` computed at build time by a compiled task using LibGit2Sharp — no `git` executable and no external package required — under plain `dotnet build` as well as `MSBuild.exe` and `bv`. The `UseVersioning` property overrides the automatic module activation in both directions. `bv release` now computes versions the same way, in-process.
- Versioned C# projects get the generated `ThisAssembly` class by default: when the `Versioning` module is active, `GenerateThisAssemblyClass` defaults to `true`, and the module contributes versioning constants alongside the default assembly-attribute constants: `SimpleVersion`, `SemVer`, `IsPublicRelease`, `IsPrerelease`, and `GitCommitId`. Compared with Nerdbank.GitVersioning's `ThisAssembly`, the `GitCommitDate`/`GitCommitAuthorDate` and `PublicKey`/`PublicKeyToken` constants are not provided, while `AssemblyDescription`, `SimpleVersion`, and `SemVer` are new.

### Changes to existing features

Expand Down Expand Up @@ -69,6 +76,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- **BREAKING CHANGE**: The `--main-branch` global option has been removed, along with `bv`'s main-branch discovery. Documentation generation on release is now gated by `release.generateDocsFrom` in `buildvana.json`: a list of regular expressions matched against the current short branch name (default `["^main$", "^master$"]`, reproducing the previous main/master discovery). The human-curated changelog permalink in generated release notes now points at the release branch itself rather than the discovered main branch.
- **BREAKING CHANGE**: The `--unstable-changelog` and `--require-changelog` options of `bv release` have been removed with no CLI replacement; changelog policy is repository-stable, not per-invocation. Configure it in `buildvana.json` instead: `release.changelogUpdates` (`none` | `stable` | `all`, default `stable`) selects which releases update the changelog, and `release.emptyChangelog` provides substitute text for an empty "Unreleased changes" section (when unset, an empty section fails the release, matching the previous `--require-changelog` default of `true`).
- `bv`'s build commands (`clean`, `restore`, `build`, `test`, `pack`) and `release` now observe cancellation. Pressing Ctrl-C (or a host cancelling the operation) stops the pipeline promptly: it stops launching further steps and terminates the running `dotnet` child process instead of waiting for it to finish, then `bv` exits with code 130. Partial build output may be left behind on cancellation; `bv clean` recovers.
- **BREAKING CHANGE**: Nerdbank.GitVersioning has been removed from Buildvana SDK and `bv`. Versions are now computed natively from a `VERSION` file and `buildvana.json` keys (see _New features_ above): the `NerdbankGitVersioning` SDK module is gone, the `Nerdbank.GitVersioning` package is no longer injected into projects, `version.json` is no longer read, and `bv` no longer invokes the `nbgv` CLI. The `GetBuildVersion` target name is retained (as a real target or a stub) for targets that depend on it. To migrate a repository:
- create a `VERSION` file at the repository root holding the `version` value from `version.json` (e.g. `2.0-preview`); Git heights remain comparable across the migration, so the computed version does not regress within a `MAJOR.MINOR` line;
- move `publicReleaseRefSpec` to `release.branches` in `buildvana.json`, converting refspec patterns to short branch-name regular expressions (e.g. `^refs/heads/main$` → `^main$`);
- move `release.firstUnstableTag` to `versioning.prereleaseTag`, and `assemblyVersion.precision` to `versioning.assemblyVersionPrecision`;
- delete `version.json` and remove `nbgv` from your tool manifest, if present.
- **BREAKING CHANGE**: The `UseNerdbankGitVersioning` property has been renamed to `UseVersioning`. The old name still works as an alias (when `UseVersioning` itself is not set), but raises warning BVSDK2001 and will be removed in a future version.
- **BREAKING CHANGE**: `version.json` features without a native equivalent are dropped: `pathFilters` is not supported (the version height is always computed from the whole history of the version line), nested `version.json` files are not supported (`VERSION` lives at the repository root only), and the NuGet package version scheme is fixed at SemVer 2.0.

### Bugs fixed in this release

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ However, Buildvana SDK has already been used successfully in production, for bot
### Benefits

- Helps you keep your project files clean and concise - even better than "plain" MSBuild SDKs
- Single source of truth for assembly versions (via [`Nerdbank.GitVersioning`(https://github.com/dotnet/Nerdbank.GitVersioning)])
- Single source of truth for assembly versions (a plain-text `VERSION` file, with the patch number computed from Git height)
- Single source of truth for package licenses and copyright notices
- More auto-generated assembly information (`ClsCompliant`, `COMVisible`)
- Automatic configuration of commonly-used code analyzers
Expand Down
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
2.0-preview
9 changes: 9 additions & 0 deletions buildvana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"release": {
"branches": ["^main$", "^v\\d+\\.\\d+$"]
},
"versioning": {
"prereleaseTag": "preview",
"assemblyVersionPrecision": "major"
}
}
10 changes: 9 additions & 1 deletion docs/DirectoryStructure.md
Original file line number Diff line number Diff line change
Expand Up @@ -268,4 +268,12 @@ TODO

## `VERSION`

TODO
The single source of truth for the version of your product: a plain-text file, in the home directory, holding a single `MAJOR.MINOR[-[tag]]` version specification, for example:

```text
2.0-preview
```

The presence of `-` after the minor version marks a prerelease line; the tag text after it is optional and informational (the effective prerelease tag comes from the `versioning.prereleaseTag` key of `buildvana.json`). The patch number is not stored in the file: it is the Git height of the version line, i.e. the number of commits since the last change of `MAJOR.MINOR`.

When a `VERSION` file is present, the Buildvana SDK computes `Version`, `AssemblyVersion`, `FileVersion`, and `InformationalVersion` for all projects in the repository; `bv` uses the same computation for releases and rewrites the file when advancing the version.
11 changes: 6 additions & 5 deletions docs/SdkDiagnostics.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
- [StandardAnalyzers module (1700-1799)](#standardanalyzers-module-1700-1799)
- [XmlDocumentation module (1800-1899)](#xmldocumentation-module-1800-1899)
- [AlternatePack module (1900-1999)](#alternatepack-module-1900-1999)
- [NerdbankGitVersioning module (2000-2099)](#nerdbankgitversioning-module-2000-2099)
- [Versioning module (2000-2099)](#versioning-module-2000-2099)
- [ReleaseAssetList module (2100-2199)](#releaseassetlist-module-2100-2199)
- [Wine module (2200-2299)](#wine-module-2200-2299)
- [ThisAssemblyClass module (2300-2399)](#thisassemblyclass-module-2300-2399)
Expand Down Expand Up @@ -109,11 +109,12 @@ This module has no associated diagnostics.
| BVSDK1901 | Error | InnoSetup script '...' referenced by '...' does not exist. | An `InnoSetup` item's `Script` metadata refers to a non-existing file. |
| BVSDK1902 | Error | InnoSetup item '...' refers to non-existent PublishFolder '...'. | An `InnoSetup` item has a `SourcePublishFolder` metadata, but no `PublishFolder` item exists with the specified name. |

## NerdbankGitVersioning module (2000-2099)
## Versioning module (2000-2099)

| Code | Severity | Message | Description |
| --------- | :------: | ------------------------------------------ | -------------------------------------------------------------------------------------------------- |
| BVSDK2000 | Error | Version specification JSON file not found. | A `version.json` or `.version.json` file for the project was not found within the repository root. |
| Code | Severity | Message | Description |
| --------- | :------: | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
| BVSDK2000 | Error | Version file (VERSION) not found in home directory. | The `UseVersioning` property was explicitly set to `true`, but no `VERSION` file was found in the home directory. |
| BVSDK2001 | Warning | The UseNerdbankGitVersioning property is deprecated; use UseVersioning instead. | The project sets the `UseNerdbankGitVersioning` property, which is a deprecated alias for `UseVersioning` kept for compatibility with older projects. |

## ReleaseAssetList module (2100-2199)

Expand Down
3 changes: 3 additions & 0 deletions src/Buildvana.Core.JsonSchema/JsonSourceMap.Frame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@

namespace Buildvana.Core.JsonSchema;

// ReSharper disable once ClassCannotBeInstantiated -- false positive: ReSharper analyzes this partial part
// in isolation, missing the instantiation in JsonSourceMap.cs (the class has a private constructor and is
// created by its static Build method).
partial class JsonSourceMap
{
// Tracks one open container while walking the document, so a value's pointer can be built from its parent.
Expand Down
17 changes: 17 additions & 0 deletions src/Buildvana.Core.Testing/Buildvana.Core.Testing.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<Title>Buildvana testing helpers</Title>
<Description>Shared test harnesses for Buildvana test projects, e.g. temporary Git repositories and home directories.</Description>
<TargetFramework>$(StandardTfm)</TargetFramework>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Buildvana.Core.HomeDirectory\Buildvana.Core.HomeDirectory.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="LibGit2Sharp" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -1,55 +1,101 @@
// Copyright (C) Tenacom and Contributors. Licensed under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using System.IO;
using System.Text;
using LibGit2Sharp;

internal sealed class TempGitRepo : IDisposable
namespace Buildvana.Core.Testing;

/// <summary>
/// A disposable real Git repository in a temporary directory, for tests exercising Git-dependent code.
/// </summary>
public sealed class TempGitRepo : IDisposable
{
private static readonly UTF8Encoding Utf8NoBom = new(encoderShouldEmitUTF8Identifier: false);

private readonly Repository _repository;

/// <summary>
/// Initializes a new instance of the <see cref="TempGitRepo"/> class, creating and initializing
/// a Git repository in a newly-created temporary directory.
/// </summary>
public TempGitRepo()
{
RootPath = Directory.CreateTempSubdirectory("bv-test-repo-").FullName;
_ = Repository.Init(RootPath);
_repository = new Repository(RootPath);
}

/// <summary>
/// Gets the full path of the repository's root directory.
/// </summary>
public string RootPath { get; }

/// <summary>
/// Gets the friendly name of the current branch.
/// </summary>
public string CurrentBranchName => _repository.Head.FriendlyName;

/// <summary>
/// Gets the SHA of the current <c>HEAD</c> commit.
/// </summary>
public string HeadSha => _repository.Head.Tip.Sha;

/// <summary>
/// Writes a file in the repository's root directory.
/// </summary>
/// <param name="name">The name of the file, relative to the root directory.</param>
/// <param name="content">The content of the file.</param>
/// <param name="encoding">The file encoding; UTF-8 without BOM if unspecified.</param>
public void WriteFile(string name, string content, Encoding? encoding = null)
=> File.WriteAllText(Path.Combine(RootPath, name), content, encoding ?? Utf8NoBom);

/// <summary>
/// Stages all changes and creates a commit, which may be empty.
/// </summary>
/// <param name="message">The commit message.</param>
public void CommitAll(string message = "Test commit")
{
Commands.Stage(_repository, "*");
var signature = new Signature("Test", "test@example.com", DateTimeOffset.Now);
_ = _repository.Commit(message, signature, signature, new CommitOptions { AllowEmptyCommit = true });
}

/// <summary>
/// Creates a new branch at the current <c>HEAD</c> commit and checks it out.
/// </summary>
/// <param name="name">The name of the new branch.</param>
public void CheckoutNewBranch(string name)
{
var branch = _repository.CreateBranch(name);
_ = Commands.Checkout(_repository, branch);
}

/// <summary>
/// Checks out an existing branch.
/// </summary>
/// <param name="name">The name of the branch.</param>
public void Checkout(string name) => _ = Commands.Checkout(_repository, _repository.Branches[name]);

/// <summary>
/// Checks out the current <c>HEAD</c> commit directly, detaching <c>HEAD</c> from any branch.
/// </summary>
public void CheckoutDetached() => _ = Commands.Checkout(_repository, _repository.Head.Tip);

/// <summary>
/// Merges a branch into the current branch, always creating a merge commit.
/// </summary>
/// <param name="branchName">The name of the branch to merge.</param>
public void Merge(string branchName)
{
var signature = new Signature("Test", "test@example.com", DateTimeOffset.Now);
var options = new MergeOptions { FastForwardStrategy = FastForwardStrategy.NoFastForward };
_ = _repository.Merge(_repository.Branches[branchName], signature, options);
}

/// <inheritdoc/>
public void Dispose()
{
_repository.Dispose();
Expand Down
44 changes: 44 additions & 0 deletions src/Buildvana.Core.Testing/TempHome.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (C) Tenacom and Contributors. Licensed under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using System.IO;
using Buildvana.Core.HomeDirectory;

namespace Buildvana.Core.Testing;

/// <summary>
/// A disposable temporary home directory (with no Git repository), for tests exercising file-based code
/// that resolves paths against a home directory.
/// </summary>
public sealed class TempHome : IDisposable
{
private readonly DirectoryInfo _directory = Directory.CreateTempSubdirectory("bv-test-home-");

/// <summary>
/// Gets the full path of the home directory.
/// </summary>
public string RootPath => _directory.FullName;

/// <summary>
/// Gets a home directory provider resolving to <see cref="RootPath"/>.
/// </summary>
public FixedHomeDirectoryProvider Provider => new(RootPath);

/// <summary>
/// Writes a file in the home directory.
/// </summary>
/// <param name="name">The name of the file, relative to the home directory.</param>
/// <param name="content">The content of the file.</param>
public void WriteFile(string name, string content) => File.WriteAllText(Path.Combine(RootPath, name), content);

/// <summary>
/// Reads a file in the home directory.
/// </summary>
/// <param name="name">The name of the file, relative to the home directory.</param>
/// <returns>The content of the file.</returns>
public string ReadFile(string name) => File.ReadAllText(Path.Combine(RootPath, name));

/// <inheritdoc/>
public void Dispose() => _directory.Delete(recursive: true);
}
Loading