-
Flutter Fastlane CI/CD(1) - iOSFlutter ν ν¬ 2023. 3. 7. 01:00
1. Fastlane μ€μΉ
brew install fastlane or sudo gem install fastlane
homebrew λ RubyGem μ ν΅ν΄ Fastlane μ μ€μΉν μ μμ΅λλ€. 곡μλ¬Έμ μ λ°λ₯΄λ©΄, Gem μ Ruby νκ²½μ μμ‘΄νκΈ° λλ¬Έμ brew λ‘ μ€μΉνλ κ²μ μΆμ²νλ€κ³ ν©λλ€
2. Fastlane init
cd ios/ fastlane init
fastlane init λͺ λ Ήμ΄λ₯Ό μ λ ₯νλ©΄ Setup μ’ λ₯λ₯Ό λ¬Όμ΄λ³΄λ μ½μμ°½μ΄ λμ΅λλ€. Manual Setupμ ν κ²μ΄κΈ°μ 4λ²μ μ λ ₯ν©λλ€
3. Fastlane Match μ€μ (μ νμ )
Fastlane Match λ, Fastlane μμ μλ μ½λ μ¬μ΄λ λ°©λ²μ ν μ’ λ₯μ λλ€.
κ°λ΅ν λ§νμλ©΄, μΈμ¦μμ νλ‘νμΌμ νλμ μ격 μ μ₯μμ μ λ‘λ νκ³ , νμλ€μ΄ ν΄λΉ μΈμ¦μμ νλ‘νμΌμ 곡μ νμ¬ μ½λ μ¬μ΄λμ λ¨μν νλ λ°©λ²μ λλ€.
Provisioning Profile μλ μ± ID, μ± μ€νμ΄ νμ©λ Device ID, μ νμμ λ°κΈν μΈμ¦μκ° ν¬ν¨λμ΄ μμΌλ©°, κ° κ°λ°μμ νκ²½μ΄ λ€λ₯΄κΈ° λλ¬Έμ μλ‘ λ€λ₯Έ Profile μ΄ μμ±λ©λλ€. λ°λΌμ Match λ₯Ό ν΅ν΄ μΈμ¦μμ νλ‘νμΌμ 곡μ νλ©΄, μ½λ μ¬μ΄λ κ΄λ¦¬ μΈ‘λ©΄μμ μ μ©νκ² μ¬μ©λ μ μμ΅λλ€.
μΈμ¦μμ νλ‘νμΌμ μ μ₯ ν μ격 μ μ₯μλ₯Ό μμ±ν΄μ€λλ€
3-2. Fastlane Match Init
match init λͺ λ Ήμ΄λ₯Ό μ λ ₯νλ©΄ Storage mode λ‘ git μ μ ννκ³ , git μ£Όμλ₯Ό μ λ ₯ν©λλ€. μ€μ μ΄ λ€ λλλ©΄ Fastlane ν΄λμ MatchFileμ΄ μμ±λ©λλ€.
3-3. MatchFile μμ
MatchFile μμ Default Type μ appstore λ‘ λ³κ²½ν΄μ€μλ€.
3-4. κΈ°μ‘΄μ κ°λ°, λ°°ν¬ μΈμ¦μ νκΈ°
fastlane match nuke development fastlane match nuke distribution
μΈμ¦μ νκΈ° λͺ λ Ήμ΄λ₯Ό μ λ ₯νλ©΄, passphase λ₯Ό λ±λ‘νλ νλ©΄μ΄ λμ¬ μ μμ΅λλ€.
3-5. μλ‘μ΄ κ°λ°, λ°°ν¬ μΈμ¦μ μμ±
fastlane match development fastlane match appstore
νμλ€μ΄ 곡μ ν μΈμ¦μλ₯Ό μμ±ν©λλ€. λ λͺ λ Ήμ΄λ₯Ό λͺ¨λ μ λ ₯νλ©΄, Matchfile μ λ±λ‘λ μ격 μ μ₯μμ μΈμ¦μμ νλ‘νμΌμ΄ μ¬λΌκ°κ² λ©λλ€.
3-6. Xcode Code Signing νμΈ
TARGETS/Signing&Capabilities/All/Signing/Provisioning Profile
Xcodeμ λ€μ΄κ° Provisioning Profile μ match [...] packageName μΌλ‘ λ³κ²½ν΄μ€λλ€.
4. Fastlane Firebase Distribution μ€μ
Fastlane μ μ΄μ©νμ¬ Firebase App Distribution μ λ°°ν¬νλ €λ©΄ νλ¬κ·ΈμΈ μ€μΉ, μΈμ¦ λ±μ ν΄μΌ ν©λλ€.
4-1. Firebase Plugin μ€μΉ
fastlane add_plugin firebase_app_distribution
Firebase νλ¬κ·ΈμΈμ μ€μΉν λ Your user account isn't allowed... λΌλ λ©μΈμ§κ° λμ€λ©΄μ Password λ₯Ό μ λ ₯νλΌκ³ ν μλ μλλ°, κ·Έλ₯ Mac password μ λ ₯νκ³ λμ΄κ°λλ€.
4-2. Firebase λ‘κ·ΈμΈ
fastlane run firebase_app_distribution_loginβ
CLIλ‘ Firebase μ λ‘κ·ΈμΈ νλ κ³Όμ μ λλ€. 컀맨λ μ λ ₯ μ μ μν μ μλ λ§ν¬ URL μ΄ ν°λ―Έλμ 보μΌν λ°, μ μν΄μ Firebase μΈμ¦ ν΄μ£Όμλ©΄ Refresh Token μ΄ λ μμ΅λλ€. ν΄λΉ ν ν°μ μ 보κ΄ν΄μ£ΌμΈμ.
5. νκ²½λ³μ[ENV] μ€μ
κ° κ°λ°μ λ§λ€ AppleID, Firebase Refresh Token λ±μ΄ νκ²½μ λ°λΌ λ¬λΌμ§ μ μλλ°, Fastlane μμλ .env νμΌλ‘ νκ²½λ³μλ₯Ό κ΄λ¦¬νμ¬ μλ‘ λ€λ₯Έ νκ²½μμλ λμΌν Lane μ μ¬μ©ν μ μμ΅λλ€.
# Appfile app_identifier("com.test.test") apple_id(ENV["APPLE_ID"]) # .env APPLE_ID="..."
Fastlane ν΄λ μμ Appfile μ λλ€. app_identifier λ μ΄λ νκ²½μμλ λμΌνμ§λ§, apple_id λ κ°λ°μ λ§λ€ λ€λ₯΄κΈ° λλ¬Έμ νκ²½λ³μλ‘ μΉνν©λλ€.
6. Xcode μμ
$(FLUTTER_BUILD_NAME)μΌλ‘ λμ΄μλ λΆλΆμ νμ¬ λ²μ (ex 1.0.4)λ‘ νλμ½λ©ν©λλ€(μ΅μ΄ 1ν)
7. Firebase Distribution Lane μμ±
7-1. Firebase μ€μ μ΄ λλ¬μΌλ, μ΄μ Firebase App Distribution μ Upload νλ Lane μ μμ±ν©λλ€.
# Firebase Distribution desc "Push a new beta build with Firebase App Distribution" lane :firebase do match(type:"adhoc") increment_build_number( build_number: latest_testflight_build_number + 1 ) build_app( workspace: "Runner.xcworkspace", scheme: "Runner", ) firebase_app_distribution( app: ENV["IOS_FIREBASE_APP_DISTRIBUTION_APP"], firebase_cli_token: "4-2. Firebase λ‘κ·ΈμΈμμ λ°μ Refresh Token", groups: "test", release_notes: "test" ) end
firebase_cli_token: 4-2. Firebase λ‘κ·ΈμΈμμ λ°μ Refresh Token
groups: Firebase App Distributionμ μλ “ν μ€νΈ λ° κ·Έλ£Ή”νλͺ©μ ν μ€νΈ κ·Έλ£Ή μ΄λ¦
7-2 Firebase μ λ°°ν¬
fastlane firebase λ₯Ό ν°λ―Έλμ μ λ ₯ν©λλ€.(fastlane + laneμ΄λ¦)
8. TestFlight Ditribution Lane μμ±
8-1. FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD μ€μ
appleid.apple.com/account/manage μ λ€μ΄κ°μ 보μ μͺ½μ μ± μνΈ μμ±μ λλ¬ μνΈλ₯Ό μμ± ν 볡λΆνμ¬ λ³΄κ΄ν΄μ£ΌμΈμ.
8-2. dotenv μ€μ
μλ λͺ λ Ήμ΄λ‘ dotenvλ₯Ό μ€μΉν΄μ£ΌμΈμ
sudo gem install dotenv
μλ λͺ λ Ήμ΄λ‘ envνμΌμ λ§λ€μ΄μ£ΌμΈμ
touch .env
μμ±λ envνμΌμ μ΄μ΄μ£ΌμΈμ
FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD = "chkl-jpdl-xutb-bqmw"μ΄λ κ² μμ±ν΄μ€λλ€.
8-3. TestFlight μ λ°°ν¬
# TestFlight desc "build app and upload to testflight" lane :beta do match(type: "appstore") increment_build_number( build_number: latest_testflight_build_number + 1 ) build_app( configuration: "Release" ) upload_to_testflight end
fastlane beta λ₯Ό ν°λ―Έλμ μ λ ₯ν©λλ€.(fastlane + laneμ΄λ¦)
iOS λ²μ λ° λΉλλ²νΈ μλ μμ λ°°ν¬
[laneμ€λͺ ]
firebase_release : private_lane :set_versionμ ν΅ν΄ λ²μ λΉλ λ²νΈλ₯Ό 1μ© μ¬λ¦° ν Firebaseμ λ°°ν¬ν©λλ€
firebase : increment_build_number(xcodeproj: "Runner.xcodeproj")λ₯Ό ν΅ν΄ λΉλ λ²νΈλ§ 1μ¬λ¦° ν Firebaseμ λ°°ν¬ν©λλ€
beta : increment_build_number(xcodeproj: "Runner.xcodeproj")λ₯Ό ν΅ν΄ λΉλ λ²νΈλ₯Ό 1 μ¬λ¦° ν Testflightμ μ λ‘λν©λλ€
private_lane :set_version : increment_version_number(xcodeproj: "Runner.xcodeproj"), increment_build_number(xcodeproj: "Runner.xcodeproj")λ₯Ό ν΅ν΄ λ²μ λ° λΉλ λ²νΈλ₯Ό 1μ© μ¬λ €μ€λλ€.
default_platform(:ios) platform :ios do desc "Upload Release IPA fo Firebase Distribution" lane :firebase_release do match(type:"adhoc") set_version build firebase_upload(release: true) end desc "Version Setting" private_lane :set_version do increment_version_number(xcodeproj: "Runner.xcodeproj") increment_build_number(xcodeproj: "Runner.xcodeproj") end desc "Build" private_lane :build do |options| build_app( workspace: "Runner.xcworkspace", scheme: "Runner", configuration: "Release" ) end desc "Upload Firebase" private_lane :firebase_upload do |options| firebase_app_distribution( app: ENV["IOS_FIREBASE_APP_DISTRIBUTION_APP"], firebase_cli_token: "4-2. Firebase λ‘κ·ΈμΈμμ λ°μ Refresh Token", groups: "test", release_notes: "test" ) end desc "Description of what the lane does" lane :custom_lane do # add actions here: https://docs.fastlane.tools/actions end # Firebase Distribution desc "Push a new beta build with Firebase App Distribution" lane :firebase do match(type:"adhoc") increment_build_number(xcodeproj: "Runner.xcodeproj") build_app( workspace: "Runner.xcworkspace", scheme: "Runner", ) firebase_app_distribution( app: ENV["IOS_FIREBASE_APP_DISTRIBUTION_APP"], firebase_cli_token: "4-2. Firebase λ‘κ·ΈμΈμμ λ°μ Refresh Token", groups: "test", release_notes: "test" ) end # TestFlight desc "build app and upload to testflight" lane :beta do match(type: "appstore") increment_build_number(xcodeproj: "Runner.xcodeproj") build_app( configuration: "Release" ) upload_to_testflight end end
iOSλ λ°°ν¬μλ£ ν appstore connectμμ μμΆ κ·μ μ 보 μ€μ μ ν΄μ€μΌ ν©λλ€
νλ¨μ “μμ μΈκΈλ μκ³ λ¦¬μ¦μ λͺ¨λ ν΄λΉνμ§ μμ”μ μ νν΄μ€λλ€.
'Flutter ν ν¬' μΉ΄ν κ³ λ¦¬μ λ€λ₯Έ κΈ
Flutter + FCM μ°λ (Flutter 3.0μ΄μ, μλ‘μ΄FCMμ μ©λ²μ , 3.0μ΄μμ΄ μλμ¬λ κ°λ₯ν©λλ€) (0) 2023.11.24 Flutter Fastlane CI/CD(2) - Android (1) 2023.03.07 [Flutter] YouTube player (0) 2022.08.25 [Flutter] host platform κ΅¬λ³ (Web, Phone) (0) 2022.07.26 [Flutter] κ²μκΈ κΈ°λ₯μ νμν ν¨μλ€(Firestoreμ¬μ©) (0) 2022.07.22