iyOmSd/Title: Swift

[Swift] Xcode Cloud(CI/CD) + Tuist(프로젝트관리툴) + dSYMs 업로드까지 자동화 배포하기 (feat. 스크립트쉘)

냄수 2022. 11. 11. 20:20
반응형

이번글은 나름 Xcode Cloud 사용에 있어서 심화?편인 것같네요

Xcode Cloud를 설정하면서 겪었던 이슈를 해결한 내용을 써내려가려고해요!

 

Tuist를 사용하는데 CI/CD를 적용하고싶어졌어요

Xcode Cloud환경에선 Tuist를 어떻게 실행시키지..? 에서 시작됬어요

 

Xcode Cloud 환경도 macOS 같을 거니까 어떠한 명령문을 실행할 수 있어요

터미널에서 입력하는 커맨드들을 이용해서 Tuist를 설치할거에요

 

설치하기앞서서

Xcode Cloud에서 지원해주는 스크립트 실행시점이 있어요

해당 레포에서 클론하고나서 실행시키는

Post-clone시점 - ci_post_clone.sh

 

xcodebuild 하기 전인

Pre-Xcodebuild시점 - ci_pre_xcodebuild.sh

 

xcodebuild 후인

Post-Xcodebuild시점 - ci_post_xcodebuild.sh

 

이렇게 3가지시점이있고

각각에 해당하는 스크립트 파일을 만들어줄수있어요

원하는 시점에 실행할 스크립트를 만들어서

ci_scripts 의 이름인 폴더를 만들어서 이 안에 넣어야해요

 

Xcode Clode에서 이 파일을 실행하기 때문에 모든 스크립트와 폴더이름은 설명과 똑같이 해줘야 실행되요

 

 

Tuist 설치

이제 진짜 Tuist를 설치해볼게요

Tuist를 링크를 통해서 설치할거에요

프로젝트 폴더에 .tuist-version 파일을 만들어줘서 트위스트 버전을 명시해준뒤에

// tuist_install.sh파일


#!/bin/sh

curl -Ls https://install.tuist.io | bash

echo "tuist generate..."
tuist clean --path ..
tuist fetch --path ..
tuist generate --path ..


// 만약 위에 명령문이 권한문제, 혹은 실행이 안되는경우 아래를 시도해주세요


#!/bin/sh

curl -Ls https://install.tuist.io | bash
tuist bundle

echo "tuist generate..."
.tuist-bin/tuist clean --path ..
.tuist-bin/tuist fetch --path ..
.tuist-bin/tuist generate --path ..

링크를 통해 설치하고

보통 트위스트 쓰듯이 사용하면되요

 

하지만 안돼는경우가 있을 수도있어서 따로 코드를 작성해봤어요

tuist bundle을 통해 명시된 버전의트위스트를 불러오고

.tuist-bin 내부실행파일을 통해 명령어를 가져다가 쓸수있어요

.tuist-bin/tuist (명령어) (경로)

를통해서 원하는 실행을할거에요

 

깃에서 클론받은뒤에

아직 xcodeproj 파일이 없어서 빌드할 수 없는 상태에요

tuist clean fetch generate를 통해서 프로젝트를 만들어줘야해요

 

이스크립트의 실행시점은

빌드전 깃클론 후가 될거니까

ci_post_clone.sh 파일로 만들고

스크립트에는

// ci_post_clone.sh파일

chmod +x tuist_install.sh

./tuist_install.sh

install파일에 대한 권한을 추가하고

파일을 실행시켜주세요

스크립트에서 스크립트를 실행시에는

sh파일에 대한 실행권한을 꼭 줘야 실행시킬 수 있어요

아니면 permission error를 볼 수 있어요

 

여기까지했으면

ci_post_clone.sh 실행 -> tuist_install.sh를 실행 -> tuist 다운 -> tuist generate 

까지 됬네요

 

이제 빌드가 잘 이뤄질거에요

 

추가로 Firebase Crashlytics를 달려고했는데 에러가 보여서 이것도 한번 해결해봤어요

우선 경로같은게 잘못되서

환경변수와 경로를 노가다로 찾아봤어요

환경변수는 Xcode Cloud 빌드로그에 다보이기때문에 원하는것 찾아다가 쓰시면되요

 

환경변수

CI=TRUE

CI_AD_HOC_SIGNED_APP_PATH=/Volumes/workspace/adhocexport

CI_APP_STORE_SIGNED_APP_PATH=/Volumes/workspace/appstoreexport

CI_ARCHIVE_PATH=/Volumes/workspace/build.xcarchive

CI_BRANCH=main

CI_BUILD_ID=358ad234-6e59-448c-bba1-8d842eea4952

CI_BUILD_NUMBER=35

CI_BUNDLE_ID=ns.test-CICD

CI_COMMIT=54d4fdb86fb179221507830d6f03ab81cf9311d6

CI_DERIVED_DATA_PATH=/Volumes/workspace/DerivedData

CI_DEVELOPMENT_SIGNED_APP_PATH=/Volumes/workspace/developmentexport

CI_GIT_REF=refs/heads/main

CI_PRIMARY_REPOSITORY_PATH=/Volumes/workspace/repository

CI_PRODUCT=test_CICD

CI_PRODUCT_ID=813261B6-2881-4594-91B2-68DCACBC5A7E

CI_PRODUCT_PLATFORM=iOS

CI_PROJECT_FILE_PATH=/Volumes/workspace/repository/test_CICD/test_CICD.xcodeproj

CI_RESULT_BUNDLE_PATH=/Volumes/workspace/resultbundle.xcresult

CI_START_CONDITION=push

CI_TEAM_ID=69a6de7a-0e5f-47e3-e053-5b8c7c11a4d1

CI_WORKFLOW=Xcode Cloud Test CICD

CI_WORKSPACE=/Volumes/workspace/repository

CI_WORKSPACE_PATH=/Volumes/workspace

CI_XCODEBUILD_ACTION=archive

CI_XCODE_PROJECT=test_CICD.xcodeproj

CI_XCODE_SCHEME=test_CICD

 

경로

Crashlytics를 적용할 dSYMs관련된 경로만 긁어봤어요

 

find 명령어를 통해서 Xcode Cloud는 혹시 경로가 다른가, 어디에 있나 해당경로를 찾아봤구요

echo "find..."
find .. GoogleService-Info.plist -type f

echo "🟢 find... project path "
find ${CI_PROJECT_FILE_PATH} firebase-ios-sdk -type d

echo "🟢 find... build path "
find ${BUILD_DIR%Build} firebase-ios-sdk -type d

echo "🟢 find... derived path "
find ${CI_DERIVED_DATA_PATH} firebase-ios-sdk -type d

echo "🟢 find... back path "
find .. firebase-ios-sdk -type d

폴더검색: find (찾을경로 시작점) (찾을 파일or폴더 이름) -type d(폴더)

파일검색: find (찾을경로 시작점) (찾을 파일or폴더 이름) -type f(파일)

무관: find (찾을경로 시작점) (찾을 파일or폴더 이름) 

 

실행파일 경로탐색

// Crashlytics 실행파일 경로
/Volumes/workspace/DerivedData/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics
/Volumes/workspace/DerivedData/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run
/Volumes/workspace/DerivedData/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/upload-symbols


// dSYM 경로1
/Volumes/workspace/build.xcarchive/dSYMs/test_CICD.app.dSYM

// dSYM 경로2
/Volumes/workspace/DerivedData/Build/Intermediates.noindex/ArchiveIntermediates/test_CICD/BuildProductsPath/Release-iphoneos/test_CICD.app.dSYM

dSYMs위치가 2개가 나오는데

경로2가 진짜 경로에요 2를 사용해주세요

 

 

환경변수 경로

//${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}
/Volumes/workspace/DerivedData/Build/Intermediates.noindex/ArchiveIntermediates/test_CICD/BuildProductsPath/Release-iphoneos/test_CICD.app.dSYM

//${CI_DERIVED_DATA_PATH}
/Volumes/workspace/DerivedData

//${CI_ARCHIVE_PATH}
/Volumes/workspace/build.xcarchive

//${BUILD_DIR%Build/*}
/Volumes/workspace/DerivedData/

주석처리가 되서 색이변했네요...

 

 

dSYMs업로드

아무튼!

문서에있는것과같이

${BUILD_DIR%Build/*}를 써도 무방할것같네요

${CI_DERIVED_DATA_PATH} 이런 CI환경변수를 넣으면

로컬빌드나 시뮬에서는 알수없는 값이라 동작하지 않을거에요

 

// CrashlyticsRunScript.sh 파일

echo "🟢🟢🟢🟢🟢🟢🟢🟢🟢"
echo "🟢${CONFIGURATION}🟢"

echo "upload dSYMs..."
if [ -d ${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME} ]; then
    "${BUILD_DIR%Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run"
else
    echo "dSYMs is not found"
fi

echo "🟢🟢🟢🟢🟢🟢🟢🟢🟢"

로그를 찾기 쉽게 이모지를 이용해서 표현하고

해당경로에서 crashlytics를 실행시켜주세요

 

${CONFIGURATION}

를 이용해서

Debug, Release등의 스킴을 구분해서 실행시킬수 있어요

 

 

이 스크립트는

2가지방법으로 실행시킬 수 있어요

1. 스크립트로 실행

2. Xcode run script에 코드를 적어서 실행

 

 

빌드 - run script - post_xcodebuild

순이기때문에

시점에 주의해야해요

 

스크립트에서 스크립트를 실행시에는

ci_post_xcodebuild.sh에서

실행권한을 꼭 추가하고

실행해주세요

#!/bin/sh

# 쉘스크립트로 실행시 권한 필요함
# chmod +x ../FrashlyticsRunScript.sh // 권한추가
# ../FrashlyticsRunScript.sh // 실행

 

 

 

검색하다보면 가끔

"${BUILD_DIR%Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run"
"${BUILD_DIR%Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/upload-symbols" -gsp "${PROJECT_DIR}/test_CICD/GoogleService-Info.plist" -p ios "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}"

이렇게 두문장 모두 실행하라하는데

시뮬빌드, 로컬빌드는 잘 동작하는데

xcode cloud가 동작을 안해요

30분 동안 실행되지않고 가만히 있게되더라구요 

왜인지는 모르겠어요...

 

Xcode Cloud는 30분동안 아무 실행이 없으면 time out에러를 내줘요

 

"${BUILD_DIR%Build/*}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run"

한줄만 사용해주세요

잘동작합니다

자동업로드에 실패하셨다면 수동으로 올릴때 쓰는게 upload-symbols 이기때문에

따로 올리시면되요

 

Xcode14부터 빌드파일에서 따로 뽑지못하지만

Xcode Cloud는 가능해요

빌드 번호에맞게 들어가서 아티팩트쪽에

iOS를 다운받아서

열고

패키지내용을 열면

잘 있으니 이파일을 드래그로 올려주면 끝이에요

 

 

 

 

 

삽질했던 과정들을 소개하며 마무리할게요 🐙

 

 

 

 

 

 

 

https://developer.apple.com/documentation/xcode/writing-custom-build-scripts

 

Apple Developer Documentation

 

developer.apple.com

 

반응형