들어가며…
앞 서 작성한 글에서는 Xcode Cloud 에 관련한 아주 기본적인 설정을 알아보았습니다. 사실 바로 사례 중심의 글을 적을까하다가 리마인드 겸 작성하였습니다.
이번에는 제가 직접 프로젝트에 설정하면서 겪은 사례 중심으로 조금 더 디테일한 설정 방법을 적어보려 합니다.
Package.resolved
현재 제가 담당하고 있는 프로젝트의 경우 여러 Swift Package 들을 automatic resolving 형태로 관리하고 있었습니다. 즉, resolving 후 생성되는 Package.resolved
파일을 SCM에 등록하지 않고 로컬에만 존재하게 했었습니다.
그러다가 Xcode Cloud 를 처음 설정할 때 가장 먼저 만난 이슈는 이 automatic resolving 때문에 발생한 빌드 실패였습니다. 같은 환경 아닌가? 혹시 사용하고 있는 Swift Package 들의 dependency 문제인가 싶어 로그들을 찬찬히 살펴봤습니다만 로컬과 다르지 않은 듯 하였고 로컬에서는 문제없는 것을 확인했습니다.
그러다가 정석대로 Xcode Cloud 문서를 보게 되었는데 거기에는 아래와 같은 구절이 있습니다.
https://developer.apple.com/documentation/xcode/making-dependencies-available-to-xcode-cloud
요약하자면, Package.resolved
파일은 gitignore
에 등록하지 말고 SCM에 포함되게 하라는 내용입니다.
문서를 조금 더 보다보면 이 이유에 대해서 아래와 같이 서술되어 있습니다.
역시 요약하자면, Automatic Resolving 을 이용하면 CI 에서 빌드될 때 SPM으로 관리되는 패키지의 버전이 달라질 수 있고 그렇게 빌드가 되거나 아카이브가 되면 원했던 결과와 정확하지 않기 때문이라고 합니다.
이 Package.resolved 파일의 위치는 [AppName].xcodeproj/project.xcworkspace/xcsharedata/swiftpm/
에 존재합니다.
Private Repository
프로젝트를 진행하다보면 간혹 Private repository 의 Package를 이용하거나 submodule 로 두거나 할 수 있습니다. 제가 맡은 프로젝트도 프로젝트 외에 딱 하나의 private repository 가 있는데 첫 빌드 때 이 때문에 빌드가 깨졌다고 언급했었습니다.
이 때는 Xcode Cloud 대시보드의 해당 빌드 상세 화면 상단에 노란색 배경의 문구가 나타나는데 포털로 이동하기 버튼을 누르면 쌩뚱맞게도 개발자 포털로 이동해버립니다. 이 때는 AppStore Connect 의 Xcode Cloud 로 이동하셔서 설정 -> 저장소를 가보시면 추가 저장소에 문제의 repository 가 나타날 것입니다.
거기서 권한을 부여해주고 다시 빌드를 하시면 됩니다.
워크플로 사이에 특정 작업 수행하기
Bitrise 의 경우 여러 워크플로 플러그인을 제공하여 조립하는 것처럼 워크플로를 완성했지만, 앞서 글에서 살펴본 것 처럼 Xcode Cloud 에서는 정해진 워크플로만 설정할 수 있습니다. 대신, 특정 단계 사이에 스크립트를 실행할 수 있도록 하고 있습니다. 이 정도만해도 충분하다고 생각하는거겠죠? 애플답게 말이죠..
모든 단계 사이가 아닌 3 구간에 스크립트를 정의할 수 있는데 아래 이미지처럼 소스코드를 가져온 후, 빌드 전, 빌드 후입니다. (아래 이미지는 https://developer.apple.com/documentation/xcode/writing-custom-build-scripts 에서 확인하실 수 있습니다.)
이 스크립트를 실행하도록 하기 위해서는 지켜야 하는 룰이 있습니다. 프로젝트 내에 ci_scripts
이름의 폴더가 존재해야 하고, 단계별로 지정된 스크립트 이름을 사용해야하며, chmod 를 통해 실행 속성을 부여하여야 합니다.
단계 별 스크립트 이름은 아래와 같습니다.
ci_post_clone.sh
: Xcode Cloud 에서 소스 코드를 가져온 후ci_pre_xcodebuild.sh
: 소스 코드를 가져와 빌드를 위한 전처리가 끝난 후 xcodebuild 가 수행되기 전ci_post_xcodebuild.sh
: xcodebuild 가 끝난 후
보통 소스코드를 가져온 후에는 필요한 환경을 설정하고, xcodebuild 가 실행되기 전에는 특정 파일의 이동 및 배치 등의 행위가 수행될테고, xcodebuild 가 수행된 이후에는 code coverage 등 보고서 작성을 위한 행위가 수행될 것입니다. 생각해보니 이 정도도 충분하다 싶네요.
기본 쉘은 zsh
로 Xcode 에서 쉘 스크립트 새 파일을 생성하면 bash
로 설정되어 있으니 되도록 수정하세요. 쉘 스크립트를 복잡하게 쓰지 않는 이상 큰 지장은 없습니다만 로그에 보면 경고가 나옵니다.
한 가지 더 재밌는 것은,
Xcode Cloud 에서 사용되는 instance는 macOS 입니다. 애플에서는 친절하게도 brew
를 기본제공해주고 있습니다. 애플에서도 이제 표준으로 인정하는 오픈소스 도구인 것 같습니다.
대신, 기본으로 내장되어 있는 brew
의 패키지들이 최신화가 되어 있지 않거나 축소된 패키지만을 가지고 있는지 제가 설치하려는 패키지는 제공되고 있지 않아 어쩔 수 없이 brew update
를 했는데 빌드 시간이 확 늘어나네요…
스크립트를 만드셨다고 바로 commit 하고 돌아가라~ 빌면 오류를 만나실 수 있습니다. 앞에서도 언급한 것처럼 꼭 chmod +x ci_*
처럼 추가한 스크립트 파일에 실행 속성을 주시고 commit 하셔야 합니다.
Xcode Cloud 환경
스크립트를 만들고 또 push 해서 로그 확인하고 하다보니 문득 Xcode Cloud 환경이 궁금했습니다.
그래서 macOS 에서 시스템 환경을 확인할 수 있는 명령어 두 개를 넣어서 돌려봤습니다.
system_profiler SPSoftwareDataType
과 uname - av
이며 결과는 아래 이미지에서 확인하세요. Xcode Cloud Server Instance 는 macOS 이며, X86_64 환경입니다. (M1인 arm64가 아닌게 의아하네요)
LFS 지원
제가 담당하는 프로젝트에서는 용량이 큰 파일이 SCM 이 포함되어 있지 않지만 문서를 살펴보다보니 LFS 는 현재 Xcode Cloud에서 지원하지 않는다고 합니다.
마치며…
하루에 하나씩 적으려다가 제 머리를 믿지 못하여 두 번째 글도 바로 이어 작성했습니다. 글로 적으니 내가 왜 삽질을 그렇게 했을까 자책을 하게 되네요. 특히 첫 번째 Package.resolved 내용처럼 automatic resolving 이 왜 안되는지 의아해하며 삽질을 많이 했던 것 같습니다. 나이 들었으면 메뉴얼부터 숙독하고 실행하는 느긋함을 가져야 할텐데 여전히 일단 해보자 정신이 몸과 정신을 해롭게 많드네요.
다음 연재 글은 1편에서도 예고했다시피 Xcode Cloud 에 danger-swift
를 적용하는 내용입니다. 이를 적용하느라 꼬박 하루가 걸렸던 것 같습니다. 잘 정리해서 작성하도록 할게요.
아래 이미지는 PR 이 올라왔을 때 설정한 조건에 의해 Xcode Cloud 가 빌드 및 테스팅을 마치고 남겨놓은 흔적입니다. (warning은 대부분 리팩토링을 위해 #warning 플래그를 임의로 달아둔거라… 많지만 많진 않습니다.. 쿨럭)
또 아래 이미지는 Xcode Cloud 가 작업을 끝내고 슬랙에 남겨놓은 흔적입니다.
끝.