[Android] Fastlane 적용하여 빌드 및 배포 자동화
개요
Fastlane은 앱의 빌드, 테스트, 배포(출시) 등 일련의 작업들을 자동화 해주는 툴로 Android, iOS 환경에서 사용할 수 있습니다.
직접 적용해보며 느낀 특징으로는,
- versionCode 자동으로 관리
- gradle 작업을 위임하여 빌드
- play store 배포 (production, alpha, beta, internal의 track 지정)
Fastlane 설치
저는 Mac OS 기준 HomeBrew를 사용하여 fastlane을 설치했습니다.
$ brew install fastlane
Fastlane 초기화
프로젝트 루트 디렉토리에서 실행
$ fastlane init
초기화 시 아래의 작업 입력
- 패키지 이름 입력
- Service Account 등록 시 다운로드 받은 비공개 키(Json) 경로 입력
- 스토어에 배포된 앱의 meta data 다운 받을지 여부 선택
입력을 완료하면 fastlane(Appfile, Fastfile), Gemfile, Gemfile.lock 파일들이 생성된 걸 확인할 수 있다.
- Appfile : 앱의 구성 정보를 정의하는 파일
- Fastfile : fastlane의 동작을 구동하는 lane(작업)을 정의하는 파일
Service Account 등록 및 비공개 키(Json) 생성 방법
fastlane을 통해서 스토어에 앱을 배포하기 위해서는 Google Play Android Developer API 사용 설정과 Service Account 등록이 필요하다.
Service Account를 등록하면 계정의 비공개 키(Json)를 생성할 수 있고, 해당 키를 사용하여 스토어에 앱을 배포할 수 있다.
1. Google Play Console -> "설정" -> "API 엑세스"로 이동
2. "새 서비스 계정 만들기" 선택
2-1. Google Cloud Platform으로 이동
2-2. "서비스 계정 만들기" 선택
2-2-1. 서비스 계정의 이름, ID, 설명 입력
2-2-2. "역할 선택"에서 "서비스 계정 사용자" 선택
2-2-3. "완료" 선택
2-3. "생성된 서비스 계정으로" 선택
2-3-1. "키" -> "키 추가" -> "새 키 만들기"
2-3-2."Json" 유형의 비공개 키 만들기
2-3-3. 비공개 키는 자동으로 다운로드 됨 (해당 키는 복구할 수 없으므로 안전하게 관리해야 함)
2-4. 다시 Google Play Console로 복귀
3. "생성된 서비스 계정"의 "권한 부여" 선택
4. 사용하고자 하는 권한을 선택 (공식문서에는 관리자(모든 권한) 선택 권장)
Fastlane 빌드 구성
fastlane을 동작 시키기 위해서 해당 작업들을 fastfile에 정의해야 한다.
fastfile은 ruby 언어로 작성하며 아래의 특징들 위주로 정리해보았다.
- versionCode 자동으로 관리
- gradle 작업을 위임하여 빌드
- play store 배포 (production, alpha, beta, internal의 track 지정)
versionCode 자동으로 관리
새로운 버전의 앱을 스토어에 배포하기 위해서는 반드시 기존의 배포된 앱보다 높은 versionCode를 적용해야 한다.
사용하는 versionCode의 규칙은 yy/MM/dd/nnn (ex. 220607001, 220607002)이고, Fastlane을 통해 스토어에 배포된 앱(internal, production)의 versionCode를 읽어와 비교하여 새로운 versionCode를 생성 및 적용한다.
PACKAGE_NAME = "com.lee.oneweekonebook"
PLAYSTORE_KEY_PATH = nil
TRACK_TYPE_PRODUCTION = "production"
TRACK_TYPE_INTERNAL = "internal"
def today_formatted
Date.today.strftime('%Y%m%d')
end
# ex) 220607001
def default_version_code
"#{today_formatted}001"[2..]
end
def version_code_from_play_store(trackType)
google_play_track_version_codes(
package_name: PACKAGE_NAME,
track: trackType, # production, beta, alpha, internal
json_key: PLAYSTORE_KEY_PATH
)[0]
end
# play store의 배포된 앱(production, internal)의 최신 버전코드를 가져온다
def latest_version_code_from_play_store
production_version_code = version_code_from_play_store(TRACK_TYPE_PRODUCTION)
internal_version_code = version_code_from_play_store(TRACK_TYPE_INTERNAL)
if production_version_code >= internal_version_code
return production_version_code
else
return internal_version_code
end
end
def create_version_code
# 최신 버전코드
latest_version_code = latest_version_code_from_play_store.to_s
# 디폴트 버전코드 (오늘 기준으로 생성)
version_code = default_version_code
if version_code > latest_version_code
return version_code
else
version_code_index = latest_version_code[6..]
new_index = version_code_index.to_i + 1
new_version_code = "#{latest_version_code[0..5]}%03d" % new_index
return new_version_code
end
end
Release 버전 앱 빌드
desc "Build release version as aab"
lane :build_release do |values|
PLAYSTORE_KEY_PATH = values[:playstore_key_path]
# 유효한 버전코드를 생성
store_version_code = create_version_code
# 프로젝트에 버전코드 적용
android_set_version_code(
version_code: store_version_code
)
# 기존에 빌드된 파일들을 제거하고
gradle(task: 'clean')
# bundle(aab), build_type(Release)로 빌드 및 스토어 키로 사이닝
gradle(
task: "bundleRelease",
properties: {
"android.injected.signing.store.file" => values[:keystore_path],
"android.injected.signing.store.password" => values[:keystore_password],
"android.injected.signing.key.alias" => values[:keystore_alias],
"android.injected.signing.key.password" => values[:keystore_password],
}
)
end
play store 배포
desc "Deploy a release version to the Google Play as internal"
lane :deploy_internal do |values|
# internal(내부 테스트) 버전으로 배포한다
upload_to_play_store(
track: TRACK_TYPE_INTERNAL,
aab: values[:aab_path],
json_key: values[:playstore_key_path],
skip_upload_metadata: true,
skip_upload_changelogs: true,
skip_upload_screenshots: true,
skip_upload_images: true,
skip_upload_apk: true,
)
end
fastlane plugin 설치
// 버전코드 변경을 위한 plugin
$ fastlane add_plugin versioning_android
fastfile의 작업 실행
release 버전 앱 빌드하여 play store 배포
$ fastlane build_production keystore_path:'/Users/.../keystore' keystore_password:'...' key_password:'...' keystore_alias:'...' playstore_key_path:'/Users/.../play_store_upload_key.json'
$ fastlane deploy_internal aab_path:'/Users/.../owob-release.aab' playstore_key_path:'/Users/.../play_store_upload_key.json'