배치 빌드
Xcode, 시뮬레이터, 스킴 매트릭스로 잡 여러 개를 한 번에 보내는 배치 API와 콘솔 배치 화면, 부분 거절 규칙과 진행률 읽는 법을 설명합니다
배치는 매트릭스(Xcode × 시뮬레이터 × 스킴)의 조합마다 잡을 하나씩 만들어 한 번에 제출하고, 묶음의 진행률과 금액을 한 객체로 보여 줍니다
만들기
curl -s https://xenoci.com/api/runner/v1/batches \
-H "Authorization: Bearer $XENOCI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"name": "릴리스 전 확인",
"recipe_id": "rcp_builtin_unit_test",
"matrix": {
"xcode": ["27.0", "26.6"],
"simulator": ["iPhone 16", "iPad Pro 13-inch (M4)"],
"scheme": ["App"]
},
"env": { "FASTLANE_SKIP_UPDATE_CHECK": "1" },
"timeout_minutes": 40,
"artifacts": ["TestResults.xcresult"],
"source": { "git_url": "https://github.com/acme/app.git", "ref": "main" }
}'이 매트릭스는 2 × 2 × 1 = 4개 잡을 만듭니다
| 필드 | 설명 |
|---|---|
matrix | 필수 축은 xcode(최대 10개), simulator(최대 20개), scheme(최대 20개) 비운 축은 조합에 참여하지 않음 |
script 또는 recipe_id | 둘 중 하나 필수 |
env, timeout_minutes, artifacts, repository | 모든 잡에 같은 값 |
source | git 소스만 업로드(upload_id)는 잡 하나에만 쓰이므로 거절 |
name | 80자 이하 표시용 |
한 배치는 기본 최대 20개 잡입니다
넘으면 400 invalid_request와 details.max_jobs, details.jobs가 돌아옵니다
각 잡에 들어가는 값
조합의 값은 환경 변수로 각 잡에 들어갑니다
레시피와 스크립트는 이 변수를 읽습니다
| 축 | 잡에 주는 값 |
|---|---|
xcode | 잡의 xcode와 환경 변수 XENOCI_XCODE |
simulator | 환경 변수 XENOCI_SIMULATOR |
scheme | 환경 변수 XENOCI_SCHEME |
직접 쓰는 스크립트도 같은 변수를 읽으면 배치에서 그대로 동작합니다
xcodebuild -scheme "$XENOCI_SCHEME" \
-destination "platform=iOS Simulator,name=${XENOCI_SIMULATOR:-iPhone 16}" \
CODE_SIGNING_ALLOWED=NO test배치가 만든 잡은 source_kind가 batch이고 잡 목록과 로그 화면에서 출처 배치로 걸러집니다
부분 거절 규칙
조합은 매트릭스 순서대로 제출됩니다
- 첫 조합이 거절되면 배치는 만들어지지 않고 그 오류로 실패합니다 (
402,429,503중 하나) - 두 번째부터는 사용 가능 잔액이 "이미 받은 잡 수 + 1"분의 요금 이상일 때만 받습니다, 모자라면 그 조합과 나머지를
insufficient_credit으로 거절합니다, 대기 잡은 잔액을 잡아 두지 않기 때문에 시작도 못 할 잡을 줄 세우지 않기 위한 규칙입니다 - 대기열 가득, 월 한도, 용량 부족 같은 다른 거절도 그 조합과 이후 전부를 같은 코드로 거절합니다
거절된 조합은 응답의 items에 status: "rejected"와 error로 남고 배치 자체는 201로 만들어집니다
거절된 조합을 다시 돌리려면 그 조합만으로 새 배치를 만듭니다
응답 읽기
{
"id": "bat_Rk4pW2nQ7c",
"organization_id": "org_b1Y4kP",
"workspace_id": "wrk_Hq8sN2",
"name": "릴리스 전 확인",
"recipe_id": "rcp_builtin_unit_test",
"status": "running",
"matrix": { "xcode": ["27.0", "26.6"], "simulator": ["iPhone 16", "iPad Pro 13-inch (M4)"], "scheme": ["App"] },
"requested_jobs": 4,
"accepted_jobs": 4,
"rejected_jobs": 0,
"progress": { "queued": 2, "preparing": 0, "running": 2, "succeeded": 0, "failed": 0, "cancelled": 0, "other_ended": 0, "done": 0, "percent": 0 },
"amount_micro_usd": 79200,
"amount_usd": "0.079200",
"created_at": "2026-10-12T03:20:00.000Z",
"cancelled_at": null,
"items": [
{ "index": 0, "xcode": "27.0", "simulator": "iPhone 16", "scheme": "App", "job_id": "job_…", "status": "running", "error": null, "amount_micro_usd": 39600, "amount_usd": "0.039600" }
]
}| 필드 | 뜻 |
|---|---|
status | running, completed(받은 잡이 모두 끝남), cancelled |
progress.percent | 끝난 잡 ÷ 받은 잡, 내림 |
progress.other_ended | timed_out, credit_exhausted, platform_error로 끝난 잡 수 |
amount_* | 받은 잡들의 금액 합 (실행 중인 잡은 지금까지 약정된 분) |
items[].job_id | 각 조합의 잡 GET /v1/jobs/{job_id}로 로그와 결과물에 접근 |
조회와 취소
curl -s "https://xenoci.com/api/runner/v1/batches?limit=20" -H "Authorization: Bearer $XENOCI_API_KEY"
curl -s https://xenoci.com/api/runner/v1/batches/bat_Rk4pW2nQ7c -H "Authorization: Bearer $XENOCI_API_KEY"
curl -s -X POST https://xenoci.com/api/runner/v1/batches/bat_Rk4pW2nQ7c/cancel -H "Authorization: Bearer $XENOCI_API_KEY"취소는 아직 끝나지 않은 잡 각각에 POST /v1/jobs/{job_id}/cancel과 같은 일을 하고 배치를 cancelled로 표시합니다
이미 끝난 잡의 과금은 그대로입니다
콘솔에서
콘솔 빌드 → 배치 메뉴에서 레시피를 고르고 Xcode, 시뮬레이터, 스킴을 쉼표로 적어 배치를 만들고, 목록에서 진행률과 조합별 상태를 보고 취소할 수 있습니다
CLI와 MCP에는 배치 명령이 없습니다
다음 단계
- Xcode 버전 선택: Xcode 축
- iOS 시뮬레이터: 시뮬레이터 축과 레시피
- 잡 상태와 종료 이유: 조합별 잡 상태