GitLab CI를 활용한 자동 Android Build
Capacitor 앱의 CI/CD 설정은 복잡하고 시간이 많이 걸릴 수 있습니다. 다음 내용을 확인해 보세요:
사전 요구사항
시작하기 전에 다음을 설정해야 합니다:
- 관리자 권한이 있는 GitLab 계정
- 올바른 서명으로 Google Play Store에 이미 출시된 앱
- Android 서명 키 및 keystore 파일
- Play Store API가 활성화된 Google Cloud Console 프로젝트
- 적절한 권한을 가진 서비스 계정
- GitLab CI/CD 워크플로우에 대한 이해
- Fastlane 설정에 대한 지식
- 파이프라인 유지 관리 및 디버깅 시간
Capgo이 제공하는 CI/CD용 Capgo Build
Fastlane, Gradle runner, keystore, upload-script 유지 관리를 건너뛰세요. Capgo 빌드 기존 CI/CD 파이프라인에서 서명된 네이티브 Android 빌드를 실행합니다:
- 기존 파이프라인과 호환: 웹 빌드 후 GitLab CI, GitHub Actions, Jenkins 또는 로컬 스크립트에서 Capgo 빌드를 트리거합니다
npx cap sync. - CI 시크릿 기반 서명: Android 키스토어, 키 별칭, 비밀번호 및 Play Console 서비스 계정 JSON을 자체 CI 시크릿에 안전하게 보관합니다.
- 네이티브 러너 관리 불필요: Capgo 빌드는 유지보수된 Android 빌드 환경을 제공하므로, SDK 이미지, Gradle 캐시 문제 또는 Fastlane 레인을 직접 관리할 필요가 없습니다.
- 아티팩트 및 제출: QA를 위해 서명된 아티팩트를 다운로드하거나 Capgo CLI을 통해 릴리스 빌드를 제출합니다.
요금제
- Capgo 플랜은 월 $12부터 시작합니다
- OTA 업데이트 및 월 약 15회 네이티브 빌드 포함
- 추가 빌드 분은 크레딧으로 분당 과금됩니다
수동 설정 가이드
다음과 같이 진행하세요:
포스트에서 따를 단계
- Fastlane 파일 복사
- GitLab 암호화 시크릿에 시크릿 저장
- Google Play 서비스 계정 키 생성 및 저장
- Android 서명 키 저장
- GitLab 워크플로 .yml 파일 설정
1. Fastlane 파일 복사
Fastlane은 일반적인 모바일 개발 작업을 자동화하기 위해 만들어진 Ruby 라이브러리입니다. Fastlane을 사용하면 보통 Android Studio에서 수행하던 작업을 실행하는 일련의 “actions”를 묶은 커스텀 “lanes”를 구성할 수 있습니다. Fastlane으로 많은 것을 할 수 있지만, 이 튜토리얼에서는 몇 가지 핵심 action만 사용하겠습니다.
프로젝트 루트에 Fastlane 폴더를 만들고 다음 파일들을 복사하세요: Fastlane
default_platform(:android)
KEYSTORE_KEY_ALIAS = ENV["KEYSTORE_KEY_ALIAS"]
KEYSTORE_KEY_PASSWORD = ENV["KEYSTORE_KEY_PASSWORD"]
KEYSTORE_STORE_PASSWORD = ENV["KEYSTORE_STORE_PASSWORD"]
platform :android do
desc "Deploy a beta version to the Google Play"
private_lane :verify_changelog_exists do |version_code: |
changelog_path = "android/metadata/en-US/changelogs/#{version_code}.txt"
UI.user_error!("Missing changelog file at #{changelog_path}") unless File.exist?(changelog_path)
UI.message("Changelog exists for version code #{version_code}")
end
private_lane :verify_upload_to_staging do |version_name: |
UI.message "Skipping staging verification step"
end
lane :beta do
keystore_path = "#{Dir.tmpdir}/build_keystore.keystore"
File.write(keystore_path, Base64.decode64(ENV['ANDROID_KEYSTORE_FILE']))
json_key_data = Base64.decode64(ENV['PLAY_CONFIG_JSON'])
previous_build_number = google_play_track_version_codes(
package_name: ENV['DEVELOPER_PACKAGE_NAME'],
track: "internal",
json_key_data: json_key_data,
)[0]
current_build_number = previous_build_number + 1
sh("export NEW_BUILD_NUMBER=#{current_build_number}")
gradle(
task: "clean bundleRelease",
project_dir: 'android/',
print_command: false,
properties: {
"android.injected.signing.store.file" => "#{keystore_path}",
"android.injected.signing.store.password" => "#{KEYSTORE_STORE_PASSWORD}",
"android.injected.signing.key.alias" => "#{KEYSTORE_KEY_ALIAS}",
"android.injected.signing.key.password" => "#{KEYSTORE_KEY_PASSWORD}",
'versionCode' => current_build_number
})
upload_to_play_store(
package_name: ENV['DEVELOPER_PACKAGE_NAME'],
json_key_data: json_key_data,
track: 'internal',
release_status: 'completed',
skip_upload_metadata: true,
skip_upload_changelogs: true,
skip_upload_images: true,
skip_upload_screenshots: true,
)
end
lane :build do
gradle(
task: "clean bundleRelease",
project_dir: 'android/',
print_command: false,
properties: {
"android.injected.signing.store.file" => "#{keystore_path}",
"android.injected.signing.store.password" => "#{KEYSTORE_STORE_PASSWORD}",
"android.injected.signing.key.alias" => "#{KEYSTORE_KEY_ALIAS}",
"android.injected.signing.key.password" => "#{KEYSTORE_KEY_PASSWORD}",
})
end
lane :prod_release do
build_gradle = File.read("../android/app/build.gradle")
verify_changelog_exists(version_code: build_gradle.match(/versionCode (\d+)/)[1])
verify_upload_to_staging(version_name: build_gradle.match(/versionName '([\d\.]+)'/)[1])
supply(
track_promote_to: 'beta',
skip_upload_apk: true,
skip_upload_aab: true,
skip_upload_metadata: false,
skip_upload_changelogs: false,
skip_upload_images: false,
skip_upload_screenshots: false
)
end
end
GitLab CI/CD 변수에 Secret 저장하기
GitLab은 GitHub의 리포지토리 시크릿과 유사하게 암호화된 CI/CD 변수를 저장할 수 있는 방법을 제공합니다. 민감한 정보를 안전하게 저장하세요.
- GitLab 프로젝트의 설정으로 이동하세요.
- CI/CD > Variables로 이동하세요
- 다음 변수를 추가하세요:
- ANDROID_KEYSTORE_FILE: base64로 인코딩된
.jks또는.keystoreAndroid 빌드를 서명하는 데 사용되는 파일입니다. Play App Signing을 사용하는 경우 업로드 키와 연결된 keystore 파일이거나, 앱 서명 키일 수 있습니다. - KEYSTORE_KEY_PASSWORD: keystore 파일과 연결된 비밀번호
- KEYSTORE_KEY_ALIAS: 키 스토어 별칭
- KEYSTORE_STORE_PASSWORD: 개인 키 비밀번호
- DEVELOPER_PACKAGE_NAME: com.example.app과 같은 Android 앱 ID
- PLAY_CONFIG_JSON: base64로 인코딩된 서비스 계정 키 JSON입니다.
Google Play 서비스 계정 키 생성하기
secret을 생성하려면 PLAY_CONFIG_JSON 다음 단계를 따르세요:
- 다음으로 이동하세요: Google Cloud Console
- 새 프로젝트를 생성하거나 기존 프로젝트를 선택하세요
- Google Play Android Developer API를 활성화하세요
- 서비스 계정을 생성하세요:
- “IAM & Admin” > “Service Accounts”로 이동하세요
- “Create Service Account”를 클릭하세요
- 이름과 설명을 입력하세요
- “Create and Continue” 클릭
- 역할 할당을 건너뛰고 “Done” 클릭
- JSON 키 생성:
- 목록에서 서비스 계정을 찾으세요
- 점 3개 메뉴 > “Manage keys” 클릭
- “Add Key” > “Create new key” 클릭
- JSON 형식 선택
- “Create” 클릭
- Play Console에서 서비스 계정에 앱 접근 권한을 부여하세요:
- 다음으로 이동: Play Console
- “사용자 및 권한”으로 이동
- “Invite new users” 클릭
- 서비스 계정 이메일 입력 (@*.iam.gserviceaccount.com으로 끝남)
- “Release to production” 권한 부여
- “Invite user” 클릭
- JSON 키를 base64로 변환:
base64 -i path/to/your/service-account-key.json | pbcopy - base64로 인코딩된 문자열을
PLAY_CONFIG_JSONGitLab 변수로 추가
GitLab CI/CD 파이프라인 설정하기
CI/CD 파이프라인 정의를 위해 프로젝트 루트에 .gitlab-ci.yml 파일을 생성합니다. 아래는 파이프라인 구성 예시입니다:
image: mingc/android-build-box:latest
stages:
- build
- upload_to_capgo
- build_and_upload_android
build:
stage: build
tags:
- saas-linux-xlarge-amd64
cache:
- key:
files:
- bun.lockb
paths:
- .node_modules/
script:
- npm install
- npm run build
artifacts:
paths:
- node_modules/
- dist/
only:
- master
upload_to_capgo:
stage: upload_to_capgo
tags:
- saas-linux-xlarge-amd64
script:
- npx @capgo/cli@latest bundle upload -a $CAPGO_TOKEN -c dev
dependencies:
- build
when: manual
only:
- master
build_and_upload_android:
tags:
- saas-linux-xlarge-amd64
stage: build_and_upload_android
cache:
- key:
files:
- android/gradle/wrapper/gradle-wrapper.properties
paths:
- ~/.gradle/caches/
script:
- npx cap sync android
- npx cap copy android
- bundle exec fastlane android beta # We do create a tag for the build to trigger XCode cloud builds
dependencies:
- build
when: manual
only:
- master
파이프라인 트리거
GitLab 저장소에 새 태그를 push하면, GitLab CI/CD가 정의된 파이프라인을 자동으로 트리거하여 Fastlane을 통해 Android 앱을 빌드하고 배포합니다.
프로젝트 구조와 요구 사항에 맞춰 경로와 의존성을 조정하세요. 이 설정을 통해 GitLab CI/CD에서 Android 앱 배포를 자동화할 수 있습니다.
마치며
mingc/android-build-box Docker 이미지를 사용해 GitLab CI/CD를 구성하면 Android 앱 빌드 프로세스를 자동화해 개발 워크플로를 더 효율적이고 안정적으로 만들 수 있습니다. 이 자동화로 시간을 확보해 앱 개발의 핵심에 집중할 수 있고, 결국 고품질 Android 앱을 더 효율적으로 제공하는 데 도움이 됩니다.
GitLab을 활용한 자동 Capacitor Android 빌드 이어서 진행하기
사용 중이라면 GitLab을 활용한 자동 Capacitor Android 빌드 CI/CD 자동화를 계획하려면, 다음을 연결하세요 Capgo CI/CD 설정하기 Capgo CI/CD의 제품 워크플로우용, Capgo Native Build Capgo Native Builds의 제품 워크플로우용, Capgo 연동 서비스 Capgo Integrations의 제품 워크플로우용, CI/CD 통합 CI/CD Integration의 구현 세부 사항은, 그리고 GitHub Actions 연동 GitHub Actions Integration의 구현 세부 사항을 참고하세요.