diff --git a/.gitversion.yml b/.gitversion.yml new file mode 100644 index 0000000..a0d761b --- /dev/null +++ b/.gitversion.yml @@ -0,0 +1,23 @@ +mode: ContinuousDelivery +branches: + main: + tag: '' + increment: Patch + prevent-increment-of-merged-branch-version: true + track-merge-target: false + develop: + tag: alpha + increment: Minor + prevent-increment-of-merged-branch-version: false + feature: + tag: beta + increment: Patch + hotfix: + tag: hotfix + increment: Patch + release: + tag: rc + increment: Patch +ignore: + sha: [] +commit-message-incrementing: Disabled diff --git a/GitVersion.yml b/GitVersion.yml index 23ce4fc..05c2cf9 100644 --- a/GitVersion.yml +++ b/GitVersion.yml @@ -4,4 +4,4 @@ branches: {} ignore: sha: [] merge-message-formats: {} -next-version: 3.0 \ No newline at end of file +next-version: "3.2" \ No newline at end of file diff --git a/MaddoShared/IVersionProvider.cs b/MaddoShared/IVersionProvider.cs new file mode 100644 index 0000000..940cae6 --- /dev/null +++ b/MaddoShared/IVersionProvider.cs @@ -0,0 +1,9 @@ +namespace MaddoShared; + +public interface IVersionProvider +{ + /// + /// Returns a human-friendly version string for display (prefer AssemblyInformationalVersion). + /// + string GetVersionString(); +} diff --git a/MaddoShared/VersionProvider.cs b/MaddoShared/VersionProvider.cs new file mode 100644 index 0000000..346714d --- /dev/null +++ b/MaddoShared/VersionProvider.cs @@ -0,0 +1,60 @@ +using System.Diagnostics; +using System.Reflection; +using System.Collections.Generic; + +namespace MaddoShared; + +public sealed class VersionProvider : IVersionProvider +{ + public string GetVersionString() + { + // Prefer the entry assembly; fall back to executing assembly + var asm = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly(); + + // 1) AssemblyInformationalVersion + var infoAttr = asm.GetCustomAttribute(); + if (!string.IsNullOrWhiteSpace(infoAttr?.InformationalVersion)) + { + return infoAttr.InformationalVersion!; + } + + // 2) File product version + try + { + var location = asm.Location; + if (!string.IsNullOrWhiteSpace(location)) + { + var fvi = FileVersionInfo.GetVersionInfo(location); + if (!string.IsNullOrWhiteSpace(fvi.ProductVersion)) + return fvi.ProductVersion!; + } + } + catch + { + // ignore and fall back to assembly version + } + + // 3) AssemblyName.Version formatted (avoid -1 and trailing .0 parts) + var ver = asm.GetName().Version; + if (ver is not null) + { + // Build a list of parts but ignore negative values + var parts = new List { ver.Major, ver.Minor }; + if (ver.Build >= 0) parts.Add(ver.Build); + if (ver.Revision >= 0) parts.Add(ver.Revision); + + // Trim trailing zeros but keep at least major.minor + for (int i = parts.Count - 1; i > 1; i--) + { + if (parts[i] == 0) + parts.RemoveAt(i); + else + break; + } + + return string.Join('.', parts); + } + + return "0.0.0"; + } +} diff --git a/imagecatalog/GitVersion.README.md b/imagecatalog/GitVersion.README.md new file mode 100644 index 0000000..5e3aca3 --- /dev/null +++ b/imagecatalog/GitVersion.README.md @@ -0,0 +1,12 @@ +This project uses GitVersion (via `GitVersion.MsBuild`) to compute semantic version numbers during build. + +How it works: +- The `GitVersion.MsBuild` package runs during `dotnet build` and sets MSBuild properties such as `Version`, `AssemblyVersion`, `FileVersion`, and `InformationalVersion`. +- The repository is configured via `.gitversion.yml` at the repo root. Tags and branch names drive the generated semantic version. + +Usage notes: +- Create annotated tags like `v1.2.3` or `1.2.3` to mark releases. +- In CI, ensure the Git clone includes tags and history (no shallow single-commit clones). +- The UI should read `AssemblyInformationalVersion` for a friendly version string; fall back to `FileVersion` or `AssemblyName.Version` if needed. + +See https://gitversion.net for more configuration options. diff --git a/imagecatalog/ImageCatalog 2.csproj b/imagecatalog/ImageCatalog 2.csproj index e3cdec0..880dc53 100644 --- a/imagecatalog/ImageCatalog 2.csproj +++ b/imagecatalog/ImageCatalog 2.csproj @@ -43,6 +43,7 @@ + all diff --git a/imagecatalog/MainForm.cs b/imagecatalog/MainForm.cs index 43940cb..35f6658 100644 --- a/imagecatalog/MainForm.cs +++ b/imagecatalog/MainForm.cs @@ -32,7 +32,7 @@ public partial class MainForm private readonly PicSettings _picSettings; public MainForm(DataModel model, ImageCreationStuff imageCreationStuff, PicSettings picSettings, - ParametriSetup parametriSetup, ILogger logger) + ParametriSetup parametriSetup, ILogger logger, IVersionProvider versionProvider) { Model = model; _parametriSetup = parametriSetup; @@ -55,8 +55,8 @@ public partial class MainForm btnOpenSourceFolder.Click += BtnOpenSourceFolder_Click; btnOpenDestFolder.Click += BtnOpenDestFolder_Click; - var version = Assembly.GetExecutingAssembly().GetName().Version; - _Label27.Text = $"Version: {version.Major}.{version.Minor}.{version.Build}.{version.Revision}"; + var versionString = versionProvider?.GetVersionString() ?? "0.0.0"; + _Label27.Text = $"Version: {versionString}"; } protected void BindControls() diff --git a/imagecatalog/Program.cs b/imagecatalog/Program.cs index ea8f2aa..6bf6acd 100644 --- a/imagecatalog/Program.cs +++ b/imagecatalog/Program.cs @@ -15,7 +15,7 @@ static class Program { [DllImport("kernel32.dll", SetLastError = true)] private static extern bool AllocConsole(); - + [DllImport("kernel32.dll", SetLastError = true)] static extern IntPtr GetStdHandle(int nStdHandle); @@ -53,7 +53,7 @@ static class Program Console.SetOut(standardOutput); Console.SetError(standardOutput); } - + public static IServiceProvider ServiceProvider { get; private set; } [STAThread] static void Main() @@ -64,7 +64,7 @@ static class Program AllocConsole(); RedirectConsoleOutput(); - + var serviceCollection = new ServiceCollection(); ConfigureServices(serviceCollection); @@ -97,10 +97,13 @@ static class Program "ImageCatalog", "userprefs.xml"); services.AddSingleton(new ParametriSetup(userPrefsPath)); services.AddSingleton(); - + // Register your forms services.AddTransient(); + // Version provider for UI and logging + services.AddSingleton(); + services.AddLogging(configure => { configure.AddCustomFormatter(); @@ -110,40 +113,42 @@ static class Program } } -public static class ConsoleLoggerExtensions -{ - public static ILoggingBuilder AddCustomFormatter( - this ILoggingBuilder builder) => - builder.AddConsole(options => options.FormatterName = nameof(CustomLoggingFormatter)) - .AddConsoleFormatter(); -} -public sealed class CustomLoggingFormatter : ConsoleFormatter, IDisposable -{ - private readonly IDisposable _optionsReloadToken; - private ConsoleFormatterOptions _formatterOptions; - public CustomLoggingFormatter(IOptionsMonitor options) +public static class ConsoleLoggerExtensions +{ + public static ILoggingBuilder AddCustomFormatter( + this ILoggingBuilder builder) => + builder + .AddConsole(options => options.FormatterName = nameof(CustomLoggingFormatter)) + .AddConsoleFormatter() + .AddFilter("LuckyPennySoftware.AutoMapper.License", LogLevel.None); +} +public sealed class CustomLoggingFormatter : ConsoleFormatter, IDisposable +{ + private readonly IDisposable _optionsReloadToken; + private ConsoleFormatterOptions _formatterOptions; + public CustomLoggingFormatter(IOptionsMonitor options) // Case insensitive - : base(nameof(CustomLoggingFormatter)) => - (_optionsReloadToken, _formatterOptions) = - (options.OnChange(ReloadLoggerOptions), options.CurrentValue); - private void ReloadLoggerOptions(ConsoleFormatterOptions options) => - _formatterOptions = options; - - public override void Write( - in LogEntry logEntry, - IExternalScopeProvider scopeProvider, - TextWriter textWriter) - { - string? message = - logEntry.Formatter?.Invoke( - logEntry.State, logEntry.Exception); - - if (message is null) - { - return; - } - - textWriter.WriteLine($"{message}"); - } - public void Dispose() => _optionsReloadToken?.Dispose(); -} \ No newline at end of file + : base(nameof(CustomLoggingFormatter)) => + (_optionsReloadToken, _formatterOptions) = + (options.OnChange(ReloadLoggerOptions), options.CurrentValue); + private void ReloadLoggerOptions(ConsoleFormatterOptions options) => + _formatterOptions = options; + + public override void Write( + in LogEntry logEntry, + IExternalScopeProvider scopeProvider, + TextWriter textWriter) + { + string? message = + logEntry.Formatter?.Invoke( + logEntry.State, logEntry.Exception); + + if (message is null) + { + return; + } + + textWriter.WriteLine($"{message}"); + } + public void Dispose() => _optionsReloadToken?.Dispose(); +} \ No newline at end of file