๐ ๊ฐ์
iOS(App Store) ยท Android(Play Store) ์คํ ์ด ๋ฐฐํฌ CICD๋ฅผ ์ ๋ฉด ๊ฐ์ ์๋ฃํ๋ค. ์ด ๋ฌธ์๋ ์ด ์ด์๋ง ๋ณด๊ณ ๋ ์ฒ์ ๋ณด๋ ์ฌ๋์ด ๋์ผํ ๋ฐฐํฌ ํ์ดํ๋ผ์ธ์ ์์ฑยท์ ์ง๋ณด์ํ ์ ์๋๋ก ํ์ผ๋ณ ์ญํ , ์์กด์ฑ, ์ํฌ๋ฆฟ, ์ค์ ์ฝ๋, ๋์ ํ๋ฆ, ํธ๋ฌ๋ธ์ํ
์ ๋ชจ๋ ์ ๋ฆฌํ๋ค.
๊ด๋ จ ์ด์: #930 (Android ๊ฑฐ์ง ์ฑ๊ณต ์ ๊ฑฐ), #931 (iOS ์ฌ์ฌ ์๋ ์ ์ถ ๋๋ฝ). ์์ธ ๊ตฌํ ๋ณด๊ณ ์๋ #931 ๋๊ธ ์ฐธ์กฐ.
์ต์ข
๊ฒฐ๊ณผ : ์ฝ๋ push ํ ๋ฒ์ผ๋ก ๋น๋ โ ์คํ ์ด ์
๋ก๋ โ (๋ชจ๋์ ๋ฐ๋ผ) ์ฌ์ฌ ์ง์ ๋๋ ์ฌ์ฌ ์๋ ์ ์ถ๊น์ง ์๋ํ. iOS 1.10.104๊ฐ ์ค์ App Store ์ฌ์ฌ ํ(Waiting for Review)์ ์๋ ์ง์
์ค์ธก ๊ฒ์ฆ ์๋ฃ. Android 1.10.101 production "๊ฒํ ์ค" ์ง์
๊ฒ์ฆ ์๋ฃ.
๐๏ธ 1. ํ์ผ ๊ตฌ์ฑ๊ณผ ์์กด์ฑ
1-1. ์ด์ ์ํฌํ๋ก์ฐ (์ค์ ๋ฐฐํฌ๊ฐ ๋๋ ๊ณณ)
ํ์ผ
์ญํ
ํธ๋ฆฌ๊ฑฐ
.github/workflows/ROMROM-IOS-TESTFLIGHT.yaml
iOS ๋น๋ โ TestFlight โ App Store deliver
push: deploy / workflow_run(CHANGELOG) / workflow_dispatch
.github/workflows/ROMROM-ANDROID-PLAYSTORE-CICD.yaml
Android ๋น๋ โ internal โ production promote
๋์ผ
์ค์ : ๋ ์ํฌํ๋ก์ฐ ๋ชจ๋ ref: deploy๋ฅผ checkout ํ๋ค. ์ฆ deploy ๋ธ๋์น์ ์ฝ๋/Fastfile๋ก ๋น๋ ํ๋ค. main์๋ง ๋จธ์งํ๋ฉด ๋ฐฐํฌ์ ๋ฐ์ ์ ๋จ โ main โ deploy ๋จธ์ง ํ์.
1-2. Fastlane ์ค์ ํ์ผ
ํ์ผ
์ญํ
๋๊ฐ ์ฌ์ฉ
android/fastlane/Fastfile.playstore
Android lane(deploy_internal, promote_internal_to_production)
Android ์ํฌํ๋ก์ฐ๊ฐ Fastfile๋ก ๋ณต์ฌํด ์ฌ์ฉ
(iOS) ์ธ๋ผ์ธ Fastfile
iOS ์ํฌํ๋ก์ฐ step ์์์ cat > ios/fastlane/Fastfile ๋ก ๋์ ์์ฑ
iOS ์ํฌํ๋ก์ฐ ์์ฒด
iOS๋ ๋ณ๋ Fastfile ํ์ผ์ด ์๋ค. ์ํฌํ๋ก์ฐ step "Install Fastlane and create Fastfile"์ด heredoc์ผ๋ก ios/fastlane/Fastfile์ ๊ทธ ์๋ฆฌ์์ ๋ง๋ ๋ค. iOS deliver ๋ก์ง์ ๊ณ ์น๋ ค๋ฉด ์ด ์ํฌํ๋ก์ฐ YAML ์์ heredoc์ ์์ ํด์ผ ํ๋ค.
1-3. ๋ง๋ฒ์ฌ(wizard) ํ
ํ๋ฆฟ โ ์ ๊ท ํ๋ก์ ํธ ์
์
์ฉ
ํ์ผ
์ญํ
.github/util/flutter/testflight-wizard/templates/Fastfile
iOS Fastfile ํ
ํ๋ฆฟ (์ ๊ท ํ๋ก์ ํธ๊ฐ ios/fastlane/Fastfile๋ก ๋ฐ์). ์ด์ ์ธ๋ผ์ธ Fastfile๊ณผ ๋์ผ ๋ก์ง ์ ์ง
.github/util/flutter/testflight-wizard/templates/Gemfile
fastlane ~> 2.228 + multi_json
.github/util/flutter/testflight-wizard/testflight-wizard-setup.sh
์ ํ
ํ๋ฆฟ๋ค์ ํ๋ก์ ํธ์ ์ค์น + Xcode Manual Signing ํจ์น
.github/util/flutter/playstore-wizard/playstore-wizard-setup.sh/.ps1
Android ์
์
(+multi_json)
์ ์ง๋ณด์ ์์น : ์ด์ ์ํฌํ๋ก์ฐ(์ธ๋ผ์ธ Fastfile)๋ฅผ ๊ณ ์น๋ฉด wizard ํ
ํ๋ฆฟ๋ ๊ฐ์ด ๊ณ ์ณ์ผ ๋์ด ๋ถ๊ธฐ๋์ง ์๋๋ค.
โ๏ธ 2. ํ์ํ GitHub Secrets / Variables
2-1. iOS Secrets
Secret
์ฉ๋
APPLE_CERTIFICATE_BASE64 / APPLE_CERTIFICATE_PASSWORD
Distribution ์ธ์ฆ์(.p12)
APPLE_PROVISIONING_PROFILE_BASE64
Provisioning Profile
APP_STORE_CONNECT_API_KEY_BASE64 / APP_STORE_CONNECT_API_KEY_ID / APP_STORE_CONNECT_ISSUER_ID
App Store Connect API Key(.p8) โ pilotยทdeliver ์ธ์ฆ
ENV_FILE, SECRETS_XCCONFIG, GOOGLE_SERVICE_INFO_PLIST
์ฑ ํ๊ฒฝ/Firebase
2-2. Android Secrets
Secret
์ฉ๋
Release Keystore ๊ด๋ จ
AAB ์๋ช
GOOGLE_PLAY_JSON_KEY(์๋น์ค ๊ณ์ )
Play Console API
2-3. Repository Variables (๋ฐฐํฌ ๋ชจ๋ ์ ์ด)
Variable
๊ธฐ๋ณธ(ํด๋ฐฑ)
ํจ๊ณผ
IOS_DEPLOY_MODE
testflight_only
iOS ํ์ ์๋ ๋ฐฐํฌ ๋ชจ๋
ANDROID_DEPLOY_MODE
store_submit
Android ํ์ ์๋ ๋ฐฐํฌ ๋ชจ๋
์ฐ์ ์์: workflow_dispatch input > repo variable > ํด๋ฐฑ.
๐๏ธ 3. ๋ฐฐํฌ ๋ชจ๋ 3๋จ๊ณ (์ ํ๋ซํผ ๊ณตํต ๊ฐ๋
)
๋ชจ๋
iOS (App Store)
Android (Play Store)
์ฌ๋ ๊ฐ์
store_only
TestFlight ์
๋ก๋๊น์ง๋ง (pilot)
internal ํธ๋ ์
๋ก๋๊น์ง๋ง
์์(ํ
์คํธ์ฉ)
store_prepare
๋ฒ์ ์์ฑ + ๋น๋ ์ ํ + What's New ์ฑ์ Prepare for Submission
production draft ์น๊ธ
ASC์์ Add for Review / ์ฝ์์์ "์ถ์ ์์"
store_submit
submit_for_review๋ก ์ฌ์ฌ ์๋ ์ ์ถ
production completed ์น๊ธ(์ฌ์ฌ ์๋ ๋ฑ๋ก)
์์(์์ ์๋)
iOS๋ testflight_only/appstore_prepare/appstore_submit ๋ค์ด๋ฐ๊ณผ store_* ๋ ๋ค ์ธ์(Fastfile์์ ๋ณ์นญ ์ฒ๋ฆฌ).
flowchart TD
A(["์ฝ๋ push โ deploy"]) --> B["Flutter ๋น๋ + ์ฝ๋์ฌ์ธ + IPA/AAB"]
B --> C["์คํ ์ด ์
๋ก๋ (pilot / internal)"]
C --> D{"DEPLOY_MODE?"}
D -->|store_only| E(["์
๋ก๋๊น์ง๋ง โ ์ข
๋ฃ"])
D -->|store_prepare| F["๋น๋ ์ฒ๋ฆฌ ๋๊ธฐ โ deliver/promote(draft)"]
D -->|store_submit| G["๋น๋ ์ฒ๋ฆฌ ๋๊ธฐ โ deliver/promote(completed)"]
F --> H(["์ ์ถ ์ง์ โ ์ฌ๋์ด ๋ฒํผ ํด๋ฆญ"])
G --> I(["์ฌ์ฌ ์๋ ์ ์ถ โ Waiting for Review"])
Loading
๐ 4. iOS deliver ํต์ฌ ์ฝ๋ (์ธ๋ผ์ธ Fastfile)
iOS ์ํฌํ๋ก์ฐ์ deploy_appstore lane ์ค deliver ๋ถ๋ถ. 6๊ฐ ์ต์
์ด ๊ฐ๊ฐ ํน์ ์คํจ๋ฅผ ๋ง๋๋ค โ ํ๋๋ผ๋ ๋น ์ง๋ฉด ๊ทธ ๋จ๊ณ์์ ์คํจํ๋ค.
# ๋ชจ๋ ํ์ (store_* / appstore_* ๋ณ์นญ ํธํ)
deploy_mode = ( ENV [ "DEPLOY_MODE" ] || "testflight_only" ) . strip
prepare_appstore = [ "appstore_prepare" , "appstore_submit" , "store_prepare" , "store_submit" ] . include? ( deploy_mode )
submit_to_appstore = [ "appstore_submit" , "store_submit" ] . include? ( deploy_mode )
# 1) TestFlight ์
๋ก๋ (ํญ์). ASC ๋ชจ๋๋ฉด ๋น๋ ์ฒ๋ฆฌ ์๋ฃ๊น์ง ๋๊ธฐ(deliver๊ฐ ๊ทธ ๋น๋๋ฅผ ๊ณจ๋ผ์ผ ํ๋ฏ๋ก)
pilot (
api_key : api_key ,
app_identifier : app_id , # ์์ผ๋ฉด ๋น๋ํํ crash
ipa : ENV [ "IPA_PATH" ] ,
changelog : ENV [ "RELEASE_NOTES" ] ,
skip_waiting_for_build_processing : !prepare_appstore # store_only๋ฉด ๋๊ธฐ ์ ํจ
)
if prepare_appstore
# whatsNew(What's New) ๋ฉํ๋ฅผ ์ ๋๊ฒฝ๋ก๋ก ์์ฑ โ โ ๏ธ ๋ก์ผ์ผ์ 'ko'๋ง ์ ํจ(ko-KR ๋ฌดํจ)
metadata_path = File . join ( ENV [ "GITHUB_WORKSPACE" ] , "ios" , "fastlane" , "metadata" )
FileUtils . mkdir_p ( File . join ( metadata_path , "ko" ) )
File . write ( File . join ( metadata_path , "ko" , "release_notes.txt" ) , release_notes )
# ์ฌ์ฌ Notes ์ด๊ธฐํ(์ด์ ๊ฑฐ์ ์๋ช
์ ์๋์น๊ณ ๋ฐฉ์ง) โ notes.txt๋ง ๋น์, ์ฐ๋ฝ์ฒยท๋ฐ๋ชจ๋ ASC ๊ธฐ์กด๊ฐ ๋ณด์กด
FileUtils . mkdir_p ( File . join ( metadata_path , "review_information" ) )
File . write ( File . join ( metadata_path , "review_information" , "notes.txt" ) , "" )
deliver (
api_key : api_key ,
app_identifier : app_id , # [์์ธ1] Bundle ID ๋ฏธ์ ๋ฌ โ crash
app_version : ENV [ "APP_VERSION" ] , # [์์ธ2] editable ๋ฒ์ ์๋ ์์ฑ/์ ํ
build_number : ENV [ "BUILD_NUMBER" ] , # [์์ธ5] ๋น๋ ๋ช
์ ์ ํ(skip_metadata:false๋ฉด ์๋์ ํ ๋๋ฝ)
submit_for_review : submit_to_appstore , # store_submit์ด๋ฉด ์ฌ์ฌ ์ ์ถ
automatic_release : submit_to_appstore ,
force : true , # CI ๋น๋ํํ
run_precheck_before_submit : false ,
skip_binary_upload : true , # pilot์ผ๋ก ์ฌ๋ฆฐ ๋น๋ ์ฌ์ฉ
skip_metadata : false , # whatsNew/notes ์
๋ก๋ ์ํด false
metadata_path : metadata_path , # [์์ธ3] ์ ๋๊ฒฝ๋ก (์๋๊ฒฝ๋ก๋ CWD ์ด๊ธ๋จ)
skip_screenshots : true
# app_review_information์ ์ ๋๊น โ ASC ๊ธฐ์กด ์ฐ๋ฝ์ฒยท๋ฐ๋ชจ๊ณ์ ๋ณด์กด(๊ฐ์ธ์ ๋ณด ํ๋์ฝ๋ฉ ๋ฐฉ์ง)
)
end
์ํฌํ๋ก์ฐ step์ด deliver์ ๋๊ธฐ๋ ENV (deploy-testflight job):
export APP_IDENTIFIER=" com.alom.romrom"
export APP_VERSION=" ${{ needs.prepare-build.outputs.version } }"
export BUILD_NUMBER=" ${{ needs.prepare-build.outputs.build_number } }"
export DEPLOY_MODE=" ${{ env.DEPLOY_MODE } }"
export RELEASE_NOTES=" $( cat final_release_notes.txt) "
๐ค 5. Android promote ํต์ฌ ์ฝ๋ (Fastfile.playstore)
deploy_mode = ( ENV [ "DEPLOY_MODE" ] || "store_submit" ) . strip
promote = [ "store_prepare" , "store_submit" , "appstore_prepare" , "appstore_submit" ] . include? ( deploy_mode )
submit = [ "store_submit" , "appstore_submit" ] . include? ( deploy_mode )
# Step1: internal ํธ๋ ์
๋ก๋ (completed)
upload_to_play_store ( package_name : 'com.alom.romrom' , track : 'internal' ,
aab : ENV [ "AAB_PATH" ] , json_key : ENV [ "GOOGLE_PLAY_JSON_KEY" ] , release_status : 'completed' , ...)
next unless promote # store_only๋ฉด ์ฌ๊ธฐ์ ์ข
๋ฃ
# Step2: production ์น๊ธ โ submit์ด๋ฉด completed(์ฌ์ฌ ์๋๋ฑ๋ก), prepare๋ฉด draft
promote_internal_to_production ( promote_status : submit ? 'completed' : 'draft' )
lane :promote_internal_to_production do |options |
upload_to_play_store (
track : 'internal' , track_promote_to : 'production' ,
track_promote_release_status : options [ :promote_status ] || 'completed' ,
rollout : '1.0' ,
changes_not_sent_for_review : false , # ๋ณ๊ฒฝ์ ์ฌ์ฌ๋ก ์ ์ก
rescue_changes_not_sent_for_review : false # [๊ฑฐ์ง์ฑ๊ณต ์ฐจ๋จ] ์คํจ ์ ์ํฌํ๋ก์ฐ ๋นจ๊ฐ๋ถ
)
end
๊ฑฐ์ง ์ฑ๊ณต์ ์ ์ฒด : fastlane supply์ rescue_changes_not_sent_for_review ๊ธฐ๋ณธ๊ฐ์ด true๋ผ, Google API๊ฐ "changesNotSentForReview๋ฅผ true๋ก ์ค์ ํ๋ผ" ์๋ฌ๋ฅผ ๋ด๋ฉด fastlane์ด ์๋ rescueํด ์ฌ์ฌ ์ ๋ณด๋ด๊ณ ์ ์ฅ๋ง ํ ์ฑ success ๋ฐํ ํ๋ค. false๋ก ๋ช
์ํด์ผ ์คํจ๊ฐ ํ๋ฉดํ๋๋ค.
โ ๏ธ 6. ํธ๋ฌ๋ธ์ํ
(์ค์ ๊ฒช์ 6๊ฐ ์์ธ)
์ฆ์(๋ก๊ทธ)
์์ธ
ํด๊ฒฐ
Could not infer your App's Bundle Identifier
deliver์ app_identifier ์์(๋น๋ํํ)
app_identifier ๋ช
์
Cannot submit for review - could not find an editable version
App Store์ ํด๋น ๋ฒ์ ํ์ด์ง ์์
app_version ๋ช
์(์๋ ์์ฑ)
missing required attribute 'whatsNew'
What's New ๋ฉํ ๋ฏธ๋ฐ์(๊ฒฝ๋ก ์ด๊ธ๋จ)
metadata_path ์ ๋๊ฒฝ๋ก
Unsupported directory name(s) ... ko-KR
fastlane ๋ฏธ์ง์ ๋ก์ผ์ผ ์ฝ๋
ko๋ง ์ฌ์ฉ(ko-KR ๊ธ์ง)
1.10.x ๋ฒ์ ์ ์๋ฑํ ์ด์ ๋น๋๊ฐ ๋ถ์
skip_metadata:false๋ฉด deliver๊ฐ ๋น๋ ์๋์ ํ ๊ฑด๋๋
build_number ๋ช
์
Notes์ ์ ๊ฑฐ์ ์๋ช
์๊ฐ ๋งค๋ฒ ๋จ์
ASC๊ฐ ์ด์ ๋ฒ์ Notes ์๋ ์น๊ณ
review_information/notes.txt ๋น ํ์ผ
Apple ๋น๋ ์ฒ๋ฆฌ(Processing) ๋ณ๋ชฉ โ ์ฝ๋ ๋ฌธ์ ์๋
store_prepare/store_submit์ deliver๊ฐ "๋ฐฉ๊ธ ์ฌ๋ฆฐ ๊ทธ ๋น๋"(๊ฐ์ ๋ฒ์ ์ ํฉ์ฑ)๋ฅผ ๊ณจ๋ผ์ผ ํ๋ฏ๋ก pilot์ด ๊ทธ ๋น๋์ Processing โ Complete ๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค. ์ด ์๊ฐ์ Apple ์๋ฒ ์ฌ์ (๋ณดํต 5~15๋ถ, ๋๋๋ก 1์๊ฐ+, ํต์ ๋ถ๊ฐ). CI๊ฐ "TestFlight ๋ฐฐํฌ" step์์ ์ค๋ ๋ฉ์ถฐ๋ hang์ด ์๋๋ค. ๊ธํ๋ฉด store_only ์ฌ์ฉ. ๋จ๊ธฐ๊ฐ ์ฐ์ ์
๋ก๋๋ Processing ํ๋ฅผ ๋ฐ๋ฆฌ๊ฒ ํ๋ฏ๋ก ์์ .
โ
7. ์ด์ ์ฒดํฌ๋ฆฌ์คํธ
๐โโ๏ธ ๋ด๋น์
๐ ๊ฐ์
iOS(App Store) ยท Android(Play Store) ์คํ ์ด ๋ฐฐํฌ CICD๋ฅผ ์ ๋ฉด ๊ฐ์ ์๋ฃํ๋ค. ์ด ๋ฌธ์๋ ์ด ์ด์๋ง ๋ณด๊ณ ๋ ์ฒ์ ๋ณด๋ ์ฌ๋์ด ๋์ผํ ๋ฐฐํฌ ํ์ดํ๋ผ์ธ์ ์์ฑยท์ ์ง๋ณด์ํ ์ ์๋๋ก ํ์ผ๋ณ ์ญํ , ์์กด์ฑ, ์ํฌ๋ฆฟ, ์ค์ ์ฝ๋, ๋์ ํ๋ฆ, ํธ๋ฌ๋ธ์ํ ์ ๋ชจ๋ ์ ๋ฆฌํ๋ค.
๊ด๋ จ ์ด์: #930(Android ๊ฑฐ์ง ์ฑ๊ณต ์ ๊ฑฐ), #931(iOS ์ฌ์ฌ ์๋ ์ ์ถ ๋๋ฝ). ์์ธ ๊ตฌํ ๋ณด๊ณ ์๋ #931 ๋๊ธ ์ฐธ์กฐ.
์ต์ข ๊ฒฐ๊ณผ: ์ฝ๋ push ํ ๋ฒ์ผ๋ก ๋น๋ โ ์คํ ์ด ์ ๋ก๋ โ (๋ชจ๋์ ๋ฐ๋ผ) ์ฌ์ฌ ์ง์ ๋๋ ์ฌ์ฌ ์๋ ์ ์ถ๊น์ง ์๋ํ. iOS 1.10.104๊ฐ ์ค์ App Store ์ฌ์ฌ ํ(
Waiting for Review)์ ์๋ ์ง์ ์ค์ธก ๊ฒ์ฆ ์๋ฃ. Android 1.10.101 production "๊ฒํ ์ค" ์ง์ ๊ฒ์ฆ ์๋ฃ.๐๏ธ 1. ํ์ผ ๊ตฌ์ฑ๊ณผ ์์กด์ฑ
1-1. ์ด์ ์ํฌํ๋ก์ฐ (์ค์ ๋ฐฐํฌ๊ฐ ๋๋ ๊ณณ)
.github/workflows/ROMROM-IOS-TESTFLIGHT.yamlpush: deploy/workflow_run(CHANGELOG)/workflow_dispatch.github/workflows/ROMROM-ANDROID-PLAYSTORE-CICD.yaml1-2. Fastlane ์ค์ ํ์ผ
android/fastlane/Fastfile.playstoredeploy_internal,promote_internal_to_production)Fastfile๋ก ๋ณต์ฌํด ์ฌ์ฉcat > ios/fastlane/Fastfile๋ก ๋์ ์์ฑ1-3. ๋ง๋ฒ์ฌ(wizard) ํ ํ๋ฆฟ โ ์ ๊ท ํ๋ก์ ํธ ์ ์ ์ฉ
.github/util/flutter/testflight-wizard/templates/Fastfileios/fastlane/Fastfile๋ก ๋ฐ์). ์ด์ ์ธ๋ผ์ธ Fastfile๊ณผ ๋์ผ ๋ก์ง ์ ์ง.github/util/flutter/testflight-wizard/templates/Gemfilefastlane ~> 2.228+multi_json.github/util/flutter/testflight-wizard/testflight-wizard-setup.sh.github/util/flutter/playstore-wizard/playstore-wizard-setup.sh/.ps1multi_json)โ๏ธ 2. ํ์ํ GitHub Secrets / Variables
2-1. iOS Secrets
APPLE_CERTIFICATE_BASE64/APPLE_CERTIFICATE_PASSWORDAPPLE_PROVISIONING_PROFILE_BASE64APP_STORE_CONNECT_API_KEY_BASE64/APP_STORE_CONNECT_API_KEY_ID/APP_STORE_CONNECT_ISSUER_IDENV_FILE,SECRETS_XCCONFIG,GOOGLE_SERVICE_INFO_PLIST2-2. Android Secrets
GOOGLE_PLAY_JSON_KEY(์๋น์ค ๊ณ์ )2-3. Repository Variables (๋ฐฐํฌ ๋ชจ๋ ์ ์ด)
IOS_DEPLOY_MODEtestflight_onlyANDROID_DEPLOY_MODEstore_submit๐๏ธ 3. ๋ฐฐํฌ ๋ชจ๋ 3๋จ๊ณ (์ ํ๋ซํผ ๊ณตํต ๊ฐ๋ )
store_onlystore_preparestore_submitsubmit_for_review๋ก ์ฌ์ฌ ์๋ ์ ์ถiOS๋
testflight_only/appstore_prepare/appstore_submit๋ค์ด๋ฐ๊ณผstore_*๋ ๋ค ์ธ์(Fastfile์์ ๋ณ์นญ ์ฒ๋ฆฌ).flowchart TD A(["์ฝ๋ push โ deploy"]) --> B["Flutter ๋น๋ + ์ฝ๋์ฌ์ธ + IPA/AAB"] B --> C["์คํ ์ด ์ ๋ก๋ (pilot / internal)"] C --> D{"DEPLOY_MODE?"} D -->|store_only| E(["์ ๋ก๋๊น์ง๋ง โ ์ข ๋ฃ"]) D -->|store_prepare| F["๋น๋ ์ฒ๋ฆฌ ๋๊ธฐ โ deliver/promote(draft)"] D -->|store_submit| G["๋น๋ ์ฒ๋ฆฌ ๋๊ธฐ โ deliver/promote(completed)"] F --> H(["์ ์ถ ์ง์ โ ์ฌ๋์ด ๋ฒํผ ํด๋ฆญ"]) G --> I(["์ฌ์ฌ ์๋ ์ ์ถ โ Waiting for Review"])๐ 4. iOS deliver ํต์ฌ ์ฝ๋ (์ธ๋ผ์ธ Fastfile)
iOS ์ํฌํ๋ก์ฐ์
deploy_appstorelane ์ค deliver ๋ถ๋ถ. 6๊ฐ ์ต์ ์ด ๊ฐ๊ฐ ํน์ ์คํจ๋ฅผ ๋ง๋๋ค โ ํ๋๋ผ๋ ๋น ์ง๋ฉด ๊ทธ ๋จ๊ณ์์ ์คํจํ๋ค.์ํฌํ๋ก์ฐ step์ด deliver์ ๋๊ธฐ๋ ENV (deploy-testflight job):
๐ค 5. Android promote ํต์ฌ ์ฝ๋ (Fastfile.playstore)
Could not infer your App's Bundle Identifierapp_identifier๋ช ์Cannot submit for review - could not find an editable versionapp_version๋ช ์(์๋ ์์ฑ)missing required attribute 'whatsNew'metadata_path์ ๋๊ฒฝ๋กUnsupported directory name(s) ... ko-KRko๋ง ์ฌ์ฉ(ko-KR ๊ธ์ง)skip_metadata:false๋ฉด deliver๊ฐ ๋น๋ ์๋์ ํ ๊ฑด๋๋build_number๋ช ์review_information/notes.txt๋น ํ์ผApple ๋น๋ ์ฒ๋ฆฌ(Processing) ๋ณ๋ชฉ โ ์ฝ๋ ๋ฌธ์ ์๋
store_prepare/store_submit์ deliver๊ฐ "๋ฐฉ๊ธ ์ฌ๋ฆฐ ๊ทธ ๋น๋"(๊ฐ์ ๋ฒ์ ์ ํฉ์ฑ)๋ฅผ ๊ณจ๋ผ์ผ ํ๋ฏ๋ก pilot์ด ๊ทธ ๋น๋์ Processing โ Complete๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค. ์ด ์๊ฐ์ Apple ์๋ฒ ์ฌ์ (๋ณดํต 5~15๋ถ, ๋๋๋ก 1์๊ฐ+, ํต์ ๋ถ๊ฐ). CI๊ฐ "TestFlight ๋ฐฐํฌ" step์์ ์ค๋ ๋ฉ์ถฐ๋ hang์ด ์๋๋ค. ๊ธํ๋ฉดstore_only์ฌ์ฉ. ๋จ๊ธฐ๊ฐ ์ฐ์ ์ ๋ก๋๋ Processing ํ๋ฅผ ๋ฐ๋ฆฌ๊ฒ ํ๋ฏ๋ก ์์ .โ 7. ์ด์ ์ฒดํฌ๋ฆฌ์คํธ
ref: deploy)store_prepare(์ ์ถ ์ง์ , ์์ ) / Androidstore_submit(์๋ ์ฌ์ฌ)IOS_DEPLOY_MODE=store_submit๋๋ dispatch์์ ์ ํko(ko-KR ๊ธ์ง), ๋ค๋ฅธ ๋ก์ผ์ผ์DELIVER_LOCALESENV๋ก ์ถ๊ฐ๐โโ๏ธ ๋ด๋น์