본문 바로가기

GitHub 작업

GitHub repository에서 iOS 및 Android build를 직접 자동화하세요. 워크플로 파일 하나와 몇 가지 repository secrets만 있으면, 모든 push, tag, 수동 트리거마다 서명되어 스토어에 바로 제출할 수 있는 앱을 생성할 수 있습니다. 팀원 누구도 Mac, Xcode, Android Studio를 설치하지 않아도 됩니다.

간단한 답변: Capacitor CI/CD를 GitHub Actions에 적용하려면, Capgo CLI를 실행하는 워크플로우 하나를 추가하세요: Capgo Builder가 서명된 iOS 및 Android 빌드를 생성하고 스토어에 업로드할 수 있으며, 추가된 bundle upload job(참고 자동 OTA 또는 Native)을 통해 동일한 워크플로우로 웹 전용 변경 사항을 Capgo 라이브 업데이트로 배포할 수 있습니다.

제공되는 항목

“주요 기능” 섹션

자동화된 릴리스

Git에서 릴리스 태그를 만들면 서명된 iOS 및 Android 바이너리가 TestFlight와 Play Store에 자동으로 제출됩니다.

로컬 설정 불필요

Windows나 Linux를 쓰는 기여자도 iOS build를 트리거할 수 있습니다. Xcode도, 번거로운 프로비저닝도, 노트북마다 공유 서명 인증서가 떠돌 일도 없습니다.

범위가 지정된 Secrets

자격 증명은 GitHub repository secrets에 저장되며, 해당 repo로 범위가 제한되어 workflow runner에만 노출됩니다. 교체도 감사도 간편합니다.

병렬 빌드

matrix job으로 iOS와 Android를 동시에 빌드하세요. 일반적인 릴리스는 10분 이내에 끝납니다.

워크플로를 설정하기 전에 다음 사항을 확인하세요:

  • 활성 구독이 있는 Capgo 계정과 Capgo API 키
  • Capgo에 등록된 앱 (bunx @capgo/cli@latest app add 등록되지 않은 경우)
  • 로컬에서 구성한 빌드 자격 증명 bunx @capgo/cli@latest build init — 아래 자격 증명 관리 위저드 안내에 따라
  • 성공한 로컬 빌드 (bunx @capgo/cli@latest build request com.example.app --platform android --build-mode debug) — CI는 첫 빌드를 디버깅할 곳이 아닙니다
  • 이 GitHub CLI (gh) 설치 및 인증 완료 (gh auth login)

Capgo CLI은 로컬 자격 증명을 바로 사용할 수 있는 .env 파일로 내보낼 수 있습니다. gh secret set -f와 함께 사용하면 수동 base64 인코딩, JSON 조작, 시크릿 복사-붙여넣기 없이 CI/CD 설정을 3개 명령어로 끝낼 수 있습니다.

  1. 저장소 시크릿으로 Capgo API 키를 추가하세요

    API 키는 앱별 자격 증명 저장소에 포함되지 않으므로 한 번만 수동으로 추가하세요:

    터미널 창
    gh secret set CAPGO_TOKEN --body "your_capgo_api_key_here"

    키를 생성하려면 Capgo 대시보드 포함 업로드 권한 이상.

  2. 자격 증명을 다음으로 내보내기 .env 파일

    대화형 자격 증명 관리자를 실행하세요:

    터미널 창
    bunx @capgo/cli@latest build credentials manage --appId com.example.app

    TUI에서 다음을 선택하세요: .env로 내보내기. CLI가 작성하는 위치는 .env.capgo.<appId> 현재 디렉토리이고 모드는 0600 (소유자만 읽기 가능) — 예시: .env.capgo.com.example.app. iOS와 Android가 모두 설정되면, 두 플랫폼의 secret은 동일한 파일에 저장되며, 위치는 # === IOS === 및 # === ANDROID === 섹션 헤더 아래입니다. iOS와 Android의 환경 변수 이름은 서로 겹치지 않으므로 함께 저장해도 충돌이 없습니다.

  3. 다음 파일을 .env GitHub Actions secrets에 push하세요.

    이 gh secret set -f 명령어는 dotenv 파일을 읽고 각 항목별로 리포지토리 시크릿을 생성합니다 KEY=value 줄:

    터미널 창
    gh secret set -f .env.capgo.com.example.app

    이것으로 끝입니다 — 워크플로우에 필요한 모든 시크릿이 이제 GitHub에 있습니다. 다음으로 확인하세요 gh secret list.

  4. 워크플로 파일 생성

    추가 .github/workflows/capgo-build.yml 리포지토리에 추가하세요. 빌드를 트리거하는 방식에 따라 아래 세 가지 패턴 중 하나를 선택하세요.

secrets에 저장되는 항목

“시크릿에 포함되는 내용” 섹션

참고로, gh secret set -f 다음 리포지토리 시크릿을 생성합니다(워크플로 YAML에서 이 이름 그대로 참조합니다):

플랫폼생성된 Secrets
iOSBUILD_CERTIFICATE_BASE64, P12_PASSWORD, CAPGO_IOS_PROVISIONING_MAP_BASE64, APPLE_KEY_ID, APPLE_ISSUER_ID, APPLE_KEY_CONTENT, APP_STORE_CONNECT_TEAM_ID
AndroidANDROID_KEYSTORE_FILE, KEYSTORE_KEY_ALIAS, KEYSTORE_KEY_PASSWORD, KEYSTORE_STORE_PASSWORD, PLAY_CONFIG_JSON
(수동으로 추가됨)CAPGO_TOKEN

이것들을 외울 필요는 없습니다. 아래 워크플로 예제에 이미 모두 참조되어 있습니다.

워크플로우 예시

“Workflow Examples” 섹션

아래 세 가지 예제는 가장 일반적인 패턴을 다룹니다. 모두 동일한 구조를 사용합니다: 리포지토리를 체크아웃하고, 의존성을 설치하고, 웹 에셋을 빌드하고, 네이티브로 동기화한 후, 자격 증명을 환경 변수로 전달하여 Capgo Build를 호출합니다.

쓰기 권한이 있는 사람이 액션 GitHub의 플랫폼 드롭다운이 있는 탭입니다. 임시 테스트 빌드나 필요 시 릴리스를 시작하는 데 유용합니다.

.github/workflows/capgo-build-manual.yml
name: Capgo Build (Manual)
on:
workflow_dispatch:
inputs:
platform:
description: 'Platform to build'
required: true
default: 'android'
type: choice
options: [ios, android, both]
mode:
description: 'Build mode'
required: true
default: 'debug'
type: choice
options: [debug, release]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bun run build
- run: bunx cap sync
- name: Trigger Capgo Build
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
CAPGO_IOS_PROVISIONING_MAP_BASE64: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP_BASE64 }}
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }}
KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }}
PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }}
run: |
bunx @capgo/cli@latest build request com.example.app \
--platform ${{ inputs.platform }} \
--build-mode ${{ inputs.mode }}

교체 com.example.app 앱 ID로 설정하세요. 커밋한 후 Actions → Capgo Build (수동) → 워크플로 실행 에서 실행을 트리거합니다.

2. 태그 생성 시 릴리스

“2. Release on Tag” 섹션

버전 태그를 푸시할 때마다 두 플랫폼을 병렬로 빌드하고 배포합니다. 예: v1.4.0. 가장 일반적인 프로덕션 설정입니다 — git tag v1.4.0 && git push --tags 릴리스 명령이 됩니다.

.github/workflows/capgo-build-release.yml
name: Capgo Build (Release)
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
platform: [ios, android]
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bun run build
- run: bunx cap sync ${{ matrix.platform }}
- name: Build ${{ matrix.platform }}
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
# iOS
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
CAPGO_IOS_PROVISIONING_MAP_BASE64: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP_BASE64 }}
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
# Android
ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }}
KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }}
PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }}
run: |
bunx @capgo/cli@latest build request com.example.app \
--platform ${{ matrix.platform }} \
--build-mode release

매트릭스는 iOS와 Android를 별도의 러너에서 병렬로 실행합니다. 설정은 fail-fast: false iOS 빌드가 실패해도 진행 중인 Android 빌드가 취소되지 않는다는 뜻입니다(반대도 마찬가지). 한 플랫폼에 일시적인 서명 문제가 있을 때 유용합니다.

3. Main 푸시 시 디버그 빌드

“3. Main에 Push 시 Debug Build” 섹션

에 push할 때마다 debug Android build를 생성하여 네이티브 빌드 회귀를 조기에 감지합니다 main. 실행 비용이 낮고 피드백이 빠르며, Play Store 업로드를 건너뛰어 순수 스모크 테스트로 유지할 수 있습니다.

.github/workflows/capgo-build-main.yml
name: Capgo Build (Main)
on:
push:
branches: [main]
paths:
- 'src/**'
- 'android/**'
- 'ios/**'
- 'package.json'
- 'capacitor.config.*'
jobs:
smoke-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bun run build
- run: bunx cap sync android
- name: Smoke build (Android debug)
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }}
KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }}
run: |
bunx @capgo/cli@latest build request com.example.app \
--platform android \
--build-mode debug \
--no-playstore-upload \
--output-upload

이 paths filter는 문서만 변경된 경우 워크플로가 실행되지 않도록 보장합니다. --no-playstore-upload Play Store 제출을 건너뜁니다(이것이 필요하지 않으며), PLAY_CONFIG_JSON 그리고 --output-upload 생성된 APK의 다운로드 URL을 만들어 테스트 디바이스에 설치할 수 있습니다.

일반적인 패턴

“Common Patterns” 섹션

Play Store / TestFlight 업로드 건너뛰기

“Play Store / TestFlight 업로드 건너뛰기” 섹션

테스트 빌드의 경우 스토어 제출을 건너뛰세요. Android는 --no-playstore-upload을(를) 사용하며, iOS는 --ios-distribution ad_hoc 로 ad-hoc 모드로 빌드합니다(App Store에 절대 제출되지 않음). 이 중 하나와 --output-upload 를(을) 조합하여 바이너리의 시간 제한 다운로드 URL을 생성할 수 있습니다.

기본적으로 릴리스 빌드는 서명된 아티팩트를 업로드하고 최종 스토어 작업을 사용자의 제어에 맡깁니다. 스토어 검토 플로우로 바로 넘어가야 하는 CI 릴리스의 경우 --submit-to-store-review.

Android는 사용자의 PLAY_CONFIG_JSON 서비스 계정을 사용합니다. 명시적인 트랙이 없으면, --submit-to-store-review 기본값은 production 트랙이며 release_status: completed. 호출 지점에서 트랙을 명시하는 것이 좋습니다: --android-track (또는 PLAY_STORE_TRACK) 상태는 다음과 같이 오버라이드할 수 있습니다: --android-release-status / PLAY_STORE_RELEASE_STATUS 필요할 때:

- name: Submit Android release for review
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }}
KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }}
PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }}
run: |
npx @capgo/cli@latest build request com.example.app \
--platform android \
--build-mode release \
--submit-to-store-review \
--android-track production \
--store-release-name "${GITHUB_REF_NAME}" \
--store-release-notes "Release ${GITHUB_REF_NAME}" \
--store-release-notes-locale "en-US=Release ${GITHUB_REF_NAME}"

production 대신 내부 완료 릴리스의 경우:

- name: Submit Android internal release
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
ANDROID_KEYSTORE_FILE: ${{ secrets.ANDROID_KEYSTORE_FILE }}
KEYSTORE_KEY_ALIAS: ${{ secrets.KEYSTORE_KEY_ALIAS }}
KEYSTORE_KEY_PASSWORD: ${{ secrets.KEYSTORE_KEY_PASSWORD }}
KEYSTORE_STORE_PASSWORD: ${{ secrets.KEYSTORE_STORE_PASSWORD }}
PLAY_CONFIG_JSON: ${{ secrets.PLAY_CONFIG_JSON }}
run: |
npx @capgo/cli@latest build request com.example.app \
--platform android \
--build-mode release \
--submit-to-store-review \
--android-track internal \
--store-release-name "${GITHUB_REF_NAME}"

iOS는 App Store Connect API 키 경로를 사용하고 처리된 TestFlight 빌드를 App Store 검토에 제출합니다. 다음이 필요합니다: app_store 배포; --ios-testflight-groups 외부 베타 배포에는 선택 사항이며 App Store 검토에는 필요하지 않습니다:

- name: Submit iOS build to App Store review
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
BUILD_CERTIFICATE_BASE64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }}
P12_PASSWORD: ${{ secrets.P12_PASSWORD }}
CAPGO_IOS_PROVISIONING_MAP: ${{ secrets.CAPGO_IOS_PROVISIONING_MAP }}
APPLE_KEY_ID: ${{ secrets.APPLE_KEY_ID }}
APPLE_ISSUER_ID: ${{ secrets.APPLE_ISSUER_ID }}
APPLE_KEY_CONTENT: ${{ secrets.APPLE_KEY_CONTENT }}
APP_STORE_CONNECT_TEAM_ID: ${{ secrets.APP_STORE_CONNECT_TEAM_ID }}
run: |
npx @capgo/cli@latest build request com.example.app \
--platform ios \
--build-mode release \
--ios-distribution app_store \
--submit-to-store-review \
--store-release-name "${GITHUB_REF_NAME}" \
--store-release-notes "Release ${GITHUB_REF_NAME}" \
--store-release-notes-locale "en-US=Release ${GITHUB_REF_NAME}" \
--no-ios-automatic-release

빌드 출력 URL 및 QR code 읽기

“빌드 출력 URL 및 QR code 읽기” 섹션

전달하세요: --output-record <path> 빌드가 성공하면 빌드 아티팩트 URL과 QR code를 디스크에 저장하고, 이후 단계에서 다음 명령어로 다시 읽어오려면 build last-output. 로그 스크래핑도, 정규식도 필요 없습니다.

- name: Build
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
# ...credentials...
run: |
bunx @capgo/cli@latest build request com.example.app \
--platform android --build-mode debug \
--output-upload --output-retention 1d \
--output-record /tmp/build.json
- name: Comment on PR with build URL
env:
GH_TOKEN: ${{ github.token }}
run: |
URL=$(bunx @capgo/cli@latest build last-output --path /tmp/build.json --field outputUrl)
if [ -n "$URL" ]; then
gh pr comment ${{ github.event.pull_request.number }} \
--body "Debug build ready: $URL"
fi

--output-record /tmp/build.json JSON 레코드를 작성하고( jobId, status, outputUrl, qrCodeAscii, qrCodePngPath, finishedAt) PNG QR code도 같은 위치에 함께 /tmp/build.json.qr.png. build last-output 다시 읽어옵니다:

  • --field outputUrl 다운로드 URL만 출력합니다(줄바꿈으로 끝나며, 다음에 그대로 써도 안전) URL=$(...)).
  • --field qrCodePngPath PNG 경로를 출력하므로 PR 첨부 파일로 업로드할 수 있습니다.
  • --qr 렌더링된 ASCII QR을 출력합니다. PR 코멘트의 Markdown code 코드 블록 안에 넣으면 바로 스캔할 수 있습니다.

빌드 번호 올리기 건너뛰기

“빌드 번호 증가 건너뛰기” 섹션

기본적으로 각 릴리스 빌드에서 빌드 번호가 증가합니다. 직접 제어하는 값(예: Git 태그)으로 고정하려면 다음을 전달하세요. --skip-build-number-bump:

- name: Set version from tag
run: |
VERSION="${GITHUB_REF#refs/tags/v}"
# Update package.json or your version source here
bun pm version "$VERSION" --no-git-tag-version
- name: Build
env:
CAPGO_TOKEN: ${{ secrets.CAPGO_TOKEN }}
# ...credentials...
run: |
bunx @capgo/cli@latest build request com.example.app \
--platform ios --build-mode release \
--skip-build-number-bump

bun install 이미 충분히 빠르므로 JS-deps 캐싱은 드물게만 효과가 있지만, Capacitor의 네이티브 의존성(CocoaPods, Gradle)은 대규모 프로젝트에서 캐싱할 가치가 있습니다:

- uses: actions/cache@v4
with:
path: |
~/.bun/install/cache
ios/App/Pods
android/.gradle
key: ${{ runner.os }}-capgo-${{ hashFiles('**/bun.lock', '**/Podfile.lock') }}
증상예상 원인
CAPGO_TOKEN is not setSecret이 추가되지 않았거나 job이 접근할 수 없습니다 (environment/branch protection 확인)
iOS / Android credential 누락 오류gh secret set -f 실행되지 않았거나 다른 repo를 대상으로 실행되었습니다. 다음으로 확인하세요 gh secret list
cap sync 로컬에서는 작동하지만 CI에서 실패함네이티브 플러그인이 package.json에 없거나, 또는 누락된 경우 bun install 첫 번째 제출이 승인되기 cap sync
Build는 성공했지만 App Store Connect에 앱이 나타나지 않음Team ID가 잘못됐거나 App Store Connect에 앱 레코드가 아직 없습니다. 로컬에서 다음 명령어로 확인하세요: bunx @capgo/cli@latest build credentials manage
“Uploading project” 이후 빌드가 멈춤프로젝트 아카이브가 비정상적으로 큼 — 다음을 확인하세요: node_modules 업로드되지 않는지 (기본적으로는 업로드되지 않아야 함)
Provisioning profile doesn't match bundle IDProvisioning map이 Xcode가 서명하는 bundle ID와 다른 bundle ID를 가리킵니다. 다시 실행하여 build init 프로필을 갱신한 후, 다음 명령으로 다시 export 하세요: build credentials manage
Credentials를 로컬에서 변경했지만 CI는 여전히 실패함다시 export하고 다시 push하는 것을 잊지 마세요: bunx @capgo/cli@latest build credentials manage → gh secret set -f .env.capgo.<appId>
Manager가 combined 파일 쓰기를 거부함플랫폼 간 Shared config keys가 다릅니다 — Manager가 경고하고 확인을 요청합니다. overwrite-one-wins로 덮어쓰려면 확인하거나, 플랫폼별로 다음으로 다시 export 하세요: --platform ios / --platform android
build last-output 빈 URL을 출력함빌드가 통과하지 못함 --output-upload, 또는 아티팩트를 생성하기 전에 실패했습니다. outputUrl 다음과 같습니다 null 레코드에 포함됩니다. 다음을 기준으로 분기하세요 [ -n "$URL" ] 사용하기 전에
build last-output 다음과 같은 오류가 발생했습니다 Unsupported record schemaVersion러너가 레코드를 작성한 것보다 오래된 CLI 버전을 사용 중입니다. 프로듀서와 리더 모두를 동일한 명시적 버전으로 고정하세요(예: bunx @capgo/cli@7.104.0 … 양쪽에) 대신 @latest, 작업(job) 간에 떠다니며 이동할 수 있습니다

플랫폼별 빌드 실패에 대해서는 다음을 참고하세요. 문제 해결 가이드.