실패 줄이기
자주 나는 빌드 실패의 원인과 고치는 방법, 그리고 승인 단계에서 거절되지 않게 하는 방법
실패는 두 종류입니다, 잡이 시작되기 전에 거절되는 경우(HTTP 오류)와 스크립트가 0이 아닌 종료 코드로 끝나는 경우(failed)입니다, 전자는 과금이 없고 후자는 실행한 분만큼 과금됩니다
시작 전에 거절되는 경우
| 오류 | 원인 | 방지 |
|---|---|---|
insufficient_credit | 사용 가능 잔액이 1분 요금 미만 | 낮은 잔액 알림을 켜 두고 미리 충전 |
workspace_spend_limit, tier_monthly_limit | 월 한도 도달 | 분석 → 한도에서 사용률 확인 |
tier_concurrency_limit | 대기열까지 가득 | 배치 크기를 줄이거나 retry_after_s 뒤 재시도 |
invalid_request (fields: ["xcode"]) | 없는 Xcode 버전 | 환경 목록의 값만 사용 |
invalid_request (missing_env) | 레시피의 required_env 누락 | 응답의 details.guide대로 env 추가 |
workspace_archived | 보관된 워크스페이스의 키 | 새 워크스페이스에서 키 발급 |
스크립트가 실패하는 경우
잡 로그 끝에 원인이 있습니다, 저장소의 진단 규칙이 분류하는 흔한 원인입니다
| 분류 | 로그의 단서 | 고치는 방법 |
|---|---|---|
| Xcode 버전 | swift-tools-version, SDK … not found, destination … unavailable | Package.swift의 도구 버전을 낮추거나 잡의 xcode를 올림, xcrun simctl list devices available에 있는 목적지만 사용 |
| 명령줄 도구만 선택됨 | xcode-select 가 /Library/Developer/CommandLineTools | 스크립트에서 xcode-select --switch를 CommandLineTools로 하지 않음 |
| 의존성 | pod install 실패, Package.resolved 충돌, command not found | 잠금 파일 커밋, 없는 도구는 스크립트에서 설치 |
| 서명 | No signing certificate, DEVELOPMENT_TEAM, keychain | 컴파일 확인이면 CODE_SIGNING_ALLOWED=NO, 서명이 필요하면 임시 키체인 생성과 잠금 해제 |
| 프로비저닝과 App Store Connect | 프로파일 불일치, 계정 잠김, 약관 미동의, 빌드 번호 중복, 아이콘 알파 채널 | Apple Developer와 App Store Connect에서 해결, CURRENT_PROJECT_VERSION 올리기 |
| 컴파일 | error: 와 파일, 줄 번호 | 첫 오류부터 고침 |
| 테스트 | assertion, crash | 실패한 단언과 크래시의 첫 프레임 |
| 메모리 부족 | killed, OOM | -jobs N, -parallel-testing-worker-count 2 |
| 네트워크 | 호스트 연결 실패 | 로그의 호스트 이름을 확인하고 허용된 출처에서 받기 |
스크립트 작성 습관
- 첫 줄에
set -euo pipefail을 두어 중간 실패가 조용히 지나가지 않게 합니다 xcodebuild -version과xcrun --sdk iphonesimulator --show-sdk-version을 먼저 찍으면 버전 문제를 바로 알 수 있습니다- 목적지는
generic/platform=iOS Simulator처럼 이름에 덜 의존하는 형태가 안전합니다 - 결과 번들(
-resultBundlePath)을artifacts에 넣어 두면 실패 원인을 로컬 Xcode로 열어 볼 수 있습니다 - 외부 입력(스킴, 워크스페이스)은
${VAR:?message}로 받아 누락을 즉시 드러냅니다
재시도와 멱등
- 같은
Idempotency-Key로 다시 제출하면 24시간 안에는 같은 잡이 돌아옵니다, 네트워크 오류 뒤의 재시도에 쓰세요 - VM 준비가 실패하면 플랫폼이 한 번 자동으로 다시 시도하고 그래도 안 되면
platform_error로 끝나며 과금하지 않습니다, 이 경우는 그냥 다시 제출하면 됩니다 timed_out은 스크립트가 제한 시간을 넘긴 것입니다, 시간을 늘리기 전에 어디서 멈췄는지 로그를 보세요
로그 읽기
xenocast logs job_2Qm7Xp9Lk4 --failure
xenocast logs job_2Qm7Xp9Lk4 --tail 200콘솔 실행 → 잡에서도 같은 로그를 봅니다, 잡 로그는 5 MiB까지 기록되고 넘으면 잘립니다, 긴 출력은 파일로 모아 artifacts로 받으세요