oto/CLAUDE.md

5.3 KiB
Raw Blame History

OTO CLI Guide for AI Assistants

Project Overview

OTO CLI is a Dart command-line tool that executes build/deploy pipelines defined in YAML files. It integrates with Jenkins, runs local test builds, and supports a scheduler mode.

Execution Flow

bin/main.dart
  └── Application (singleton)
        └── DataComposer  ← parses YAML + Jenkins env
              └── Pipeline
                    └── Command.byType(CommandType) → Command.execute(DataCommand)
  1. bin/main.dart Entry point. Registers three CLI commands: template, exe, scheduler.
  2. lib/cli/commands/command_exe.dart Parses CLI flags (-j Jenkins, -t test, -f file path) and calls Application.build().
  3. lib/oto/application.dart Singleton. Owns property map, commonData, commandStates. Calls registerAllCommands() then runs the pipeline.
  4. lib/oto/core/data_composer.dart Reads YAML and Jenkins env into structured data.
  5. lib/oto/pipeline/pipeline.dart Iterates DataCommand list and dispatches to Command.byType().
  6. lib/oto/commands/command_registry.dart Single place where all CommandType → Command mappings are registered.

BuildType Enum

Defined in lib/oto/application.dart:

Value Description
jenkins CI mode reads workspace and env from Jenkins environment variables
test Local test mode uses hardcoded test data
file Reads pipeline YAML from a local file path
scheduler Scheduler daemon mode

Tag System (lib/oto/core/tag_system.dart)

Tags are resolved inside YAML values at runtime.

Read tag: <!namespace.key>

Substitutes a value from the runtime store.

param:
  workspace: <!property.workspace>        # flat property access
  version:   <!property.build.version>    # nested property access
  state:     <!state.myCommandId>         # command state (ready/progress/complete)
  • If the tag occupies the entire string, the original type is returned (e.g. a List stays a List).
  • If the tag is embedded in a string, it is converted via toString().

Write tag: <@namespace.key>

Stores the command result back into a property.

param:
  set-version: <@property.appVersion>   # saves result into property["appVersion"]

Used via Command.setProperty() / TagSystem.setPropertyValue().

Adding a New Command

  1. Define data model in the appropriate lib/oto/data/*_data.dart file, extending DataParam.
  2. Add enum value to CommandType in lib/oto/commands/command.dart.
  3. Implement command class extending Command with execute(DataCommand).
  4. Register in lib/oto/commands/command_registry.dart.
  5. Run dart run build_runner build if you added a new @JsonSerializable class.

Key Directory Structure

lib/
├── bin/main.dart                    # entry point
├── cli/commands/                    # CLI-layer commands (exe, template, scheduler)
└── oto/
    ├── application.dart             # singleton orchestrator, BuildType enum
    ├── commands/
    │   ├── command.dart             # Command base class, CommandType enum
    │   ├── command_registry.dart    # all command registrations
    │   ├── build/                   # iOS/Flutter/Dart/MSBuild build commands
    │   ├── file/                    # file operations (copy, rename, delete, zip…)
    │   ├── git/                     # git commands
    │   ├── infra/                   # FTP, SMB
    │   ├── notification/            # Slack, Mattermost
    │   ├── process/                 # process management
    │   └── util/                    # timers, JSON, string utils
    ├── core/
    │   ├── tag_system.dart          # tag substitution engine
    │   ├── data_composer.dart       # YAML + env → structured data
    │   └── defined_data.dart        # built-in YAML templates
    ├── data/
    │   ├── base_data.dart           # DataParam (base), DataCommon (Jenkins env)
    │   ├── command_data.dart        # DataCommand (re-exports all data types)
    │   └── *_data.dart              # domain-specific data models
    └── pipeline/
        └── pipeline.dart            # command dispatch loop

Data Model Conventions

  • All command parameters extend DataParam (lib/oto/data/base_data.dart).
  • JSON serialization uses json_annotation. Generated files are *.g.dart.
  • *.g.dart files are normally generated by dart run build_runner build but can be edited directly when needed.
  • DataCommon holds Jenkins environment data (workspace, job name, build number, etc.).
  • DataCommand (in command_data.dart) is the unified container passed to every Command.execute().

Error Handling

  • Application.build() in application.dart uses catch (e, stacktrace) (not on Exception) to also catch Error subtypes such as TypeError.
  • On error, exit(10) is called to signal failure to the parent process.

Workspace Resolution (Command base class)

getWorkspace() in command.dart resolves in this order:

  1. workspace field on the command's data model
  2. property['workspace'] in the global property map
  3. commonData.workspace (Jenkins environment)