Fastlane 설치 및 안드로이드 적용은 1편에 있으니 참고 부탁드립니다!
Flutter 앱 배포 자동화하기 ① (with. Fastlane)
iOS Fastlane 적용
Fastlane 초기화
$ cd ios
$ fastlane init
초기화 명령어를 실행하면
앱 사용 목적을 물어보는 프롬프트가 나오는데
앱 자동 배포가 목적이라 3을 입력합니다.
로그인 프롬프트가 나오는데
애플 아이디(이메일), 비밀번호, 이중인증 번호 등을 입력해줍니다
그리고 앱의 메타데이터를 fastlane으로 관리할거냐는 질문이 나오는데 y 를 입력합니다.
완료되면 fastlane 폴더와 Gemfile 파일이 생성됩니다.
Fastlane 작성을 위한 셋팅
배포할 때 릴리즈 노트를 작성해야하는데 (물론, 배포 옵션에 릴리즈 노트를 skip할 수도 있음)
초기화할 때 메타데이터를 관리한다고 했기 때문에 metadata 폴더가 생성 되어 이곳에서 수정하면 된다.
fastlane/metadata/ko(언어)/release_notes.txt에서 수정하면
fastlane이 알아서 인식해서 배포할 때 가지고 가게 된다.
추가로
배포 여부에 따라 Slack 알림이 가는데 이 Slack 웹훅 URL을 가지고 있을 .env 파일을 fastlane 폴더 안에 생성한다.
(.env파일도 gitignore에 추가 필요)
이런 식으로 정의하면 된다.
그리고, 메타데이터 가져올 때 리뷰 관련한 정보는
제대로 못 가져오는 것 같아 fastlane/metadata/review_information 폴더는 삭제한다.
Fastlane 암호 설정
https://account.apple.com/account/manage
앱 암호를 클릭해서 새로 발급을 받는다.
발급받은 암호는
위에서 만든 .env 파일 안에 넣어준다.
Fastlane 작성
fastlane/Fastfile에 아래와 같이 작성한다.
default_platform(:ios)
# Slack 메시지를 전송하는 함수
def send_slack_message(success:, app_name:, version_name:, version_code:, error_message: nil)
# 성공 또는 실패에 따른 메시지 구성
message = if success
"✅ *#{app_name}* App Store 배포 완료!\n*버전*: #{version_name} (#{version_code})\n\n"
else
"❌ *#{app_name}* App Store 배포 실패\n*버전*: #{version_name} (#{version_code})\n*에러 메시지*: #{error_message}"
end
UI.message(ENV['SLACK_URL'])
# Slack 알림 전송
slack(
message: message,
success: success,
slack_url: ENV['SLACK_URL']
)
end
# build.gradle 대신 xcodeproj에서 현재 버전 가져오기
def get_version_name
get_version_number(xcodeproj: "Runner.xcodeproj")
end
def get_version_code
get_build_number(xcodeproj: "Runner.xcodeproj").to_i
end
# 버전 증가 로직
def increment_version(version_name, version_type)
return version_name if version_type == 4 # 버전 타입이 4이면 현재 버전을 그대로 반환
version_numbers = version_name.split('.').map(&:to_i)
case version_type
when 1
version_numbers[0] += 1
version_numbers[1] = 0
version_numbers[2] = 0
when 2
version_numbers[1] += 1
version_numbers[2] = 0
when 3
version_numbers[2] += 1
else
UI.user_error!("올바르지 않은 버전 유형입니다.")
end
version_numbers.join('.')
end
def get_version_type_from_user
version_type = UI.input("증가할 버전 유형을 입력하세요: 1은 Major, 2는 Minor, 3은 Patch, 4는 변경 없음").to_i
unless [1, 2, 3, 4].include?(version_type)
UI.user_error!("잘못된 입력입니다. 1, 2, 3 또는 4를 입력하세요.")
end
version_type
end
platform :ios do
desc "배포"
lane :deploy do
begin
app_name = "앱이름"
# 현재 버전 가져오기
current_version_name = get_version_name
current_version_code = get_version_code
version_type = get_version_type_from_user
# 새 버전 계산
new_version_name = increment_version(current_version_name, version_type)
new_version_code = current_version_code + 1
UI.message("새 버전: #{new_version_name} (#{new_version_code})")
# 버전 업데이트
increment_version_number(
version_number: new_version_name,
xcodeproj: "Runner.xcodeproj"
)
increment_build_number(
build_number: new_version_code,
xcodeproj: "Runner.xcodeproj"
)
# 빌드 및 배포
build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
upload_to_app_store(
# HTML report를 스킵
force: true,
skip_screenshots: true,
submit_for_review: true,
automatic_release: true,
)
send_slack_message(
success: true,
app_name: app_name,
version_name: new_version_name,
version_code: new_version_code
)
rescue => e
# 실패시 버전 되돌리기
increment_version_number(
version_number: current_version_name,
xcodeproj: "Runner.xcodeproj"
)
increment_build_number(
build_number: current_version_code,
xcodeproj: "Runner.xcodeproj"
)
send_slack_message(
success: false,
app_name: app_name,
version_name: new_version_name,
version_code: new_version_code,
error_message: e.message
)
UI.user_error!("배포 중 오류가 발생했습니다.")
end
end
desc "TestFlight 배포"
lane :beta do
begin
app_name = "앱이름"
# 현재 버전 가져오기
current_version_name = get_version_name
current_version_code = get_version_code
version_type = get_version_type_from_user
# 새 버전 계산
new_version_name = increment_version(current_version_name, version_type)
new_version_code = current_version_code + 1
UI.message("새 버전: #{new_version_name} (#{new_version_code})")
# 버전 업데이트
increment_version_number(
version_number: new_version_name,
xcodeproj: "Runner.xcodeproj"
)
increment_build_number(
build_number: new_version_code,
xcodeproj: "Runner.xcodeproj"
)
# 빌드 및 TestFlight 배포
build_app(workspace: "Runner.xcworkspace", scheme: "Runner")
upload_to_testflight(
skip_waiting_for_build_processing: true
)
send_slack_message(
success: true,
app_name: "#{app_name} (TestFlight)",
version_name: new_version_name,
version_code: new_version_code
)
rescue => e
# 실패시 버전 되돌리기
increment_version_number(
version_number: current_version_name,
xcodeproj: "Runner.xcodeproj"
)
increment_build_number(
build_number: current_version_code,
xcodeproj: "Runner.xcodeproj"
)
send_slack_message(
success: false,
app_name: "#{app_name} (TestFlight)",
version_name: new_version_name,
version_code: new_version_code,
error_message: e.message
)
UI.user_error!("TestFlight 배포 중 오류가 발생했습니다.")
end
end
end
실행
ios 폴더에서 아래 명령어를 실행하면 위 과정이 자동으로 실행된다.
$ fastlane deploy
중간에 위와 같이 버전 업데이트 어떤 걸 할 건지 물어보는 프롬프트가 뜨는데
원하는 숫자를 입력하면 된다. (변경 안 하려면 4번)
iOS는 안드로이드보다 한참 걸린다..
Testflight 올라가기까지 기다리고 있기 때문,,,
아무래도 시간이 많이 걸리기 때문에,
심사 없이 testflight로 올리고 싶으면 아래 명령어를 입력하면 된다.
$ fastlane beta
'💻 개발IT > Flutter' 카테고리의 다른 글
Flutter 앱 배포 자동화하기 ① (with. Fastlane) (4) | 2024.11.10 |
---|---|
[Flutter] .pub-cache/hosted/pub.dev/http-0.13.5/lib/src/io_client.dart 에러 (0) | 2023.03.30 |
[Flutter] 앱 배포 전 설정 정리! (ios, android) (0) | 2023.03.19 |
[Flutter] hot reload 안 될 때 (0) | 2023.03.12 |
[Flutter] Unable to boot the simulator 에러 (0) | 2023.03.10 |
[Flutter] main.dart 구조 분석 (0) | 2023.01.25 |
Flutter 프로젝트 폴더 구조 (0) | 2023.01.24 |