CLI
빌드하고 실행하는 방법, 그리고 명령줄 옵션입니다.
오류 메시지별 대처는 트러블슈팅에 있습니다.
빌드
build/ 폴더에 플랫폼별 빌드 스크립트가 있습니다.
| 플랫폼 | 빌드 스크립트 | 산출 위치 |
|---|---|---|
| Windows | build-win64.ps1 | bin/win-x64/tabbit.exe · bin/win-arm64/tabbit.exe |
| Linux | build-linux64.sh | bin/linux-x64/tabbit · bin/linux-arm64/tabbit |
| macOS | build-osx64.sh | bin/osx-arm64/tabbit · bin/osx-x64/tabbit |
빌드 전에 .NET 10 SDK를 설치해야 합니다.
아키텍처
아키텍처는 실행한 머신에서 판정합니다.
셸은 uname -m, PowerShell은 RuntimeInformation.OSArchitecture를 사용합니다.
애플 실리콘에서 build-osx64.sh를 실행하면 osx-arm64가 생성됩니다.
self-contained 산출물은 네이티브 코드이므로 아키텍처가 어긋나면 실행 자체가 되지 않습니다.
다른 아키텍처가 필요하면 런타임 식별자를 인자로 넘깁니다.
./build/build-osx64.sh osx-x64 # 인텔 맥
./build/build-linux64.sh linux-arm64
.\build\build-win64.ps1 win-arm64
.\build\build-osx64.ps1 osx-x64 # 윈도우에서 맥용으로 크로스 퍼블리시
build/의 PowerShell 스크립트는 각 플랫폼용으로 크로스 퍼블리시하는 용도이기도 합니다.
리눅스와 맥에서는 같은 이름의 .sh를 사용하면 되고, 그쪽이 아키텍처까지 판정합니다.
런타임 식별자마다 디렉터리가 분리됩니다
self-contained 퍼블리시는 네이티브 의존 파일을 실행 파일 옆에 둡니다.
예전에는 전부 bin/ 하나를 공유했는데, 그러면 두 플랫폼을 한 머신에서 빌드했을 때 나중 것이
앞의 것의 의존 파일을 덮어씁니다.
트리밍을 사용하지 않는 이유
생성되는 실행 파일은 self-contained 단일 파일입니다.
PublishTrimmed는 의도적으로 사용하지 않습니다.
NPOI, Newtonsoft.Json, Google.Apis가 모두 리플렉션으로 타입을 찾으므로, 트리밍이 런타임에
필요한 멤버를 제거합니다.
배포
dotnet publish src/Tabbit.csproj -c Release -r win-x64 --self-contained true -o out
-r은 win-x64, linux-x64, osx-arm64 등으로 바꿉니다.
결과는 실행 파일 하나(약 60MB)와 네이티브 의존 두 개뿐이며, .NET이 설치되지 않은 머신에서 그대로 동작합니다.
프레임워크 의존(--self-contained false)으로 배포한다면 대상 머신에 ASP.NET Core 런타임이
필요합니다.
기본 .NET 런타임만으로는 --serve뿐 아니라 빌드도 시작되지 않습니다. 웹서버가 프레임워크
참조로 들어가 있기 때문입니다.
대상 머신에 무엇이 설치되어 있을지 확신할 수 없다면 self-contained가 안전합니다.
CI가 매 실행마다 linux-x64로 self-contained 퍼블리시를 만들고, 그 결과물로 빌드를 한 번 돌립니다. 위 문장은 주장이 아니라 검증된 사실입니다.
실행
tabbit --recipe recipe.json
recipe와 실행 범위
| 옵션 | 설명 |
|---|---|
-r, --recipe | 사용할 recipe 파일 |
--new-recipe <파일> | 시작용 recipe를 만들고 종료합니다 |
--template <이름> | --new-recipe가 사용할 시작점. 시작점 고르기 |
--target-side <side> | 실행 전체를 한쪽으로 좁힙니다. client / server / both(기본) |
--time-zone <시간대> | 시트의 datetime 셀을 읽을 시간대를 강제 지정합니다 |
-e, --env <이름> | 이 실행이 어느 환경의 것인지. 아래 |
@<파일> | 인자를 파일에서 읽습니다. 한 줄에 옵션 하나이며, 인자를 이것 하나만 줄 때 동작합니다 |
--new-recipe가 만드는 파일에는 모든 목록에 기본값이 채워진 항목이 하나씩 들어 있습니다.
어떤 설정이 있는지 파일만 보고 알 수 있게 하기 위한 것입니다. 필요 없는 항목은 지우면 되고, 경로가 빈 항목은 꺼진 것으로 취급하므로 그냥 두어도 됩니다.
--time-zone은 recipe의 전역 설정과 소스별 설정을 둘 다 덮어씁니다.
recipe가 시간대를 잘못 적고 있는 실행을 위한 것이므로, 덮어쓸 대상이 바로 소스별 설정입니다. 적용한 값은 실행 로그에 한 줄로 남습니다. 시트의 값
검증
| 옵션 | 설명 |
|---|---|
--validate-only | 검증까지만 실행하고 종료합니다. 산출물을 만들지 않으므로 PR 검사가 사용합니다 |
--skip-runtime-validation | 외부 저장소를 읽는 rules/runtime/ 규칙만 건너뜁니다. 건너뛴 규칙 수가 기록에 남습니다 |
--new-validator <테이블> | 해당 테이블의 시작 검증 규칙을 만들고 종료합니다. 이미 있으면 덮어쓰지 않습니다 |
--list-validators | 검증 규칙을 실행 순서대로 출력하고 종료합니다. 시트를 하나도 읽지 않습니다 |
우선순위는 규칙마다 붙이므로 전체 순서가 한곳 에 모이지 않습니다.
--list-validators의 출력이 그 자리입니다. 목록 파일과 달리 출력한 것이 곧 실행되는
것입니다.
자세한 내용은 검증에 있습니다.
기록과 조회
| 옵션 | 설명 |
|---|---|
--commit <id> | 이 빌드가 어느 커밋의 것인지. 생략하면 워킹카피에서 git으로 읽습니다 |
--branch <name> | 스냅샷이 속할 브랜치. 생략하면 git에서 읽습니다 |
--commit-author "Name <email>" | 작성자를 직접 지정합니다. git 값을 덮어씁니다 |
--commit-date <ISO8601> | 변경 시각을 직접 지정합니다. git 값을 덮어씁니다 |
--repository <경로> | 커밋 정보를 읽을 워킹카피. 생략하면 시트의 소스 디렉터리, 그다음 현재 디렉터리를 봅니다 |
--history | 빌드 대신 변경 내역을 조회하고 종료합니다 |
--stats | 빌드 대신 한 커밋의 통계를 조회하고 종료합니다 |
--serve | 빌드 대신 HTTP로 히스토리를 서비스하고 계속 실행합니다 |
--prune | 빌드 대신 오래된 스냅샷의 변경 상세를 정리하고 종료합니다 |
자세한 내용은 Summary와 히스토리에 있습니다.
캐시
| 옵션 | 설명 |
|---|---|
--full | 캐시를 보지 않고 전부 빌드합니다. 캐시의 판정 자체를 의심할 때 사용합니다 |
--force-output | 입력 판정은 캐시를 그대로 쓰고 출력 항목만 전부 실행합니다 |
--cache-dir <경로> | 캐시를 둘 위치. 생략하면 작업 디렉터리의 .tabbit/ |
다시 하지 않기 — 빌드 캐시에서 무엇이 전체 실행을 만드는지 설명합니다.
출력과 진단
| 옵션 | 설명 |
|---|---|
--detailed-exit-code | 할 일이 없어서 끝난 실행을 종료 코드로 구분합니다. 종료 코드 |
-v, --verbose | 디버그 로그까지 출력합니다 |
-q, --silent | ERROR 아래로는 출력하지 않습니다 |
--debug | 오류 발생 시 콜스택까지 출력합니다 |
-h, --help | 도움말을 출력하고 종료합니다. 종료 코드는 0입니다 |
--version | 버전, 커밋, 런타임을 출력하고 종료합니다. 아래 |
--show-report | 이 recipe의 마지막 빌드 리포트를 열고 종료합니다. 아래 |
--new-encryption-key | 바이너리 암호화 키를 새로 만들고 종료합니다 |
--new-encryption-key는 운영체제의 난수원에서 키를 뽑습니다.
표준 출력에는 키 한 줄만 나가므로(안내문은 표준 오류로) 시크릿 저장소에 그대로 파이프할 수
있고, --out을 주면 파일로 씁니다. 이미 있는 파일은 덮어쓰지 않습니다.
내보내기
실행이 여는 첫 줄
어느 빌드가 무엇으로 돌고 있는지를 먼저 적습니다.
[I] [Tabbit ] Tabbit 1.5.0+8b2a884d84bf
[I] [Tabbit ] .tcb v106 · .NET 10.0.11 (win-x64)
[I] [Loading ] Start working with recipe 전량 변환 recipe
두 줄로 나눠 적고 아래에 빈 줄을 둡니다.
버전과 형식 번호와 런타임과 플랫폼을 한 줄에 담으면 아무것도 찾을 수 없는 줄이 되고, 빈 줄이 없으면 이 줄들이 그 뒤 수백 줄의 앞 두 줄이 됩니다.
넷을 적는 이유는 받은 로그에 대해 묻게 되는 것이 대개 이 넷 중 하나이기 때문입니다. 어느 빌드인지, 어느 런타임인지, 어느 운영체제인지, 그리고 바이너리 형식이 몇 번인지입니다.
마지막 것이 유일하게 읽는 쪽과 어긋날 수 있는 값입니다. 생성된 리더는 각자 형식 상수의 사본을 가지므로, 클라이언트가 파일을 거부하면 그것은 다른 무엇보다 먼저 버전 불일치입니다.
여기 적히는 빌드 문자열은 빌드 캐시의 키에 들어가는 것과 같은 값입니다. 「다른 빌드가 쓴 캐시입니다」라는 보고와 이 줄이 어긋나면 아무도 무엇을 해야 할지 알 수 없으므로, 한 곳에서 생성합니다.
표준 출력이 다른 프로그램의 입력인 실행에는 적지 않습니다.
--new-encryption-key는 키 한 줄만, --out 없는 --history와 --stats는 JSON만 표준 출력에
내보내므로 그대로 파이프할 수 있어야 합니다. 파일 로그에는 언제나 남습니다.