Section 9/151 menit

9. CI Caching untuk Hybrid Project

9. CI Caching untuk Hybrid Project

Hybrid project butuh cache untuk keduanya secara terpisah.

GitHub Actions: Hybrid Cache Strategy

swift
# .github/workflows/hybrid-ci.yml

name: Hybrid CI (CocoaPods + SPM)

on:
  push:
    branches: [main]
  pull_request:

jobs:
  build-test:
    runs-on: macos-15
    
    env:
      DERIVED_DATA_PATH: ${{ github.workspace }}/DerivedData
    
    steps:
      - uses: actions/checkout@v4
      
      - name: Setup Ruby & Bundler
        uses: ruby/setup-ruby@v1
        with:
          ruby-version: '3.3'
          bundler-cache: true

      # === COCOAPODS CACHE ===
      
      - name: Cache CocoaPods Specs
        uses: actions/cache@v4
        with:
          path: ~/.cocoapods/repos/trunk
          key: cocoapods-trunk-${{ hashFiles('Podfile.lock') }}
          restore-keys: cocoapods-trunk-
      
      - name: Cache Pods Folder
        id: cocoapods-cache
        uses: actions/cache@v4
        with:
          path: Pods
          key: pods-${{ runner.os }}-${{ hashFiles('Podfile.lock') }}
          restore-keys: pods-${{ runner.os }}-
      
      - name: Install Pods
        if: steps.cocoapods-cache.outputs.cache-hit != 'true'
        run: bundle exec pod install --no-repo-update

      # === SPM CACHE ===
      
      - name: Cache SPM Packages
        uses: actions/cache@v4
        with:
          path: ${{ env.DERIVED_DATA_PATH }}/SourcePackages
          key: spm-${{ runner.os }}-${{ hashFiles('MyApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved') }}
          restore-keys: spm-${{ runner.os }}-
      
      - name: Resolve SPM Packages
        run: |
          xcodebuild -resolvePackageDependencies \
            -workspace MyApp.xcworkspace \
            -scheme MyApp \
            -derivedDataPath "$DERIVED_DATA_PATH"

      # === BUILD & TEST ===
      
      - name: Run Tests
        run: |
          xcodebuild test \
            -workspace MyApp.xcworkspace \
            -scheme MyApp \
            -derivedDataPath "$DERIVED_DATA_PATH" \
            -destination "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.4" \
            -resultBundlePath TestResults.xcresult \
            | xcpretty --report junit --output test-results.xml
      
      - name: Upload Test Results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: test-results
          path: test-results.xml

      # === CACHE SIZE MONITORING ===
      
      - name: Report Cache Sizes
        if: always()
        run: |
          echo "=== Cache Sizes ==="
          du -sh Pods/ 2>/dev/null || echo "Pods: not found"
          du -sh "$DERIVED_DATA_PATH/SourcePackages" 2>/dev/null || echo "SPM: not found"
          du -sh ~/.cocoapods/repos/trunk 2>/dev/null || echo "Specs: not found"

Strategi Cache Key yang Robust

swift
# Prinsip cache key yang baik:
#
# 1. UNIK per konten yang relevant
#    - CocoaPods: hash Podfile.lock
#    - SPM: hash Package.resolved
#
# 2. RESTORE KEYS untuk partial match
#    - Jika Podfile.lock berubah (satu pod update),
#      fallback ke cache lama daripada download ulang semua
#
# 3. INCLUDE OS/PLATFORM
#    - Cache macOS tidak bisa dipakai di Ubuntu
#    - Cache ARM tidak kompatibel dengan x86_64
#
# 4. INCLUDE XCODE VERSION (untuk binary compatibility)
#    xcode_version: $(xcodebuild -version | head -1 | awk '{print $2}')

# Contoh key yang comprehensive:
key: pods-macos15-xcode16.3-${{ hashFiles('Podfile.lock') }}
key: spm-macos15-xcode16.3-${{ hashFiles('**/Package.resolved') }}