일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- clean architecture
- Xcode
- swift documentation
- uitableview
- collectionview
- combine
- ribs
- rxswift
- HIG
- RxCocoa
- ios
- MVVM
- Protocol
- uiscrollview
- tableView
- UICollectionView
- UITextView
- 애니메이션
- 리팩토링
- 리펙토링
- Refactoring
- swiftUI
- 스위프트
- 리펙터링
- SWIFT
- Clean Code
- Human interface guide
- 클린 코드
- Observable
- map
- Today
- Total
김종권의 iOS 앱 개발 알아가기
[fastlane] 4. build_app (빌드, 배포, firebase에 배포, firebase_app_distribution, 빌드 번호 증가) 본문
[fastlane] 4. build_app (빌드, 배포, firebase에 배포, firebase_app_distribution, 빌드 번호 증가)
jake-kim 2020. 12. 12. 13:111. fastlane이란?
3. fastlane match (certificate, provisioning profile 정보를 git에 저장)
4. fastlane build_app (빌드, firebase에 배포)
5. fastlane 앱 스토어에 배포 (App Store Connect)
6. fastlane register devices, 디바이스 정보(UDID, Name) Apple Developer에 등록 방법 (register_devices)
*7. fastlane 총 정리 및 phase별 configuration 설정, 환경변수 설정
*8. fastlane과 Bitrise를 이용한 자동 배포 구축 방법
cf) fastlane 환경 변수 (.env.default) 사용하여 가장 단순한 match 사용 방법
빌드 후 배포 과정
- fastfile에 각각 alpha, release라는 lane을 정의하여 사용
- 각 lane은 우선 sync_codesign을 불러서 인증서를 획득하고 빌드를 수행 -> .ipa파일과 dSYM파일 획득 -> 이 파일들을 배포
- .ipa파일이란? iOS 디바이스에서만 설치할 수 있는 ARM아키텍쳐 용 바이너리 파일이 압축 된 파일
- dSYM(debug symbol file)파일이란? 컴파일러가 소스코드를 기계어로 변환할 때 생성되고 기계어를 다시 매핑하는 정보를 지닌 파일
xcode에서 archive를 하면 생성되는데, 앱스토어에서 크래시 리포트를 줄 때 이 파일을 이용하여 해석할 수 있음
fastlane build_app을 이용하여 빌드
- 공통 빌드 lane 정의
* 먼저 여기를 참고하여 match관련 lane정의
- 각 빌드 lane 정의
- 아래와 같은 오류 발생 시 여기 참고하여 pod 설정
- 전체 코드 (주의사항: build_bump가 동작하려면 xcode에서 또다른 설정 필요 - 아래 내용에서 계속)
default_platform(:ios)
ENV["FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"] = "xtjt-hxui-nyix-bsnm"
platform :ios do
# match 갱신 - git에 push (certificate, profile visioning)
private_lane :renew_codesign do|options|
match(type:options[:type], force_for_new_devices: true)
end
lane :renew_codesign_debug do
renew_codesign(type:"development")
end
lane :renew_codesign_alpha do
renew_codesign(type:"adhoc")
end
lane :renew_codesign_beta do
renew_codesign(type:"adhoc")
end
lane :renew_codesign_release do
renew_codesign(type:"appstore")
end
# match 로드 (certificate, profile visioning)
private_lane :sync_codesign do|options|
match(type:options[:type], readonly: true)
end
lane :sync_codesign_debug do
sync_codesign(type:"development")
end
lane :sync_codesign_alpha do
sync_codesign(type:"adhoc")
end
lane :sync_codesign_beta do
sync_codesign(type:"adhoc")
end
lane :sync_codesign_release do
sync_codesign(type:"appstore")
end
# 공통 빌드 lane
desc "common build"
lane :common_build do |options|
cocoapods(
clean_install: true,
try_repo_update_on_error: true
)
case options[:configuration]
when "Debug"
scheme = "Debug"
export_type = "development"
when "Alpha"
scheme = "Alpha"
export_type = "ad-hoc"
when "Beta"
scheme = "Beta"
export_type = "ad-hoc"
else
scheme = "Release"
export_type = "app-store"
end
build_app(
scheme: "MemoryCam", # app name
configuration: scheme,
export_method: export_type,
output_directory: "./fastlane/distribute",
clean: true
)
end
# 빌드 호출
lane :build_debug do # debug로 할 경우 오류
sync_codesign(type:"development")
build_number_bump()
common_build(configuration:"Debug")
end
lane :build_alpha do
sync_codesign(type:"adhoc")
build_number_bump()
common_build(configuration:"Alpha")
end
lane :build_beta do |options|
sync_codesign(type:"adhoc")
build_number_bump()
common_build(configuration: "Beta")
end
lane :build_release do
sync_codesign(type:"appstore")
build_number_bump()
common_build(configuration:"Appstore")
end
# 빌드 번호 업 & commit
lane :build_number_bump do
ensure_git_status_clean
increment_build_number(xcodeproj: "./MemoryCam/MemoryCam.xcodeproj")
build_number = get_build_number(xcodeproj: "./MemoryCam/MemoryCam.xcodeproj")
commit_version_bump(message: "Bump build number to #{build_number} by fastlane", xcodeproj: "./MemoryCam/MemoryCam.xcodeproj")
push_to_git_remote
end
end
- 빌드 실행 시 아래 에러 주의 (원인: xcode에 provisioning profile이 세팅 안된 것, Signing & Capabilities가서 해주면 해결)
fastlane을 통하여 Firebase에 배포를 하는 이유
* fastlane없이 firebase에 배포 방법: ios-development.tistory.com/251
- 주의: firebase프레임워크는 share_pod으로 쓰면 안되고 반드시 한 프로젝트에만 의존성을 주입해주어야 오류가 나지 않음
- fastlane으로 Firebase에 배포하는 이유는? fastlane을 사용하면, fastfile에서 tester group을 미리 정해놓고 ipa파일도 자동으로 올려질 수 있게 하는 편리함
- 단, Apple Developer 사이트에서 테스터들의 UDID등록하는 것은 수동으로 해주어야 함
- UDID등록 후 fastlane에서 재배포 하면 테스터들에게 배포 성공
Firebase에서 Configuration별 GoogleService-info.plist파일 다운
- multiple project 세팅 (debug, alpha, beta, release Configuration 마다 각각의 GoogleService-info.plist를 갖음)
- multiple project 세팅을 하는 이유: firebase SDK 종속적이기 때문
(google analytics를 쓴다고 하면 alpha버전, testing버전이 분석 대상이 되면 안되기 때문) - Firebase 사이트에 있는 한 프로젝트에서 각 Configuration별로 다운
- 프로젝트에 GoogleService-info.plist추가
- Configurations에 Debug / Alpha / Beta / Release이름 기억
- 프로젝트 target -> Build Phases -> '+'버튼을 눌러서 "New Run Script Phase"선택
- Run Script에 GoogleService-Info파일들을 Configuration 별로 관리하기 위하여 아래처럼 작성
- 디렉토리 주소 확인: root/{product_name}/service/
if [ ${CONFIGURATION} == "Release" ]; then
echo "Release"
cp -r "${PROJECT_DIR}/${PRODUCT_NAME}/Service/GoogleService-Info-release.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
elif [ ${CONFIGURATION} == "Beta" ]; then
echo "Beta"
cp -r "${PROJECT_DIR}/${PRODUCT_NAME}/Service/GoogleService-Info-beta.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
else
echo "Debug / Alpha"
cp -r "${PROJECT_DIR}/${PRODUCT_NAME}/Service/GoogleService-Info-alpha.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
fi
Firebase SDK연동
- Firebase cocoapod 설치
pod 'Firebase'
- AppDelegate에 application(_, didFinishLaunchingWithOptions) -> Bool 함수에서 초기화: FirebaseApp.configure()
Firebase에 배포
- 프로젝트의 루트에서 아래 명령어 실행: 옵션을 선택하라고 나오면, "Option 3: RubyGems.org" 선택
fastlane add_plugin firebase_app_distribution
- gemfile에 "plugins_path"와 파일 "Pluginfile"이 생긴 것 확인
- firebase 업로드 할 lane에 bundle id를 적용시킬 수 있도록 Appfile에 정의
# 디폴트 값 정의 (밑의 for_lane과 일치하지 않는 fastfile의 함수 lane들은 해당 값 적용)
# default 번들 ID
app_identifier("com.jake.Kimp.debug")
# Your Apple email address
apple_id("palatable7@naver.com")
# Developer Portal Team ID
team_id("SS7U83UJNK")
# fastfile에 가기전에 app_identifier가 설정
for_platform :ios do
# debug: 위에서 정한 default 번들 ID를 사용
# alpha
...
for_lane :upload_firebase_alpha do
app_identifier 'com.jake.Kimp.alpha'
end
# beta
...
for_lane :upload_firebase_beta do
app_identifier 'com.jake.Kimp.beta'
end
end
- firebase에 업로드 하는 lane을 fastfile에 정의
- ipa_path 수정: `MemoryCam`부분 -> 앱 이름
- firebase_cli_token 정보 수정
1. firebase CLI설치
$ curl -sL https://firebase.tools | bash
2. firebase로그인
$ firebase login:ci
// 로그아웃 하고싶을 경우, firebase logout
3. terminal에 출력되는 토큰 정보 복사하여 위 lane에 firebase_cli_token에 붙여넣기
- appid
- tester_group
* group생성방법은 여기 참고: ios-development.tistory.com/251
주의: debug가 디폴트로 되어 있으므로 alpha버전 bundle id를 누른 후 "시작하기"버튼을 누르지 않으면 firebase에 배포할 때 오류
Build_bump: 빌드 넘버 추가
- 프로젝트 세팅 1) agvtool 활성화
- build bump lane 관련 fastfile 내용 (각 빌드에서 호출)
- 배포 전 체크 리스트
- 주의0: framework(Domain, CommonExtension), pod 프로젝트 파일 모두 Configuration을 main처럼 alpha, beta, release을 생성해야 모두 빌드 실패 방지
- 주의1: remote git에 프로젝트가 존재
- 주의2: simulator가 선택되어 있으면 x
- 주의3: commit할 내용이 working directory에 존재 x
- 주의4: bundle exec pod update, bundle update 시도 후 ./install_pods 할 것
- 주의5: Firebase홈페이지에서 AppDistribution -> 해당 앱 번들 선택 -> 시작하기 버튼 눌러야 가능
$ bundle exec fastlane upload_firebase_alpha
- 배포 성공
주의: 모바일 테스트 기기에서는 첫 번째 배포에서 debug오류 뜨므로, 2번째 배포부터 정상적으로 다운 가능
* 참고: AppDevice UUID테스터 추가 방법
* firebase업로드 할 때 terminal에서 아래 오류 대처 방법 - git의 remote이름을 origin으로 하지 않으면 오류 뜨므로, origin으로 수정하여 다시 시도 할 것
Exit status of command 'git push origin master:master --tags' was 128 instead of 0.
fatal: 'origin' does not appear to be a git repository
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
전체코드 - Appfile
# 디폴트 값 정의 (밑의 for_lane과 일치하지 않는 fastfile의 함수 lane들은 해당 값 적용)
# default 번들 ID
app_identifier("com.jake.Kimp.debug")
# Your Apple email address
apple_id("palatable7@naver.com")
# Developer Portal Team ID
team_id("SS7U83UJNK")
# fastfile에 가기전에 app_identifier가 설정
for_platform :ios do
# debug: 위에서 정한 default 번들 ID를 사용
# alpha
for_lane :build_alpha do
app_identifier 'com.jake.Kimp.alpha'
end
for_lane :renew_codesign_alpha do
app_identifier 'com.jake.Kimp.alpha'
end
for_lane :sync_codesign_alpha do
app_identifier 'com.jake.Kimp.alpha'
end
for_lane :upload_firebase_alpha do
app_identifier 'com.jake.Kimp.alpha'
end
# beta
for_lane :build_beta do
app_identifier 'com.jake.Kimp.beta'
end
for_lane :renew_codesign_beta do
app_identifier 'com.jake.Kimp.beta'
end
for_lane :sync_codesign_beta do
app_identifier 'com.jake.Kimp.beta'
end
for_lane :upload_firebase_beta do
app_identifier 'com.jake.Kimp.beta'
end
# release
for_lane :renew_codesign_release do
app_identifier 'com.jake.Kimp'
end
for_lane :sync_codesign_release do
app_identifier 'com.jake.Kimp'
end
for_lane :build_release do
app_identifier 'com.jake.Kimp'
end
for_lane :upload_testflight do
app_identifier 'com.jake.Kimp'
end
for_lane :upload_appstore do
app_identifier 'com.jake.Kimp'
end
end
전체코드 - fastfile
default_platform(:ios)
ENV["FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"] = "xtjt-haui-nyix-bsnm"
platform :ios do
# match 갱신 - git에 push (certificate, profile visioning)
private_lane :renew_codesign do|options|
match(type:options[:type], force_for_new_devices: true)
end
lane :renew_codesign_debug do
renew_codesign(type:"development")
end
lane :renew_codesign_alpha do
renew_codesign(type:"adhoc")
end
lane :renew_codesign_beta do
renew_codesign(type:"adhoc")
end
lane :renew_codesign_release do
renew_codesign(type:"appstore")
end
# match 로드 (certificate, profile visioning)
private_lane :sync_codesign do|options|
match(type:options[:type], readonly: true)
end
lane :sync_codesign_debug do
sync_codesign(type:"development")
end
lane :sync_codesign_alpha do
sync_codesign(type:"adhoc")
end
lane :sync_codesign_beta do
sync_codesign(type:"adhoc")
end
lane :sync_codesign_release do
sync_codesign(type:"appstore")
end
# 공통 빌드
desc "common build"
lane :common_build do |options|
cocoapods(
clean_install: true,
try_repo_update_on_error: true
)
case options[:configuration]
when "Debug"
scheme = "Debug"
export_type = "development"
when "Alpha"
scheme = "Alpha"
export_type = "ad-hoc"
when "Beta"
scheme = "Beta"
export_type = "ad-hoc"
else
scheme = "Release"
export_type = "app-store"
end
build_app(
scheme: "Kimp", # app name
configuration: scheme,
export_method: export_type,
output_directory: "./fastlane/distribute",
clean: true
)
end
# 빌드 호출
lane :build_debug do # debug로 할 경우 오류
sync_codesign(type:"development")
build_number_bump()
common_build(configuration:"Debug")
end
lane :build_alpha do
sync_codesign(type:"adhoc")
build_number_bump()
common_build(configuration:"Alpha")
end
lane :build_beta do
sync_codesign(type:"adhoc")
build_number_bump()
common_build(configuration: "Beta")
end
lane :build_release do
sync_codesign(type:"appstore")
build_number_bump()
common_build(configuration:"Appstore")
end
# 빌드 번호 업 & commit
lane :build_number_bump do
ensure_git_status_clean
increment_build_number(xcodeproj: "./Kimp/Kimp.xcodeproj")
build_number = get_build_number(xcodeproj: "./Kimp/Kimp.xcodeproj")
commit_version_bump(message: "Bump build number to #{build_number} by fastlane", xcodeproj: "./Kimp/Kimp.xcodeproj")
push_to_git_remote
end
# firebase 업로드
lane :upload_to_firebase do |options|
firebase_app_distribution(
app: options[:appid],
groups: options[:tester_group],
firebase_cli_token: "1//0e-h7nTIJyTgeCgYIARAAGA4SNwF-L9IraFQcr4OVscUk376dZjnWCwHsiDmQBYSNL_pnZECOiScrtUCFn21ibJWKP_PM31gy10o",
ipa_path: "./fastlane/distribute/Kimp.ipa"
)
end
lane :upload_firebase_alpha do
build_alpha()
upload_to_firebase(appid: "1:1018046236453:ios:e162fe01a3c6sde5ca857ccc", tester_group: "inHouse")
end
lane :upload_firebase_beta do
build_beta()
upload_to_firebase(appid: "1:1018046236453:ios:72ee3bbe45c6sd57ab857ccc", tester_group: "inHouse")
end
# TestFlight
lane :upload_testflight do
build_release()
upload_to_testflight(
ipa: "./fastlane/distribute/Kimp.ipa",
skip_waiting_for_build_processing: true # false면 테스터에게 빌드된 것이 배포되지 않음
)
end
# Appstore
lane :upload_appstore do
release()
# capture_screenshots
deliver
end
end
'iOS 앱 배포와 출시' 카테고리의 다른 글
[ipa 파일을 디바이스에 설치] Apple Configurator2 (0) | 2020.12.17 |
---|---|
[iOS - Crashlytics] Firebase Crashlytics 사용방법 (0) | 2020.12.15 |
[fastlane] 3. match (configuration 설정, certificate, provisioning profile정보 apple developer, git 업로드, 동기화) (0) | 2020.12.03 |
[fastlane] 1. fastlane이란 (0) | 2020.12.03 |
[fastlane] 2. cocoapods, pod install 동기화 (Bundler, Bundle, gem, ruby) (0) | 2020.12.01 |