Build günlüğü

Unity CI build'leri kendi Mac mini'nizde nasıl çalıştırılır?

Mac mini'yi kendi etiketleriyle bir GitHub Actions runner'ı olarak kaydedin, Unity'yi bir konteyner yerine bir betikten batch modunda çağırın ve çalışma alanını koşular arasında koruyun ki Library sıcak kalsın. GoTasty'de bir Android geliştirme build'i soğukken 52 dakikadan sıcakken 8 dakikanın altına indi.

6 dk okuma

Siyah beyaz, fotoğraf görünümlü bir görüntü: karanlık bir masada harici bir SSD'nin yanında bir Mac mini, akan build loglarıyla parlayan bir terminal penceresi ve low-poly bir sokak sahnesi oynatan bir telefon.

GOGOGO LLC'de geliştirdiğim Unity 6 sokak lezzetleri oyunu GoTasty'de build almak için Unity Editor'ü açan kimse yok. Derleyici CI. Kasıma kadar bu CI GitHub'ın barındırdığı makinelerde çalışıyordu: Unity için Linux'ta Docker içinde GameCI, Xcode arşivi için barındırılan bir macOS makinesi. 3 Kasım'da ücretli runner dakikaları organizasyonun harcama sınırına dayandı. 4 Kasım'da iki iş akışı da masamdaki bir Mac mini M4'e taşındı. Notlar bunlar.

Neden barındırılan runner yerine kendi Mac'imiz?

  • Maliyet. Zaten sahip olduğunuz bir makine dakika başına fatura kesmez ve Unity build'leri uzun sürer.
  • Sıcak bir Library. Unity'nin Library klasörü onun içe aktarma önbelleği. Barındırılan bir runner her koşuda boş başlar ya da büyük bir önbelleği geri yükler. Kendi runner'ınız onu basitçe saklayabilir.
  • İki platform için tek makine. Aynı Mac Android APK'sını ya da AAB'sini derliyor, iOS Xcode projesini yazıyor ve Xcode ile arşivliyor. Unity 6 içe aktarmaları platform başına tuttuğu için Android ile iOS arasında geçiş her şeyi yeniden içe aktarmıyor.

Bedeli, makineyi ayakta tutmanın size kalması ve aynı anda yalnızca bir Unity build'inin çalışması.

Her koşu için runner nasıl seçilir?

İki iş akışı da iki değerli bir runner girdisi alıyor: varsayılan olan mac (push'lar da onu kullanıyor) ve cloud. İş runner'ını bu girdiden seçiyor; böylece Mac meşgul ya da kapalıyken eski barındırılan yol hâlâ çalışıyor:

runs-on: ${{ inputs.runner == 'cloud' && 'gotasty-8core'
  || fromJSON('["self-hosted","macOS","ARM64","gotasty-mac"]') }}

Özel gotasty-mac etiketi önemli. Organizasyondaki başka self-hosted işlerin yanlışlıkla bu makineye düşmesini engelliyor.

Unity GameCI olmadan nasıl çalıştırılır?

GameCI, Unity'yi bir Linux konteynerine sarar; barındırılan Linux runner'larında doğru araç budur. Mac'te ise editör ikili dosyasını doğrudan çağırabilirsiniz. Küçük bir betik (depomuzda tools/ci_mac_unity.sh), Unity Hub üzerinden Android ve iOS modülleriyle kurulmuş Unity 6000.0.85f2'yi build metodumuzla batch modunda çalıştırıyor ve üç şey daha yapıyor:

  • shlock ile makine genelinde bir kilit alıyor; böylece iki iş aynı projeyi asla aynı anda açmıyor;
  • build'den önce ve build sırasında boş belleği ve Android emülatörlerinin çalışıp çalışmadığını logluyor, çünkü aynı makinedeki bir emülatör RAM için yarışıyor;
  • çıktıları diskte sabit bir klasöre, Builds/GoTasty/<platform>/<run>/ altına yazıyor ve büyük artifact'ler yüklemek yerine yolu koşu özetine basıyor.

Lisans, bir konteynere aktarılan bir gizli değer değil, makinede etkinleştirilmiş normal bir Unity Personal lisansı.

Koşular arasında ne kalmalı, ne kalmamalı?

Mac'te checkout adımı çalışma alanını silmiyor. Her build'den önce bir temizlik adımı yalnızca yeniden üretilmesi gereken klasörleri (örneğin Addressables ayarlarını) siliyor ve gerisini tutuyor: Library, üretilmiş kod, hazırlanmış şehir kiti prefab'ları ve indirilmiş Firebase SDK'sı. Zaman orada harcanıyor. Bir Android geliştirme APK'sı için ölçtüğümüz rakamlar: soğukken yaklaşık 52 dakika (43'ü Unity'nin içinde, artı tam geçmişli bir checkout), sıcakken 7,7 dakika.

Checkout fetch-depth: 0 kullanıyor. Android versionCode'unu, GameCI'ın anlamsal sürümlemesinde olduğu gibi commit sayısından alıyoruz; sığ bir klon her build'e aynı sürümü verirdi. iOS build numarası ise iş akışının koşu numarası.

Push'tan APK'ya bir koşu nasıl görünür?

  1. main'e bir push ya da runner: mac ile elle tetikleme, işi gotasty-mac etiketi için kuyruğa alır.
  2. Checkout mevcut çalışma alanını tam geçmişle günceller, temizlik adımı yalnızca üretilmiş klasörleri siler.
  3. Build betiği Unity kilidini alır, belleği loglar ve Unity'yi build metoduyla batch modunda çalıştırır.
  4. APK ya da AAB Builds/GoTasty/Android/<run>/ altına düşer ve koşu özeti bu yolu basar.
  5. Mağaza paketi için CDN'imizden yüklenen şehir içeriği aynı işte yüklenir.

Oradan QA ajanları build'i doğrudan o klasörden emülatöre kurabilir; GitHub'dan geri hiçbir şey indirmek gerekmez.

Yeniden başlatmadan sonra runner nasıl ayakta tutulur?

Depomuz ve build çıktılarımız harici bir SSD'de duruyor ve bir launchd servisi o diske erişemedi. Çözüm daha az zarif ama çalışıyor: bir LaunchAgent oturum açılışında Terminal'de küçük bir .command betiği açıyor ve betik runner'ın run.sh'ı her kapandığında onu yeniden başlatıyor. Her macOS güncellemesinden sonra hâlâ başladığını kontrol edin.

Aynı Mac'te Xcode ve CocoaPods ne olacak?

iOS arşivi, güncel Firebase paketleri ve App Store yüklemeleri için Xcode 26 istiyor. İşin sudo'ya ihtiyacı yok: sürümü 26 ve üzeri olan en yeni /Applications/Xcode*.app'i buluyor ve DEVELOPER_DIR'i yalnızca o iş için ayarlıyor. CocoaPods Homebrew'dan geliyor, çünkü sistem Ruby'sindeki pod Xcode 26 projeleri için çok eskiydi. Pod kaynakları diskte önbellekte kalıyor; bu da GitHub'ın sürüm indirmelerinin yaklaşık yarım saat çöktüğü 8 Kasım'da önemli oldu. O hikâyenin kendi yazısı var.

Yine yapar mıydım?

Evet, bulut yolunu yedek olarak canlı tutarak. Tek makine tek bir arıza noktası ve bazı haftalar aynı anda iki build gerektiriyor. Ama hızlı yerel bir diskte sıcak bir Unity Library, ne sıklıkla build alabileceğimizi değiştirdi; bu da ajanların ve insanların ne kadar hızlı geri bildirim aldığını değiştiriyor. Büyük resim, yani oyunu yapay zekâ kodlama ajanlarıyla geliştirmek, atakanozalan.com'da.

Kaynaklar

  1. Unity 6 · Unity Technologies
  2. Mac mini · Apple
  3. Self-hosted runners · GitHub Docs
  4. Using labels with self-hosted runners · GitHub Docs
  5. Configuring the self-hosted runner application as a service · GitHub Docs
  6. GitHub Actions billing · GitHub Docs
  7. Getting started · GameCI
  8. Unity Editor command line arguments reference · Unity Documentation
  9. actions/checkout · GitHub
  10. Homebrew Formulae: cocoapods · Homebrew

Sorular

Bu yazı hakkında sorulanlar.

Unity build'leri self-hosted bir GitHub Actions runner'ında çalıştırılabilir mi?
Evet. Makineyi kendi etiketleriyle bir runner olarak kaydedin, Unity'yi gereken platform modülleriyle Unity Hub üzerinden kurun, makinede bir lisans etkinleştirin ve Unity'yi bir iş akışı adımından batch modunda çağırın.
Unity CI için neden Mac mini?
Xcode arşivi dahil Android ve iOS'u tek makinede derliyor ve Unity Library'yi koşular arasında sıcak tutuyor. GoTasty'de bu, sıcak bir Android geliştirme build'ini soğuktaki yaklaşık 52 dakikaya karşı 7,7 dakikaya indirdi.
Self-hosted bir Mac'te GameCI gerekir mi?
Hayır. GameCI Unity'yi bir Linux konteynerinde çalıştırır; bu barındırılan Linux runner'larına uyar. Mac'te Unity editör ikili dosyasını bir betikten doğrudan batch modunda çağırabilirsiniz.
macOS'ta bir GitHub Actions runner'ı oturum açılışında nasıl başlatılır?
Olağan yol bir launchd servisi. Runner, servisin erişemediği harici bir diskteyse, oturum açılışında Terminal'de bir yeniden başlatma betiği açan bir LaunchAgent onun yerine çalışır.