Skip to content

Latest commit

 

History

History
109 lines (86 loc) · 5.26 KB

File metadata and controls

109 lines (86 loc) · 5.26 KB

Architecture

Project Summary

AppVeyor CLI is a .NET 10 command-line tool for the AppVeyor CI/CD REST API. It uses Spectre.Console.Cli for structured command parsing, Spectre.Console for rich terminal output, and System.Text.Json source generators for AOT-compatible serialization. Every command supports dual output: rich Spectre tables for humans and clean JSON for AI agents and scripts.

Module Map

graph TD
    Program["Program.cs<br/><i>DI + CommandApp</i>"]

    Program --> IConsole["IConsoleProvider"]
    Program --> IConfig["IConfigService"]
    Program --> IClient["IAppVeyorClient"]

    IConsole --> ORF["OutputRendererFactory"]
    IConfig --> CS["ConfigService"]
    IClient --> AC["AppVeyorClient"]

    ORF --> CR["ConsoleRenderer<br/><i>Spectre tables</i>"]
    ORF --> JR["JsonRenderer<br/><i>JSON stdout</i>"]
    CS --> CF["~/.appveyor/config.json"]
    CS --> EV["Environment Variables"]
    AC --> API["AppVeyor REST API<br/><i>ci.appveyor.com/api</i>"]

    subgraph Commands
        direction LR
        Config["config<br/>set · get · test"]
        Projects["project<br/>list · get · add · delete · settings"]
        Builds["build<br/>start · history · cancel · rerun · log"]
        Envs["environment<br/>list · get · add · delete"]
        Deploys["deployment<br/>get · start · cancel"]
        Users["user<br/>list · get · add · delete"]
        Collabs["collaborator<br/>list · add · delete"]
        Roles["role<br/>list · get · add · delete"]
    end

    Program --> Commands
Loading

Command Flow

sequenceDiagram
    actor User
    participant CLI as Spectre.Console.Cli
    participant Cmd as AsyncCommand
    participant Guard as ReadOnlyGuard
    participant Client as IAppVeyorClient
    participant API as AppVeyor API
    participant Renderer as IOutputRenderer

    User->>CLI: appveyor project list --json
    CLI->>CLI: Parse args, validate settings
    CLI->>Cmd: ExecuteAsync(context, settings)

    opt Write commands only
        Cmd->>Guard: ThrowIfReadOnly(settings)
    end

    Cmd->>Client: GetProjectsAsync()
    Client->>API: GET /api/projects
    API-->>Client: JSON response
    Client-->>Cmd: Project[]

    Cmd->>Renderer: OutputRendererFactory.Create(json, console)
    alt --json flag or APPVEYOR_OUTPUT=json
        Renderer-->>User: Clean JSON to stdout
    else Default
        Renderer-->>User: Spectre.Console table
    end
Loading

Phases

Phase Name Status Summary
0 Design Complete Scope, tech choices, command tree, architecture
1 CLI Framework Complete .NET 10 project, Spectre.Console.Cli, DI bridge
2 API Client and Output Complete Models, API client, dual output rendering
3 Build and CI/CD Complete Cake SDK, GitHub Actions, install scripts
4 Commands and Features Complete 20 commands, read-only mode
5 Testing Complete 31 tests, MockAppVeyorServer
6 Team Management Complete Users, collaborators, roles (11 commands)

Architecture Decision Records

ADR Decision Date Related Phase
001 Spectre.Console.Cli over System.CommandLine 2026-03 Phase 1
002 Dual output: rich terminal + JSON 2026-03 Phase 2
003 System.Text.Json source generators 2026-03 Phase 2
004 Cake SDK build system 2026-03 Phase 3
005 Read-only mode for safe exploration 2026-03 Phase 4
006 IConsoleProvider DI workaround 2026-03 Phase 2

Key Patterns

  • Command structure -- Each command is an AsyncCommand<TSettings> with settings inheriting from GlobalSettings. Commands are organized in domain folders (Config, Projects, Builds, Environments, Deployments, Users, Collaborators, Roles).
  • DI bridge -- TypeRegistrar/TypeResolver bridge Spectre.Console.Cli to Microsoft.Extensions.DependencyInjection. IConsoleProvider wraps IAnsiConsole to avoid Spectre's DI override.
  • Output abstraction -- Commands call OutputRendererFactory.Create(settings.Json, console) and use the returned IOutputRenderer for all output. The renderer handles both Spectre tables and JSON serialization.
  • API client -- Single AppVeyorClient using HttpClient with Bearer token auth. All paths are relative to the /api/ base URL. Error responses are mapped to typed AppVeyorApiException.
  • Serialization -- All models are C# records with [JsonPropertyName] attributes, registered in AppVeyorJsonContext for source-gen serialization. Reflection is disabled.
  • Read-only guard -- Write commands call ReadOnlyGuard.ThrowIfReadOnly(settings) as the first line in ExecuteAsync.

Developer Guidance

See AGENTS.md for AI agent guidelines and step-by-step instructions for adding commands and models.