Skip to content

Commit ada298d

Browse files
authored
+semver:minor - context.LogOnPipelineEnd(...) method (#497)
* `context.LogOnPipelineEnd(...)` method to easily log information at the end of the pipeline where it's easier to find in logs * Formatting Markdown * Tests * catch * Move call to AfterPipelineLogger --------- Co-authored-by: Tom Longhurst <[email protected]>
1 parent 4c9a840 commit ada298d

File tree

9 files changed

+150
-6
lines changed

9 files changed

+150
-6
lines changed

src/ModularPipelines.Build/Modules/NugetVersionGeneratorModule.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Microsoft.Extensions.Options;
33
using ModularPipelines.Build.Settings;
44
using ModularPipelines.Context;
5+
using ModularPipelines.Extensions;
56
using ModularPipelines.Git.Extensions;
67
using ModularPipelines.Modules;
78

@@ -21,12 +22,13 @@ public NugetVersionGeneratorModule(IOptions<PublishSettings> publishSettings)
2122
{
2223
var gitVersionInformation = await context.Git().Versioning.GetGitVersioningInformation();
2324

24-
if (_publishSettings.Value.IsAlpha)
25-
{
26-
return $"{gitVersionInformation.FullSemVer}-alpha{gitVersionInformation.CommitsSinceVersionSourcePadded!}";
27-
}
25+
var version = _publishSettings.Value.IsAlpha
26+
? $"{gitVersionInformation.FullSemVer}-alpha{gitVersionInformation.CommitsSinceVersionSourcePadded!}"
27+
: gitVersionInformation.FullSemVer!;
2828

29-
return gitVersionInformation.FullSemVer;
29+
context.LogOnPipelineEnd($"Generated Version Number: {version}");
30+
31+
return version;
3032
}
3133

3234
/// <inheritdoc/>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
* Throw an exception when defining duplicate constraint keys on the same NotInParallel attribute
2+
* `context.LogOnPipelineEnd(...)` method to easily log information at the end of the pipeline where it's easier to find in logs

src/ModularPipelines/DependencyInjection/DependencyInjectionSetup.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public static void Initialize(IServiceCollection services)
6767
// Singletons
6868
services
6969
.AddSingleton<IConsolePrinter, ConsolePrinter>()
70+
.AddSingleton<IAfterPipelineLogger, AfterPipelineLogger>()
7071
.AddSingleton<IExceptionContainer, ExceptionContainer>()
7172
.AddSingleton<IPipelineContextProvider, ModuleContextProvider>()
7273
.AddSingleton<IDependencyChainProvider, DependencyChainProvider>()

src/ModularPipelines/Engine/Executors/ExecutionOrchestrator.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Diagnostics;
22
using Microsoft.Extensions.Logging;
33
using ModularPipelines.Helpers;
4+
using ModularPipelines.Logging;
45
using ModularPipelines.Models;
56
using ModularPipelines.Modules;
67

@@ -14,6 +15,7 @@ internal class ExecutionOrchestrator : IExecutionOrchestrator
1415
private readonly IPrintProgressExecutor _printProgressExecutor;
1516
private readonly IPipelineExecutor _pipelineExecutor;
1617
private readonly IConsolePrinter _consolePrinter;
18+
private readonly IAfterPipelineLogger _afterPipelineLogger;
1719
private readonly EngineCancellationToken _engineCancellationToken;
1820
private readonly ILogger<ExecutionOrchestrator> _logger;
1921

@@ -27,6 +29,7 @@ public ExecutionOrchestrator(IPipelineInitializer pipelineInitializer,
2729
IPrintProgressExecutor printProgressExecutor,
2830
IPipelineExecutor pipelineExecutor,
2931
IConsolePrinter consolePrinter,
32+
IAfterPipelineLogger afterPipelineLogger,
3033
EngineCancellationToken engineCancellationToken,
3134
ILogger<ExecutionOrchestrator> logger)
3235
{
@@ -36,6 +39,7 @@ public ExecutionOrchestrator(IPipelineInitializer pipelineInitializer,
3639
_printProgressExecutor = printProgressExecutor;
3740
_pipelineExecutor = pipelineExecutor;
3841
_consolePrinter = consolePrinter;
42+
_afterPipelineLogger = afterPipelineLogger;
3943
_engineCancellationToken = engineCancellationToken;
4044
_logger = logger;
4145
}
@@ -48,9 +52,13 @@ public async Task<PipelineSummary> ExecuteAsync(CancellationToken cancellationTo
4852
}
4953
catch
5054
{
51-
await Task.Delay(TimeSpan.FromSeconds(1));
55+
await Task.Delay(TimeSpan.FromSeconds(1), CancellationToken.None);
5256
throw;
5357
}
58+
finally
59+
{
60+
_afterPipelineLogger.WriteLogs();
61+
}
5462
}
5563

5664
private async Task<PipelineSummary> ExecuteInternal(CancellationToken cancellationToken)

src/ModularPipelines/Engine/Executors/PipelineExecutor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Diagnostics;
22
using Microsoft.Extensions.Logging;
3+
using ModularPipelines.Logging;
34
using ModularPipelines.Models;
45
using ModularPipelines.Modules;
56

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using ModularPipelines.Context;
2+
using ModularPipelines.Logging;
3+
4+
namespace ModularPipelines.Extensions;
5+
6+
public static class ContextExtensions
7+
{
8+
public static void LogOnPipelineEnd(this IPipelineHookContext pipelineContext, string value)
9+
{
10+
var afterPipelineLogger = pipelineContext.Get<IAfterPipelineLogger>()!;
11+
afterPipelineLogger.LogOnPipelineEnd(value);
12+
}
13+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Microsoft.Extensions.Logging;
2+
3+
namespace ModularPipelines.Logging;
4+
5+
internal class AfterPipelineLogger : IAfterPipelineLogger
6+
{
7+
private readonly ILogger<AfterPipelineLogger> _logger;
8+
private readonly List<string> _values = [];
9+
10+
public AfterPipelineLogger(ILogger<AfterPipelineLogger> logger)
11+
{
12+
_logger = logger;
13+
}
14+
15+
public void LogOnPipelineEnd(string value)
16+
{
17+
_values.Add(value);
18+
}
19+
20+
public void WriteLogs()
21+
{
22+
foreach (var value in _values)
23+
{
24+
_logger.LogInformation("{Value}", value);
25+
}
26+
}
27+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
namespace ModularPipelines.Logging;
2+
3+
public interface IAfterPipelineLogger
4+
{
5+
void LogOnPipelineEnd(string value);
6+
7+
internal void WriteLogs();
8+
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using System.Text;
2+
using Microsoft.Extensions.DependencyInjection;
3+
using Microsoft.Extensions.Logging;
4+
using ModularPipelines.Context;
5+
using ModularPipelines.Extensions;
6+
using ModularPipelines.Modules;
7+
using ModularPipelines.TestHelpers;
8+
using NReco.Logging.File;
9+
using TUnit.Assertions.Extensions;
10+
using File = ModularPipelines.FileSystem.File;
11+
using Type = System.Type;
12+
13+
namespace ModularPipelines.UnitTests;
14+
15+
public class AfterPipelineLoggerTests
16+
{
17+
private class AfterPipelineLoggingModule : Module
18+
{
19+
protected override async Task<IDictionary<string, object>?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken)
20+
{
21+
context.LogOnPipelineEnd("Blah!");
22+
await Task.CompletedTask;
23+
return null;
24+
}
25+
}
26+
27+
private class AfterPipelineLoggingWithExceptionModule : Module
28+
{
29+
protected override async Task<IDictionary<string, object>?> ExecuteAsync(IPipelineContext context, CancellationToken cancellationToken)
30+
{
31+
context.LogOnPipelineEnd("Blah!");
32+
await Task.CompletedTask;
33+
throw new Exception();
34+
}
35+
}
36+
37+
[Test]
38+
public async Task LogsAfterPipeline()
39+
{
40+
var stringBuilder = new StringBuilder();
41+
var host = await TestPipelineHostBuilder.Create()
42+
.ConfigureServices((_, collection) =>
43+
{
44+
collection.AddSingleton(stringBuilder);
45+
collection.AddSingleton(typeof(ILogger<>), typeof(StringLogger<>));
46+
})
47+
.AddModule<AfterPipelineLoggingModule>()
48+
.BuildHostAsync();
49+
50+
await host.ExecutePipelineAsync();
51+
52+
await host.DisposeAsync();
53+
54+
await Assert.That(stringBuilder.ToString().Trim()).Does.EndWith("Blah!");
55+
}
56+
57+
[Test]
58+
public async Task LogsAfterPipelineWithException()
59+
{
60+
var stringBuilder = new StringBuilder();
61+
var host = await TestPipelineHostBuilder.Create()
62+
.ConfigureServices((_, collection) =>
63+
{
64+
collection.AddSingleton(stringBuilder);
65+
collection.AddSingleton(typeof(ILogger<>), typeof(StringLogger<>));
66+
})
67+
.AddModule<AfterPipelineLoggingWithExceptionModule>()
68+
.BuildHostAsync();
69+
70+
try
71+
{
72+
await host.ExecutePipelineAsync();
73+
}
74+
catch
75+
{
76+
// Ignored
77+
}
78+
79+
await host.DisposeAsync();
80+
81+
await Assert.That(stringBuilder.ToString().Trim()).Does.EndWith("Blah!");
82+
}
83+
}

0 commit comments

Comments
 (0)