베이스 이미지
모든 잡이 복제해 쓰는 macOS 베이스 이미지에 들어 있는 macOS와 Xcode, 시뮬레이터 런타임, 도구와 갱신 주기를 설명합니다
모든 잡 VM은 봉인된 베이스 이미지 하나를 복제해 만들고 잡이 끝나면 지워지므로, 스크립트가 만나는 환경은 매번 이 이미지 그대로입니다
들어 있는 것
| 항목 | 값 |
|---|---|
| macOS | 26.6.2 (Tahoe) |
| Xcode | 27.0 (기본, 빌드 27A266a), 26.6 |
| iOS 시뮬레이터 런타임 | iOS 27.0 (Xcode 27.0), iOS 26.5 (Xcode 26.6) |
| Xcode 경로 | /Applications/Xcode_27.0.app, /Applications/Xcode_26.6.app |
| 라이선스 | 두 Xcode 모두 동의 완료 |
GET /v1/environments가 이 이미지의 Xcode와 런타임 목록을 돌려주고 콘솔 실행 → 환경 메뉴가 같은 내용을 보여 줍니다
도구
베이스 이미지에는 다음 도구가 들어 있습니다
정확한 버전은 잡에서 --version으로 확인하세요
| 도구 | 명령 |
|---|---|
| CocoaPods | pod |
| fastlane | fastlane |
| Node.js LTS | node, npm |
| Ruby 3.4 (Homebrew) | ruby, gem, bundle |
| Flutter | flutter |
| Homebrew | brew (/opt/homebrew) |
| git, bash, curl, tar | macOS 기본 |
PATH에는 /opt/homebrew/bin, /opt/homebrew/sbin, Homebrew Ruby 3.4의 bin과 gem bin, ~/.rbenv/shims가 앞에 붙어 있습니다
버전을 확인하는 잡 예시입니다
xenocast build --script 'sw_vers; xcodebuild -version; xcrun simctl list runtimes; pod --version; fastlane --version; node --version; ruby --version; flutter --version'없는 것
- Xcode 27.0과 26.6 밖의 버전 다른 버전을 요청하면
400 invalid_request - 사용자 계정에 남는 캐시 잡 사이에
DerivedData,~/.cocoapods,node_modules가 이어지지 않습니다 - 서명 인증서와 프로비저닝 프로파일 서명된 빌드가 필요하면 소스에 포함해 올리고 스크립트에서 키체인에 넣습니다
- GitHub Actions 러너 바이너리
runs-on으로 이 러너를 고르는 방식은 제공하지 않고xeno-ci/build액션으로 잡을 보냅니다
외부 접속
VM의 외부 접속은 프록시를 지나며 HTTPS_PROXY, HTTP_PROXY가 미리 설정되어 있습니다
허용되지 않은 호스트는 403으로 막히고 로그에 안내가 남습니다
내부로 들어오는 접속은 없습니다
갱신 주기
- 새 Xcode 정식판이 나오면 2주 안에 베이스 이미지에 넣고 최신 두 버전을 유지합니다, 가장 오래된 버전이 빠집니다
- macOS 보안 업데이트는 월 1회 확인하고 다음 교체 때 함께 넣습니다
- 교체는 Mac 한 대씩 진행하며 실행 중인 잡은 끊지 않습니다
- 이미지가 바뀌어도 잡 요청 형식과 API는 같습니다, 바뀌는 Xcode 목록은 변경 기록과
GET /v1/environments로 확인합니다
왜 잡마다 새 VM인가
- 이전 잡의 파일, 키체인 항목, 켜 둔 시뮬레이터가 다음 잡에 남지 않습니다
- 다른 조직의 잡과 같은 VM을 쓰는 일이 없습니다
- 복제는 APFS 클론이라 빠르고 준비 시간은 과금하지 않습니다, 조직별 실제 준비 시간은 콘솔 분석 → 준비 시간 메뉴에 있습니다
다음 단계
- Xcode 버전 선택: 이미지의 Xcode 고르기
- 러너 사양: VM의 CPU, 메모리, 디스크
- 소스 올리기: 캐시 대신 소스에 의존성 포함하기