관리 메뉴

김종권의 iOS 앱 개발 알아가기

[fastlane] *7. fastlane 총 정리 및 phase별 configuration 설정 (alpha, beta, real), 환경 변수 설정 본문

iOS 앱 배포와 출시

[fastlane] *7. fastlane 총 정리 및 phase별 configuration 설정 (alpha, beta, real), 환경 변수 설정

jake-kim 2021. 11. 2. 01:43

1fastlane이란?

2. Bundler란? cocoapod 동기화 방법?

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 사용 방법


phase 별 configuration 세팅

- Xcode에서 각 phase 별로 Debug와 Release가 있으며, 로컬에서 두 가지 모두 빌드해볼 수 있으며 배포되는 버전은 Release 환경으로 배포

- 주의: 이름에 괄호가 들어가면 추후에 firebase 관련 오류가 나므로, 아래처럼 작성

Debug-alpha
Debug-beta
Debug-real
Release-alpha
Release-beta
Release-real

Xcode에서 configuration 설정 방법

  • Configurations 생성
    • Duplicate "Debug" Configuration 눌러서 총 6개되도록 생성 (alpha, beta, real 각 두 개씩 존재)

  • 완성
    • 주의할점은 Name에 괄호가 들어가면 Firebase관련 파일에서 에러가 나므로 괄호 없이 아래처럼 작성

Configurations 파일 생성

  • 현재 "No Configurations Set"인 상태이므로 아래처럼 Configuration 파일을 생성하여 추가

추가된 모습 (아래에서 추가)

  • configuration 파일
    • alpha, beta, real 각각 하나씩 만들어서 총 3개 생성 (Debug와 Release는 동일 config 파일을 공유)

  • 생성 완료

  • 내용 작성
// Configuration-alpha.xcconfig

// Bundle
X_BUNDLE_DISPLAY_NAME = SavePhoto (alpha)
X_BUNDLE_ID = com.jake.SavePhoto.alpha

// Phase
X_DEPLOY_PHASE = alpha

// API
X_API_SERVER_URL = http:/$()/localhost:3000
// Configuration-beta.xcconfig

// Bundle
X_BUNDLE_DISPLAY_NAME = SavePhoto (beta)
X_BUNDLE_ID = com.jake.SavePhoto.beta

// Phase
X_DEPLOY_PHASE = beta

// API
X_API_SERVER_URL = http:/$()/localhost:3000
// Configuration-real.xcconfig

// Bundle
X_BUNDLE_DISPLAY_NAME = SavePhoto
X_BUNDLE_ID = com.jake.SavePhoto

// Phase
X_DEPLOY_PHASE = real

// API
X_API_SERVER_URL = http:/$()/localhost:3000
  • 만들어진 .xcconfig 파일을 Xcode Configurations에 설정
    • Project와 Target 모두 설정 필요

  • Configurations 모두 설정 완료

cf) cocoapods 사용 시 추가적으로 세팅해줘야 하는 내용 참고: https://ios-development.tistory.com/660

xcconfig에서 정의한 key값 매핑

1) .swift파일 코드에서 현재 phase에 해당하는 값을 가져오고 싶은 경우, info.plist에서 값을 가져올 수 있고 info.plist에서는 정의한 xcconfig의 내용에 접근할 수 있으므로 info.plist에 xcconfig 내용 매핑

code에서는 DEPLOY_PHASE로 접근, config파일에는 X_DEPLOY_PHASE 키값으로 정의

// code에서 info.plist 접근 방법

struct AppConfiguration {
    static var apiServerURL: String {
        guard let apiServerURL = Bundle.main.object(forInfoDictionaryKey: "API_SERVER_URL") as? String else {
            fatalError("API_SERVER_URL could not be found in plist.")
        }
        return apiServerURL
    }

    static var deployPhase: String {
        guard let phase = Bundle.main.object(forInfoDictionaryKey: "DEPLOY_PHASE") as? String else {
            fatalError("DEPLOY_PHASE could not be found in plist.")
        }
        return phase
    }
}

2) 내부 자체적으로 사용되는 info.plist key에 value값도 xcconfig에서 설정한 값으로 매핑

  • Bundle display name
  • bundle id

  • 단, info.plist에 위처럼 세팅해도 xcode에서는 아직 bundle id가 반영이 안되어 있으므로 다른 처리도 필요

  • Target > Build Settings > "product bundle id" 검색
    • value값을 xcconfig에서 설정한 key값으로 설정 $(X_APP_BUNDLE_ID)

  • Project에도 동일하게 세팅하면 bundle id 세팅 완료

Sceme 설정

  • Target > Manage Schemes 선택

  • 기존에 존재하던 scheme name 변경
    • {appName} > {appName} alpha

  • 설정 > Duplicate

  • Scheme name 변경

  • 왼쪽 탭에서, Run부터 Archive Phase 탭의 info에서 phase 설정 변경

  • real scheme도 동일하게 생성하여 총 3개의 scheme 생성 설정

  • Scheme에서 Shared 모두 체크

Phase 별 flag값 정의 (전처리기 이용)

  • flag를 이용한 전처리기를 phase별로 나누어서 사용하기 위해 세팅

  • TARGETS > Build Settings > 'swift comipler' 검색하여 설정


Fastlane으로 Phase별 match, build, 배포 구축 방법

1) fastlane match

  • 개념
    • provisioning profile을 git의 remote repository에 저장하여, 서로 다른 개발자, 다른 맥북에서도 해당 git을 땡겨서 쓰면 provisioning profile관리에 용이하기 때문에 사용
    • adhoc 배포 할 때 profile이 필요한데, 이 빌드 시 remote repository에서 땡겨서 이 정보를 사용하면 편리
  • provisioning profile이 저장될 repository를 위해서 git ssh key 등록 (이미 존재할 경우 설정 x)
// ssh 생성
$ ssh-keygen -t rsa -b 4096 -C "youtEmail@example.com"

// ssh 복사
$ pbcopy < ~/.ssh/id_rsa.pub
  • git에 key 등록

  • private repo 생성

  • fastlane폴더 생성
$ fastlane init

4번 선택

  • match 파일 생성
$ fastlane match init

1번 git 선택 후 위에서 만든 git repository 주소 입력
생성된 fastlane 관련 파일
생성된 Matchfile

  • matchfile에 사용될 app identifiers 생성 (Apple Devloper에서 생성)
    • 프로젝트 Configuration 설정한 대로 alpha, beta, real 각각 생성

  • fastfile 구현
    • 먼저 appfile에서 fastfile에 선언할 lane에 해당하는 App identifier를 무엇으로할지 정의
# 디폴트 app identifier, apple id
app_identifier("com.jake.SavePhoto.alpha")
apple_id("palatable7@naver.com")

for_platform :ios do

    # deploy

    for_lane :beta_deploy do
        app_identifier 'com.jake.SavePhoto.beta'
    end

    for_lane :real_deploy do
        app_identifier 'com.jake.SavePhoto'
    end

    # sync

    for_lane :sync_codesign_beta do
        app_identifier 'com.jake.SavePhoto.beta'
    end

    for_lane :sync_codesign_real do
        app_identifier 'com.jake.SavePhoto'
    end

    # renew

    for_lane :renew_codesign_beta do
        app_identifier 'com.jake.SavePhoto.beta'
    end

    for_lane :renew_codesign_real do
        app_identifier 'com.jake.SavePhoto'
    end

end
  • fastfile 작성 전 준비 1) Firebase distribution을 통해 ad-hoc 배포 준비

> GoogleService-info 파일 alpha, beta, real 생성하여 추가 (생성 방법은 여기 참고)

GoogleService-info 파일 3개 생성

> build script 생성 "Firebase GoogleService-info"

echo "Build Configuration: " ${CONFIGURATION}

if [ ${CONFIGURATION} == *"real" ]; then
    echo "real"
    cp -r "${PROJECT_DIR}/${PRODUCT_NAME}/Service/GoogleService-Info-real.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
elif [ ${CONFIGURATION} == *"alpha" ]; then  
    echo "alpha"
    cp -r "${PROJECT_DIR}/${PRODUCT_NAME}/Service/GoogleService-Info-alpha.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
else 
    echo "beta"
    cp -r "${PROJECT_DIR}/${PRODUCT_NAME}/Service/GoogleService-Info-beta.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist"
fi
  • fastfile 구현 전 준비 2) firebase_cli_token 값 획득
// fastfile에서 아래처럼 사용
private_lane :upload_to_firebase do |options|
  firebase_app_distribution(
    app: options[:appid],
    groups: options[:tester_group],
    firebase_cli_token: "1//0e0saldfkjsdaflkjasdflkalj01-L9IrCA1CthxNgn4KToxuJFRlkLUSkBYfhGut5aXWPpdmWLfeKeKRsuws74fZYnZnf5ITrbg",
    ipa_path: "./fastlane/distribute/{your app name}.ipa"
    #release_notes: "Lots of amazing new features to test out!"
  )
end

> firebase cli 설치

$ curl -sL https://firebase.tools | bash

> firebase 로그인

$ firebase login:ci

// 로그아웃 하고싶을 경우, firebase logout

> terminal에 출력되는 토큰 정보를 복사하여 따로 저장

  • fastfile 구현 전 준비 2) firebase_cli_token 값 획득

> fastlane에서 firebase 배포 시 firebase plugin이 필요하므로, 프로젝트 루트 디렉토리에서 생성

$ fastlane add_plugin firebase_app_distribution

> Xcode에서 Firebase SDK를 받은 후 FirebaseApp.configure()

SPM을 사용할 경우, firebase-ios-sdk를 선택하고 위 화면에서 `FirebaseAnalytics` 선택
configure() 호출

  • fastfile 구현 전 준비 3) Firebase 앱 ID 값 복사
# fastfile에서 아래 appid에 들어갈 값
firebase_app_distribution(
  app: options[:appid],
  groups: options[:tester_group],
  firebase_cli_token: "1//0e0wVtCoLc5QFCgYIARAAGA4sadlkfjdsaf-L9IrCA1CthxNgn4KToxuJFRlkLUSkBYfhGut5aXWPpdmWLfeKeKRsuws74fZYnZnf5ITrbg",
  ipa_path: "./fastlane/distribute/{AppName}.ipa"
  #release_notes: "Lots of amazing new features to test out!"
)

Firebase 홈페이지에서 복사

  • fastfile 구현 전 준비 4) Firebase distribution 탭에서 배포 그룹 & 대상 설정 (alpha, beta 모두 App Distribution 탭을 누른 다음 "시작하기" 버튼을 눌러야 배포가되는것을 주의)

  • fastfile 구현 전 준비 4) xcode build number 초기화

> PROJECT > Current Project Version의 value값을 1로 설정

  • fastfile 작성
    • upload_to_firebase는 아래에서 작성
default_platform(:ios)

# TODO: ENV["FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"] = ...

platform :ios do
  
  # deploy

  lane :deploy_alpha do |options|
    sync_codesign_alpha()
    bump_build_number()
    build(configuration: "alpha")
    upload_to_firebase(appid: "1:773589851865:ios:d1dcae5400c3304acce8c8", tester_group: "tester-first, tester-second" )
  end

  lane :deploy_beta do |options|
    sync_codesign_beta()
    bump_build_number()
    build(configuration: "beta")
    upload_to_firebase(appid: "1:773589851865:ios:749c1a7bffb649b1cce8c8", tester_group: "tester-first, tester-second" )
  end

  lane :deploy_real do |options|
    sync_codesign_real()
    bump_build_number()
    build(configuration: "real")

    # TODO: 2FA 인증용도의 key 값
    # TODO: upload_to_testflight
  end

  # sync

  lane :sync_codesign_alpha do
    sync_codesign(type:"development")
    sync_codesign(type:"adhoc")
  end

  lane :sync_codesign_beta do
    sync_codesign(type:"development")
    sync_codesign(type:"adhoc")
  end

  lane :sync_codesign_real do
    sync_codesign(type:"development")
    sync_codesign(type:"appstore")
  end

  private_lane :sync_codesign do|options|
    match(type:options[:type], readonly: true)
  end

  # renew

  lane :renew_codesign_alpha do
    renew_codesign(type:"development")
    renew_codesign(type:"adhoc")
  end

  lane :renew_codesign_beta do
    renew_codesign(type:"development")
    renew_codesign(type:"adhoc")
  end

  lane :renew_codesign_real do
    renew_codesign(type:"development")
    renew_codesign(type:"appstore")
  end

  private_lane :renew_codesign do|options|
    match(type:options[:type], force_for_new_devices: true)
  end

  # TODO: register new device

  # private

  private_lane :build do |options|
    case options[:configuration]
    when "alpha"
      scheme = "SavePhoto alpha"
      export_type = "ad-hoc"
    when "beta"
      scheme = "SavePhoto beta"
      export_type = "ad-hoc"
    when "real"
      scheme = "SavePhoto real"
      export_type = "app-store"
    end

    build_app(
      scheme: scheme,
      export_method: export_type,
      output_directory: "./fastlane/distribute",
      clean: true
    )
  end

  private_lane :upload_to_firebase do |options|
    firebase_app_distribution(
      app: options[:appid],
      groups: options[:tester_group],
      firebase_cli_token: "1//0ePS_knB0VXuOCgYIARAAGA4SNwF-L9IrcIritOpKCIwYh5Mdj288Jgw7euJG_uu6UPVsUgeuQzoIoCuPStvAu2o9qhNYKM_Lv6E",
      ipa_path: "./fastlane/distribute/SavePhoto.ipa"
      #release_notes: "Lots of amazing new features to test out!"
    )
  end

  private_lane :bump_build_number do
    ensure_git_status_clean
    increment_build_number(xcodeproj: "./SavePhoto.xcodeproj")
    build_number = get_build_number(xcodeproj: "./SavePhoto.xcodeproj")
    commit_version_bump(message: "Bump build number to #{build_number} by fastlane", xcodeproj: "./SavePhoto.xcodeproj")
    push_to_git_remote
  end

end

cf) cocoapods 사용 시 주의할 점

> pod 프로젝트 파일 모두 Configuration을 main처럼 alpha, beta, real(release)을 생성해야 모두 빌드 실패 방지
(아래 이미지는 다른 프로젝트의 예시 이미지)

  • renew, sync하여 signing 파일 교체
    • Automatically maange signing 옵션 해제
    • 아래 명령어를 shell script로 만들어서 사용하면 편리
// renew

bundle exec fastlane renew_codesign_alpha
bundle exec fastlane renew_codesign_beta
bundle exec fastlane renew_codesign_real

// sync

bundle exec fastlane sync_codesign_alpha
bundle exec fastlane sync_codesign_beta
bundle exec fastlane sync_codesign_real

register_new_devices 추가

  • ad-hoc 배포에서의 profile에는 설치하려는 유저의 UDID정보가 입력되어야 설치가 가능
  • UDID 정보 입력방법: Apple Developer의 devices 탭에서 UDID 추가 > fastlane의 match를 이용하여 업데이트
  • 여기서, `Apple Developer의 devices 탭에서 UDID 추가` 부분을 fastlane으로 간편히 사용 가능
  lane :register_new_devices do
    register_devices(
      devices_file: "./fastlane/devices.txt",
      team_id: "SS7U83UJNK"
    )
  end

> devices.txt 파일 생성

(주의 할 점: 아래 값 사이의 여백은 tab, space bar로 입력하지 않고 아래 여백을 그대로 복사&붙여넣기하여 입력해야 오류 발생 x)

Device ID	Device Name
00008030-000135E4321321dAC	Jake(iPhone 13 Pro)

fastlane폴더에 생성 완료

> 명령어 실행

$ bundle exec fastlane register_new_devices

> 2FA 인증을 완료하면, Apple Developer의 Devices 항목에 등록 완료

upload_to_testflight

  • apple application specific password값 획득
    • testflight 빌드를 app store에 올릴 때 사용되는 값
# fastlane에서 아래와 같이 사용
ENV["FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"] = {이곳에 암호 입력}

>  appleid.apple.com/account/manage 사이트에서 로그인 후 암호 생성

암호 생성 후 복사

  • upload_to_testflight 추가
# deploy_real 레인에 추가
upload_to_testflight(skip_waiting_for_build_processing: true, 
                          ipa: "fastlane/distribute/SavePhoto.ipa")
  • fastfile 전체 코드
default_platform(:ios)

ENV["FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"] = "wzwy-zcxl-xkev-lyft"

platform :ios do
  
  # deploy

  lane :deploy_alpha do |options|
    sync_codesign_alpha()
    bump_build_number()
    build(configuration: "alpha")
    upload_to_firebase(appid: "1:773589851865:ios:d1dcae5400c3304acce8c8", tester_group: "tester-first, tester-second" )
  end

  lane :deploy_beta do |options|
    sync_codesign_beta()
    bump_build_number()
    build(configuration: "beta")
    upload_to_firebase(appid: "1:773589851865:ios:749c1a7bffb649b1cce8c8", tester_group: "tester-first, tester-second" )
  end

  lane :deploy_real do |options|
    sync_codesign_real()
    bump_build_number()
    build(configuration: "real")

    # TODO: 2FA 인증용도의 key 값
    upload_to_testflight(skip_waiting_for_build_processing: true, 
                          ipa: "fastlane/distribute/SavePhoto.ipa")
  end

  # sync

  lane :sync_codesign_alpha do
    sync_codesign(type:"development")
    sync_codesign(type:"adhoc")
  end

  lane :sync_codesign_beta do
    sync_codesign(type:"development")
    sync_codesign(type:"adhoc")
  end

  lane :sync_codesign_real do
    sync_codesign(type:"development")
    sync_codesign(type:"appstore")
  end

  private_lane :sync_codesign do|options|
    match(type:options[:type], readonly: true)
  end

  # renew

  lane :renew_codesign_alpha do
    renew_codesign(type:"development")
    renew_codesign(type:"adhoc")
  end

  lane :renew_codesign_beta do
    renew_codesign(type:"development")
    renew_codesign(type:"adhoc")
  end

  lane :renew_codesign_real do
    renew_codesign(type:"development")
    renew_codesign(type:"appstore")
  end

  private_lane :renew_codesign do|options|
    match(type:options[:type], force_for_new_devices: true)
  end

  # register new device

  lane :register_new_devices do
    register_devices(
      devices_file: "./fastlane/devices.txt",
      team_id: "SS7U83UJNK"
    )
  end

  # private

  private_lane :build do |options|
    case options[:configuration]
    when "alpha"
      scheme = "SavePhoto alpha"
      export_type = "ad-hoc"
    when "beta"
      scheme = "SavePhoto beta"
      export_type = "ad-hoc"
    when "real"
      scheme = "SavePhoto real"
      export_type = "app-store"
    end

    build_app(
      scheme: scheme,
      export_method: export_type,
      output_directory: "./fastlane/distribute",
      clean: true
    )
  end

  private_lane :upload_to_firebase do |options|
    firebase_app_distribution(
      app: options[:appid],
      groups: options[:tester_group],
      firebase_cli_token: "1//0ePS_knB0VXuOCgYIARAAGA4SNwF-L9IrcIritOpKCIwYh5Mdj288Jgw7euJG_uu6UPVsUgeuQzoIoCuPStvAu2o9qhNYKM_Lv6E",
      ipa_path: "./fastlane/distribute/SavePhoto.ipa"
      #release_notes: "Lots of amazing new features to test out!"
    )
  end

  private_lane :bump_build_number do
    ensure_git_status_clean
    increment_build_number(xcodeproj: "./SavePhoto.xcodeproj")
    build_number = get_build_number(xcodeproj: "./SavePhoto.xcodeproj")
    commit_version_bump(message: "Bump build number to #{build_number} by fastlane", xcodeproj: "./SavePhoto.xcodeproj")
    push_to_git_remote
  end

end
  • 만약 git repository를 생성하지 않았다면 생성 후 git 연결

  • app store connect에서 앱 등록

  • fastlane을 통해 build시키기 전에 xcode에서 빌드하여 정상 동작하는지 먼저 확인 후 아래 진행
  • testflight에 업로드하기 위해서 아래 명령어 실행
    • 만약 fastlane 실행 중 build_app() 함수에서 에러가 나는 경우, xcode를 종료한 후에 아래 명령어 다시 실행하면 해결
$ bundle exec fastlane deploy_real

> Passpharase 입력하는 창이 나오는데, match패스워드를 입력

(특수문자 + 영문)

ex) myPw*()

match 패스워드를 물어보는 화면 (최초 한번 입력 후 성공 시 키체인에 저장되어 자동으로 패스)

> 성공 

> (약 3~4시간 후) app store connect에 빌드 올라간것 확인

testflight에 앱 빌드를 올릴 때 사용될 2FA 인증 키 .p8파일 준비

  • bitrise와 같이 자동 배포 시 2FA를 수동으로 해줄 수 없기 때문에 인증서 파일을 추가
# fastfile에서 api_key값으로 사용
upload_to_testflight(api_key: api_key, 
                     skip_waiting_for_build_processing: true, 
                     ipa: "fastlane/distribute/SavePhoto.ipa")

> App store connect 사이트 접속 후 `사용자 및 액세스` 탭

> Key 생성 `액세스 요청`

> API 키 생성 클릭

> 생성된 key 확인 및 다운로드 - 최초 한번만 다운받을 수 있기 때문에 안전한 곳에 저장

(API 키 다운로드가 안보일 경우, 홈페이지 재접속하면 나타남)

> fastlane 폴더 안에 삽입

> key 정보를 입력하여 uplaod_to_testflight의 파라미터에 api_key 정보 추가

  lane :deploy_real do |options|

    renew_codesign_real()
    sync_codesign_real()
    bump_build_number()
    build(configuration: "real")

    # TODO: 2FA 인증용도의 key 값
    api_key = app_store_connect_api_key(
      key_id: "4KRU955ZYH",
      issuer_id: "c2fd1c9b-7e84-42ee-a638-8f1a776042ae",
      key_filepath: "fastlane/AuthKey_U4M68Y6BJ3.p8",
      duration: 1200,
      in_house: false
    )

    upload_to_testflight(api_key: api_key,
                          skip_waiting_for_build_processing: true, 
                          ipa: "fastlane/distribute/SavePhoto.ipa")
  end

완료된 전체 fastfile 내용

default_platform(:ios)

ENV["FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD"] = "wzwy-zcxl-xkev-lyft"

platform :ios do
  
  # deploy

  lane :deploy_alpha do |options|
    sync_codesign_alpha()
    bump_build_number()
    build(configuration: "alpha")
    upload_to_firebase(appid: "1:773589851865:ios:d1dcae5400c3304acce8c8", tester_group: "tester-first, tester-second" )
  end

  lane :deploy_beta do |options|
    sync_codesign_beta()
    bump_build_number()
    build(configuration: "beta")
    upload_to_firebase(appid: "1:773589851865:ios:749c1a7bffb649b1cce8c8", tester_group: "tester-first, tester-second" )
  end

  lane :deploy_real do |options|
    sync_codesign_real()
    bump_build_number()
    build(configuration: "real")

    # TODO: 2FA 인증용도의 key 값
    api_key = app_store_connect_api_key(
      key_id: "4KRU955ZYH",
      issuer_id: "c2fd1c9b-7e84-42ee-a638-8f1a776042ae",
      key_filepath: "fastlane/AuthKey_U4M68Y6BJ3.p8",
      duration: 1200,
      in_house: false
    )

    upload_to_testflight(api_key: api_key,
                          skip_waiting_for_build_processing: true, 
                          ipa: "fastlane/distribute/SavePhoto.ipa")
  end

  # sync

  lane :sync_codesign_alpha do
    sync_codesign(type:"development")
    sync_codesign(type:"adhoc")
  end

  lane :sync_codesign_beta do
    sync_codesign(type:"development")
    sync_codesign(type:"adhoc")
  end

  lane :sync_codesign_real do
    sync_codesign(type:"development")
    sync_codesign(type:"appstore")
  end

  private_lane :sync_codesign do|options|
    match(type:options[:type], readonly: true)
  end

  # renew

  lane :renew_codesign_alpha do
    renew_codesign(type:"development")
    renew_codesign(type:"adhoc")
  end

  lane :renew_codesign_beta do
    renew_codesign(type:"development")
    renew_codesign(type:"adhoc")
  end

  lane :renew_codesign_real do
    renew_codesign(type:"development")
    renew_codesign(type:"appstore")
  end

  private_lane :renew_codesign do|options|
    match(type:options[:type], force_for_new_devices: true)
  end

  # register new device

  lane :register_new_devices do
    register_devices(
      devices_file: "./fastlane/devices.txt",
      team_id: "SS7U83UJNK"
    )
  end

  # private

  private_lane :build do |options|
    case options[:configuration]
    when "alpha"
      scheme = "SavePhoto alpha"
      export_type = "ad-hoc"
    when "beta"
      scheme = "SavePhoto beta"
      export_type = "ad-hoc"
    when "real"
      scheme = "SavePhoto real"
      export_type = "app-store"
    end

    build_app(
      scheme: scheme,
      export_method: export_type,
      output_directory: "./fastlane/distribute",
      clean: true
    )
  end

  private_lane :upload_to_firebase do |options|
    firebase_app_distribution(
      app: options[:appid],
      groups: options[:tester_group],
      firebase_cli_token: "1//0ePS_knB0VXuOCgYIARAAGA4SNwF-L9IrcIritOpKCIwYh5Mdj288Jgw7euJG_uu6UPVsUgeuQzoIoCuPStvAu2o9qhNYKM_Lv6E",
      ipa_path: "./fastlane/distribute/SavePhoto.ipa"
      #release_notes: "Lots of amazing new features to test out!"
    )
  end

  private_lane :bump_build_number do
    ensure_git_status_clean
    increment_build_number(xcodeproj: "./SavePhoto.xcodeproj")
    build_number = get_build_number(xcodeproj: "./SavePhoto.xcodeproj")
    commit_version_bump(message: "Bump build number to #{build_number} by fastlane", xcodeproj: "./SavePhoto.xcodeproj")
    push_to_git_remote
  end

end

Fastlane 환경변수 설정하기

  • Fastlane은 환경 변수를 설정하여 쉽게 구현이 가능
  • fastlane 폴더에 (Appfile, Fastfile, Matchfile이 있는 디렉토리)에 .env.default로 생성
vi .env.default
  • 환경 변수로 사용할 내용 입력
GIT_BRANCH="master"
APP_IDENTIFIER="com.my.app"
APPLE_ID="jake@hpcnt.com"
TEAM_ID="29Wm219ADSD"
  • Appfile, Fastfile에 위 환경변수를 사용
    • ENV['KeyName']으로 접근

ex) Appfile에서 사용

app_identifier(ENV['APP_IDENTIFIER']) # The bundle identifier of your app
apple_id(ENV['APPLE_ID']) # Your Apple email address
team_id(ENV['TEAM_ID'])
Comments