# OTO CLI YAML로 정의된 CI/CD 파이프라인을 실행하는 Dart 기반 자동화 도구. Jenkins, FTP, Git, Slack/Mattermost, iOS/Flutter/Android 빌드 등 다양한 작업을 커맨드로 추상화하고, 파이프라인 엔진이 순차 실행한다. --- ## 설치 ```bash dart pub get dart compile exe bin/main.dart -o oto ``` --- ## 실행 모드 | 플래그 | 모드 | 설명 | |--------|------|------| | `-j` | `jenkins` | Jenkins 환경 변수에서 워크스페이스·YAML 읽기 | | `-t` | `test` | 하드코딩된 테스트 데이터로 로컬 실행 | | `-f ` | `file` | 지정한 YAML 파일 경로에서 파이프라인 실행 | | (daemon) | `scheduler` | 스케줄러 데몬 모드 | ```bash oto -j # Jenkins CI 모드 oto -t # 로컬 테스트 모드 oto -f ./build.yaml # 파일 기반 실행 ``` --- ## 실행 흐름 ``` bin/main.dart └── Application (singleton) └── DataComposer ← YAML + Jenkins env 파싱 └── Pipeline └── Command.byType(CommandType) → execute(DataCommand) ``` --- ## YAML 파이프라인 구조 ```yaml property: workspace: /path/to/project version: 1.0.0 env: prod commands: - command: BuildiOS id: buildApp param: workspacePath: /ios/Runner.xcworkspace scheme: Runner pipeline: workflow: - exe: buildApp ``` ### 태그 시스템 | 태그 | 방향 | 설명 | |------|------|------| | `` | 읽기 | property에서 값 치환 | | `<@property.key>` | 쓰기 | 커맨드 결과를 property에 저장 | - 태그가 문자열 전체이면 원본 타입(List, Map 등) 유지 - 태그가 문자열 일부이면 `toString()` 변환 - 중첩 접근 지원: `` --- ## 파이프라인 흐름 제어 ### exe — 단순 실행 ```yaml - exe: buildApp ``` ### exe-handle — 성공/실패 분기 ```yaml - exe-handle: id: uploadArtifact on-success: - exe: notifySuccess on-fail: - exe: notifyError ``` ### if — 조건 분기 ```yaml - if: condition-string: " == prod" on-true: - exe: deployProd on-false: - exe: deployDev ``` **지원 연산자:** `==`, `!=`, `<`, `<=`, `>`, `>=` **지원 타입:** `string`, `int`, `float`, `bool`, `date`, `version`, `object` ### foreach — 반복 ```yaml - foreach: iterator: # List 또는 Map setValue: <@property.target> on-do: - exe: buildTarget ``` ### while — 조건 루프 ```yaml - while: condition-int: < 3 on-do: - exe: checkStatus ``` ### switch — 멀티 케이스 ```yaml - switch: condition-string: cases: - value: prod tasks: - exe: deployProd - value: dev tasks: - exe: deployDev ``` ### wait-until — 대기 ```yaml - async: buildStep - wait-until-string: != complete ``` ### async — 비동기 실행 ```yaml - async: notifyStart # 완료를 기다리지 않고 다음 단계 진행 ``` --- ## 커맨드 목록 ### 빌드 | 커맨드 | 설명 | |--------|------| | `BuildiOS` | xcodebuild로 iOS 앱 빌드 | | `ArchiveiOS` | xcodebuild archive | | `ExportiOS` | xcodebuild -exportArchive | | `PublishiOS` | App Store Connect 배포 | | `TestflightUpload` | TestFlight 업로드 | | `TestflightStatusCheck` | TestFlight 처리 상태 확인 | | `TestflightDistribute` | TestFlight 그룹 배포 | | `BuildFlutter` | flutter build | | `BuildDart` | dart build | | `BuildDartCompile` | dart compile | | `BuildDotNet` | dotnet build | | `BuildMSBuild` | MSBuild (.NET) | | `XcodeprojAddFile` | Xcode 프로젝트 파일 추가 | | `CodeSign` | macOS codesign | | `CodeSignVerify` | codesign 검증 | | `ProductBuild` | macOS productbuild | | `Notarize` | macOS 공증 | ### 파일 | 커맨드 | 설명 | |--------|------| | `Copy` | 파일/디렉토리 복사 (이동 포함) | | `Delete` | 파일/디렉토리 삭제 | | `Rename` | 이름 변경 | | `FileRead` | 파일 읽기 → property 저장 | | `FileWrite` | property 값 → 파일 쓰기 | | `Files` | 파일 목록 조회 | | `FileInfo` | 파일 메타데이터 조회 | | `DirectoryCreate` | 디렉토리 생성 | | `Zip` | 압축/해제 | ### Git | 커맨드 | 설명 | |--------|------| | `Git` | 임의 git 명령 실행 | | `GitCommit` | 변경사항 커밋 | | `GitPull` | pull | | `GitPush` | push | | `GitCheckout` | 브랜치/파일 체크아웃 | | `GitRev` | 리비전 해시 조회 | | `GitCount` | 커밋 수 조회 | | `GitReset` | reset | | `GitStashPush` / `GitStashApply` | stash 관리 | | `GitBranch` | 브랜치 목록/생성/삭제 | | `GitHub` | GitHub API 호출 | | `GitHubPullRequestCreate` / `List` / `Close` | PR 관리 | ### 알림 | 커맨드 | 설명 | |--------|------| | `Slack` | Slack 메시지 전송 | | `SlackFile` | Slack 파일 업로드 | | `SlackBuild` | 빌드 결과 Slack 리포트 | | `Mattermost` | Mattermost 메시지 전송 | | `MattermostBuild` | 빌드 결과 Mattermost 리포트 | ### 네트워크 / FTP | 커맨드 | 설명 | |--------|------| | `Upload` | FTP 업로드 | | `Download` | FTP 다운로드 | | `WebRequest` | HTTP 요청 | | `WebFile` | HTTP multipart 파일 업로드 | | `URLInfo` | URL 정보 파싱 | ### 문자열 / 유틸 | 커맨드 | 설명 | |--------|------| | `Print` | 메시지 출력 | | `SetValue` | property 값 직접 설정 | | `Delay` | 지연 (초) | | `StringSub` | 문자열 자르기 | | `StringReplace` | 문자열 치환 | | `StringReplacePattern` | 정규식 치환 | | `StringIndex` | 인덱스 검색 | | `JsonReader` | JSON 값 읽기 | | `JsonReaderFile` | JSON 파일 읽기 | | `JsonWriterFile` | JSON 파일 쓰기 | ### 셸 / 프로세스 | 커맨드 | 설명 | |--------|------| | `Shell` | 셸 명령 실행 | | `ShellFile` | 셸 스크립트 파일 실행 | | `ProcessRun` | 프로세스 실행 | | `ProcessKill` | 프로세스 종료 | | `ProcessPortUse` | 포트 사용 여부 확인 | ### 외부 서비스 | 커맨드 | 설명 | |--------|------| | `Jira` | Jira 이슈 조회/수정 | | `AwsCli` | AWS CLI 명령 실행 | | `Docker` | Docker 명령 실행 | | `Gradle` | Gradle 빌드 실행 | | `Protobuf` | protoc 컴파일 | | `JenkinsParameterModify` | Jenkins 파라미터 수정 | | `SMBAuth` | SMB 인증 | --- ## 데이터 모델 구조 모든 커맨드 파라미터는 `DataParam`을 상속한다. ```dart DataParam ├── workspace?: String // 기본 작업 디렉토리 ├── passExitCodes?: List // 성공으로 간주할 exit code ├── setResult?: String // 결과 저장 태그 ├── setExitCode?: String // exit code 저장 태그 └── showPrint?: bool // 예시 DataBuildiOS extends DataParam { workspacePath: String scheme: String destination: String ... } ``` **워크스페이스 해석 우선순위:** 1. `param.workspace` 2. `property.workspace` 3. `DataCommon.workspace` (Jenkins env) --- ## 새 커맨드 추가 ``` 1. lib/oto/data/*.dart DataParam 상속 모델 정의 + @JsonSerializable 2. lib/oto/commands/command.dart CommandType enum에 값 추가 3. lib/oto/commands/{category}/ Command 상속 클래스 구현 4. Command.register(..., spec: CommandSpec(...))에 구현체/데이터 모델/샘플 경로 등록 5. lib/oto/commands/command_registry.dart registerAllCommands()에 등록 함수 연결 6. dart run build_runner build *.g.dart 생성 ``` --- ## 스케줄러 ```bash oto scheduler -r build.yaml # 스케줄러 등록 oto scheduler -l # 목록 조회 oto scheduler -e true # 활성화/비활성화 oto scheduler -u # 해제 ``` **YAML 스케줄러 설정:** ```yaml scheduler: alias: nightly-build cron: "0 2 * * *" # cron 표현식 또는 # interval: 3600 # 초 단위 interval enableLog: true ``` **플랫폼별 실행 메커니즘:** - **Linux:** cron - **macOS:** LaunchAgent - **Windows:** Task Scheduler --- ## 프로젝트 구조 ``` lib/ ├── cli/ # CLI 인자 파싱, 스케줄러 관리 └── oto/ ├── application.dart # 싱글턴 오케스트레이터 ├── commands/ # 커맨드 구현체 (카테고리별) ├── core/ # 태그 시스템, 데이터 합성, 정의 데이터 ├── data/ # JSON 직렬화 데이터 모델 (*.g.dart 포함) ├── pipeline/ # 파이프라인 흐름 제어 엔진 └── utils/ # 공통 유틸리티 ``` --- ## 기술 스택 - **언어:** Dart (SDK >=2.18.6 <4.0.0) - **의존성:** dart_framework (커스텀), http, json_annotation, cron, xml - **코드 생성:** json_serializable + build_runner ```bash dart run build_runner build # 데이터 모델 생성 ``` --- ## 에러 처리 - `Application.build()`는 `catch (e, stacktrace)`로 Exception과 Error 모두 처리 - 실패 시 `BuildResult.failure(..., exitCode: 10)`을 반환하고 CLI가 부모 프로세스에 exit code 전달 - `passExitCodes`로 성공으로 간주할 exit code 지정 가능