작업 일지

앱 27개, Fastfile 하나

앱마다 복사해 둔 배포 스크립트 27개가 조금씩 달라져 있었다. 어떤 앱은 업로드만 하려다 심사에 들어갔고, 어떤 앱은 버전이 안 오르고 있었다. 레인을 한 곳으로 모은 기록과, 모은 뒤에도 남은 함정.

3분#ios#fastlane#release

iOS 앱은 전부 fastlane으로 올린다. 처음엔 앱 하나의 Fastfile을 복사해서 다음 앱을 만들었고, 그게 27번 반복됐다. 27개 파일, 5,324줄. xcconfig에서 버전을 읽는 헬퍼가 25벌 복붙되어 있었다.

갈라진 자리들

7월에 14개 앱을 한 번에 배포하다가 이 갈라짐이 사고로 나타났다.

  • PhotoDiff의 release 레인은 업로드가 끝나면 곧장 심사에 제출했다. 다른 앱은 업로드만 했다. "업로드만" 하려던 배치에서 앱 하나가 심사 큐에 들어갔다.
  • 버전을 올리는 인자 이름이 앱마다 달랐다. 대부분 bump_type:인데 PhotoDiff는 bump:. 인자가 안 맞으면 마케팅 버전이 그대로라 "version previously used"로 거부된다.
  • 14개 앱이 수동 출시로 굳어 있었다. 정책은 승인 즉시 자동 출시인데, 복사한 원본이 automatic_release: false였다.
  • 테스트 시뮬레이터가 iPhone 15인 앱, 16인 앱, 17 Pro인 앱이 섞여 있었다.
  • QuickPack의 xcconfig는 KEY = v처럼 등호 양쪽에 공백이 있었다. 복붙된 파서는 KEY=v만 읽어서, 이 앱은 버전 bump가 아예 안 되고 있었다.
  • 위젯이나 워치 확장이 있는 앱은 deliver가 .ipa를 못 찾고 skip_binary_upload로 조용히 돌았다. 로그엔 uploaded, ASC엔 빌드 없음.

한 곳으로

8월에 레인을 _fastlane 한 곳으로 모았다. 앱의 Fastfile은 22줄 스텁이 됐다. 위로 6단계까지 _fastlane을 찾고, 없으면 private git에서 가져온다. 폴백은 _fastlane이 없는 임시 클론에서 실제로 돌려 확인했다.

앱마다 적던 것은 유도한다.

  • scheme과 workspace는 Project.swift의 이름에서. 27개 전부 맞았다.
  • 버전은 xcconfig에서. 두 표기 모두 읽고 원래 간격을 유지한다.
  • ASC 키는 앱의 .env에서. 키 파일이 있으면 파일 우선. 내용을 직접 주입하면 invalid curve name이 나는 앱이 있었다.
  • 메타데이터 업로드 여부는 fastlane/metadata 폴더 유무.

정책도 고정했다. release는 제출하지 않는다. 제출은 submit:true나 별도 레인으로만. bump 기본값은 build. 시뮬레이터는 iPhone 17 Pro 하나.

예외는 앱 폴더의 pentarab.yml 한 파일에만 적는다. 그리고 fastlane info. 해석된 값만 찍고 빌드도 업로드도 안 한다. 배선 확인은 항상 이걸로 한다.

27개 앱 전부 info 통과. 미출시 앱 하나는 다른 앱의 workspace를 빌드하도록 적혀 있었다. 복붙 버그였고, 출시 전이라 안 터졌을 뿐이다.

모은 뒤에도 남은 함정

빈 What's New. 메타데이터를 건너뛰는 앱은 새 버전의 릴리즈 노트가 26개 로케일 전부 비어 있다. 전 버전 노트는 승계되지 않는다. ASC는 이걸 "This resource cannot be reviewed"라고만 말한다. 무엇이 빠졌는지는 안 알려준다. 처방은 로컬 release_notes.txt를 읽어 whatsNew만 PATCH하는 것. 전체 메타데이터 레인을 돌리면 안 된다. 그 앱들의 로컬 메타데이터는 스토어와 대조돼 있지 않아서 건너뛰고 있던 것이다.

디스크. 9월에 release 세 개를 병렬로 돌리면서 컴파일 확인 13개를 같이 돌렸다. 여유 9GB가 몇 분 만에 0이 됐고, altool이 "패키지가 손상됐다"고 했다. 서버 문제가 아니라 로컬 ENOSPC였다. 아카이브 하나가 DerivedData 수백 MB에 공유 ModuleCache 3GB를 쓴다.

지금은 순차로 돌리고, 앱마다 시작 전에 여유 3GB 미만이면 멈춘다. 실패한 레인은 xcconfig 버전이 이미 올라가 있으니 재실행은 bump_type:build로 한다. 업로드와 제출은 한 러너에 묶지 않는다.