빌드 배포
CI 파이프라인을 연결하면 빌드가 App Center에 자동으로 등록되어 팀원 누구든 바로 확인할 수 있습니다.
동작 방식
CI 파이프라인
→ POST /api/v1/builds (tapflow relay)
→ App Center에 빌드 등록
→ 팀원이 브라우저에서 기기를 선택하고 직접 테스트
PO / PM: 기획한 대로 나왔는지
디자이너: 디자인 스펙에 맞는지
백엔드: API 연동이 맞는지
QA: 버그가 있는지CI 잡이 빌드 파일을 업로드하면 누구나 별도 도구 설치나 기기 세팅 없이 브라우저에서 바로 테스트할 수 있습니다.
두 가지 테스트 경로
이 가이드는 수동 리뷰 경로를 다룹니다. CI가 빌드를 전달하고, 팀원이 직접 테스트하는 방식입니다.
LLM 에이전트가 시뮬레이터를 자동으로 조작하는 방식은 CI/CD에서 MCP 활용을 참고하세요. 이는 별도의 실험적 기능입니다.
어떤 빌드 도구든
tapflow는 빌드 도구가 아니라 완성된 아티팩트를 다룹니다. 네이티브 Xcode·Gradle 빌드, React Native, Flutter, 클라우드 빌드 서비스가 만드는 빌드를 모두 같은 방식으로 업로드합니다. 아티팩트(.app.zip·.tar.gz/.tgz·.apk)만 나오면 이후 과정은 이 페이지 그대로입니다.
사전 조건
| 항목 | 설명 |
|---|---|
| tapflow relay | 실행 중이고 CI 환경에서 접근 가능해야 합니다 |
| Personal Access Token | Settings → Tokens에서 builds:write 권한으로 생성합니다 |
CI가 relay에 도달하려면
CI 잡이 relay의 POST /api/v1/builds에 접근할 수 있어야 합니다. relay는 에이전트와 같은 내부 네트워크에 두는 것이 원칙입니다(릴레이 배포). 그래서 CI가 어디서 실행되는지에 따라 경로가 갈립니다.
| relay 배치 | CI가 업로드하는 방법 |
|---|---|
| LAN 전용 (기본) | 클라우드 러너(GitHub 호스티드 등)는 LAN relay에 닿지 못합니다. 내부 네트워크에 둔 self-hosted 러너에서 relay 내부 주소(http://192.168.x.x:4000)로 업로드하세요 |
| VPS + rathole 터널 | relay를 외부 접근용으로 열어 두면 공개 URL(https://your-vps.com)로 어디서든 업로드할 수 있어 클라우드 CI에 가장 잘 맞습니다 |
| Tailscale 터널 | tailnet 멤버만 접근할 수 있으므로 CI 러너도 tailnet에 연결돼 있어야 합니다 |
relay는 클라우드에 직접 올리지 않습니다
relay를 fly.io·Railway 같은 서비스에 직접 배포하면 에이전트→relay 구간이 인터넷을 타면서 스트림이 끊깁니다(미지원). 공개 접근이 필요하면 relay는 내부 네트워크에 둔 채 터널로 노출하세요. VPS는 relay 호스트가 아니라 터널 호스트입니다.
1. 토큰 생성
대시보드의 Settings → Tokens → New Token에서 생성합니다.
- Name:
GitHub Actions처럼 용도를 알 수 있는 이름 - Scope:
builds:write - Expiry: 선택 사항
토큰은 생성 시 한 번만 표시됩니다. CI 시크릿(예: TAPFLOW_PAT)으로 저장하세요.
2. 빌드 업로드
빌드 파일이 준비되면 POST /api/v1/builds를 호출합니다.
# iOS (.app.zip)
curl -X POST https://your-relay/api/v1/builds \
-H "Authorization: Bearer $TAPFLOW_PAT" \
-F "file=@MyApp.app.zip" \
-F "status=In Progress" \
-F "label=$GIT_BRANCH"
# Android (.apk)
curl -X POST https://your-relay/api/v1/builds \
-H "Authorization: Bearer $TAPFLOW_PAT" \
-F "file=@MyApp.apk" \
-F "status=In Progress" \
-F "label=$GIT_BRANCH"status=In Progress는 팀에게 리뷰 준비가 됐다는 신호입니다.label에는 브랜치명, 티켓 번호 등 맥락을 담을 수 있습니다.
iOS 빌드
.ipa 파일은 지원하지 않습니다. 시뮬레이터 빌드는 .app.zip 또는 .tar.gz/.tgz를 올립니다. .app.zip은 xcodebuild -sdk iphonesimulator로 빌드해 .app 폴더를 zip으로 압축하고, .tar.gz/.tgz는 클라우드 시뮬레이터 빌드가 만드는 아카이브입니다.
3. 빌드 메타데이터 첨부 (선택)
커밋과 브랜치 정보를 코멘트로 남기면 리뷰어가 무엇이 바뀌었는지 바로 확인할 수 있습니다.
BUILD_ID=$(curl -sf -X POST https://your-relay/api/v1/builds \
-H "Authorization: Bearer $TAPFLOW_PAT" \
-F "file=@MyApp.app.zip" \
-F "status=In Progress" \
-F "label=$GIT_BRANCH" | jq -r '.id')
curl -X POST https://your-relay/api/v1/comments \
-H "Authorization: Bearer $TAPFLOW_PAT" \
-F "build_id=$BUILD_ID" \
-F "body=Branch: $GIT_BRANCH
Commit: $GIT_SHA
$GIT_COMMIT_MSG"GitHub Actions 예시
name: tapflow에 업로드
on:
push:
branches: [main, 'release/**']
pull_request:
jobs:
upload:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: 앱 빌드
run: |
xcodebuild -scheme MyApp -sdk iphonesimulator \
-configuration Debug \
CONFIGURATION_BUILD_DIR=build/Debug
cd build/Debug && zip -r MyApp.app.zip MyApp.app
- name: tapflow에 업로드
env:
TAPFLOW_PAT: ${{ secrets.TAPFLOW_PAT }}
TAPFLOW_RELAY_URL: ${{ secrets.TAPFLOW_RELAY_URL }}
BRANCH: ${{ github.head_ref || github.ref_name }}
COMMIT: ${{ github.sha }}
COMMIT_MSG: ${{ github.event.head_commit.message || github.event.pull_request.title }}
run: |
BUILD_RESPONSE=$(curl -sf -X POST "$TAPFLOW_RELAY_URL/api/v1/builds" \
-H "Authorization: Bearer $TAPFLOW_PAT" \
-F "file=@build/Debug/MyApp.app.zip" \
-F "status=In Progress" \
-F "label=$BRANCH")
BUILD_ID=$(echo "$BUILD_RESPONSE" | jq -r '.id')
COMMENT="Branch: $BRANCH"$'\n'"Commit: $COMMIT"$'\n'"$COMMIT_MSG"
curl -sf -X POST "$TAPFLOW_RELAY_URL/api/v1/comments" \
-H "Authorization: Bearer $TAPFLOW_PAT" \
-F "build_id=$BUILD_ID" \
-F "body=$COMMENT"빌드 상태 참고
| 상태 | 의미 |
|---|---|
Backlog | 업로드됐지만 아직 리뷰 준비 전 |
In Progress | 준비 완료 — 팀이 테스트를 시작할 수 있음 |
Done | 이해관계자 승인 완료 |
Rejected | 문제 발견, 수정 필요 |
CI는 업로드 시 In Progress로 설정합니다. Done과 Rejected는 리뷰 후 팀원이 직접 변경합니다.