Info
iOS, Android 프로젝트에서 배포를 위해 아카이브 파일 (.ipa), 패키지파일 (.apk) 을 추출하고 업로드 및 공유하는데 귀찮은 작업들이 상당히 많다.
(iOS는 scheme 바꾸고, 아카이빙하고 파일 추출하고 업로드하고 공유하고.., 안드로이드도 뭐 작업중에는 뭘 할 수가 없으니까 )
그래서 이런 귀찮은 작업을 좀 편하게 할 수 있는 방법을 찾다가 Fastlane 이라는 것을 찾다.
Fastlane 은 인증서 자동갱신, 스냅샷 추출, 아카이빙, crashlytics 배포, slack 공유, s3업로드, 테스트 플라이트, 앱스토어 등록 등등 다양한 동작을 하도록 구성할 수 있다.
자세한 내용은 아래 fastlane 사이트를 참고하는걸로 하고..
일단은 내부 배포를 위하여 프로젝트 내에서 provisioning 파일을 생성/갱신, 테스트용 뱃지 추가, 아카이브 후 추출, aws-s3에 파일 업로드, Crashlytics 에 배포 파일 업로드, slack에 결과 공유 까지만 작업을 하는 방법을 소개하려고 한다.
1. Fastlane 설치
기능을 사용하기 위해서 mac에 fastlane을 설치 해야한다. 설치 방법은 세가지가 있으니 자신의 mac 에서 주로 사용하는 방법을 선택하여 설치를 진행하면 된다.
(Homebrew 로 설치하면 fastlane 내부 ruby가 동작해서 작업이 귀찮아짐. ruby 모듈들을 fastlane 안에 ruby에 설치해줘야함. 맘편하게 Script로 설치하세요)
Homebrew
$ brew cask install fastlane
Installer Script
아래 링크에서 zip 파일을 다운로드 받고, install 스크립트를 실행
https://download.fastlane.tools/fastlane.zip
Rubygems
$ sudo gem install fastlane -NV
2. Fastlane 초기화
Fastfile, Appfile, .env 파일을 직접 생성해서 작업을 해도 되지만 귀찮으니까 iOS혹은 Android 프로젝트 루트에서 아래 명령어로 관련 파일들을 생성해주자
# fastlane 초기화
$ fastlane init
초기화 작업이 완료되면
./fastlane
폴더 내부에 Fastfile
, Appfile
, .env
파일이 생성되어 기본적인 준비가 된다.3. Plugin 설치 (aws_s3, badge) - optional
Badge
앱을 내부배포할 때 dev, stage등 여러가지 앱 스킴을 사용하는 경우들이 있는데 이럴경우 어떤 버전이 설치되어 있는지 직관적으로 알 수 있는 방법이 없다.
그래서 badge 라는 plugin을 사용하여 앱 아이콘에 뱃지를 넣어주어 직관적인 버전 확인이 가능하도록 해줄 수 있다.
아래를 참고하여 플러그인을 설치하고, 관련된 모듈들을 설치하도록 하자.
더 자세한 내용은 아래 사이트를 참고하자
# badge 플러그인 설치
$ fastlane add_plugin badge
# 관련 모듈 설치
$ brew install imagemagick
$ brew install librsvh
aws_s3
내부 배포를 위한 파일 서버가 S3로 설정되어 있는 경우 아카이브 파일 (.ipa), 패키지파일 (.apk) 을 생성한 후 Amazon S3 Bucket 으로 바로 전송을 할 수가 있다.
이 기능을 사용하려면 아래를 참고하여 S3 플러그인을 설치하면 되고, 조금 더 자세한 정보 및 사용법은 아래 링크에서 확인하면 된다.
# aws-s3 플러그인 설치
$ fastlane add_plugin aws_s3
4. Fastlane 파일 설정
이제 fastlane 초기 세팅 작업들은 마무리가 되었고, 실제로 동작시킬 내용들을 추가하는 방법을 알아보도록 하자.
Fastfile
우선 가장 핵심이 되는
Fastfile
에 대해서 살펴보자. 이 파일은 platform과 lane 을 설정하고 lane 별로 어떤 동작을 시킬지, lane 실행전/후에 어떤 동작을 수행할 지 설정하는 곳이다.
아래 예제 파일을 보면서 동작들을 확인해보자.
# More documentation about how to customize your build
# can be found here:
# https://docs.fastlane.tools
fastlane_version "2.18.3"
# This value helps us track success metrics for Fastfiles
# we automatically generate. Feel free to remove this line
# once you get things running smoothly!
generated_fastfile_id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # fastfile 생성시 설정됨
default_platform :ios
#######
# iOS #
#######
platform :ios do
before_all do
# lane 실행전 수행할 동작을 설정해줄 수 있다
end
##################################################
# First iOS App Lanes - 계정 정보 A를 사용하는 앱
##################################################
lane :firstapp_debug do
# provisioning profile 생성, 갱신, 다운로드
sigh
# (Optional) badge 설정
# badge(dark: true) # 이렇게 쓸 수도 있고
badge(shield: "Version-dev-red", no_badge: true) # 이렇게 shield를 사용해서 할 수도 있다
# iOS app을 build, archive, export 한다
gym(
# 키가 workspace 인것을 확인하자
workspace: "[Project path].xcworkspace", # [Project path]: 프로젝트 xcworkspace 경로 (xcodeproj 는 secondapp 참고)
configuration: "Debug", # configuration 설정값
scheme: "[Project scheme]", # [Project scheme]: 프로젝트 scheme
silent: true,
clean: true,
output_name: "[file name]", # [file name]: 파일 추출시 파일명
include_symbols: false, # (optional)개인 설정에 맞게
include_bitcode: true, # (optional)개인 설정에 맞게 - default:false
export_method: "development", # export 작업시 method 지정
)
# (Optional) S3에 파일을 업로드 한다
aws_s3(
access_key: ENV['S3_ACCESS_KEY'], # .env 파일에 세팅
secret_access_key: ENV['S3_SECRET_ACCESS_KEY'], # .env 파일에 세팅
bucket: ENV['S3_BUCKET'], # .env 파일에 세팅
region: ENV['S3_REGION'], # .env 파일에 세팅
path: '[bucket path]', # [bucket path]: 버킷의 경로 설정
ipa: '[file name].ipa', # export되는 파일명으로 설정
upload_metadata: true,
)
# (Optional) Crashlytics에 업로드
crashlytics(
api_token: ENV['CRASHLYTICS_API_TOKEN'], # .env 파일에 세팅
build_secret: ENV['CRASHLYTICS_SECRET'] # .env 파일에 세팅
)
end
lane :firstapp_stage do
sigh
badge(shield: "Version-stage-blue", no_badge: true)
gym(
workspace: "[Project path]",
configuration: "Stage",
scheme: "[Project scheme]",
silent: true,
clean: true,
output_name: "[file name]",
include_symbols: false,
include_bitcode: true,
export_method: "ad-hoc",
)
aws_s3(
access_key: ENV['S3_ACCESS_KEY'],
secret_access_key: ENV['S3_SECRET_ACCESS_KEY'],
bucket: ENV['S3_BUCKET'],
region: ENV['S3_REGION'],
path: '[bucket path]',
ipa: '[file name].ipa',
upload_metadata: true,
)
crashlytics(
api_token: ENV['CRASHLYTICS_API_TOKEN'],
build_secret: ENV['CRASHLYTICS_SECRET']
)
end
###########################################################
# Second iOS App Lane - 계정 정보 B를 사용하는 다른 iOS 앱
###########################################################
lane :secondapp_debug do
sigh
badge(shield: "Version-dev-red", no_badge: true)
gym(
# 키가 project 인것을 확인하자
project: "[Project path].xcodeproj", # [Project path]: 프로젝트 xcodeproj 경로
configuration: "Debug",
scheme: "[Project scheme]",
silent: true,
clean: true,
output_name: "[file name]",
include_symbols: false,
include_bitcode: true,
export_method: "development",
)
aws_s3(
access_key: ENV['S3_ACCESS_KEY'],
secret_access_key: ENV['S3_SECRET_ACCESS_KEY'],
bucket: ENV['S3_BUCKET'],
region: ENV['S3_REGION'],
path: '[bucket path]',
ipa: '[file name].ipa',
upload_metadata: true,
)
crashlytics(
api_token: ENV['CRASHLYTICS_API_TOKEN'],
build_secret: ENV['CRASHLYTICS_SECRET']
)
end
# lane 수행이 성공적으로 완료된 후 수행할 동작 설정
after_all do |lane|
# slack으로 메시지를 전송한다.
slack(
message: "FastLane success",
slack_url: ENV['SLACK_URL']
)
end
# lane 수행이 실패하였을 경우 수행할 동작 설정
error do |lane, exception|
slack(
message: exception.message,
success: false,
slack_url: ENV['SLACK_URL']
)
end
end
##############################################################################################
##############################################################################################
###########
# Android #
###########
platform :android do
before_all do
end
##################################################
# First iOS App Lanes - 계정 정보 A를 사용하는 앱
##################################################
lane :firstapp_debug do
gradle(task: 'clean', project_dir: "[Project path]") # [Project path]: 프로젝트 root 경로
gradle(task: "assemble",
build_type: "Debug",
project_dir: "[Project path]") # [Project path]: 프로젝트 root 경로
# (Optional) 필요에 따라 shell script 를 넣을 수 있다
# shell script는 Fastfile이 있는 폴더에서 수행되기 때문에 폴더 경로가 fastlane/ 폴더로 인식된다
sh "mv ../firstapp_android/app/build/outputs/apk/firstapp-debug.apk ../firstapp_android/app/build/outputs/apk/[File name].apk" # [File name]: 파일명
# (Optional) S3에 파일을 업로드 한다
# plugin 에서 사용되는 폴더 경로는 fastlane을 실행한 위치로 인식된다
aws_s3(
access_key: ENV['S3_ACCESS_KEY'], # .env 파일에 세팅
secret_access_key: ENV['S3_SECRET_ACCESS_KEY'], # .env 파일에 세팅
bucket: ENV['S3_BUCKET'], # .env 파일에 세팅
region: ENV['S3_REGION'], # .env 파일에 세팅
path: '[bucket path]', # [bucket path]: 버킷의 경로 설정
ipa: './firstapp_android/app/build/outputs/apk/[File name].apk', # export되는 파일의 총 경로를 설정
upload_metadata: true,
)
end
lane :firstapp_stage do
gradle(task: 'clean', project_dir: "[Project path]")
gradle(
task: "assemble",
build_type: "Release",
# signing 정보를 넣어줄 수 있다
properties: {
# 'versionCode' => [version code], # (Optional) [version code]: 버전코드
# 'versionName' => [version name], # (Optional) [version name]: 버전명
'android.injected.signing.store.file'=> ENV['ANDROID_APP_SIGNING_KEY'], # .env 파일에 세팅
'android.injected.signing.store.password'=> ENV['ANDROID_APP_SIGNING_PASSWORD'], # .env 파일에 세팅
'android.injected.signing.key.alias'=> ENV['ANDROID_APP_SIGNING_ALIAS'], # .env 파일에 세팅
'android.injected.signing.key.password'=> ENV['ANDROID_APP_SIGNING_PASSWORD'] # .env 파일에 세팅
},
project_dir: "[Project path]")
sh "mv ../firstapp_android/app/build/outputs/apk/firstapp-release.apk ../firstapp_android/app/build/outputs/apk/[File name].apk"
aws_s3(
access_key: ENV['S3_ACCESS_KEY'],
secret_access_key: ENV['S3_SECRET_ACCESS_KEY'],
bucket: ENV['S3_BUCKET'],
region: ENV['S3_REGION'],
path: '[bucket path]',
ipa: './firstapp_android/app/build/outputs/apk/[File name].apk',
upload_metadata: true,
)
end
after_all do |lane|
slack(
message: "FastLane success",
slack_url: ENV['SLACK_URL']
)
end
error do |lane, exception|
slack(
message: exception.message,
success: false,
slack_url: ENV['SLACK_URL']
)
end
end
.env
다음은 환경변수를 선언해 놓고 사용하는 dotenv 형태의
.env
파일이다.이 파일에 선언된 값들을
Fastfile
에서 ENV[‘ ‘]
형태로 사용할 수 있다.아래는 예제용으로 작성된
Fastfile
의 .env
파일이다.# for Slack
SLACK_URL="https://hooks.slack.com/services/~~~" # slack 에서 생성한 hook 주소
# for S3
S3_ACCESS_KEY='XXXXXXX' # S3의 Access key
S3_SECRET_ACCESS_KEY='xxxxxxxxxxxxxxxx' # S3의 Sceret Access key
S3_BUCKET='example-buket' # S3의 Bucket name
S3_REGION='ap-northeast-2' # S3의 Region
# for Crashlytics
CRASHLYTICS_API_TOKEN='xxxxxxxxxxxxxxxx' # Crashlytics 에서 생성한 API token
CRASHLYTICS_SECRET='xxxxxxxxxxxxxxxx' # Crashlytics 에서 생성한 Secret 값
# for Android
ANDROID_APP_SIGNING_KEY='./keystore/firstapp_key.keystore' # Signing key
ANDROID_APP_SIGNING_PASSWORD='xxxx' # signing pw
ANDROID_APP_SIGNING_ALIAS='firstapp_android' # signing alias
Appfile
마지막으로 앱 관련 설정을 가지고 있는
Appfile
이다.이 파을은 AppStore Id, Bundle Id, Team Id 등 식별자 값이 설정되어있는 파일이다.
Appfile 과 관련해서 더 자세한 내용은 링크를 참고하면 된다. (https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Appfile.md)
아래 파일도 예제용으로 작성된
Fastfile
의 Appfile
이다.# Default
app_identifier "kr.tez.firstapp" # The bundle identifier of your app
apple_id "dev@tez.kr" # Your Apple email address
team_id "XXXXXXX" # Developer Portal Team ID
for_platform :ios do
for_lane :first_debug do
app_identifier "kr.tez.firstapp"
apple_id "dev@tez.kr"
team_id "XXXXXXX"
end
for_lane :first_stage do
app_identifier "kr.tez.firstapp"
apple_id "dev@tez.kr"
team_id "XXXXXXX"
end
for_lane :second_debug do
app_identifier "kr.tez.secondapp"
apple_id "tez_enterprise@tez.kr"
team_id "XYXYXYXY"
end
end
# you can even provide different app identifiers, Apple IDs and team names per lane:
# More information: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Appfile.md
5. Fastlane 기본 명령어
lane 과 파일 작성이 완료되면 몇가지 기본적인 명령어를 확인하고 사용해보도록 하자.
$ fastlane lanes
우선 사용가능한 lane들을 조회하는 명령어 이다.
이 명령어로 추가해 놓은 lane들이 정상적으로 로드되는지 확인하면 된다.
$ fastlane lanes
+------------------------+---------+--------+
| Used plugins |
+------------------------+---------+--------+
| Plugin | Version | Action |
+------------------------+---------+--------+
| fastlane-plugin-aws_s3 | 0.2.4 | aws_s3 |
+------------------------+---------+--------+
[18:47:48]: -------------------------------------------------
[18:47:48]: --- Step: Verifying required fastlane version ---
[18:47:48]: -------------------------------------------------
[18:47:48]: Your fastlane version 2.28.7 matches the minimum requirement of 2.18.3 ✅
[18:47:48]: ------------------------------
[18:47:48]: --- Step: default_platform ---
[18:47:48]: ------------------------------
--------- ios---------
----- fastlane ios firstapp_debug
----- fastlane ios firstapp_stage
----- fastlane ios secondapp_debug
--------- android---------
----- fastlane android firstapp_debug
----- fastlane android firstapp_stage
Execute using `fastlane [lane_name]`
$ fastlane env
이 명령어는 fastlane 환경 체크를 하는 명령이다.
fasatlane이 정상적으로 실행되지 않거나 정보를 확인할 경우 이용하면 된다.
$ fastlane env
...
#너무 길어서 생략
...
6. Fastlane 실행
이제 기나긴 작업이 끝나고 완성된 lane들을 사용하는 방법이다!
작업은 길지만 실제 사용은 별거 없다.
platform과 lane 을 선택해주면 설정해준 작업들이 수행된다.
fastlane {platform} {lane}
$ fastlane ios firstapp_debug
...
# working...
...
[13:48:03]: ▸ Archive Succeeded
...
[13:48:06]: Successfully exported and compressed dSYM file
[13:48:06]: Successfully exported and signed the ipa file:
...
[13:48:06]: -------------------
[13:48:06]: --- Step: slack ---
[13:48:06]: -------------------
[13:48:07]: Successfully sent Slack notification
+------+-------------------------------------+-------------+
| fastlane summary |
+------+-------------------------------------+-------------+
| Step | Action | Time (in s) |
+------+-------------------------------------+-------------+
| 1 | Verifying required fastlane version | 0 |
| 2 | default_platform | 0 |
| 3 | gym | 23 |
| 4 | slack | 1 |
+------+-------------------------------------+-------------+
...
[13:48:07]: fastlane.tools finished successfully
위와 같이 진행과정이 표시되고 모든 작업이 완료되면
fastlane.tools finished successfully
이라는 메시지와 함께 작업이 완료된다.끝
반응형
'Programming > iOS - Support' 카테고리의 다른 글
[Documentation] Appledoc 문서화 (Objective-c 문서화) (0) | 2018.05.08 |
---|---|
[Plugin] Xcode8 에서 Plugin, Package Manager 사용 (0) | 2017.01.15 |
.plist 에서 사용하는 키 목록 (0) | 2014.12.02 |
App store icloud reject 문제 + 해결법 (2) | 2012.11.01 |