namespace Campaign_Tracker.Server.LegacyData.Schema;
///
/// Release-gate entry point (Story 1.7 AC #4).
///
/// Invoked from Program.cs when the application is launched with the
/// --check-legacy-schema argument. Builds the host, runs the
/// compatibility check synchronously, prints a structured report, and returns
/// an exit code: 0 when the schema matches the baseline, non-zero (1)
/// when drift is detected. The CI/CD pipeline blocks releases on the non-zero
/// exit code.
///
public static class LegacySchemaReleaseGate
{
public const string CommandLineFlag = "--check-legacy-schema";
public const int ExitCodePass = 0;
public const int ExitCodeFail = 1;
public static bool ShouldRun(string[] args) =>
args.Any(a => string.Equals(a, CommandLineFlag, StringComparison.Ordinal));
public static async Task ExecuteAsync(
ILegacySchemaCompatibilityCheck check,
ILegacySchemaCheckHistory history,
TextWriter output,
CancellationToken cancellationToken = default)
{
var result = await check.RunAsync(cancellationToken).ConfigureAwait(false);
history.Record(result);
WriteReport(result, output);
return result.Passed ? ExitCodePass : ExitCodeFail;
}
public static void WriteReport(LegacySchemaCheckResult result, TextWriter output)
{
if (result.Passed)
{
output.WriteLine(
$"[legacy-schema-check] PASS — {result.TablesVerified} tables verified at {result.CheckedAt:O}, drift=0.");
return;
}
output.WriteLine(
$"[legacy-schema-check] FAIL — {result.TablesVerified} tables verified at {result.CheckedAt:O}, drift={result.DriftCount}.");
foreach (var drift in result.Drifts)
{
var location = drift.ColumnName is null
? drift.TableName
: $"{drift.TableName}.{drift.ColumnName}";
output.WriteLine($" - [{drift.ChangeType}] {location}: {drift.Detail}");
}
}
}