Skip to content

Commit 2dbf4d6

Browse files
authored
Merge pull request #27 from MikDal002/26-dodać-możliwość-logowania
✨ feat(logging): add robust Serilog logging with parameter sanitization
2 parents 7369653 + 679df5f commit 2dbf4d6

22 files changed

+519
-214
lines changed
Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
// In ZtrTemplates.Configuration.Shared/UpdateOptions.cs
2-
namespace ZtrTemplates.Configuration.Shared
2+
namespace ZtrTemplates.Configuration.Shared;
3+
4+
public class UpdateOptions
35
{
4-
public class UpdateOptions
5-
{
6-
// This property name directly corresponds to the JSON key "UpdateUrl"
7-
public string? UpdateUrl { get; set; }
8-
}
6+
// This property name directly corresponds to the JSON key "UpdateUrl"
7+
public string? UpdateUrl { get; set; }
98
}

build/Build.ApplicationConfiguration.cs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ public partial class Build
1111
readonly string UpdateBaseUrl = "https://frog02-20366.wykr.es";
1212

1313
Target ConfigureAppSettings => _ => _
14-
.DependsOn(Clean)
14+
.DependsOn(Clean)
1515
.TriggeredBy(Clean)
16-
.Unlisted()
16+
.Unlisted()
1717
.Executes(() =>
1818
{
1919
Log.Information("Configuring appsettings.json for deployment...");
@@ -44,17 +44,15 @@ public partial class Build
4444
rootNode = null;
4545
}
4646

47-
4847
rootNode ??= new JsonObject();
4948

50-
5149
if (rootNode[nameof(UpdateOptions)] is not JsonObject updateOptionsNode)
5250
{
5351
updateOptionsNode = new JsonObject();
5452
rootNode[nameof(UpdateOptions)] = updateOptionsNode;
5553
}
56-
updateOptionsNode[nameof(UpdateOptions.UpdateUrl)] = updateUrl;
5754

55+
updateOptionsNode[nameof(UpdateOptions.UpdateUrl)] = updateUrl;
5856

5957
var jsonOptions = new JsonSerializerOptions { WriteIndented = true };
6058
File.WriteAllText(appSettingsPath, rootNode.ToJsonString(jsonOptions));

build/Build.GitHub.cs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
1-
using Nuke.Common.CI.GitHubActions;
1+
using Nuke.Common;
2+
using Nuke.Common.CI.GitHubActions;
23
using Nuke.Common.IO;
34
using Nuke.Common.Tools.GitHub;
45
using Nuke.Common.Tools.GitVersion;
5-
using Nuke.Common;
6-
using Octokit;
7-
using System;
8-
using System.Collections.Generic;
9-
using System.Linq;
10-
using System.Text;
11-
using System.Threading.Tasks;
126
using Nuke.Common.Utilities;
13-
using static System.Net.Mime.MediaTypeNames;
7+
using Octokit;
148
using Octokit.Internal;
159
using System.IO;
1610

build/Build.Velopack.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@
33
using Nuke.Common.Tooling;
44
using Nuke.Common.Utilities;
55
using Renci.SshNet;
6-
using Serilog;
7-
using System.IO;
8-
using System.Text.Json;
9-
using System.Text.Json.Nodes;
10-
using ZtrTemplates.Configuration.Shared;
116

127
partial class Build
138
{
@@ -18,13 +13,12 @@ partial class Build
1813
[Parameter] readonly int SshPort = 10366;
1914
[Parameter] readonly string SshUser = "frog";
2015
[Parameter] readonly string SshServer = "frog02.mikr.us";
21-
ConnectionInfo SshConnectionInfo => new ConnectionInfo(SshServer, port: SshPort, SshUser, new PrivateKeyAuthenticationMethod(SshUser, new PrivateKeyFile(SshPrivateKey)));
16+
ConnectionInfo SshConnectionInfo => new(SshServer, port: SshPort, SshUser, new PrivateKeyAuthenticationMethod(SshUser, new PrivateKeyFile(SshPrivateKey)));
2217

2318
[Parameter] readonly int MaxReleasesOnServer = 2;
2419
[Parameter] readonly string DirectoryForReleases = "releases";
2520
string Channel => $"{OperationSystem}-{SystemArchitecture}" + (GitVersion.PreReleaseLabel.IsNullOrWhiteSpace() ? "" : "-alpha");
2621

27-
2822
AbsolutePath SshPrivateKey = RootDirectory / "ztrtemplates";
2923

3024
AbsolutePath VelopackDirectory = RootDirectory / "Velopack";
@@ -58,7 +52,7 @@ partial class Build
5852
using var sshClient = new SshClient(SshConnectionInfo);
5953
sshClient.Connect();
6054
using var cmd = sshClient.RunCommand($"mkdir -p /var/www/html/{NameProjectDirectoryOnTheServer}/{DirectoryForReleases}");
61-
55+
6256
VelopackReleaseMirroredFromRemoteServer.CreateOrCleanDirectory();
6357
Scp.Invoke(
6458
$"-i {SshPrivateKey} -r -P {SshPort} {SshUser}@{SshServer}:/var/www/html/{NameProjectDirectoryOnTheServer}/{DirectoryForReleases} {VelopackReleaseMirroredFromRemoteServer}");

build/Build.cs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
11
using Nuke.Common;
2-
using Nuke.Common.CI.GitHubActions;
32
using Nuke.Common.Git;
43
using Nuke.Common.IO;
54
using Nuke.Common.ProjectModel;
65
using Nuke.Common.Tooling;
76
using Nuke.Common.Tools.DotNet;
87
using Nuke.Common.Tools.Git;
9-
using Nuke.Common.Tools.GitHub;
108
using Nuke.Common.Tools.GitVersion;
11-
using Nuke.Common.Utilities;
129
using Nuke.Common.Utilities.Collections;
1310
using Serilog;
14-
using System.IO;
1511

1612
public partial class Build : NukeBuild
1713
{
@@ -32,7 +28,6 @@ public partial class Build : NukeBuild
3228
[Parameter("System architecture to build, deafults to current architecture. Change if you want to cross compile")]
3329
readonly SystemArchitecture SystemArchitecture = SystemArchitecture.GetCurrentConfiguration();
3430

35-
3631
string Runtime => $"{OperationSystem}-{SystemArchitecture}";
3732

3833
/// <summary>

build/Parameters/Configuration.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
using System.ComponentModel;
2-
using System.Linq;
31
using Nuke.Common.Tooling;
2+
using System.ComponentModel;
43

54
[TypeConverter(typeof(TypeConverter<Configuration>))]
65
public class Configuration : Enumeration

build/Parameters/OperationSystem.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
using System;
2-
using System.ComponentModel;
3-
using Nuke.Common;
1+
using Nuke.Common;
42
using Nuke.Common.Tooling;
3+
using System;
4+
using System.ComponentModel;
55

66
[TypeConverter(typeof(TypeConverter<OperationSystem>))]
77
public class OperationSystem : Enumeration

build/Parameters/SystemArchitecture.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
using System;
2-
using System.ComponentModel;
3-
using Nuke.Common;
1+
using Nuke.Common;
42
using Nuke.Common.Tooling;
3+
using System;
4+
using System.ComponentModel;
55

66
[TypeConverter(typeof(TypeConverter<SystemArchitecture>))]
77
public class SystemArchitecture : Enumeration
Lines changed: 60 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,76 @@
11
using ConsoleTemplate.Infrastructure;
22

3-
namespace ConsoleTemplate.Tests.Infrastructure
3+
namespace ConsoleTemplate.Tests.Infrastructure;
4+
5+
[TestFixture]
6+
public class ConsoleAppCancellationTokenSourceTests
47
{
5-
[TestFixture]
6-
public class ConsoleAppCancellationTokenSourceTests
7-
{
8-
private ConsoleAppCancellationTokenSource _sut = null!; // System Under Test
8+
private ConsoleAppCancellationTokenSource _sut = null!; // System Under Test
99

10-
[SetUp]
11-
public void Setup()
12-
{
13-
// Create a new instance before each test
14-
_sut = new ConsoleAppCancellationTokenSource();
15-
}
10+
[SetUp]
11+
public void Setup()
12+
{
13+
// Create a new instance before each test
14+
_sut = new ConsoleAppCancellationTokenSource();
15+
}
1616

17-
[TearDown]
18-
public void Teardown()
19-
{
20-
// Ensure disposal after each test
21-
_sut?.Dispose();
22-
}
17+
[TearDown]
18+
public void Teardown()
19+
{
20+
// Ensure disposal after each test
21+
_sut?.Dispose();
22+
}
2323

24-
[Test]
25-
public void Constructor_ShouldInitializeToken_WhichIsNotCancelled()
26-
{
27-
// Act
28-
var token = _sut.Token;
24+
[Test]
25+
public void Constructor_ShouldInitializeToken_WhichIsNotCancelled()
26+
{
27+
// Act
28+
var token = _sut.Token;
2929

30-
// Assert
31-
token.IsCancellationRequested.Should().BeFalse();
32-
token.CanBeCanceled.Should().BeTrue();
33-
}
30+
// Assert
31+
token.IsCancellationRequested.Should().BeFalse();
32+
token.CanBeCanceled.Should().BeTrue();
33+
}
3434

35-
[Test]
36-
public void Dispose_ShouldCancelTheToken()
37-
{
38-
// Arrange
39-
var token = _sut.Token;
40-
token.IsCancellationRequested.Should().BeFalse(); // Pre-condition
35+
[Test]
36+
public void Dispose_ShouldCancelTheToken()
37+
{
38+
// Arrange
39+
var token = _sut.Token;
40+
token.IsCancellationRequested.Should().BeFalse(); // Pre-condition
4141

42-
// Act
43-
_sut.Dispose();
42+
// Act
43+
_sut.Dispose();
4444

45-
// Assert
46-
// Give a brief moment for potential background operations triggered by Dispose/Cancel
47-
Thread.Sleep(50); // Small delay might be needed depending on thread scheduling
48-
token.IsCancellationRequested.Should().BeTrue();
49-
}
45+
// Assert
46+
// Give a brief moment for potential background operations triggered by Dispose/Cancel
47+
Thread.Sleep(50); // Small delay might be needed depending on thread scheduling
48+
token.IsCancellationRequested.Should().BeTrue();
49+
}
5050

51-
[Test]
52-
public void Dispose_CanBeCalledMultipleTimes_WithoutThrowing()
53-
{
54-
// Arrange
55-
_sut.Dispose(); // First call
51+
[Test]
52+
public void Dispose_CanBeCalledMultipleTimes_WithoutThrowing()
53+
{
54+
// Arrange
55+
_sut.Dispose(); // First call
5656

57-
// Act & Assert
58-
Action secondDispose = () => _sut.Dispose();
59-
secondDispose.Should().NotThrow();
60-
}
57+
// Act & Assert
58+
Action secondDispose = () => _sut.Dispose();
59+
secondDispose.Should().NotThrow();
60+
}
6161

62-
[Test]
63-
public void Token_ShouldReturnSameInstance()
64-
{
65-
// Act
66-
var token1 = _sut.Token;
67-
var token2 = _sut.Token;
62+
[Test]
63+
public void Token_ShouldReturnSameInstance()
64+
{
65+
// Act
66+
var token1 = _sut.Token;
67+
var token2 = _sut.Token;
6868

69-
// Assert
70-
// CancellationToken is a struct, so we compare properties or rely on reference equality of the source
71-
// For simplicity, we check CanBeCanceled as an indicator it's from the same source.
72-
// A more robust check might involve reflection or modifying the SUT, but this is sufficient for basic validation.
73-
token1.CanBeCanceled.Should().Be(token2.CanBeCanceled);
74-
token1.IsCancellationRequested.Should().Be(token2.IsCancellationRequested);
75-
}
69+
// Assert
70+
// CancellationToken is a struct, so we compare properties or rely on reference equality of the source
71+
// For simplicity, we check CanBeCanceled as an indicator it's from the same source.
72+
// A more robust check might involve reflection or modifying the SUT, but this is sufficient for basic validation.
73+
token1.CanBeCanceled.Should().Be(token2.CanBeCanceled);
74+
token1.IsCancellationRequested.Should().Be(token2.IsCancellationRequested);
7675
}
7776
}

templates/console/Commands/Base/CancellableAsyncCommand.cs

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,50 +4,49 @@
44
using System.Threading;
55
using System.Threading.Tasks;
66

7-
namespace ConsoleTemplate.Commands.Base
7+
namespace ConsoleTemplate.Commands.Base;
8+
9+
/// <summary>
10+
/// Base class for Spectre.Console commands that support cancellation via Ctrl+C or process exit.
11+
/// </summary>
12+
/// <typeparam name="TSettings">The command settings type.</typeparam>
13+
public abstract class CancellableAsyncCommand<TSettings> : AsyncCommand<TSettings>
14+
where TSettings : CommandSettings
815
{
16+
private readonly Lazy<ConsoleAppCancellationTokenSource> _cancellationTokenSource =
17+
new(() => new());
18+
919
/// <summary>
10-
/// Base class for Spectre.Console commands that support cancellation via Ctrl+C or process exit.
20+
/// Executes the command asynchronously with cancellation support.
21+
/// This method is sealed and cannot be overridden by derived classes.
22+
/// Implement the cancellation-aware logic in <see cref="ExecuteAsync(CommandContext, TSettings, CancellationToken)"/>.
1123
/// </summary>
12-
/// <typeparam name="TSettings">The command settings type.</typeparam>
13-
public abstract class CancellableAsyncCommand<TSettings> : AsyncCommand<TSettings>
14-
where TSettings : CommandSettings
24+
/// <param name="context">The command context.</param>
25+
/// <param name="settings">The command settings.</param>
26+
/// <returns>The exit code.</returns>
27+
public sealed override async Task<int> ExecuteAsync(CommandContext context, TSettings settings)
1528
{
16-
private readonly Lazy<ConsoleAppCancellationTokenSource> _cancellationTokenSource =
17-
new(() => new());
18-
19-
/// <summary>
20-
/// Executes the command asynchronously with cancellation support.
21-
/// This method is sealed and cannot be overridden by derived classes.
22-
/// Implement the cancellation-aware logic in <see cref="ExecuteAsync(CommandContext, TSettings, CancellationToken)"/>.
23-
/// </summary>
24-
/// <param name="context">The command context.</param>
25-
/// <param name="settings">The command settings.</param>
26-
/// <returns>The exit code.</returns>
27-
public sealed override async Task<int> ExecuteAsync(CommandContext context, TSettings settings)
29+
try
2830
{
29-
try
30-
{
31-
var cancellationToken = _cancellationTokenSource.Value.Token;
32-
return await ExecuteAsync(context, settings, cancellationToken);
33-
}
34-
finally
31+
var cancellationToken = _cancellationTokenSource.Value.Token;
32+
return await ExecuteAsync(context, settings, cancellationToken);
33+
}
34+
finally
35+
{
36+
if (_cancellationTokenSource.IsValueCreated)
3537
{
36-
if (_cancellationTokenSource.IsValueCreated)
37-
{
38-
_cancellationTokenSource.Value.Dispose();
39-
}
38+
_cancellationTokenSource.Value.Dispose();
4039
}
4140
}
42-
43-
/// <summary>
44-
/// Executes the command asynchronously with cancellation support.
45-
/// Derived classes must implement this method to provide the command logic.
46-
/// </summary>
47-
/// <param name="context">The command context.</param>
48-
/// <param name="settings">The command settings.</param>
49-
/// <param name="cancellationToken">The cancellation token.</param>
50-
/// <returns>A task representing the asynchronous operation, returning the exit code.</returns>
51-
public abstract Task<int> ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken);
5241
}
42+
43+
/// <summary>
44+
/// Executes the command asynchronously with cancellation support.
45+
/// Derived classes must implement this method to provide the command logic.
46+
/// </summary>
47+
/// <param name="context">The command context.</param>
48+
/// <param name="settings">The command settings.</param>
49+
/// <param name="cancellationToken">The cancellation token.</param>
50+
/// <returns>A task representing the asynchronous operation, returning the exit code.</returns>
51+
public abstract Task<int> ExecuteAsync(CommandContext context, TSettings settings, CancellationToken cancellationToken);
5352
}

0 commit comments

Comments
 (0)