Panduan

Cara menjalankan runner self-hosted CircleCI di Mac

CircleCI machine runner 3 dipasang di macOS dari Homebrew tap milik CircleCI dan berjalan sebagai LaunchAgent. Buat namespace dan resource class, salin token-nya, taruh di config.yaml milik runner, lalu bootstrap layanannya. Job menjangkaunya dengan machine: true dan resource_class: namespace/name.

Yang Anda butuhkan lebih dulu

  • Hak admin organisasi di CircleCI. Seorang admin harus menyetujui ketentuan runner di Org, lalu Runners, sebelum menunya muncul.
  • Minimal satu kredit di akun. Menurut CircleCI, job runner tidak memakai kredit, tapi penyimpanan dan transfer jaringan bisa.
  • Mac Apple silicon dengan akses admin, Homebrew, dan Xcode.
  • sha256sum, yang dicantumkan CircleCI sebagai prasyarat. Dapatkan dengan brew install coreutils.

1. Buat namespace dan resource class

Di aplikasi web, buka Runners dan pilih Create Resource Class. Setiap organisasi mendapat satu namespace. Jika Anda menerbitkan orb, Anda sudah punya namespace. Beri nama resource class seperti mac-mini-m6. Simpan, lalu salin token-nya. CircleCI hanya menampilkannya sekali.

CLI melakukan hal yang sama:

circleci namespace create <name> --org-id <your-organization-id>
circleci runner resource-class create <namespace>/<resource-class> <description> --generate-token

2. Pasang runner dengan Homebrew

brew tap circleci-public/circleci
brew trust circleci-public/circleci
brew install circleci-runner

Baris tengahnya baru. Homebrew 7.0.7, versi di Mac kami pada Oktober 2026, menolak memuat package dari tap pihak ketiga sampai Anda memercayainya. Halaman CircleCI belum menampilkan langkah ini. Runner-nya datang sebagai Homebrew cask.

macOS mungkin menampilkan pemberitahuan bahwa item latar belakang dari Circle Internet Services telah ditambahkan. Itu wajar. Homebrew juga menulis plist LaunchAgent ke ~/Library/LaunchAgents/com.circleci.runner.plist.

3. Tambahkan token ke config.yaml

nano $HOME/Library/Preferences/com.circleci.runner/config.yaml
runner:
  name: "mac-mini-m6"
  working_directory: "/Users/$USER/Library/com.circleci.runner/workdir"
  cleanup_working_directory: true
api:
  auth_token: "your-resource-class-token"

Dengan cleanup_working_directory aktif, setiap job mulai dari checkout yang bersih. Secara default DerivedData Xcode ada di ~/Library/Developer/Xcode/DerivedData, jadi cache build tetap bertahan. Jika Anda memakai -derivedDataPath di dalam working directory, proses pembersihan menghapusnya setelah setiap job.

Lindungi token-nya

Token resource class adalah yang membuat sebuah mesin bisa mengambil job untuk class itu. Siapa pun yang membacanya bisa memasang mesinnya sendiri dan menerima job Anda, lengkap dengan secret Anda. Kunci file config hanya untuk pengguna Anda, dan ganti token jika pernah bocor.

chmod 600 $HOME/Library/Preferences/com.circleci.runner/config.yaml
ls -l $HOME/Library/Preferences/com.circleci.runner/config.yaml

Logika yang sama berlaku untuk job. Job berjalan sebagai pengguna macOS yang menyalakan runner, di disk yang sama dengan semua hal lain. Arahkan hanya proyek tepercaya ke resource class ini.

4. Terima notarisasinya

Binary-nya berasal dari internet, jadi macOS harus menyetujuinya. CircleCI mendokumentasikan pengecekan tanda tangan lebih dulu, lalu penghapusan flag karantina.

spctl -a -vvv -t install "$(brew --prefix)/bin/circleci-runner"
sudo xattr -r -d com.apple.quarantine "$(brew --prefix)/bin/circleci-runner"

Perintah pertama seharusnya menampilkan accepted, dengan source Notarized Developer ID.

5. Jalankan runner di GUI domain

Jalankan perintah ini dari Terminal di desktop Mac. GUI domain adalah sesi desktop yang sedang login. Di sanalah Simulator dan login keychain berada.

launchctl bootstrap gui/$(id -u) $HOME/Library/LaunchAgents/com.circleci.runner.plist
launchctl enable gui/$(id -u)/com.circleci.runner
launchctl kickstart -k gui/$(id -u)/com.circleci.runner
launchctl print gui/$(id -u)/com.circleci.runner

CircleCI juga mendokumentasikan opsi user domain untuk sesi headless. Opsi itu memindahkan plist ke /Library/LaunchAgents. Di macOS 27, kami melihat plist di folder itu merusak login otomatis di setiap boot. Lihat login otomatis di Mac headless. Untuk pekerjaan iOS, kami menyarankan GUI domain dengan login otomatis.

6. Pastikan bertahan setelah reboot

Plist di ~/Library/LaunchAgents dimuat saat penggunanya login. Nyalakan login otomatis untuk akun ini di System Settings, bagian Users and Groups. Matikan sleep dengan sudo pmset -a sleep 0. Reboot sekali dan cek launchctl print lagi. Log ada di ~/Library/Logs/com.circleci.runner/runner.log.

7. Arahkan job ke Mac

version: 2.1

jobs:
  ios-tests:
    machine: true
    resource_class: your-namespace/mac-mini-m6
    steps:
      - checkout
      - run:
          name: Run tests
          command: |
            rm -rf build/TestResults.xcresult
            xcodebuild test -project MyApp.xcodeproj -scheme MyApp -destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5' -resultBundlePath build/TestResults.xcresult
      - run:
          name: Zip result bundle
          when: always
          command: ditto -c -k --keepParent build/TestResults.xcresult TestResults.xcresult.zip
      - store_artifacts:
          path: TestResults.xcresult.zip

workflows:
  ios:
    jobs:
      - ios-tests

Dokumentasi CircleCI menyebut dua field yang wajib ada di job runner: machine: true dan resource_class. Tidak ada key macos: xcode: di sini, karena Anda tidak memilih image. Job memakai versi Xcode apa pun yang dipilih di Mac. Di Mac MacRun, itu Xcode 26.6 dengan runtime simulator iOS 26.5.

Error umum dan cara memperbaikinya

  • Refusing to load cask ... from untrusted tap. Jalankan brew trust circleci-public/circleci, lalu pasang lagi.
  • macOS memblokir binary-nya. Anda melewatkan langkah notarisasi. Jalankan perintah xattr di atas.
  • Job masuk antrean tapi tidak pernah mulai. Cek apakah resource class di config.yml sama dengan yang Anda buat, lalu baca runner.log.
  • Docker layer caching tidak berjalan. CircleCI mencantumkannya sebagai fitur yang tidak didukung di runner self-hosted.
  • xcodebuild: error: Existing file at -resultBundlePath. Hapus bundle lama sebelum step test. Kami mengalami ini di Xcode 26.6.

Untuk menghentikan runner, pakai launchctl bootout gui/$(id -u)/com.circleci.runner. Untuk menghapusnya, jalankan brew uninstall --cask circleci-public/homebrew-circleci/circleci-runner.

Mengapa Mac khusus membantu

Keuntungan utamanya adalah cache yang hangat. Dalam benchmark kami, kami mem-build aplikasi iOS Wikipedia dengan Xcode 26.6. Job biasa setelah perubahan kecil butuh 27 detik di M6 yang hangat. Di runner macos-26 baru yang di-hosting GitHub, butuh 269 detik. Clean build butuh 86 detik, dibanding 183 detik.

Kapan macOS hosted dari CircleCI sudah cukup

CircleCI menjalankan executor Mac miliknya sendiri. Dokumentasinya, yang kami baca pada Oktober 2026, mencantumkan m4pro.medium dengan 6 vCPU dan 28 GB, serta m4pro.large dengan 12 vCPU dan 56 GB. Keduanya punya memori lebih besar dari M6 16 GB kami. Jika test suite Anda butuh memori sebanyak itu, atau Anda build beberapa kali seminggu, tetaplah di hosted. Lewati juga MacRun jika Anda butuh SLA, IP statis, atau beberapa region.

Lihat sistem CI lain untuk setup di sisi MacRun, atau bandingkan biaya dengan jumlah menit Anda sendiri.

Pertanyaan yang sering diajukan

Apakah runner self-hosted CircleCI gratis?

+

Menurut CircleCI, eksekusi di runner tidak memakai kredit. Anda tetap butuh minimal satu kredit di akun, karena penyimpanan dan transfer jaringan masih bisa ditagih.

Di mana config runner CircleCI di macOS?

+

Di $HOME/Library/Preferences/com.circleci.runner/config.yaml. Log masuk ke $HOME/Library/Logs/com.circleci.runner/runner.log.

Sebaiknya saya memakai GUI domain atau user domain?

+

Untuk build iOS, GUI domain dengan login otomatis. Runner berjalan di dalam sesi desktop yang dibutuhkan Simulator dan login keychain.

Apakah Docker layer caching berjalan di runner self-hosted CircleCI?

+

Tidak. CircleCI mencantumkan Docker layer caching sebagai fitur yang tidak didukung di runner self-hosted.

Panduan terkait