From 129bc52661448de97d04425b71cb28889ee05f97 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:01:02 +0200 Subject: [PATCH 01/23] add debugging to release-it in CI --- .github/workflows/create-release.yml | 4 ++++ .../DotNetConsoleLogger.cs | 19 +++++++++++-------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 3a283d7..996d68e 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -52,6 +52,9 @@ jobs: - name: install release-it with plugins run: npm install -g release-it @release-it/keep-a-changelog + - name: Check Node.js version + run: node --version + - name: run release-it run: | params=() @@ -76,3 +79,4 @@ jobs: release-it "${params[@]}" env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} + DEBUG: release-it:* diff --git a/Neolution.DotNet.Console/DotNetConsoleLogger.cs b/Neolution.DotNet.Console/DotNetConsoleLogger.cs index 5692252..852d097 100644 --- a/Neolution.DotNet.Console/DotNetConsoleLogger.cs +++ b/Neolution.DotNet.Console/DotNetConsoleLogger.cs @@ -49,15 +49,18 @@ public static void Initialize(IConfiguration configuration) // Create a simple NLog configuration that logs to the console var config = new NLog.Config.LoggingConfiguration(); consoleTarget = new ConsoleTarget("console"); - config.AddRule(LogLevel.Trace, LogLevel.Fatal, consoleTarget); - LogManager.Configuration = config; - logger = LogManager.GetCurrentClassLogger(); - logger.Error(ex, "Logger initialization failed"); - } - finally - { - consoleTarget?.Dispose(); + try + { + config.AddRule(LogLevel.Trace, LogLevel.Fatal, consoleTarget); + LogManager.Configuration = config; + logger = LogManager.GetCurrentClassLogger(); + logger.Error(ex, "Logger initialization failed"); + } + finally + { + consoleTarget.Dispose(); + } } } From 2eae61b2b07ff1739d1479f653de14a0498bf8de Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:08:22 +0200 Subject: [PATCH 02/23] debug --- .github/workflows/create-release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 996d68e..e5f7b2c 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -74,9 +74,10 @@ jobs: fi params+=(--ci) + params+=(--verbose) echo "command: release-it ${params[@]}" release-it "${params[@]}" env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - DEBUG: release-it:* + DEBUG: "*" From 7c07402b542e9c975fb013db437b4ffbb0d82668 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:14:57 +0200 Subject: [PATCH 03/23] debug --- .github/workflows/create-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index e5f7b2c..036cf3b 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -50,7 +50,7 @@ jobs: git config user.email release-bot@neolution.ch - name: install release-it with plugins - run: npm install -g release-it @release-it/keep-a-changelog + run: npm install -g release-it@18.7.0 @release-it/keep-a-changelog@6.0.0 - name: Check Node.js version run: node --version From 643e03b788d2162e6c3f400940c6fe87588b6dc8 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:17:52 +0200 Subject: [PATCH 04/23] debug --- .github/workflows/create-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 036cf3b..fd0190d 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -50,7 +50,7 @@ jobs: git config user.email release-bot@neolution.ch - name: install release-it with plugins - run: npm install -g release-it@18.7.0 @release-it/keep-a-changelog@6.0.0 + run: npm install -g release-it@18.1.2 @release-it/keep-a-changelog@6.0.0 - name: Check Node.js version run: node --version From 3fd44464110290df2d27d85167035845bd7e8c8a Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:22:20 +0200 Subject: [PATCH 05/23] debug --- .github/workflows/create-release.yml | 4 +--- .release-it.json | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index fd0190d..0c5050f 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -50,7 +50,7 @@ jobs: git config user.email release-bot@neolution.ch - name: install release-it with plugins - run: npm install -g release-it@18.1.2 @release-it/keep-a-changelog@6.0.0 + run: npm install -g release-it@17.6.0 @release-it/keep-a-changelog@5.0.0 - name: Check Node.js version run: node --version @@ -65,8 +65,6 @@ jobs: if [[ ${{ github.event.inputs.versioning_phase }} != "stable" ]]; then params+=(--preRelease=${{ github.event.inputs.versioning_phase }}) - params+=(--plugins.@release-it/keep-a-changelog.keepUnreleased) - params+=(--no-plugins.@release-it/keep-a-changelog.strictLatest) fi if [[ ${{ github.event.inputs.is_dry_run }} == "true" ]]; then diff --git a/.release-it.json b/.release-it.json index 3f22ba4..d456224 100644 --- a/.release-it.json +++ b/.release-it.json @@ -14,7 +14,8 @@ "filename": "CHANGELOG.md", "addVersionUrl": true, "addUnreleased": true, - "strictLatest": false + "strictLatest": false, + "keepUnreleased": false } }, "hooks": { From b074519a2f24dc16ab13fd25a0c52764efd3179e Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:28:33 +0200 Subject: [PATCH 06/23] debug --- .github/workflows/create-release.yml | 41 +++++++++++++++++++++++++++- .release-it.json | 3 +- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 0c5050f..298f884 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -53,10 +53,36 @@ jobs: run: npm install -g release-it@17.6.0 @release-it/keep-a-changelog@5.0.0 - name: Check Node.js version - run: node --version + run: | + node --version + npm --version + echo "=== PACKAGE.JSON DEBUG ===" + if [ -f package.json ]; then + echo "package.json exists:" + cat package.json + else + echo "No package.json found" + fi + echo "=== RELEASE-IT CONFIG DEBUG ===" + if [ -f .release-it.json ]; then + echo ".release-it.json contents:" + cat .release-it.json + else + echo "No .release-it.json found" + fi + echo "================================" - name: run release-it run: | + echo "=== WORKFLOW INPUTS DEBUG ===" + echo "bump_version_number: '${{ github.event.inputs.bump_version_number }}'" + echo "versioning_phase: '${{ github.event.inputs.versioning_phase }}'" + echo "is_dry_run: '${{ github.event.inputs.is_dry_run }}'" + echo "GITHUB_TOKEN (first 10 chars): ${GITHUB_TOKEN:0:10}..." + echo "Node.js version: $(node --version)" + echo "release-it version: $(release-it --version)" + echo "================================" + params=() if [[ ${{ github.event.inputs.bump_version_number }} != "consecutive" ]]; then @@ -74,7 +100,20 @@ jobs: params+=(--ci) params+=(--verbose) + echo "=== RELEASE-IT EXECUTION ===" echo "command: release-it ${params[@]}" + echo "Working directory: $(pwd)" + echo "Git status:" + git status --porcelain + echo "Git tags (last 5):" + git tag --sort=-version:refname | head -5 + echo "================================" + + # First try a dry run to see what happens + echo "=== DRY RUN TEST ===" + release-it --dry-run --ci --verbose "${params[@]}" || echo "Dry run failed with exit code $?" + + echo "=== ACTUAL RELEASE ===" release-it "${params[@]}" env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} diff --git a/.release-it.json b/.release-it.json index d456224..3f22ba4 100644 --- a/.release-it.json +++ b/.release-it.json @@ -14,8 +14,7 @@ "filename": "CHANGELOG.md", "addVersionUrl": true, "addUnreleased": true, - "strictLatest": false, - "keepUnreleased": false + "strictLatest": false } }, "hooks": { From eecd20d56440437e54b532baff9b4b93f29becd0 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:40:26 +0200 Subject: [PATCH 07/23] debug --- .github/workflows/create-release.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 298f884..efdea80 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -98,9 +98,7 @@ jobs: fi params+=(--ci) - params+=(--verbose) - - echo "=== RELEASE-IT EXECUTION ===" + params+=(--verbose) echo "=== RELEASE-IT EXECUTION ===" echo "command: release-it ${params[@]}" echo "Working directory: $(pwd)" echo "Git status:" @@ -109,11 +107,6 @@ jobs: git tag --sort=-version:refname | head -5 echo "================================" - # First try a dry run to see what happens - echo "=== DRY RUN TEST ===" - release-it --dry-run --ci --verbose "${params[@]}" || echo "Dry run failed with exit code $?" - - echo "=== ACTUAL RELEASE ===" release-it "${params[@]}" env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} From e221e820716382e44d81e5910c633d97a9d047a8 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:44:31 +0200 Subject: [PATCH 08/23] Fix missing newline in workflow script --- .github/workflows/create-release.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index efdea80..2677999 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -98,7 +98,9 @@ jobs: fi params+=(--ci) - params+=(--verbose) echo "=== RELEASE-IT EXECUTION ===" + params+=(--verbose) + + echo "=== RELEASE-IT EXECUTION ===" echo "command: release-it ${params[@]}" echo "Working directory: $(pwd)" echo "Git status:" From a422d1e1c25d641a925d615a11fd92c67016c844 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:49:33 +0200 Subject: [PATCH 09/23] Try older release-it version and remove DEBUG/prettier hook --- .github/workflows/create-release.yml | 3 +-- .release-it.json | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 2677999..966c100 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -50,7 +50,7 @@ jobs: git config user.email release-bot@neolution.ch - name: install release-it with plugins - run: npm install -g release-it@17.6.0 @release-it/keep-a-changelog@5.0.0 + run: npm install -g release-it@16.10.1 @release-it/keep-a-changelog@4.3.0 - name: Check Node.js version run: | @@ -112,4 +112,3 @@ jobs: release-it "${params[@]}" env: GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - DEBUG: "*" diff --git a/.release-it.json b/.release-it.json index 3f22ba4..e1ed358 100644 --- a/.release-it.json +++ b/.release-it.json @@ -18,6 +18,5 @@ } }, "hooks": { - "before:git:release": "npx prettier -y --write CHANGELOG.md && git add CHANGELOG.md" } } \ No newline at end of file From 08890abbabb76d21860836b7bd6587d29e154d58 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:52:45 +0200 Subject: [PATCH 10/23] Test with basic release-it only (no plugins) --- .github/workflows/create-release.yml | 2 +- .release-it.json | 6 ------ 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 966c100..e04ebe9 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -50,7 +50,7 @@ jobs: git config user.email release-bot@neolution.ch - name: install release-it with plugins - run: npm install -g release-it@16.10.1 @release-it/keep-a-changelog@4.3.0 + run: npm install -g release-it@17.6.0 - name: Check Node.js version run: | diff --git a/.release-it.json b/.release-it.json index e1ed358..65a21d8 100644 --- a/.release-it.json +++ b/.release-it.json @@ -10,12 +10,6 @@ "release": true }, "plugins": { - "@release-it/keep-a-changelog": { - "filename": "CHANGELOG.md", - "addVersionUrl": true, - "addUnreleased": true, - "strictLatest": false - } }, "hooks": { } From 81512be5ab6a75cee01b6e3a1fbbbe46a4169fbb Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 11:57:32 +0200 Subject: [PATCH 11/23] Try release-it@16.10.1 with explicit GitHub release config --- .github/workflows/create-release.yml | 2 +- .release-it.json | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index e04ebe9..0d4d347 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -50,7 +50,7 @@ jobs: git config user.email release-bot@neolution.ch - name: install release-it with plugins - run: npm install -g release-it@17.6.0 + run: npm install -g release-it@16.10.1 - name: Check Node.js version run: | diff --git a/.release-it.json b/.release-it.json index 65a21d8..dadbf0b 100644 --- a/.release-it.json +++ b/.release-it.json @@ -7,7 +7,9 @@ "skipChecks": true }, "github": { - "release": true + "release": true, + "releaseName": "Release ${version}", + "releaseNotes": null }, "plugins": { }, From 6a12c339ac7775599cd9354e0208f0c4f5acd421 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 12:01:02 +0200 Subject: [PATCH 12/23] Fix version to use existing release-it@16.3.0 --- .github/workflows/create-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index 0d4d347..f6ccf86 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -50,7 +50,7 @@ jobs: git config user.email release-bot@neolution.ch - name: install release-it with plugins - run: npm install -g release-it@16.10.1 + run: npm install -g release-it@16.3.0 - name: Check Node.js version run: | From 557e5b69a70265c62397fa2261636d2f3cb0e075 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 12:16:52 +0200 Subject: [PATCH 13/23] Add keep-a-changelog plugin with conditional behavior for pre-releases vs stable --- .github/workflows/create-release.yml | 2 +- .release-it.json | 9 ++++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/create-release.yml b/.github/workflows/create-release.yml index f6ccf86..c8b6d95 100644 --- a/.github/workflows/create-release.yml +++ b/.github/workflows/create-release.yml @@ -50,7 +50,7 @@ jobs: git config user.email release-bot@neolution.ch - name: install release-it with plugins - run: npm install -g release-it@16.3.0 + run: npm install -g release-it@16.3.0 @release-it/keep-a-changelog@2.1.0 - name: Check Node.js version run: | diff --git a/.release-it.json b/.release-it.json index dadbf0b..c178c34 100644 --- a/.release-it.json +++ b/.release-it.json @@ -9,9 +9,16 @@ "github": { "release": true, "releaseName": "Release ${version}", - "releaseNotes": null + "releaseNotes": "auto" }, "plugins": { + "@release-it/keep-a-changelog": { + "filename": "CHANGELOG.md", + "strictLatest": false, + "addUnreleased": true, + "head": "Unreleased", + "keepUnreleased": "${preRelease}" + } }, "hooks": { } From c598037ae57cab069298d5ff9304d715eb71536f Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 12:20:03 +0200 Subject: [PATCH 14/23] Fix releaseNotes configuration - remove auto directive --- .release-it.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.release-it.json b/.release-it.json index c178c34..a951416 100644 --- a/.release-it.json +++ b/.release-it.json @@ -8,8 +8,7 @@ }, "github": { "release": true, - "releaseName": "Release ${version}", - "releaseNotes": "auto" + "releaseName": "Release ${version}" }, "plugins": { "@release-it/keep-a-changelog": { From 24ddfe16bc8c23391db49f9770a40b01a0406943 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 15:08:13 +0200 Subject: [PATCH 15/23] Improves fallback logging configuration --- Neolution.DotNet.Console/DotNetConsoleLogger.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Neolution.DotNet.Console/DotNetConsoleLogger.cs b/Neolution.DotNet.Console/DotNetConsoleLogger.cs index 852d097..0586ef9 100644 --- a/Neolution.DotNet.Console/DotNetConsoleLogger.cs +++ b/Neolution.DotNet.Console/DotNetConsoleLogger.cs @@ -39,19 +39,18 @@ public static Logger Log /// The configuration used to initialize the logger. public static void Initialize(IConfiguration configuration) { - ConsoleTarget? consoleTarget = null; try { logger = LogManager.Setup().LoadConfigurationFromSection(configuration).GetCurrentClassLogger(); } catch (Exception ex) { - // Create a simple NLog configuration that logs to the console - var config = new NLog.Config.LoggingConfiguration(); - consoleTarget = new ConsoleTarget("console"); + // Create a console target for fallback logging + var consoleTarget = new ConsoleTarget("console"); try { + var config = new NLog.Config.LoggingConfiguration(); config.AddRule(LogLevel.Trace, LogLevel.Fatal, consoleTarget); LogManager.Configuration = config; logger = LogManager.GetCurrentClassLogger(); From a3ef2ed14e4fbb68f72c3621907ab62f501a5881 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 15:32:35 +0200 Subject: [PATCH 16/23] re-adding pre-release hook --- .release-it.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.release-it.json b/.release-it.json index a951416..c2530de 100644 --- a/.release-it.json +++ b/.release-it.json @@ -20,5 +20,6 @@ } }, "hooks": { + "before:git:release": "npx prettier -y --write CHANGELOG.md && git add CHANGELOG.md" } } \ No newline at end of file From a2392a829b970760d4e7801933eaf96d2cd7d7d2 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 20:09:39 +0200 Subject: [PATCH 17/23] Initializes logger within builder --- Neolution.DotNet.Console.Demo/Program.cs | 2 - .../DotNetConsoleBuilder.cs | 13 ++++-- .../DotNetConsoleLogger.cs | 40 +++++++------------ 3 files changed, 24 insertions(+), 31 deletions(-) diff --git a/Neolution.DotNet.Console.Demo/Program.cs b/Neolution.DotNet.Console.Demo/Program.cs index 305c94d..eaeb986 100644 --- a/Neolution.DotNet.Console.Demo/Program.cs +++ b/Neolution.DotNet.Console.Demo/Program.cs @@ -15,8 +15,6 @@ public static async Task Main(string[] args) try { var builder = DotNetConsole.CreateDefaultBuilder(args); - DotNetConsoleLogger.Initialize(builder.Configuration); - var startup = new Startup(builder.Environment, builder.Configuration); startup.ConfigureServices(builder.Services); var console = builder.Build(); diff --git a/Neolution.DotNet.Console/DotNetConsoleBuilder.cs b/Neolution.DotNet.Console/DotNetConsoleBuilder.cs index 442f4d0..e008d1d 100644 --- a/Neolution.DotNet.Console/DotNetConsoleBuilder.cs +++ b/Neolution.DotNet.Console/DotNetConsoleBuilder.cs @@ -113,13 +113,19 @@ internal static DotNetConsoleBuilder CreateBuilderInternal(Assembly assembly, Ty var environment = DotNetConsoleDefaults.CreateConsoleEnvironment(args); var configuration = DotNetConsoleDefaults.CreateConsoleConfiguration(assembly, args, environment); - // Create a HostBuilder + // Initialize NLog logger from configuration with fallback; any config errors are handled in Initialize + DotNetConsoleLogger.Initialize(configuration); + + // Create a HostBuilder and configure logging and services var builder = Host.CreateDefaultBuilder(args) .UseContentRoot(environment.ContentRootPath) - .ConfigureLogging((context, logging) => + .ConfigureLogging((_, logging) => { + // Remove default providers and add core providers for debug and event sources AdjustDefaultBuilderLoggingProviders(logging); - logging.AddNLog(context.Configuration); + + // Add NLog provider using existing LogManager configuration + logging.AddNLog(); }) .ConfigureServices((_, services) => { @@ -137,6 +143,7 @@ internal static DotNetConsoleBuilder CreateBuilderInternal(Assembly assembly, Ty var parsedArguments = Parser.Default.ParseArguments(args, verbTypes); var consoleBuilder = new DotNetConsoleBuilder(builder, parsedArguments, environment, configuration); + // Determine if this is a check-deps run: only DI validation should run if (args.Length == 1 && string.Equals(args[0], "check-deps", StringComparison.OrdinalIgnoreCase)) { consoleBuilder.checkDependencies = true; diff --git a/Neolution.DotNet.Console/DotNetConsoleLogger.cs b/Neolution.DotNet.Console/DotNetConsoleLogger.cs index 0586ef9..914ee22 100644 --- a/Neolution.DotNet.Console/DotNetConsoleLogger.cs +++ b/Neolution.DotNet.Console/DotNetConsoleLogger.cs @@ -4,7 +4,6 @@ using Microsoft.Extensions.Configuration; using NLog; using NLog.Extensions.Logging; - using NLog.Targets; /// /// Provides static methods to initialize and manage a logger instance. @@ -26,18 +25,26 @@ public static Logger Log { if (logger == null) { - throw new InvalidOperationException("Logger has not been initialized. Call Initialize(configuration) first."); + throw new InvalidOperationException("Logger has not yet been initialized."); } return logger; } } + /// + /// Ensures the logger flushes messages and shuts down internal timers. + /// + public static void Shutdown() + { + LogManager.Shutdown(); + } + /// /// Initializes the logger based on the provided configuration. /// /// The configuration used to initialize the logger. - public static void Initialize(IConfiguration configuration) + internal static void Initialize(IConfiguration configuration) { try { @@ -45,30 +52,11 @@ public static void Initialize(IConfiguration configuration) } catch (Exception ex) { - // Create a console target for fallback logging - var consoleTarget = new ConsoleTarget("console"); - - try - { - var config = new NLog.Config.LoggingConfiguration(); - config.AddRule(LogLevel.Trace, LogLevel.Fatal, consoleTarget); - LogManager.Configuration = config; - logger = LogManager.GetCurrentClassLogger(); - logger.Error(ex, "Logger initialization failed"); - } - finally - { - consoleTarget.Dispose(); - } + // Fallback: minimal console logger setup using NLog fluent API + LogManager.Setup().LoadConfiguration(builder => builder.ForLogger().WriteToConsole()); + logger = LogManager.GetCurrentClassLogger(); + logger.Error(ex, "Logger initialization failed."); } } - - /// - /// Ensures the logger flushes messages and shuts down internal timers. - /// - public static void Shutdown() - { - LogManager.Shutdown(); - } } } From e6ba1517c19380dc13a33072007df78ea711d0e3 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Fri, 11 Jul 2025 21:15:34 +0200 Subject: [PATCH 18/23] Separates logger setup from retrieval. --- Neolution.DotNet.Console/DotNetConsoleLogger.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Neolution.DotNet.Console/DotNetConsoleLogger.cs b/Neolution.DotNet.Console/DotNetConsoleLogger.cs index 914ee22..c579472 100644 --- a/Neolution.DotNet.Console/DotNetConsoleLogger.cs +++ b/Neolution.DotNet.Console/DotNetConsoleLogger.cs @@ -48,7 +48,8 @@ internal static void Initialize(IConfiguration configuration) { try { - logger = LogManager.Setup().LoadConfigurationFromSection(configuration).GetCurrentClassLogger(); + LogManager.Setup().LoadConfigurationFromSection(configuration); + logger = LogManager.GetCurrentClassLogger(); } catch (Exception ex) { From 00dd40cf3e10546d23452a92da8090265cd5bd3d Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Mon, 14 Jul 2025 13:38:28 +0200 Subject: [PATCH 19/23] Log Info message if check-deps ran successfully --- Neolution.DotNet.Console/DotNetConsoleBuilder.cs | 4 ++-- .../Internal/{NoOperationConsole.cs => CheckDepsConsole.cs} | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) rename Neolution.DotNet.Console/Internal/{NoOperationConsole.cs => CheckDepsConsole.cs} (61%) diff --git a/Neolution.DotNet.Console/DotNetConsoleBuilder.cs b/Neolution.DotNet.Console/DotNetConsoleBuilder.cs index e008d1d..6891b0e 100644 --- a/Neolution.DotNet.Console/DotNetConsoleBuilder.cs +++ b/Neolution.DotNet.Console/DotNetConsoleBuilder.cs @@ -89,8 +89,8 @@ public IDotNetConsole Build() this.hostBuilder.UseEnvironment("Development"); this.hostBuilder.Build(); - // If build was successful and did not throw an exception, return a console that does nothing and then terminates. - return new NoOperationConsole(); + // If build was successful and did not throw an exception, return a console that logs a success message and then terminates. + return new CheckDepsConsole(); } var host = this.hostBuilder.Build(); diff --git a/Neolution.DotNet.Console/Internal/NoOperationConsole.cs b/Neolution.DotNet.Console/Internal/CheckDepsConsole.cs similarity index 61% rename from Neolution.DotNet.Console/Internal/NoOperationConsole.cs rename to Neolution.DotNet.Console/Internal/CheckDepsConsole.cs index 2e43ace..f65f1ec 100644 --- a/Neolution.DotNet.Console/Internal/NoOperationConsole.cs +++ b/Neolution.DotNet.Console/Internal/CheckDepsConsole.cs @@ -1,15 +1,16 @@ namespace Neolution.DotNet.Console.Internal { using System; + using System.Globalization; using System.Threading.Tasks; using Microsoft.Extensions.DependencyInjection; using Neolution.DotNet.Console.Abstractions; /// - /// The no operation console application. + /// The check dependencies console application. /// /// - public class NoOperationConsole : IDotNetConsole + internal class CheckDepsConsole : IDotNetConsole { /// public IServiceProvider Services => new ServiceCollection().BuildServiceProvider(); @@ -17,6 +18,7 @@ public class NoOperationConsole : IDotNetConsole /// public Task RunAsync() { + DotNetConsoleLogger.Log.Info(CultureInfo.InvariantCulture, message: "Dependency injection validation succeeded. All registered services can be constructed and no DI issues were found."); return Task.CompletedTask; } } From c347f8ee20bfe515f394689df854366a3b01e16e Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Mon, 14 Jul 2025 13:51:38 +0200 Subject: [PATCH 20/23] Adds integration tests Adds integration tests to verify the correct behavior of the demo console application, specifically focusing on the check-deps scenario. --- .../CheckDepsConsoleTests.cs | 64 +++++++++++++++++++ ...ion.DotNet.Console.IntegrationTests.csproj | 22 +++++++ Neolution.DotNet.Console.sln | 6 ++ 3 files changed, 92 insertions(+) create mode 100644 Neolution.DotNet.Console.IntegrationTests/CheckDepsConsoleTests.cs create mode 100644 Neolution.DotNet.Console.IntegrationTests/Neolution.DotNet.Console.IntegrationTests.csproj diff --git a/Neolution.DotNet.Console.IntegrationTests/CheckDepsConsoleTests.cs b/Neolution.DotNet.Console.IntegrationTests/CheckDepsConsoleTests.cs new file mode 100644 index 0000000..1c81b1c --- /dev/null +++ b/Neolution.DotNet.Console.IntegrationTests/CheckDepsConsoleTests.cs @@ -0,0 +1,64 @@ +namespace Neolution.DotNet.Console.IntegrationTests +{ + using System.Diagnostics; + using System.IO; + using System.Threading.Tasks; + using Shouldly; + using Xunit; + + /// + /// Integration tests for the CheckDepsConsole scenario. + /// + public class CheckDepsConsoleTests + { + /// + /// Given the Demo app, when run with 'check-deps', then it prints the expected DI validation message. + /// + /// A task representing the asynchronous operation. + [Fact] + public async Task GivenDemoApp_WhenRunWithCheckDeps_ThenPrintsDependencyInjectionValidationSucceeded() + { + // Arrange + // Find the solution directory by traversing up from the current directory + var dir = Directory.GetCurrentDirectory(); + while (dir != null && !File.Exists(Path.Combine(dir, "Neolution.DotNet.Console.sln"))) + { + dir = Path.GetDirectoryName(dir); + } + + if (dir is null) + { + throw new DirectoryNotFoundException("Could not find solution directory."); + } + + var solutionDir = dir; + var demoProjPath = Path.Combine(solutionDir, "Neolution.DotNet.Console.Demo", "Neolution.DotNet.Console.Demo.csproj"); + + File.Exists(demoProjPath).ShouldBeTrue($"Demo project file not found: {demoProjPath}"); + var psi = new ProcessStartInfo + { + FileName = "dotnet", + Arguments = $"run --project \"{demoProjPath}\" check-deps", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true, + }; + + // Act + using var process = Process.Start(psi); + if (process is null) + { + throw new System.InvalidOperationException("Failed to start process for Demo app."); + } + + var output = await process.StandardOutput.ReadToEndAsync(); + var error = await process.StandardError.ReadToEndAsync(); + await process.WaitForExitAsync(); + + // Assert + output.ShouldContain("Dependency injection validation succeeded. All registered services can be constructed and no DI issues were found."); + process.ExitCode.ShouldBe(0, $"Process exited with code {process.ExitCode}. Error: {error}"); + } + } +} diff --git a/Neolution.DotNet.Console.IntegrationTests/Neolution.DotNet.Console.IntegrationTests.csproj b/Neolution.DotNet.Console.IntegrationTests/Neolution.DotNet.Console.IntegrationTests.csproj new file mode 100644 index 0000000..2d8635c --- /dev/null +++ b/Neolution.DotNet.Console.IntegrationTests/Neolution.DotNet.Console.IntegrationTests.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + false + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + diff --git a/Neolution.DotNet.Console.sln b/Neolution.DotNet.Console.sln index 67bf04b..5e64a93 100644 --- a/Neolution.DotNet.Console.sln +++ b/Neolution.DotNet.Console.sln @@ -22,6 +22,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Neolution.DotNet.Console.Un EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neolution.DotNet.Console.Demo", "Neolution.DotNet.Console.Demo\Neolution.DotNet.Console.Demo.csproj", "{3F17699A-2864-0EEC-AC50-93648D6E5BDE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Neolution.DotNet.Console.IntegrationTests", "Neolution.DotNet.Console.IntegrationTests\Neolution.DotNet.Console.IntegrationTests.csproj", "{8C6D9105-CEF3-66FD-11A3-73BFF67273F6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -40,6 +42,10 @@ Global {3F17699A-2864-0EEC-AC50-93648D6E5BDE}.Debug|Any CPU.Build.0 = Debug|Any CPU {3F17699A-2864-0EEC-AC50-93648D6E5BDE}.Release|Any CPU.ActiveCfg = Release|Any CPU {3F17699A-2864-0EEC-AC50-93648D6E5BDE}.Release|Any CPU.Build.0 = Release|Any CPU + {8C6D9105-CEF3-66FD-11A3-73BFF67273F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8C6D9105-CEF3-66FD-11A3-73BFF67273F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8C6D9105-CEF3-66FD-11A3-73BFF67273F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8C6D9105-CEF3-66FD-11A3-73BFF67273F6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 61ac89b2518380391fccb35b73552b1c35cd7b12 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Mon, 14 Jul 2025 14:00:10 +0200 Subject: [PATCH 21/23] Refactors integration tests for better reliability --- .../CheckDepsConsoleTests.cs | 48 +++++++++++++------ .../SolutionDirectoryFixture.cs | 42 ++++++++++++++++ 2 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 Neolution.DotNet.Console.IntegrationTests/SolutionDirectoryFixture.cs diff --git a/Neolution.DotNet.Console.IntegrationTests/CheckDepsConsoleTests.cs b/Neolution.DotNet.Console.IntegrationTests/CheckDepsConsoleTests.cs index 1c81b1c..2c87f27 100644 --- a/Neolution.DotNet.Console.IntegrationTests/CheckDepsConsoleTests.cs +++ b/Neolution.DotNet.Console.IntegrationTests/CheckDepsConsoleTests.cs @@ -1,7 +1,6 @@ namespace Neolution.DotNet.Console.IntegrationTests { using System.Diagnostics; - using System.IO; using System.Threading.Tasks; using Shouldly; using Xunit; @@ -9,8 +8,22 @@ /// /// Integration tests for the CheckDepsConsole scenario. /// - public class CheckDepsConsoleTests + public class CheckDepsConsoleTests : IClassFixture { + /// + /// The fixture that provides solution and project paths. + /// + private readonly SolutionDirectoryFixture fixture; + + /// + /// Initializes a new instance of the class. + /// + /// The solution directory fixture. + public CheckDepsConsoleTests(SolutionDirectoryFixture fixture) + { + this.fixture = fixture; + } + /// /// Given the Demo app, when run with 'check-deps', then it prints the expected DI validation message. /// @@ -19,26 +32,33 @@ public class CheckDepsConsoleTests public async Task GivenDemoApp_WhenRunWithCheckDeps_ThenPrintsDependencyInjectionValidationSucceeded() { // Arrange - // Find the solution directory by traversing up from the current directory - var dir = Directory.GetCurrentDirectory(); - while (dir != null && !File.Exists(Path.Combine(dir, "Neolution.DotNet.Console.sln"))) + var restorePsi = new ProcessStartInfo { - dir = Path.GetDirectoryName(dir); - } + FileName = "dotnet", + Arguments = $"restore \"{this.fixture.DemoProjectPath}\"", + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + CreateNoWindow = true, + }; - if (dir is null) + using (var restoreProcess = Process.Start(restorePsi)) { - throw new DirectoryNotFoundException("Could not find solution directory."); - } + if (restoreProcess is null) + { + throw new System.InvalidOperationException("Failed to start dotnet restore for Demo app."); + } - var solutionDir = dir; - var demoProjPath = Path.Combine(solutionDir, "Neolution.DotNet.Console.Demo", "Neolution.DotNet.Console.Demo.csproj"); + await restoreProcess.StandardOutput.ReadToEndAsync(); + await restoreProcess.StandardError.ReadToEndAsync(); + await restoreProcess.WaitForExitAsync(); + restoreProcess.ExitCode.ShouldBe(0, "dotnet restore failed for Demo app"); + } - File.Exists(demoProjPath).ShouldBeTrue($"Demo project file not found: {demoProjPath}"); var psi = new ProcessStartInfo { FileName = "dotnet", - Arguments = $"run --project \"{demoProjPath}\" check-deps", + Arguments = $"run --project \"{this.fixture.DemoProjectPath}\" check-deps", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, diff --git a/Neolution.DotNet.Console.IntegrationTests/SolutionDirectoryFixture.cs b/Neolution.DotNet.Console.IntegrationTests/SolutionDirectoryFixture.cs new file mode 100644 index 0000000..f73d8dd --- /dev/null +++ b/Neolution.DotNet.Console.IntegrationTests/SolutionDirectoryFixture.cs @@ -0,0 +1,42 @@ +namespace Neolution.DotNet.Console.IntegrationTests +{ + using System.IO; + + /// + /// Provides the solution directory and Demo project path for integration tests. + /// + public class SolutionDirectoryFixture + { + /// + /// Initializes a new instance of the class. + /// + public SolutionDirectoryFixture() + { + var dir = Directory.GetCurrentDirectory(); + while (dir != null && !File.Exists(Path.Combine(dir, "Neolution.DotNet.Console.sln"))) + { + dir = Path.GetDirectoryName(dir); + } + + // Set the solution directory to the one containing the solution file + this.SolutionDirectory = dir ?? throw new DirectoryNotFoundException("Could not find solution directory."); + + // Set the Demo project path relative to the solution directory + this.DemoProjectPath = Path.Combine(this.SolutionDirectory, "Neolution.DotNet.Console.Demo", "Neolution.DotNet.Console.Demo.csproj"); + if (!File.Exists(this.DemoProjectPath)) + { + throw new FileNotFoundException($"Demo project file not found: {this.DemoProjectPath}"); + } + } + + /// + /// Gets the solution directory path. + /// + public string SolutionDirectory { get; } + + /// + /// Gets the Demo project file path. + /// + public string DemoProjectPath { get; } + } +} From 6a23de46a3977e8ff82c934efa7e9c04cafa09e5 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Mon, 14 Jul 2025 14:12:31 +0200 Subject: [PATCH 22/23] Splits tests into unit and integration tests --- .github/workflows/ci.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f87933f..fad4b29 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,5 +31,8 @@ jobs: - name: Run check-deps in Demo Application run: dotnet run --project Neolution.DotNet.Console.Demo --no-build --configuration '${{ env.BUILD_CONFIGURATION }}' -- check-deps - - name: Test - run: dotnet test --no-build --verbosity normal --configuration '${{ env.BUILD_CONFIGURATION }}' + - name: Unit Tests + run: dotnet test --no-build --verbosity normal --configuration '${{ env.BUILD_CONFIGURATION }}' --filter FullyQualifiedName~UnitTests + + - name: Integration Tests + run: dotnet test --no-build --verbosity normal --configuration '${{ env.BUILD_CONFIGURATION }}' --filter FullyQualifiedName~IntegrationTests From 77095ec8ba2bf1ef492ac4285be5d3a8c7997173 Mon Sep 17 00:00:00 2001 From: Sandro Ciervo Date: Wed, 16 Jul 2025 11:40:32 +0200 Subject: [PATCH 23/23] Fixed loading of `appsettings.Development.json` during `check-deps` runs --- CHANGELOG.md | 1 + .../DotNetConsoleBuilderTests.cs | 2 +- .../DotNetConsoleBuilder.cs | 6 +++-- .../DotNetConsoleDefaults.cs | 25 ++++++++++++++++++- .../Properties/AssemblyInfo.cs | 3 +++ 5 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 Neolution.DotNet.Console/Properties/AssemblyInfo.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index 96c89fc..f1f6272 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Fixed loading of `appsettings.Development.json` during `check-deps` runs by forcing the Development environment for dependency validation. - Updated Scrutor to v6.1.0. - Updated Microsoft.Extensions packages to latest patch versions. diff --git a/Neolution.DotNet.Console.UnitTests/DotNetConsoleBuilderTests.cs b/Neolution.DotNet.Console.UnitTests/DotNetConsoleBuilderTests.cs index e3544f0..cd914b9 100644 --- a/Neolution.DotNet.Console.UnitTests/DotNetConsoleBuilderTests.cs +++ b/Neolution.DotNet.Console.UnitTests/DotNetConsoleBuilderTests.cs @@ -17,7 +17,7 @@ public class DotNetConsoleBuilderTests /// /// The argument string for the internal check-deps command /// - private const string CheckDependenciesArgumentString = "check-deps"; + private const string CheckDependenciesArgumentString = DotNetConsoleDefaults.CheckDependenciesCommand; /// /// Given a mistyped verb, when a default verb is defined, then should throw on console building. diff --git a/Neolution.DotNet.Console/DotNetConsoleBuilder.cs b/Neolution.DotNet.Console/DotNetConsoleBuilder.cs index 6891b0e..fbe4316 100644 --- a/Neolution.DotNet.Console/DotNetConsoleBuilder.cs +++ b/Neolution.DotNet.Console/DotNetConsoleBuilder.cs @@ -85,7 +85,9 @@ public IDotNetConsole Build() if (this.checkDependencies) { - // Use development environment before building because that's where ValidateScopes and ValidateOnBuild are enabled. + // Ensure development environment is used for dependency checking + // Note: The environment should already be set to Development during CreateConsoleEnvironment + // but we explicitly set it here as well to ensure ValidateScopes and ValidateOnBuild are enabled. this.hostBuilder.UseEnvironment("Development"); this.hostBuilder.Build(); @@ -144,7 +146,7 @@ internal static DotNetConsoleBuilder CreateBuilderInternal(Assembly assembly, Ty var consoleBuilder = new DotNetConsoleBuilder(builder, parsedArguments, environment, configuration); // Determine if this is a check-deps run: only DI validation should run - if (args.Length == 1 && string.Equals(args[0], "check-deps", StringComparison.OrdinalIgnoreCase)) + if (DotNetConsoleDefaults.IsCheckDependenciesRun(args)) { consoleBuilder.checkDependencies = true; return consoleBuilder; diff --git a/Neolution.DotNet.Console/DotNetConsoleDefaults.cs b/Neolution.DotNet.Console/DotNetConsoleDefaults.cs index 6744df4..b4dd50a 100644 --- a/Neolution.DotNet.Console/DotNetConsoleDefaults.cs +++ b/Neolution.DotNet.Console/DotNetConsoleDefaults.cs @@ -12,6 +12,21 @@ /// internal static class DotNetConsoleDefaults { + /// + /// The command argument used to trigger dependency validation. + /// + internal const string CheckDependenciesCommand = "check-deps"; + + /// + /// Determines if the given arguments represent a check-deps run. + /// + /// The command line arguments. + /// True if this is a check-deps run, false otherwise. + public static bool IsCheckDependenciesRun(string[] args) + { + return args.Length == 1 && string.Equals(args[0], CheckDependenciesCommand, StringComparison.OrdinalIgnoreCase); + } + /// /// Creates the console environment. /// @@ -27,9 +42,17 @@ internal static DotNetConsoleEnvironment CreateConsoleEnvironment(string[] args) // The apps root directory is where the appsettings.json are located var appRootDirectory = AppContext.BaseDirectory; + // Check if this is a check-deps run - if so, always use Development environment + var isCheckDepsRun = IsCheckDependenciesRun(args); + + // Default to Production for normal runs, matching ASP.NET Core behavior + // For check-deps, always use Development to ensure appsettings.Development.json is loaded + // Environment can be overridden via DOTNET_ENVIRONMENT or command line arguments + var defaultEnvironment = isCheckDepsRun ? Environments.Development : Environments.Production; + return new DotNetConsoleEnvironment { - EnvironmentName = configuration[HostDefaults.EnvironmentKey] ?? Environments.Production, + EnvironmentName = isCheckDepsRun ? Environments.Development : (configuration[HostDefaults.EnvironmentKey] ?? defaultEnvironment), ApplicationName = AppDomain.CurrentDomain.FriendlyName, ContentRootPath = appRootDirectory, ContentRootFileProvider = new PhysicalFileProvider(appRootDirectory), diff --git a/Neolution.DotNet.Console/Properties/AssemblyInfo.cs b/Neolution.DotNet.Console/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..44efd0d --- /dev/null +++ b/Neolution.DotNet.Console/Properties/AssemblyInfo.cs @@ -0,0 +1,3 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Neolution.DotNet.Console.UnitTests")]