Skip to content

Commit f0b24ed

Browse files
authored
V4.0.0/prepare for launch (#11)
🔧 problem with port 5001 👷 applied openssf recommendation for token permissions 💬 updated community health pages 🚨 analysis set to default recommended ⬆️ bump dependencies 🚨 fixes CA1200 🚨 fixes CS0419 ⚡ fixes CA1848
1 parent f0bcd1b commit f0b24ed

File tree

10 files changed

+118
-32
lines changed

10 files changed

+118
-32
lines changed

.github/workflows/pipelines.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ on:
1818
- Debug
1919
- Release
2020

21+
permissions:
22+
contents: read
23+
2124
jobs:
2225
build:
2326
name: 🛠️ Build
@@ -130,13 +133,18 @@ jobs:
130133
name: call-codeql
131134
needs: [build,test]
132135
uses: codebeltnet/jobs-codeql/.github/workflows/default.yml@v1
136+
permissions:
137+
security-events: write
133138

134139
deploy:
135140
if: github.event_name != 'pull_request'
136141
name: 🚀 Deploy v${{ needs.build.outputs.version }}
137142
runs-on: ubuntu-24.04
138143
needs: [build, pack, test, sonarcloud, codecov, codeql]
139144
environment: Production
145+
permissions:
146+
contents: write
147+
packages: write
140148
steps:
141149
- uses: codebeltnet/nuget-push@v1
142150
with:

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
44

55
For more details, please refer to `PackageReleaseNotes.txt` on a per assembly basis in the `.nuget` folder.
66

7-
## [4.0.0] - TBD
7+
## [4.0.0] - 2025-04-12
88

99
This major release revisits and refines some of the earlier design decisions to offer a more consistent and flexible API. It also brings forward improvements to reliability and maintainability.
1010

Directory.Build.props

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@
3232
<GenerateDocumentationFile>true</GenerateDocumentationFile>
3333
<SignAssembly Condition="('$(CI)' == 'true' OR '$(IsMainAuthor)' == 'true') AND '$(SkipSignAssembly)' == 'false'">true</SignAssembly>
3434
<AssemblyOriginatorKeyFile>$(MSBuildThisFileDirectory)bootstrapper.snk</AssemblyOriginatorKeyFile>
35+
<EnableNETAnalyzers>true</EnableNETAnalyzers>
36+
<AnalysisLevel>latest</AnalysisLevel>
37+
<AnalysisMode>Recommended</AnalysisMode>
3538
</PropertyGroup>
3639

3740
<ItemGroup Condition="'$(NuGetPackageRoot)' != ''">

Directory.Packages.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
</PropertyGroup>
55
<ItemGroup>
66
<PackageVersion Include="Codebelt.Extensions.Swashbuckle.AspNetCore" Version="9.0.1" />
7-
<PackageVersion Include="Codebelt.Extensions.Xunit.App" Version="10.0.0-preview.3" />
7+
<PackageVersion Include="Codebelt.Extensions.Xunit.App" Version="10.0.0" />
88
<PackageVersion Include="Cuemon.Core" Version="9.0.4" />
99
<PackageVersion Include="Cuemon.Extensions.Hosting" Version="9.0.4" />
1010
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"profiles": {
33
"Codebelt.Bootstrapper.WebApp.App": {
4-
"commandName": "Project",
5-
"dotnetRunMessages": "true",
6-
"launchBrowser": true,
7-
"applicationUrl": "https://localhost:5001;http://localhost:5000",
8-
"environmentVariables": {
9-
"ASPNETCORE_ENVIRONMENT": "LocalDevelopment",
10-
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
11-
}
4+
"commandName": "Project",
5+
"dotnetRunMessages": "true",
6+
"launchBrowser": true,
7+
"applicationUrl": "https://localhost:7173;http://localhost:5249",
8+
"environmentVariables": {
9+
"ASPNETCORE_ENVIRONMENT": "LocalDevelopment",
10+
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
11+
}
1212
}
1313
}
1414
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
{
22
"profiles": {
33
"Codebelt.Bootstrapper.WebMvc.App": {
4-
"commandName": "Project",
5-
"dotnetRunMessages": "true",
6-
"launchBrowser": true,
7-
"applicationUrl": "https://localhost:5001;http://localhost:5000",
8-
"environmentVariables": {
9-
"ASPNETCORE_ENVIRONMENT": "LocalDevelopment",
10-
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
11-
}
4+
"commandName": "Project",
5+
"dotnetRunMessages": "true",
6+
"launchBrowser": true,
7+
"applicationUrl": "https://localhost:7173;http://localhost:5249",
8+
"environmentVariables": {
9+
"ASPNETCORE_ENVIRONMENT": "LocalDevelopment",
10+
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
11+
}
1212
}
1313
}
1414
}

src/Codebelt.Bootstrapper.Console/ConsoleHostedService.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
using System;
2-
using System.Threading;
3-
using System.Threading.Tasks;
1+
using Cuemon;
42
using Microsoft.Extensions.DependencyInjection;
53
using Microsoft.Extensions.Hosting;
64
using Microsoft.Extensions.Logging;
5+
using System;
6+
using System.Threading;
7+
using System.Threading.Tasks;
78

89
namespace Codebelt.Bootstrapper.Console
910
{
@@ -55,13 +56,13 @@ public Task StartAsync(CancellationToken cancellationToken)
5556
{
5657
try
5758
{
58-
_logger.LogInformation("RunAsync started.");
59+
Decorator.EncloseToExpose(_logger, false).RunAsyncStarted();
5960
await startup.RunAsync(_provider, cancellationToken).ConfigureAwait(false);
6061
_ranToCompletion = true;
6162
}
6263
catch (Exception e)
6364
{
64-
_logger.LogCritical(e, "Fatal error occurred while activating {TypeFullName}.", typeof(TStartup).FullName);
65+
Decorator.EncloseToExpose(_logger, false).FatalErrorActivating(typeof(TStartup).FullName, e);
6566
}
6667
}, cancellationToken);
6768

@@ -70,7 +71,7 @@ public Task StartAsync(CancellationToken cancellationToken)
7071
}
7172
else
7273
{
73-
_logger.LogWarning("Unable to activate an instance of {TypeFullName}.", typeof(TStartup).FullName);
74+
Decorator.EncloseToExpose(_logger, false).UnableToActivateInstance(typeof(TStartup).FullName);
7475
}
7576

7677
return Task.CompletedTask;
@@ -91,11 +92,11 @@ public Task StopAsync(CancellationToken cancellationToken)
9192
{
9293
if (!_ranToCompletion)
9394
{
94-
_logger?.LogInformation("RunAsync ended prematurely.");
95+
Decorator.EncloseToExpose(_logger, false)?.RunAsyncPrematureEnd();
9596
}
9697
else
9798
{
98-
_logger?.LogInformation("RunAsync completed successfully.");
99+
Decorator.EncloseToExpose(_logger, false)?.RunAsyncCompleted();
99100
}
100101

101102
return Task.CompletedTask;

src/Codebelt.Bootstrapper.Console/MinimalConsoleHostedService.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Threading;
66
using System.Threading.Tasks;
7+
using Cuemon;
78

89
namespace Codebelt.Bootstrapper.Console
910
{
@@ -57,18 +58,18 @@ public Task StartAsync(CancellationToken cancellationToken)
5758
{
5859
if (program != null)
5960
{
60-
_logger.LogInformation("RunAsync started.");
61+
Decorator.EncloseToExpose(_logger, false).RunAsyncStarted();
6162
await program.RunAsync(_provider, cancellationToken).ConfigureAwait(false);
6263
_ranToCompletion = true;
6364
}
6465
else
6566
{
66-
_logger.LogWarning("Unable to activate an instance of {TypeFullName}.", programType.FullName);
67+
Decorator.EncloseToExpose(_logger, false).UnableToActivateInstance(programType.FullName);
6768
}
6869
}
6970
catch (Exception e)
7071
{
71-
_logger.LogCritical(e, "Fatal error occurred while activating {TypeFullName}.", programType.FullName);
72+
Decorator.EncloseToExpose(_logger, false).FatalErrorActivating(programType.FullName, e);
7273
}
7374
}, cancellationToken);
7475

@@ -93,11 +94,11 @@ public Task StopAsync(CancellationToken cancellationToken)
9394
{
9495
if (!_ranToCompletion)
9596
{
96-
_logger?.LogInformation("RunAsync ended prematurely.");
97+
Decorator.EncloseToExpose(_logger, false)?.RunAsyncPrematureEnd();
9798
}
9899
else
99100
{
100-
_logger?.LogInformation("RunAsync completed successfully.");
101+
Decorator.EncloseToExpose(_logger, false)?.RunAsyncCompleted();
101102
}
102103

103104
return Task.CompletedTask;

src/Codebelt.Bootstrapper/BootstrapperLifetime.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ private void OnApplicationStopping()
8787
}
8888

8989
/// <summary>
90-
/// Called when this object is being disposed by either <see cref="M:Cuemon.Disposable.Dispose" /> or <see cref="M:Cuemon.Disposable.Dispose(System.Boolean)" /> having <c>disposing</c> set to <c>true</c> and <see cref="P:Cuemon.Disposable.Disposed" /> is <c>false</c>.
90+
/// Called when this object is being disposed by either <see cref="Disposable.Dispose()" /> or <see cref="Disposable.Dispose(bool)" /> having <c>disposing</c> set to <c>true</c> and <see cref="Disposable.Disposed" /> is <c>false</c>.
9191
/// </summary>
9292
protected override void OnDisposeManagedResources()
9393
{
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System;
2+
using Cuemon;
3+
using Microsoft.Extensions.Logging;
4+
5+
namespace Codebelt.Bootstrapper
6+
{
7+
/// <summary>
8+
/// Provides centralized logging messages for the Bootstrapper SDK using the LoggerMessage pattern.
9+
/// This API supports the product infrastructure and is not intended to be used directly from your code.
10+
/// </summary>
11+
/// <remarks>https://learn.microsoft.com/en-us/dotnet/core/extensions/high-performance-logging</remarks>
12+
public static class BootstrapperLogMessages
13+
{
14+
// Information messages
15+
private static readonly Action<ILogger, Exception> RunAsyncStartedDefinition = LoggerMessage.Define(LogLevel.Information, new EventId(1000, nameof(RunAsyncStarted)), "RunAsync started.");
16+
private static readonly Action<ILogger, Exception> RunAsyncPrematureEndDefinition = LoggerMessage.Define(LogLevel.Information, new EventId(1001, nameof(RunAsyncPrematureEnd)), "RunAsync ended prematurely.");
17+
private static readonly Action<ILogger, Exception> RunAsyncCompletedDefinition = LoggerMessage.Define(LogLevel.Information, new EventId(1002, nameof(RunAsyncCompleted)), "RunAsync completed successfully.");
18+
19+
// Warning messages
20+
private static readonly Action<ILogger, string, Exception> UnableToActivateInstanceDefinition = LoggerMessage.Define<string>(LogLevel.Warning, new EventId(2000, nameof(UnableToActivateInstance)), "Unable to activate an instance of {TypeFullName}.");
21+
22+
// Critical messages
23+
private static readonly Action<ILogger, string, Exception> FatalErrorActivatingDefinition = LoggerMessage.Define<string>(LogLevel.Critical, new EventId(3000, nameof(FatalErrorActivating)), "Fatal error occurred while activating {TypeFullName}.");
24+
25+
/// <summary>
26+
/// Logs that RunAsync has started.
27+
/// </summary>
28+
/// <param name="logger">The logger instance.</param>
29+
public static void RunAsyncStarted(this IDecorator<ILogger> logger)
30+
{
31+
RunAsyncStartedDefinition(logger.Inner, null);
32+
}
33+
34+
/// <summary>
35+
/// Logs that RunAsync ended prematurely.
36+
/// </summary>
37+
/// <param name="logger">The logger instance.</param>
38+
public static void RunAsyncPrematureEnd(this IDecorator<ILogger> logger)
39+
{
40+
RunAsyncPrematureEndDefinition(logger.Inner, null);
41+
}
42+
43+
/// <summary>
44+
/// Logs that RunAsync completed successfully.
45+
/// </summary>
46+
/// <param name="logger">The logger instance.</param>
47+
public static void RunAsyncCompleted(this IDecorator<ILogger> logger)
48+
{
49+
RunAsyncCompletedDefinition(logger.Inner, null);
50+
}
51+
52+
/// <summary>
53+
/// Logs an inability to activate the specified type.
54+
/// </summary>
55+
/// <param name="logger">The logger instance.</param>
56+
/// <param name="typeFullName">The full name of the type that couldn't be activated.</param>
57+
public static void UnableToActivateInstance(this IDecorator<ILogger> logger, string typeFullName)
58+
{
59+
UnableToActivateInstanceDefinition(logger.Inner, typeFullName, null);
60+
}
61+
62+
/// <summary>
63+
/// Logs a fatal error that occurred while activating a type.
64+
/// </summary>
65+
/// <param name="logger">The logger instance.</param>
66+
/// <param name="typeFullName">The full name of the type being activated.</param>
67+
/// <param name="exception">The exception that occurred.</param>
68+
public static void FatalErrorActivating(this IDecorator<ILogger> logger, string typeFullName, Exception exception)
69+
{
70+
FatalErrorActivatingDefinition(logger.Inner, typeFullName, exception);
71+
}
72+
}
73+
}

0 commit comments

Comments
 (0)