Section 14/151 menit
14. Real Use Cases
14. Real Use Cases
Use Case 1: Setup CI Lengkap untuk Project Hybrid (GitHub Actions)
Project nyata: app dengan Firebase (CocoaPods) + Alamofire, Kingfisher (SPM).
swift
# .github/workflows/ci.yml
name: iOS CI — Hybrid Project
on:
push:
branches: [main, 'release/*']
pull_request:
branches: [main]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true # Batalkan run lama jika ada push baru
jobs:
test:
name: Build & Test
runs-on: macos-15
timeout-minutes: 30
env:
XCODE_VERSION: '16.3'
DERIVED_DATA: ${{ github.workspace }}/DerivedData
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 1 # Shallow clone untuk kecepatan
- name: Select Xcode ${{ env.XCODE_VERSION }}
run: sudo xcode-select -s /Applications/Xcode_${{ env.XCODE_VERSION }}.app
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: '3.3'
bundler-cache: true
# ── COCOAPODS CACHE ─────────────────────────────────────────
- name: Restore CocoaPods Specs Cache
id: specs-cache
uses: actions/cache/restore@v4
with:
path: ~/.cocoapods/repos/trunk
key: cocoapods-trunk-v1-${{ hashFiles('Podfile.lock') }}
restore-keys: cocoapods-trunk-v1-
- name: Restore Pods Cache
id: pods-cache
uses: actions/cache/restore@v4
with:
path: Pods
key: pods-v1-${{ runner.os }}-xcode${{ env.XCODE_VERSION }}-${{ hashFiles('Podfile.lock') }}
restore-keys: pods-v1-${{ runner.os }}-xcode${{ env.XCODE_VERSION }}-
- name: Install CocoaPods
if: steps.pods-cache.outputs.cache-hit != 'true'
run: |
bundle exec pod install --no-repo-update
echo "✓ Pods installed"
- name: Save Pods Cache
if: steps.pods-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: Pods
key: pods-v1-${{ runner.os }}-xcode${{ env.XCODE_VERSION }}-${{ hashFiles('Podfile.lock') }}
# ── SPM CACHE ────────────────────────────────────────────────
- name: Restore SPM Cache
id: spm-cache
uses: actions/cache/restore@v4
with:
path: ${{ env.DERIVED_DATA }}/SourcePackages
key: spm-v1-${{ runner.os }}-xcode${{ env.XCODE_VERSION }}-${{ hashFiles('MyApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }}
restore-keys: spm-v1-${{ runner.os }}-xcode${{ env.XCODE_VERSION }}-
- name: Resolve SPM Packages
run: |
xcodebuild -resolvePackageDependencies \
-workspace MyApp.xcworkspace \
-scheme MyApp \
-derivedDataPath "$DERIVED_DATA" \
| grep -E "Fetching|Cloning|Resolved" || true
- name: Save SPM Cache
if: steps.spm-cache.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: ${{ env.DERIVED_DATA }}/SourcePackages
key: spm-v1-${{ runner.os }}-xcode${{ env.XCODE_VERSION }}-${{ hashFiles('MyApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }}
# ── BUILD & TEST ─────────────────────────────────────────────
- name: Build for Testing
run: |
xcodebuild build-for-testing \
-workspace MyApp.xcworkspace \
-scheme MyApp \
-destination "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.4" \
-derivedDataPath "$DERIVED_DATA" \
| xcpretty
- name: Run Tests
run: |
xcodebuild test-without-building \
-workspace MyApp.xcworkspace \
-scheme MyApp \
-destination "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.4" \
-derivedDataPath "$DERIVED_DATA" \
-resultBundlePath TestResults.xcresult \
| xcpretty --report junit --output test-report.xml
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results-${{ github.run_number }}
path: |
test-report.xml
TestResults.xcresult
# Job terpisah untuk cache warming (opsional, untuk branch utama)
warm-cache:
name: Warm Dependency Cache
runs-on: macos-15
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
needs: test # Jalankan setelah test sukses
steps:
- uses: actions/checkout@v4
- name: Pre-warm cache untuk developer baru
run: echo "Cache sudah di-warm oleh job test di atas"
Use Case 2: Script Audit Dependency — CocoaPods vs SPM Overlap Check
swift
#!/bin/bash
# scripts/check-dependency-overlap.sh
# Cek apakah ada library yang sama di CocoaPods dan SPM
set -e
echo "=== Checking for dependency overlaps ==="
# Extract pod names dari Podfile.lock
PODS=$(grep " - " Podfile.lock | grep -v "//" | awk '{print $2}' | cut -d'(' -f1 | tr '[:upper:]' '[:lower:]')
# Extract SPM package names dari Package.resolved
SPM_PACKAGES=$(cat "MyApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved" \
| python3 -c "
import json, sys
data = json.load(sys.stdin)
for pin in data.get('pins', []):
print(pin['identity'].lower())
")
# Cari overlap
OVERLAPS=()
while IFS= read -r pod; do
if echo "$SPM_PACKAGES" | grep -qi "^${pod}$"; then
OVERLAPS+=("$pod")
fi
done <<< "$PODS"
if [ ${#OVERLAPS[@]} -gt 0 ]; then
echo "⚠️ OVERLAP DETECTED — These packages appear in BOTH CocoaPods and SPM:"
for overlap in "${OVERLAPS[@]}"; do
echo " - $overlap"
done
echo ""
echo "This may cause duplicate symbols! Remove from one dependency manager."
exit 1
else
echo "✓ No overlaps found between CocoaPods and SPM"
fi
Use Case 3: Makefile untuk Hybrid Project Development
swift
# Makefile
.PHONY: install update clean ci
# Setup semua dependencies (pertama kali atau setelah clone)
install:
@echo "Installing CocoaPods..."
bundle exec pod install --no-repo-update
@echo "Resolving SPM packages..."
xcodebuild -resolvePackageDependencies \
-workspace MyApp.xcworkspace \
-scheme MyApp
@echo "✓ All dependencies installed"
# Update semua (hati-hati!)
update-pods:
bundle exec pod update
update-spm:
# Buka Xcode → File → Packages → Update to Latest Package Versions
@echo "Update SPM via Xcode: File → Packages → Update to Latest Package Versions"
# Check overlaps
check-deps:
./scripts/check-dependency-overlap.sh
# Clean semua artifacts
clean:
rm -rf DerivedData/
rm -rf build/
xcodebuild clean -workspace MyApp.xcworkspace -scheme MyApp
# Full CI simulation lokal
ci: check-deps
xcodebuild test \
-workspace MyApp.xcworkspace \
-scheme MyApp \
-destination "platform=iOS Simulator,name=iPhone 16 Pro" \
| xcpretty
# Report cache sizes
cache-sizes:
@echo "=== Dependency Cache Sizes ==="
@du -sh Pods/ 2>/dev/null && echo "(CocoaPods)" || echo "Pods/: not found"
@du -sh ~/Library/Developer/Xcode/DerivedData/*/SourcePackages 2>/dev/null \
| tail -1 && echo "(SPM)" || echo "SPM SourcePackages: not found"