Build günlüğü

Bir GitHub kesintisinde iOS build'iniz nasıl ayakta kalır?

pod install'u önce yerel önbellekten çalışır hâle getirin, gerekmeyen kaynakları kaldırın ve ağ hatalarında ilk hatada düşmek yerine bekleyerek yeniden deneyin. 8 Kasım 2026'da GitHub sürüm indirmeleri yaklaşık 30 dakika boyunca 503 döndü ve GOGOGO LLC'nin Unity oyunu GoTasty'nin iki TestFlight build'ini de beraberinde götürdü; çözüm bu.

6 dk okuma

Siyah beyaz bir görüntü: karanlık bir sunucu odası koridorunda bir ekran HTTP 503 hatası, ikinci ekran yeniden denemeden sonra yeşile dönen bir build logu gösteriyor; kapüşonlu bir figür uzaktan izliyor.

8 Kasım 2026'da GitHub'ın sürüm indirmeleri yaklaşık yarım saat boyunca HTTP 503 döndü. GOGOGO LLC'deki Unity oyunumuz GoTasty'nin iki iOS build'i aynı adımda düştü: Unity Ads aracılık adaptörü için UnityAds.zip indirilirken pod install'da. Kodumuzda hiçbir şey değişmemişti. Build'ler, bir bağımlılık indirmesi tam o dakikada github.com'un ayakta olmasına ihtiyaç duyduğu için düştü.

iOS projeniz CocoaPods kullanıyorsa büyük ihtimalle aynı riski taşıyorsunuz. Birçok pod, CocoaPods CDN'indeki bir podspec'ten ibaret ve bir GitHub sürümündeki zip dosyasını gösteriyor. Değiştirdiklerimiz şunlar.

pod install neden GitHub'a bağlı?

İki nedenle. Birincisi, bir pod'un kaynağı çoğu zaman bir GitHub sürüm dosyası; pod'u indirmek GitHub'dan indirmek demek. İkincisi, bazı araçlar eski git spec deposunu, https://github.com/CocoaPods/Specs'i, CDN'in yanına kaynak olarak ekliyor. Bizde bu satırı Google Mobile Ads Unity eklentisi üretilen Podfile'a yazıyor. Kullandığımız her pod CDN'de; bu yüzden git kaynağı bir github.com isteği ve bir yığın "Found multiple specifications" uyarısı dışında hiçbir şey eklemiyordu.

Adım 1: gerekmeyen kaynakları kaldırın

Podfile'ı her build'de Unity'nin External Dependency Manager'ı üretiyor; elle düzenlemek kalıcı olmuyor. Git spec kaynağını build betiğinde, pod install'dan hemen önce siliyoruz:

sed -i '' "\#^source 'https://github.com/CocoaPods/Specs'#d" Podfile
grep -n '^source' Podfile || true

grep kalan kaynakları loga basıyor; böylece build'in gerçekte neyi kullandığını görebiliyorsunuz.

Adım 2: önce önbellekten kurun

CocoaPods indirilen pod'ları ~/Library/Caches/CocoaPods altında, spec'leri ~/.cocoapods altında tutuyor. İkisi de sıcaksa ve pod'larınız değişmediyse pod install hiç ağa ihtiyaç duymuyor. Bu yüzden ilk deneme --repo-update olmadan düz bir pod install. Yalnızca o başarısız olursa, genellikle bir spec eksik olduğu için, sonraki denemeler depoyu güncelliyor.

Önbelleğin nerede durduğu runner'a bağlı. Kendi Mac mini'mizde koşular arasında kendiliğinden kalıyor. Barındırılan bir macOS runner'ında actions/cache gerekiyor. Arşiv işimizde checkout yok, yani hash'lenecek bir kilit dosyası yok: en yeni önbelleği önekle geri yüklüyor ve her koşuda yenisini kaydediyoruz.

- name: CocoaPods cache (cloud)
  if: ${{ inputs.runner == 'cloud' }}
  uses: actions/cache@v4
  with:
    path: |
      ~/Library/Caches/CocoaPods
      ~/.cocoapods/repos/trunk
    key: pods-${{ runner.os }}-${{ github.run_id }}
    restore-keys: pods-${{ runner.os }}-

Adım 3: bekleyerek yeniden deneyin

Bu tür kesintiler genellikle kısa sürer. İlk 503'te düşen bir build, bir dakikalık beklemeden kaçmak için kendisinden önce gelen Unity dışa aktarımını çöpe atar. Betiğimiz dört kez deniyor: önce düz kurulum, sonra arada 60 ve ardından 180 saniye bekleyerek --repo-update ile üç deneme.

attempts=("" "--repo-update" "--repo-update" "--repo-update")
waits=(0 60 180 0)
for i in "${!attempts[@]}"; do
  echo "::group::pod install ${attempts[$i]} (attempt $((i + 1))/${#attempts[@]})"
  if pod install ${attempts[$i]}; then echo "::endgroup::"; exit 0; fi
  echo "::endgroup::"
  if [ "$i" -lt $((${#attempts[@]} - 1)) ] && [ "${waits[$i]}" -gt 0 ]; then
    echo "pod install failed; next attempt in ${waits[$i]} s"
    sleep "${waits[$i]}"
  fi
done
echo "::error::pod install failed after ${#attempts[@]} attempts"
exit 1

Her deneme kendi katlanabilir log grubunu alıyor; böylece yeniden deneme çıktıyı gömmeden koşuda görünüyor. Dördü de başarısız olursa hata bunu tek satırda söylüyor.

Bir kesinti beklemeden nasıl test edilir?

GitHub'ın çökmesini beklemeniz gerekmiyor. Üç kontrol yeterli:

  • Sıcak önbellek, ağ yok. Projeyi daha önce derlemiş bir makinede github.com'u engelleyin (bir test makinesinde hosts dosyasına bir satır yeter) ve kurulum betiğini çalıştırın. Pod'lar değişmediyse ilk denemede başarılı olmalı.
  • Eksik bir spec. Hiç indirmediğiniz bir pod sürümü ekleyin ve github.com'u engelli tutun. Betik dört denemenin hepsinden geçmeli, aralarda beklemeli ve takılıp kalmak yerine tek satırlık hatayla bitmeli.
  • Normal ağ. Engeli kaldırıp yeniden çalıştırın. Başarılı olan deneme yine düz kurulum olmalı; bu, build'lerinizin gerçekten önbellek yolunu kullandığını kanıtlar.

Sonra log gruplarını okumaya devam edin. Pod'ları değişmemiş bir build bir gün ikinci denemeye ulaşırsa, önbellek sandığınız yerde değildir ve bir sonraki kesinti bunu sizin yerinize ortaya çıkarır.

Bu neyi çözmez?

  • Hiç indirmediğiniz bir pod yine ağa ihtiyaç duyar. Kesinti sırasında eklenen yeni bir bağımlılık yine başarısız olur, yalnızca daha geç ve daha kibar.
  • Geri yüklenmiş önbelleği olmayan soğuk bir barındırılan runner eskisi kadar açıkta kalır.
  • Swift paketleri ayrı bir yoldan gelir. Xcode onları kendisi çözer; kullanıyorsanız onları ayrıca sabitleyip önbelleğe alın.

Yaptığı şey, kısa bir GitHub kesintisini bağımlılıkları değişmemiş her build için düşen bir build'den daha yavaş bir build'e çevirmek; build'lerin çoğu da böyle.

Onun yerine pod'ları depoya mı koymalı?

Pods klasörünü commit'lemek ağı build'den tamamen çıkarır ve bazı ekipler bunu yapar. Xcode projesinin ve Podfile'ın her build'de yeniden üretildiği bir Unity projesinde ise incelenecek büyük ve gürültülü bir klasör ekler. Sıcak bir önbellek ve yeniden denemeler, deponun ağırlığı olmadan faydanın çoğunu verdi. O önbelleği sıcak tutan makine kendi Mac mini'nizde Unity CI yazısında anlatılıyor.

Kaynaklar

  1. Releases · Unity-Technologies/unity-ads-ios · GitHub
  2. CocoaPods 1.8 Beta is Here! · CocoaPods Blog
  3. Podfile Syntax Reference · CocoaPods Guides
  4. Command-line Reference · CocoaPods Guides
  5. googlesamples/unity-jar-resolver (External Dependency Manager for Unity) · GitHub
  6. googleads/googleads-mobile-unity · GitHub
  7. Dependency caching reference · GitHub Docs
  8. actions/cache · GitHub

Sorular

Bu yazı hakkında sorulanlar.

GitHub çöktüğünde pod install neden başarısız olur?
Birçok pod kaynağını bir GitHub sürümünden indirir ve bazı Podfile'lar github.com'daki git spec deposunu da listeler. GitHub HTTP 503 gibi hatalarla yanıt verdiğinde bu indirmeler ve onlarla birlikte pod install başarısız olur.
GitHub Actions'ta CocoaPods nasıl önbelleğe alınır?
~/Library/Caches/CocoaPods ve ~/.cocoapods/repos/trunk klasörlerini actions/cache ile önbelleğe alın. Self-hosted bir Mac'te bu klasörler koşular arasında kendiliğinden kalır. Sıcak önbellek ağ istemesin diye pod install'u önce --repo-update olmadan çalıştırın.
CI'da pod install --repo-update kullanmalı mı?
İlk denemede değil. Önce önbellekten düz bir pod install deneyin, --repo-update'i yalnızca bir spec eksik olduğunda, bir yeniden denemede kullanın.
CocoaPods önbelleği her kesintiye karşı korur mu?
Hayır. Hiç indirilmemiş bir pod yine ağa ihtiyaç duyar, önbelleği geri yüklenmemiş soğuk bir runner yine açıktadır ve Swift paketleri ayrı çözülür.