Section 9/171 menit
9. Custom Build Scripts (ci_scripts)
9. Custom Build Scripts (ci_scripts)
Tiga Script Hooks
swift
ci_scripts/
├── ci_post_clone.sh — setelah git clone, sebelum apapun
├── ci_pre_xcodebuild.sh — sebelum setiap action (build/test/archive)
└── ci_post_xcodebuild.sh — setelah setiap action
Script harus:
- Executable:
chmod +x ci_scripts/*.sh - Shebang line di baris pertama
- Return exit code 0 untuk sukses, non-zero untuk gagal
ci_post_clone.sh — Setup Dependencies
swift
#!/bin/zsh
# ci_scripts/ci_post_clone.sh
# Dijalankan SEKALI setelah clone — cocok untuk install dependencies
set -e # exit on error
echo "=== ci_post_clone.sh ==="
echo "Branch: $CI_BRANCH"
echo "Action: $CI_XCODEBUILD_ACTION"
# Install CocoaPods jika project menggunakan Pods
if [ -f "$CI_PRIMARY_REPOSITORY_PATH/Podfile" ]; then
echo "Installing CocoaPods..."
cd "$CI_PRIMARY_REPOSITORY_PATH"
# Gunakan bundler jika ada Gemfile
if [ -f "Gemfile" ]; then
bundle install
bundle exec pod install
else
pod install
fi
fi
# Decode secrets berdasarkan environment
if [[ "$CI_BRANCH" == "main" || -n "$CI_TAG" ]]; then
echo "Production environment detected"
echo "$PROD_GOOGLE_SERVICE_INFO" | base64 --decode \
> "$CI_PRIMARY_REPOSITORY_PATH/MyApp/GoogleService-Info.plist"
else
echo "Staging environment detected"
echo "$STAGING_GOOGLE_SERVICE_INFO" | base64 --decode \
> "$CI_PRIMARY_REPOSITORY_PATH/MyApp/GoogleService-Info.plist"
fi
echo "=== ci_post_clone.sh selesai ==="
ci_pre_xcodebuild.sh — Pre-Build Setup
swift
#!/bin/zsh
# ci_scripts/ci_pre_xcodebuild.sh
# Dijalankan SETIAP KALI sebelum action (build, test, atau archive)
set -e
echo "=== ci_pre_xcodebuild.sh ==="
echo "Action: $CI_XCODEBUILD_ACTION"
# Bump build number hanya saat archive
if [[ "$CI_XCODEBUILD_ACTION" == "archive" ]]; then
echo "Bumping build number to $CI_BUILD_NUMBER"
# Update CFBundleVersion di semua Info.plist
find "$CI_PRIMARY_REPOSITORY_PATH" -name "Info.plist" \
-not -path "*/Pods/*" \
-not -path "*/build/*" | while read -r plist; do
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $CI_BUILD_NUMBER" "$plist" 2>/dev/null || true
done
# Update xcconfig jika menggunakan CURRENT_PROJECT_VERSION
if [ -f "$CI_PRIMARY_REPOSITORY_PATH/Configuration/Version.xcconfig" ]; then
sed -i '' "s/CURRENT_PROJECT_VERSION = .*/CURRENT_PROJECT_VERSION = $CI_BUILD_NUMBER/" \
"$CI_PRIMARY_REPOSITORY_PATH/Configuration/Version.xcconfig"
fi
fi
# Generate version info file untuk in-app display
cat > "$CI_PRIMARY_REPOSITORY_PATH/Sources/Generated/BuildInfo.swift" << EOF
// Auto-generated oleh ci_pre_xcodebuild.sh — jangan edit manual
enum BuildInfo {
static let buildNumber = "$CI_BUILD_NUMBER"
static let commitHash = "$CI_COMMIT"
static let branch = "$CI_BRANCH"
static let buildDate = "$(date -u +"%Y-%m-%dT%H:%M:%SZ")"
}
EOF
echo "=== ci_pre_xcodebuild.sh selesai ==="
ci_post_xcodebuild.sh — Post-Build Actions
swift
#!/bin/zsh
# ci_scripts/ci_post_xcodebuild.sh
# Dijalankan setelah action selesai — cocok untuk upload artifact atau notifikasi custom
set -e
echo "=== ci_post_xcodebuild.sh ==="
echo "Action: $CI_XCODEBUILD_ACTION"
# Upload ke Sentry setelah archive untuk source map / dSYM
if [[ "$CI_XCODEBUILD_ACTION" == "archive" && -n "$SENTRY_AUTH_TOKEN" ]]; then
echo "Uploading dSYMs to Sentry..."
# Download Sentry CLI
curl -sL https://sentry.io/get-cli/ | bash
# Upload dSYMs dari archive
DSYM_PATH="$CI_ARCHIVE_PATH/dSYMs"
if [ -d "$DSYM_PATH" ]; then
sentry-cli --auth-token "$SENTRY_AUTH_TOKEN" \
upload-dif \
--org "$SENTRY_ORG" \
--project "$SENTRY_PROJECT" \
"$DSYM_PATH"
fi
fi
# Parse test results dan kirim custom metric
if [[ "$CI_XCODEBUILD_ACTION" == "test" && -n "$CI_RESULT_BUNDLE_PATH" ]]; then
echo "Parsing test results..."
# Xcresulttool untuk mengekstrak summary
SUMMARY=$(xcrun xcresulttool get \
--format json \
--path "$CI_RESULT_BUNDLE_PATH" 2>/dev/null || echo "{}")
echo "Test result bundle: $CI_RESULT_BUNDLE_PATH"
fi
echo "=== ci_post_xcodebuild.sh selesai ==="
Mengelola Swift Package Dependencies
Untuk project yang menggunakan Swift Package Manager, Xcode Cloud otomatis resolve packages. Namun untuk project besar, pertimbangkan:
swift
#!/bin/zsh
# ci_scripts/ci_post_clone.sh (SPM cache strategy)
set -e
# Untuk mempercepat build, bisa menggunakan local SPM mirror
# atau pre-download packages ke lokasi yang di-cache
# Resolve packages secara eksplisit (opsional — Xcode melakukan ini otomatis)
cd "$CI_PRIMARY_REPOSITORY_PATH"
xcodebuild -resolvePackageDependencies \
-project "MyApp.xcodeproj" \
-scheme "MyApp" || true
echo "SPM packages resolved"