< Summary

Information
Class: Orchestrator.Commands.Utility.UploadContext.UploadContextCommand.ContextDocumentJson
Assembly: Orchestrator
File(s): /home/runner/work/KicktippAi/KicktippAi/src/Orchestrator/Commands/Utility/UploadContext/UploadContextCommand.cs
Line coverage
100%
Covered lines: 4
Uncovered lines: 0
Coverable lines: 4
Total lines: 155
Line coverage: 100%
Branch coverage
N/A
Covered branches: 0
Total branches: 0
Branch coverage: N/A
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor()100%11100%

File(s)

/home/runner/work/KicktippAi/KicktippAi/src/Orchestrator/Commands/Utility/UploadContext/UploadContextCommand.cs

#LineLine coverage
 1using System.Text.Json;
 2using EHonda.KicktippAi.Core;
 3using Microsoft.Extensions.Logging;
 4using Orchestrator.Infrastructure;
 5using Orchestrator.Infrastructure.Factories;
 6using Spectre.Console;
 7using Spectre.Console.Cli;
 8
 9namespace Orchestrator.Commands.Utility.UploadContext;
 10
 11public sealed class UploadContextCommand : AsyncCommand<UploadContextSettings>
 12{
 13    private readonly IAnsiConsole _console;
 14    private readonly IFirebaseServiceFactory _firebaseServiceFactory;
 15    private readonly ILogger<UploadContextCommand> _logger;
 16
 17    public UploadContextCommand(
 18        IAnsiConsole console,
 19        IFirebaseServiceFactory firebaseServiceFactory,
 20        ILogger<UploadContextCommand> logger)
 21    {
 22        _console = console;
 23        _firebaseServiceFactory = firebaseServiceFactory;
 24        _logger = logger;
 25    }
 26
 27    protected override async Task<int> ExecuteAsync(
 28        CommandContext context,
 29        UploadContextSettings settings,
 30        CancellationToken cancellationToken)
 31    {
 32        try
 33        {
 34            var inputPath = Path.GetFullPath(settings.Input);
 35            if (!File.Exists(inputPath))
 36            {
 37                _console.MarkupLine($"[red]Context document JSON not found:[/] {inputPath}");
 38                return 1;
 39            }
 40
 41            await using var stream = File.OpenRead(inputPath);
 42            var document = await JsonSerializer.DeserializeAsync<ContextDocumentJson>(
 43                stream,
 44                new JsonSerializerOptions { PropertyNameCaseInsensitive = true },
 45                cancellationToken);
 46
 47            if (document is null)
 48            {
 49                _console.MarkupLine("[red]Failed to parse context document JSON[/]");
 50                return 1;
 51            }
 52
 53            if (!ValidateDocument(document))
 54            {
 55                return 1;
 56            }
 57
 58            var competition = CompetitionResolver.ResolveCompetition(
 59                settings.Competition,
 60                communityContext: document.CommunityContext);
 61            var repositoryCompetition = CompetitionResolver.ToRepositoryCompetitionArgument(competition);
 62
 63            _console.MarkupLine($"[green]Upload context command initialized for document:[/] [yellow]{document.DocumentN
 64            _console.MarkupLine($"[blue]Using community context:[/] [yellow]{document.CommunityContext}[/]");
 65            _console.MarkupLine($"[blue]Using competition:[/] [yellow]{competition}[/]");
 66            _console.MarkupLine($"[blue]Reading context document from:[/] {inputPath}");
 67
 68            if (settings.Verbose)
 69            {
 70                _console.MarkupLine("[dim]Verbose mode enabled[/]");
 71                _console.MarkupLine($"[dim]Content length: {document.Content.Length} characters[/]");
 72            }
 73
 74            if (settings.DryRun)
 75            {
 76                _console.MarkupLine("[magenta]Dry run mode enabled - no Firestore document will be written[/]");
 77                _console.MarkupLine($"[magenta]Would upload context document:[/] {document.DocumentName}");
 78                return 0;
 79            }
 80
 81            var contextRepository = _firebaseServiceFactory.CreateContextRepository(repositoryCompetition);
 82            var existingDocument = await contextRepository.GetLatestContextDocumentAsync(
 83                document.DocumentName,
 84                document.CommunityContext,
 85                cancellationToken);
 86
 87            if (existingDocument is null)
 88            {
 89                _console.MarkupLine($"[blue]No existing context document found for '{document.DocumentName}' - will crea
 90            }
 91            else
 92            {
 93                _console.MarkupLine($"[blue]Found existing context document '{document.DocumentName}' (version {existing
 94            }
 95
 96            var savedVersion = await contextRepository.SaveContextDocumentAsync(
 97                document.DocumentName,
 98                document.Content,
 99                document.CommunityContext,
 100                cancellationToken);
 101
 102            if (existingDocument is not null && savedVersion is null)
 103            {
 104                _console.MarkupLine($"[green]Content unchanged - context document '[/][white]{document.DocumentName}[/][
 105            }
 106            else if (existingDocument is not null)
 107            {
 108                _console.MarkupLine($"[green]Content changed - created new version {savedVersion} for context document '
 109            }
 110            else
 111            {
 112                _console.MarkupLine($"[green]Created context document '[/][white]{document.DocumentName}[/][green]' as v
 113            }
 114
 115            return 0;
 116        }
 117        catch (Exception ex)
 118        {
 119            _logger.LogError(ex, "Error in upload-context command");
 120            _console.MarkupLine($"[red]Error:[/] {ex.Message}");
 121            return 1;
 122        }
 123    }
 124
 125    private bool ValidateDocument(ContextDocumentJson document)
 126    {
 127        if (string.IsNullOrWhiteSpace(document.DocumentName))
 128        {
 129            _console.MarkupLine("[red]Context document JSON is missing documentName[/]");
 130            return false;
 131        }
 132
 133        if (string.IsNullOrWhiteSpace(document.CommunityContext))
 134        {
 135            _console.MarkupLine("[red]Context document JSON is missing communityContext[/]");
 136            return false;
 137        }
 138
 139        if (string.IsNullOrWhiteSpace(document.Content))
 140        {
 141            _console.MarkupLine("[red]Context document JSON is missing content[/]");
 142            return false;
 143        }
 144
 145        return true;
 146    }
 147
 148    private sealed class ContextDocumentJson
 149    {
 1150        public string DocumentName { get; set; } = string.Empty;
 1151        public string Content { get; set; } = string.Empty;
 1152        public string Description { get; set; } = string.Empty;
 1153        public string CommunityContext { get; set; } = string.Empty;
 154    }
 155}

Methods/Properties

.ctor()