Skip to content

Commit

Permalink
feat(launchSettings.json): add empty commandName to support new proje…
Browse files Browse the repository at this point in the history
…ct commands

refactor(MigrationExecuteCommand.cs, MigrationInitCommand.cs): change logger type to improve logging context
refactor(MigrationInitCommand.cs): change ExecuteAsync method to async to improve readability and performance
refactor(MigrationService.cs): skip first command line argument to avoid application name in arguments
refactor(MigrationToolHost.cs): refactor host configuration and services setup to improve code readability and maintainability
style(HostExtensions.cs): remove unused import to improve code cleanliness
style(MigrationToolHost.cs): remove commented out code to improve code cleanliness

feat(MigrationTools.Host.csproj): add Spectre.Console.Cli.Extensions.DependencyInjection package to support dependency injection
  • Loading branch information
MrHinsh committed Jul 23, 2024
1 parent d15c9a3 commit e02601e
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 123 deletions.
3 changes: 3 additions & 0 deletions src/MigrationTools.ConsoleCore/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"MigrationTools.ConsoleUI": {
"commandName": "Project",
"commandLineArgs": "execute --config \"configuration.json\""
},
"empty": {
"commandName": "Project"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ internal class MigrationExecuteCommand : AsyncCommand<MigrationExecuteCommandSet
private readonly ITelemetryLogger Telemetery;

public MigrationExecuteCommand(IServiceProvider services,
ILogger<ExecuteHostedService> logger,
ILogger<MigrationExecuteCommand> logger,
IHostApplicationLifetime appLifetime, ITelemetryLogger telemetryLogger)
{
Telemetery = telemetryLogger;
Expand Down
4 changes: 2 additions & 2 deletions src/MigrationTools.Host/Commands/MigrationInitCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ internal class MigrationInitCommand : AsyncCommand<MigrationInitCommandSettings>
public MigrationInitCommand(
IEngineConfigurationBuilder configurationBuilder,
ISettingsWriter settingsWriter,
ILogger<InitHostedService> logger,
ILogger<MigrationInitCommand> logger,
ITelemetryLogger telemetryLogger,
IHostApplicationLifetime appLifetime)
{
Expand All @@ -35,7 +35,7 @@ public MigrationInitCommand(
}


public override Task<int> ExecuteAsync(CommandContext context, MigrationInitCommandSettings settings)
public override async Task<int> ExecuteAsync(CommandContext context, MigrationInitCommandSettings settings)
{
int _exitCode;
try
Expand Down
1 change: 0 additions & 1 deletion src/MigrationTools.Host/HostExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using MigrationTools.Host.CommandLine;

namespace MigrationTools.Host
{
Expand Down
3 changes: 2 additions & 1 deletion src/MigrationTools.Host/MigrationService.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -25,7 +26,7 @@ public MigrationService(ICommandApp appCommand, IHostApplicationLifetime appLife

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await AppCommand.RunAsync(Environment.GetCommandLineArgs());
await AppCommand.RunAsync(Environment.GetCommandLineArgs().Skip(1));
AppLifetime.StopApplication();
}
}
Expand Down
201 changes: 83 additions & 118 deletions src/MigrationTools.Host/MigrationToolHost.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,82 +18,74 @@
using Serilog.Core;
using Serilog.Events;
using Serilog.Sinks.SystemConsole.Themes;
using Spectre.Console.Cli.Extensions.DependencyInjection;
using Spectre.Console.Cli;

namespace MigrationTools.Host
{
public static class MigrationToolHost
{
public static IHostBuilder CreateDefaultBuilder(string[] args)
{
(var initOptions, var executeOptions) = ParseOptions(args);
var hostBuilder = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args);

if (initOptions is null && executeOptions is null)
hostBuilder.UseSerilog((hostingContext, services, loggerConfiguration) =>
{
return null;
}



var hostBuilder = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args)
.UseSerilog((hostingContext, services, loggerConfiguration) =>
string outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] [" + GetVersionTextForLog() + "] {Message:lj}{NewLine}{Exception}";
string logsPath = CreateLogsPath();
var logPath = Path.Combine(logsPath, "migration.log");
var logLevel = hostingContext.Configuration.GetValue<LogEventLevel>("LogLevel");
var levelSwitch = new LoggingLevelSwitch(logLevel);
loggerConfiguration
.MinimumLevel.ControlledBy(levelSwitch)
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithProcessId()
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Debug, theme: AnsiConsoleTheme.Code, outputTemplate: outputTemplate)
.WriteTo.ApplicationInsights(services.GetService<TelemetryClient>(), new CustomConverter(), LogEventLevel.Error)
.WriteTo.File(logPath, LogEventLevel.Verbose, outputTemplate: outputTemplate);
});

hostBuilder.ConfigureLogging((context, logBuilder) =>
{
string outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] [" + GetVersionTextForLog() + "] {Message:lj}{NewLine}{Exception}";
string logsPath = CreateLogsPath();
var logPath = Path.Combine(logsPath, "migration.log");
var logLevel = hostingContext.Configuration.GetValue<LogEventLevel>("LogLevel");
var levelSwitch = new LoggingLevelSwitch(logLevel);
loggerConfiguration
.MinimumLevel.ControlledBy(levelSwitch)
.ReadFrom.Configuration(hostingContext.Configuration)
.Enrich.FromLogContext()
.Enrich.WithMachineName()
.Enrich.WithProcessId()
.WriteTo.Console(restrictedToMinimumLevel: LogEventLevel.Debug, theme: AnsiConsoleTheme.Code, outputTemplate: outputTemplate)
.WriteTo.ApplicationInsights(services.GetService<TelemetryClient>(), new CustomConverter(), LogEventLevel.Error)
.WriteTo.File(logPath, LogEventLevel.Verbose, outputTemplate: outputTemplate);
})
.ConfigureLogging((context, logBuilder) =>
{
})
.ConfigureAppConfiguration(builder =>
{
if (executeOptions is not null)
{
builder.AddJsonFile(executeOptions.ConfigFile);
}
})
.ConfigureServices((context, services) =>
});
//.ConfigureAppConfiguration(builder =>
//{
// if (executeOptions is not null)
// {
// builder.AddJsonFile(executeOptions.ConfigFile);
// }
//})

hostBuilder.ConfigureServices((context, services) =>
{
services.AddOptions();
services.Configure<EngineConfiguration>((config) =>
{
if(executeOptions is null)
{
return;
}
var sp = services.BuildServiceProvider();
var logger = sp.GetService<ILoggerFactory>().CreateLogger<EngineConfiguration>();
if (!File.Exists(executeOptions.ConfigFile))
{
logger.LogInformation("The config file {ConfigFile} does not exist, nor does the default 'configuration.json'. Use '{ExecutableName}.exe init' to create a configuration file first", executeOptions.ConfigFile, Assembly.GetEntryAssembly().GetName().Name);
throw new ArgumentException("missing configfile");
}
logger.LogInformation("Config Found, creating engine host");
var reader = sp.GetRequiredService<IEngineConfigurationReader>();
var parsed = reader.BuildFromFile(executeOptions.ConfigFile);
config.ChangeSetMappingFile = parsed.ChangeSetMappingFile;
config.FieldMaps = parsed.FieldMaps;
config.GitRepoMapping = parsed.GitRepoMapping;
config.CommonEnrichersConfig = parsed.CommonEnrichersConfig;
config.Processors = parsed.Processors;
config.Source = parsed.Source;
config.Target = parsed.Target;
config.Version = parsed.Version;
config.workaroundForQuerySOAPBugEnabled = parsed.workaroundForQuerySOAPBugEnabled;
config.WorkItemTypeDefinition = parsed.WorkItemTypeDefinition;
//if (!File.Exists(executeOptions.ConfigFile))
//{
// logger.LogInformation("The config file {ConfigFile} does not exist, nor does the default 'configuration.json'. Use '{ExecutableName}.exe init' to create a configuration file first", executeOptions.ConfigFile, Assembly.GetEntryAssembly().GetName().Name);
// throw new ArgumentException("missing configfile");
//}
//logger.LogInformation("Config Found, creating engine host");
//var reader = sp.GetRequiredService<IEngineConfigurationReader>();
//var parsed = reader.BuildFromFile(executeOptions.ConfigFile);
//config.ChangeSetMappingFile = parsed.ChangeSetMappingFile;
//config.FieldMaps = parsed.FieldMaps;
//config.GitRepoMapping = parsed.GitRepoMapping;
//config.CommonEnrichersConfig = parsed.CommonEnrichersConfig;
//config.Processors = parsed.Processors;
//config.Source = parsed.Source;
//config.Target = parsed.Target;
//config.Version = parsed.Version;
//config.workaroundForQuerySOAPBugEnabled = parsed.workaroundForQuerySOAPBugEnabled;
//config.WorkItemTypeDefinition = parsed.WorkItemTypeDefinition;
});
// Application Insights
ApplicationInsightsServiceOptions aiso = new ApplicationInsightsServiceOptions();
aiso.ApplicationVersion = Assembly.GetExecutingAssembly().GetName().Version.ToString();
Expand All @@ -102,7 +94,7 @@ public static IHostBuilder CreateDefaultBuilder(string[] args)
//aiso.DeveloperMode = true;
//#endif
services.AddApplicationInsightsTelemetryWorkerService(aiso);
// Services
services.AddTransient<IDetectOnlineService, DetectOnlineService>();
//services.AddTransient<IDetectVersionService, DetectVersionService>();
Expand All @@ -120,36 +112,30 @@ public static IHostBuilder CreateDefaultBuilder(string[] args)
// Host Services
services.AddTransient<IStartupService, StartupService>();
if (initOptions is not null)
{
services.Configure<InitOptions>((opts) =>
{
opts.ConfigFile = initOptions.ConfigFile;
opts.Options = initOptions.Options;
});
services.AddHostedService<InitHostedService>();
}
if (executeOptions is not null)
{
services.Configure<NetworkCredentialsOptions>(cred =>
{
cred.Source = new Credentials
{
Domain = executeOptions.SourceDomain,
UserName = executeOptions.SourceUserName,
Password = executeOptions.SourcePassword
};
cred.Target = new Credentials
{
Domain = executeOptions.TargetDomain,
UserName = executeOptions.TargetUserName,
Password = executeOptions.TargetPassword
};
});
services.AddHostedService<ExecuteHostedService>();
}
})
.UseConsoleLifetime();
});

hostBuilder.ConfigureServices((context, services) =>
{
using var registrar = new DependencyInjectionRegistrar(services);
var app = new CommandApp(registrar);
app.Configure(config =>
{
config.PropagateExceptions();
config.AddCommand<Commands.MigrationExecuteCommand>("execute");
config.AddCommand<Commands.MigrationInitCommand>("init");
});
services.AddSingleton<ICommandApp>(app);
});

hostBuilder.ConfigureServices((context, services) =>
{
services.AddHostedService<MigrationService>();
});

hostBuilder.UseConsoleLifetime();



return hostBuilder;
Expand All @@ -173,19 +159,14 @@ public static async Task RunMigrationTools(this IHostBuilder hostBuilder, string


// Disanle telemitery from options
(var initOptions, var executeOptions) = ParseOptions(args);
if (initOptions is null && executeOptions is null)
{
return;
}
bool DisableTelemetry = false;
Serilog.ILogger logger = host.Services.GetService<Serilog.ILogger>();
if (executeOptions is not null && bool.TryParse(executeOptions.DisableTelemetry, out DisableTelemetry))
{
TelemetryConfiguration ai = host.Services.GetService<TelemetryConfiguration>();
ai.DisableTelemetry = DisableTelemetry;
}
logger.Information("Telemetry: {status}", !DisableTelemetry);
//bool DisableTelemetry = false;
//Serilog.ILogger logger = host.Services.GetService<Serilog.ILogger>();
//if (executeOptions is not null && bool.TryParse(executeOptions.DisableTelemetry, out DisableTelemetry))
//{
// TelemetryConfiguration ai = host.Services.GetService<TelemetryConfiguration>();
// ai.DisableTelemetry = DisableTelemetry;
//}
//logger.Information("Telemetry: {status}", !DisableTelemetry);

await host.RunAsync();
}
Expand All @@ -202,21 +183,5 @@ private static string CreateLogsPath()

return exportPath;
}

private static (InitOptions init, ExecuteOptions execute) ParseOptions(string[] args)
{
InitOptions initOptions = null;
ExecuteOptions executeOptions = null;
Parser.Default.ParseArguments<InitOptions, ExecuteOptions>(args)
.WithParsed<InitOptions>(opts =>
{
initOptions = opts;
})
.WithParsed<ExecuteOptions>(opts =>
{
executeOptions = opts;
});
return (initOptions, executeOptions);
}
}
}
1 change: 1 addition & 0 deletions src/MigrationTools.Host/MigrationTools.Host.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
<PackageReference Include="Serilog.Sinks.Console" Version="6.0.0" />
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
<PackageReference Include="Spectre.Console.Cli" Version="0.49.1" />
<PackageReference Include="Spectre.Console.Cli.Extensions.DependencyInjection" Version="0.2.0" />
<PackageReference Include="WGet.NET" Version="4.1.0" />
<PackageReference Include="YamlDotNet" Version="16.0.0" />
</ItemGroup>
Expand Down

0 comments on commit e02601e

Please sign in to comment.