using System.CommandLine;
using JdeScoping.ConfigManager.Core.Services;
using Microsoft.Extensions.DependencyInjection;
namespace JdeScoping.ConfigManager.Cli.Commands;
///
/// Validation command implementations.
///
public static class ValidateCommand
{
///
/// Creates the validate appsettings command.
///
public static Command CreateAppSettingsCommand(
IServiceProvider serviceProvider,
Option configPathOption,
Option verboseOption,
Option quietOption)
{
var command = new Command("appsettings", "Validate appsettings.json");
command.SetHandler(async (string? configPath, bool verbose, bool quiet) =>
{
var exitCode = await ValidateAppSettingsAsync(serviceProvider, configPath, verbose, quiet);
Environment.ExitCode = exitCode;
}, configPathOption, verboseOption, quietOption);
return command;
}
///
/// Creates the validate pipelines command.
///
public static Command CreatePipelinesCommand(
IServiceProvider serviceProvider,
Option configPathOption,
Option verboseOption,
Option quietOption)
{
var command = new Command("pipelines", "Validate pipeline configuration files");
command.SetHandler(async (string? configPath, bool verbose, bool quiet) =>
{
var exitCode = await ValidatePipelinesAsync(serviceProvider, configPath, verbose, quiet);
Environment.ExitCode = exitCode;
}, configPathOption, verboseOption, quietOption);
return command;
}
///
/// Creates the validate all command.
///
public static Command CreateAllCommand(
IServiceProvider serviceProvider,
Option configPathOption,
Option verboseOption,
Option quietOption)
{
var command = new Command("all", "Validate all configuration files");
command.SetHandler(async (string? configPath, bool verbose, bool quiet) =>
{
var exitCode1 = await ValidateAppSettingsAsync(serviceProvider, configPath, verbose, quiet);
var exitCode2 = await ValidatePipelinesAsync(serviceProvider, configPath, verbose, quiet);
Environment.ExitCode = Math.Max(exitCode1, exitCode2);
}, configPathOption, verboseOption, quietOption);
return command;
}
///
/// Creates the validate runtime command.
///
public static Command CreateRuntimeCommand(
IServiceProvider serviceProvider,
Option configPathOption,
Option verboseOption,
Option quietOption)
{
var command = new Command("runtime", "Run Infrastructure validators");
command.SetHandler(async (string? configPath, bool verbose, bool quiet) =>
{
var exitCode = await ValidateRuntimeAsync(serviceProvider, configPath, verbose, quiet);
Environment.ExitCode = exitCode;
}, configPathOption, verboseOption, quietOption);
return command;
}
private static async Task ValidateAppSettingsAsync(
IServiceProvider serviceProvider,
string? configPath,
bool verbose,
bool quiet)
{
var folderPath = await GetConfigFolderAsync(serviceProvider, configPath);
if (folderPath == null)
{
Console.Error.WriteLine("Error: Could not find configuration folder. Use --config-path to specify.");
return 1;
}
var configFileService = serviceProvider.GetRequiredService();
var validationService = serviceProvider.GetRequiredService();
var appSettingsPath = Path.Combine(folderPath, "appsettings.json");
if (!File.Exists(appSettingsPath))
{
Console.Error.WriteLine($"Error: appsettings.json not found at {appSettingsPath}");
return 1;
}
try
{
var config = await configFileService.LoadAppSettingsAsync(appSettingsPath);
var result = validationService.ValidateAppSettings(config);
if (!quiet)
{
Console.WriteLine("=== AppSettings Validation ===");
Console.WriteLine($"File: {appSettingsPath}");
}
if (result.IsValid)
{
if (!quiet)
Console.WriteLine("Status: Valid");
return 0;
}
foreach (var error in result.Errors)
{
Console.Error.WriteLine($"Error: {error}");
}
foreach (var warning in result.Warnings)
{
if (!quiet)
Console.WriteLine($"Warning: {warning}");
}
return 1;
}
catch (ConfigLoadException ex)
{
Console.Error.WriteLine($"Error loading configuration: {ex.Message}");
return 1;
}
}
private static async Task ValidatePipelinesAsync(
IServiceProvider serviceProvider,
string? configPath,
bool verbose,
bool quiet)
{
var folderPath = await GetConfigFolderAsync(serviceProvider, configPath);
if (folderPath == null)
{
Console.Error.WriteLine("Error: Could not find configuration folder. Use --config-path to specify.");
return 1;
}
var configFileService = serviceProvider.GetRequiredService();
var validationService = serviceProvider.GetRequiredService();
var pipelinesDir = Path.Combine(folderPath, "Pipelines");
try
{
var pipelines = await configFileService.LoadAllPipelinesAsync(pipelinesDir);
var result = validationService.ValidatePipelines(pipelines);
if (!quiet)
{
Console.WriteLine("=== Pipelines Validation ===");
Console.WriteLine($"Directory: {pipelinesDir}");
Console.WriteLine($"Pipelines found: {pipelines.Count}");
}
if (result.IsValid)
{
if (!quiet)
Console.WriteLine("Status: Valid");
return 0;
}
foreach (var error in result.Errors)
{
Console.Error.WriteLine($"Error: {error}");
}
foreach (var warning in result.Warnings)
{
if (!quiet)
Console.WriteLine($"Warning: {warning}");
}
return result.Errors.Count > 0 ? 1 : 0;
}
catch (Exception ex)
{
Console.Error.WriteLine($"Error validating pipelines: {ex.Message}");
return 1;
}
}
private static async Task ValidateRuntimeAsync(
IServiceProvider serviceProvider,
string? configPath,
bool verbose,
bool quiet)
{
var folderPath = await GetConfigFolderAsync(serviceProvider, configPath);
if (folderPath == null)
{
Console.Error.WriteLine("Error: Could not find configuration folder. Use --config-path to specify.");
return 1;
}
var runtimeValidationService = serviceProvider.GetRequiredService();
if (!quiet)
{
Console.WriteLine("=== Runtime Configuration Validation ===");
Console.WriteLine($"Folder: {folderPath}");
}
var results = runtimeValidationService.ValidateRuntimeConfig(folderPath);
var hasErrors = false;
foreach (var result in results)
{
if (result.Errors.Count > 0)
{
hasErrors = true;
Console.Error.WriteLine($"\n[{result.ValidatorName}]");
foreach (var error in result.Errors)
{
Console.Error.WriteLine($" Error: {error}");
}
}
else if (!quiet)
{
Console.WriteLine($"[{result.ValidatorName}]: OK");
}
foreach (var warning in result.Warnings)
{
if (!quiet)
Console.WriteLine($" Warning: {warning}");
}
}
return hasErrors ? 1 : 0;
}
private static async Task GetConfigFolderAsync(IServiceProvider serviceProvider, string? configPath)
{
if (!string.IsNullOrEmpty(configPath))
{
if (Directory.Exists(configPath))
return configPath;
return null;
}
var autoDiscoveryService = serviceProvider.GetRequiredService();
return await autoDiscoveryService.FindConfigFolderAsync();
}
}