1. Зачем использовать self-hosted раннер CircleCI на Mac?
CircleCI предлагает облачные среды выполнения macOS, но они имеют значительные затраты и ограничения. Ресурсы macOS в CircleCI используют систему кредитов, где каждая минута на macOS executor потребляет 50–100 кредитов в зависимости от класса ресурсов. Для команд, часто выполняющих сборки iOS, это может быстро составить $300–$500 в месяц и более.
Self-hosted раннер на выделенном Mac Mini M4 от MyRemoteMac полностью устраняет поминутную оплату. Вы получаете выделенную машину Apple Silicon с постоянным хранилищем, тёплыми кешами и полным root-доступом за фиксированную месячную плату от $75/месяц. Вот детальное сравнение:
| Характеристика | Облачный macOS CircleCI | Self-hosted MyRemoteMac |
|---|---|---|
| Модель оплаты | 50–100 кредитов/мин (~$0.06–$0.12/мин) | $75/мес фиксированно (неограниченные минуты) |
| Архитектура | Intel x86 или M1 (общий) | Apple M4 (выделенный, последняя модель) |
| Скорость сборки | ~14 мин (средний iOS-проект) | ~5 мин (тот же проект) |
| Сохранение кеша | Эфемерный (восстановление при каждой задаче) | Постоянный на диске (мгновенно) |
| Время ожидания в очереди | 30 с — 5 мин (зависит от тарифа) | 0 с (выделенное оборудование) |
| Конфиденциальность / Контроль данных | Общая инфраструктура | Выделенная машина, полный контроль |
| Пользовательское ПО | Только предустановленный образ | Полный root-доступ, любое ПО |
Ключевое преимущество: При использовании постоянного self-hosted раннера DerivedData, кеши Swift Package Manager и CocoaPods сохраняются между сборками. Одно это может сократить время сборки на 50–70% по сравнению с эфемерными облачными macOS окружениями CircleCI, которые каждый раз начинают с нуля. В сочетании с превосходной однопоточной производительностью чипа M4 ваши сборки iOS будут значительно быстрее.
2. Предварительные требования
Прежде чем начать, убедитесь, что у вас есть следующее:
- Сервер Mac Mini M4 от MyRemoteMac (от $75/мес)
- Аккаунт CircleCI с тарифом Performance, Scale или Server (self-hosted раннеры требуют платный план)
- SSH-доступ к вашему Mac Mini (предоставляется с подпиской MyRemoteMac)
- Аккаунт Apple Developer (для подписи кода и профилей обеспечения)
- Базовое знакомство с YAML, конфигурацией CircleCI и командами терминала
3. Шаг 1: Подключение к Mac Mini по SSH и установка зависимостей
Сначала подключитесь к Mac Mini M4 через SSH. Вы получили учётные данные при настройке сервера MyRemoteMac. Нам нужно установить Xcode и инструменты, необходимые для сборок iOS, прежде чем настраивать раннер CircleCI.
Подключение через SSH
# Connect to your Mac Mini M4
ssh admin@your-server-ip
# Verify you're on Apple Silicon
uname -m
# Expected output: arm64
# Check macOS version
sw_vers
# ProductName: macOS
# ProductVersion: 15.2
# BuildVersion: 24C101
Установка Homebrew и Xcode Command Line Tools
# Install Homebrew (if not already installed)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
# Add Homebrew to PATH
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
# Install Xcode Command Line Tools
xcode-select --install
# Accept the license agreement
sudo xcodebuild -license accept
Установка Xcode (полная версия)
Для сборок iOS вам нужно полное приложение Xcode. Самый быстрый способ установить его на безголовом сервере — использовать xcodes:
# Install xcodes CLI tool
brew install xcodes
# List available Xcode versions
xcodes list
# Install the latest stable Xcode
xcodes install 16.2
# Set it as the active Xcode
sudo xcode-select -s /Applications/Xcode-16.2.app/Contents/Developer
# Verify installation
xcodebuild -version
# Xcode 16.2
# Build version 16C5032a
Установка iOS-симуляторов и инструментов сборки
# Install the iOS 18 simulator runtime
xcodebuild -downloadPlatform iOS
# Verify simulator availability
xcrun simctl list runtimes
# == Runtimes ==
# iOS 18.2 (18.2 - 22C150) - com.apple.CoreSimulator.SimRuntime.iOS-18-2
# Install additional build tools
brew install xcbeautify fastlane swiftlint
4. Шаг 2: Установка агента раннера CircleCI
CircleCI использует агент machine runner для подключения вашего Mac Mini к платформе CircleCI. Machine runner получает задачи от CircleCI и выполняет их непосредственно на хосте macOS. Это отличается от container runner (который работает только на Linux).
Создание выделенного пользователя для раннера
Рекомендуется создать выделенного пользователя для запуска агента CircleCI с целью изоляции безопасности:
# Create a circleci user (optional but recommended)
sudo dscl . -create /Users/circleci
sudo dscl . -create /Users/circleci UserShell /bin/zsh
sudo dscl . -create /Users/circleci RealName "CircleCI Runner"
sudo dscl . -create /Users/circleci UniqueID 550
sudo dscl . -create /Users/circleci PrimaryGroupID 20
sudo dscl . -create /Users/circleci NFSHomeDirectory /Users/circleci
sudo mkdir -p /Users/circleci
sudo chown circleci:staff /Users/circleci
# Or simply use your existing admin user (simpler setup)
Скачивание и установка агента раннера
# Create a directory for the runner
sudo mkdir -p /opt/circleci
# Download the latest CircleCI machine runner for macOS ARM64
# Check https://circleci.com/docs/runner-installation-mac/ for latest version
curl -o /tmp/circleci-runner.pkg \
https://circleci-binary-releases.s3.amazonaws.com/circleci-runner/1.0/circleci-runner_darwin_arm64.pkg
# Install the runner package
sudo installer -pkg /tmp/circleci-runner.pkg -target /
# Verify the installation
circleci-runner --version
Настройка агента раннера
Создайте конфигурационный файл раннера. Вам понадобится токен аутентификации раннера из панели управления CircleCI (описано в Шаге 3). Пока создайте структуру конфигурационного файла:
# Create the configuration directory
sudo mkdir -p /opt/circleci/config
# Create the runner configuration file
sudo tee /opt/circleci/config/runner-agent-config.yaml << 'EOF'
api:
auth_token: YOUR_RUNNER_TOKEN_HERE
runner:
name: mac-mini-m4-runner
working_directory: /opt/circleci/workdir
cleanup_working_directory: true
max_run_time: 5h
# Optional: limit concurrent tasks
# command_prefix: ["nice", "-n", "10"]
logging:
file: /opt/circleci/logs/runner.log
EOF
# Create required directories
sudo mkdir -p /opt/circleci/workdir
sudo mkdir -p /opt/circleci/logs
# Set permissions (adjust user if using dedicated circleci user)
sudo chown -R admin:staff /opt/circleci
Создание macOS Launch Agent для автозапуска
Чтобы раннер запускался автоматически при загрузке и перезапускался при сбое, создайте macOS LaunchDaemon:
# Create the LaunchDaemon plist
sudo tee /Library/LaunchDaemons/com.circleci.runner.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN"
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.circleci.runner</string>
<key>ProgramArguments</key>
<array>
<string>/opt/circleci/circleci-runner</string>
<string>machine</string>
<string>--config</string>
<string>/opt/circleci/config/runner-agent-config.yaml</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>StandardOutPath</key>
<string>/opt/circleci/logs/runner-stdout.log</string>
<key>StandardErrorPath</key>
<string>/opt/circleci/logs/runner-stderr.log</string>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin</string>
</dict>
</dict>
</plist>
EOF
# Load and start the service
sudo launchctl load /Library/LaunchDaemons/com.circleci.runner.plist
# Verify the service is running
sudo launchctl list | grep circleci
# Expected: PID listed with com.circleci.runner
# Check the logs
tail -f /opt/circleci/logs/runner.log
Важно: Агент раннера не подключится, пока вы не добавите действительный токен аутентификации. Сначала выполните Шаг 3 для генерации токена, затем обновите файл runner-agent-config.yaml реальным токеном и перезапустите сервис.
5. Шаг 3: Настройка раннера в панели управления CircleCI
Теперь вам нужно зарегистрировать раннер в веб-интерфейсе CircleCI и сгенерировать токен аутентификации. Это связывает ваш Mac Mini с вашей организацией CircleCI.
Создание класса ресурсов
В CircleCI self-hosted раннеры организованы по классам ресурсов. Класс ресурсов — это метка, которая связывает ваш .circleci/config.yml с определённым набором раннеров.
- Перейдите в Панель управления CircleCI → Настройки организации → Self-Hosted Runners
- Нажмите "Create Resource Class"
- Задайте Namespace — имя вашей организации (например,
your-org) - Задайте имя Resource Class — описательное (например,
mac-runner) - Это создаст идентификатор класса ресурсов:
your-org/mac-runner
Генерация токена аутентификации раннера
- После создания класса ресурсов нажмите "Create New Token"
- Дайте токену описательное имя (например,
mac-mini-m4-token) - Скопируйте сгенерированный токен немедленно — он будет показан только один раз
Обновление конфигурации раннера с вашим токеном
# SSH back into your Mac Mini
ssh admin@your-server-ip
# Update the runner configuration with your real token
sudo nano /opt/circleci/config/runner-agent-config.yaml
# Replace YOUR_RUNNER_TOKEN_HERE with the actual token:
# api:
# auth_token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
# Restart the runner service to apply the new token
sudo launchctl unload /Library/LaunchDaemons/com.circleci.runner.plist
sudo launchctl load /Library/LaunchDaemons/com.circleci.runner.plist
# Verify the runner connects successfully
tail -20 /opt/circleci/logs/runner.log
# Look for: "Runner is ready to receive jobs"
После подключения раннер должен отображаться как "Online" в панели управления CircleCI в разделе Self-Hosted Runners. Если он не появляется в течение 60 секунд, проверьте файл логов на наличие ошибок.
Использование CircleCI CLI (альтернативный способ)
Вы также можете управлять раннерами через CircleCI CLI:
# Install the CircleCI CLI
brew install circleci
# Authenticate with CircleCI
circleci setup
# Create a resource class via CLI
circleci runner resource-class create your-org/mac-runner \
"Mac Mini M4 Runner" --generate-token
# List your runners
circleci runner instance list your-org/mac-runner
6. Шаг 4: Создание .circleci/config.yml для сборок iOS
Создайте файл .circleci/config.yml в корне вашего репозитория. Ключевое отличие от стандартной конфигурации CircleCI — использование machine: true с вашим пользовательским resource_class для направления задач на self-hosted раннер.
version: 2.1
jobs:
build-and-test:
machine: true
resource_class: your-org/mac-runner
environment:
SCHEME: "MyApp"
DESTINATION: "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.2"
DERIVED_DATA_PATH: "DerivedData"
SPM_CACHE_PATH: ".spm-cache"
steps:
- checkout
- run:
name: Select Xcode version
command: |
sudo xcode-select -s /Applications/Xcode-16.2.app/Contents/Developer
xcodebuild -version
- run:
name: Resolve Swift Package Dependencies
command: |
xcodebuild -resolvePackageDependencies \
-scheme "$SCHEME" \
-clonedSourcePackagesDirPath "$SPM_CACHE_PATH"
- run:
name: Build the app
command: |
xcodebuild build \
-scheme "$SCHEME" \
-destination "$DESTINATION" \
-clonedSourcePackagesDirPath "$SPM_CACHE_PATH" \
-derivedDataPath "$DERIVED_DATA_PATH" \
| xcbeautify
- run:
name: Run unit tests
command: |
xcodebuild test \
-scheme "$SCHEME" \
-destination "$DESTINATION" \
-clonedSourcePackagesDirPath "$SPM_CACHE_PATH" \
-derivedDataPath "$DERIVED_DATA_PATH" \
-resultBundlePath TestResults.xcresult \
| xcbeautify
- store_test_results:
path: TestResults.xcresult
- store_artifacts:
path: TestResults.xcresult
destination: test-results
workflows:
ios-pipeline:
jobs:
- build-and-test:
filters:
branches:
only:
- main
- develop
Примечание: Значение resource_class: your-org/mac-runner должно точно совпадать с классом ресурсов, который вы создали в панели управления CircleCI. Если значение не совпадает, задачи будут оставаться в очереди бесконечно.
7. Шаг 5: Оптимизация с помощью кеширования и параллелизма
Одно из главных преимуществ self-hosted раннера — постоянное кеширование. Поскольку файловая система раннера постоянна, вам не нужно загружать и скачивать кеши, как при использовании облачных ресурсов CircleCI. Однако есть дополнительные оптимизации для максимальной скорости сборки.
Использование постоянного DerivedData
Поскольку диск раннера сохраняется между сборками, DerivedData уже кешируется автоматически. Используйте постоянный путь:
# In your config.yml steps, always use a consistent DerivedData path:
- run:
name: Build with persistent cache
command: |
xcodebuild build \
-scheme "$SCHEME" \
-destination "$DESTINATION" \
-derivedDataPath ~/DerivedData/"$SCHEME" \
-clonedSourcePackagesDirPath ~/spm-cache \
| xcbeautify
# Periodically clean old DerivedData on the runner (cron job):
# 0 3 * * 0 find ~/DerivedData -maxdepth 1 -mtime +7 -exec rm -rf {} +
Сохранение рабочего пространства между задачами
Используйте рабочие пространства CircleCI для передачи артефактов между задачами в одном рабочем процессе:
jobs:
build:
machine: true
resource_class: your-org/mac-runner
steps:
- checkout
- run:
name: Build
command: |
xcodebuild build \
-scheme "MyApp" \
-destination "generic/platform=iOS" \
-derivedDataPath DerivedData
- persist_to_workspace:
root: .
paths:
- DerivedData
test:
machine: true
resource_class: your-org/mac-runner
steps:
- checkout
- attach_workspace:
at: .
- run:
name: Run tests
command: |
xcodebuild test \
-scheme "MyApp" \
-destination "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.2" \
-derivedDataPath DerivedData \
| xcbeautify
workflows:
build-test:
jobs:
- build
- test:
requires:
- build
Параллельное выполнение тестов
- run:
name: Run tests in parallel
command: |
xcodebuild test \
-scheme "MyApp" \
-destination "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.2" \
-destination "platform=iOS Simulator,name=iPhone 15,OS=17.5" \
-parallel-testing-enabled YES \
-maximum-parallel-testing-workers 4 \
-derivedDataPath DerivedData \
| xcbeautify
Разделение тестов CircleCI
Для больших наборов тестов используйте встроенное разделение тестов CircleCI для распределения тестов между параллельными раннерами:
jobs:
test:
machine: true
resource_class: your-org/mac-runner
parallelism: 3
steps:
- checkout
- run:
name: Split and run tests
command: |
# Generate test plan
TESTS=$(circleci tests glob "**/*Tests.swift" | \
circleci tests split --split-by=timings)
# Run only this container's portion of tests
xcodebuild test \
-scheme "MyApp" \
-destination "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.2" \
-only-testing:$TESTS \
| xcbeautify
8. Примеры рабочих процессов
Вот полные, готовые к продакшену примеры рабочих процессов для типичных сценариев iOS CI/CD.
Полный пайплайн сборки, тестирования и деплоя iOS
version: 2.1
jobs:
lint:
machine: true
resource_class: your-org/mac-runner
steps:
- checkout
- run:
name: Run SwiftLint
command: swiftlint lint --reporter json > swiftlint-results.json || true
- store_artifacts:
path: swiftlint-results.json
build-and-test:
machine: true
resource_class: your-org/mac-runner
steps:
- checkout
- run:
name: Select Xcode
command: sudo xcode-select -s /Applications/Xcode-16.2.app/Contents/Developer
- run:
name: Resolve dependencies
command: |
xcodebuild -resolvePackageDependencies \
-scheme "MyApp" \
-clonedSourcePackagesDirPath ~/spm-cache
- run:
name: Build and test
command: |
xcodebuild test \
-scheme "MyApp" \
-destination "platform=iOS Simulator,name=iPhone 16 Pro,OS=18.2" \
-clonedSourcePackagesDirPath ~/spm-cache \
-derivedDataPath ~/DerivedData/MyApp \
-resultBundlePath TestResults.xcresult \
-parallel-testing-enabled YES \
| xcbeautify
- store_test_results:
path: TestResults.xcresult
- store_artifacts:
path: TestResults.xcresult
deploy-testflight:
machine: true
resource_class: your-org/mac-runner
steps:
- checkout
- run:
name: Select Xcode
command: sudo xcode-select -s /Applications/Xcode-16.2.app/Contents/Developer
- run:
name: Install certificates with Fastlane Match
command: |
fastlane match appstore --readonly
- run:
name: Build and upload to TestFlight
command: |
fastlane beta
environment:
FASTLANE_USER: ${APPLE_ID}
MATCH_PASSWORD: ${MATCH_PASSWORD}
workflows:
ios-pipeline:
jobs:
- lint
- build-and-test:
requires:
- lint
- deploy-testflight:
requires:
- build-and-test
filters:
branches:
only: main
Пример интеграции с Fastlane
Если вы используете Fastlane для автоматизации сборки, вот как интегрировать его с self-hosted раннером CircleCI:
# Fastfile (fastlane/Fastfile)
default_platform(:ios)
platform :ios do
desc "Run tests"
lane :test do
scan(
scheme: "MyApp",
device: "iPhone 16 Pro",
derived_data_path: "~/DerivedData/MyApp",
result_bundle: true,
output_directory: "./test_output"
)
end
desc "Build and push to TestFlight"
lane :beta do
match(type: "appstore", readonly: true)
increment_build_number(
build_number: ENV["CIRCLE_BUILD_NUM"]
)
gym(
scheme: "MyApp",
export_method: "app-store",
derived_data_path: "~/DerivedData/MyApp"
)
pilot(skip_waiting_for_build_processing: true)
end
end
# .circleci/config.yml using Fastlane
version: 2.1
jobs:
fastlane-test:
machine: true
resource_class: your-org/mac-runner
steps:
- checkout
- run:
name: Install dependencies
command: bundle install
- run:
name: Run Fastlane tests
command: bundle exec fastlane test
- store_test_results:
path: ./test_output
- store_artifacts:
path: ./test_output
fastlane-deploy:
machine: true
resource_class: your-org/mac-runner
steps:
- checkout
- run:
name: Install dependencies
command: bundle install
- run:
name: Deploy to TestFlight
command: bundle exec fastlane beta
workflows:
ios-workflow:
jobs:
- fastlane-test
- fastlane-deploy:
requires:
- fastlane-test
filters:
branches:
only: main
9. Сравнение производительности
Вот детальное сравнение производительности и стоимости между облачными macOS ресурсами CircleCI и self-hosted Mac Mini M4 от MyRemoteMac:
Бенчмарки времени сборки
| Сценарий | Облачный macOS CircleCI | Self-hosted Mac Mini M4 | Улучшение |
|---|---|---|---|
| Чистая сборка (средний проект) | 14 мин | 5 мин | В 2.8 раза быстрее |
| Инкрементальная сборка | 14 мин (без кеша) | 1.5 мин | В 9.3 раза быстрее |
| Разрешение зависимостей SPM | 3–5 мин (загрузка каждый раз) | 5 сек (кеш на диске) | ~В 60 раз быстрее |
| Набор unit-тестов (500 тестов) | 8 мин | 2.5 мин | В 3.2 раза быстрее |
| Время ожидания в очереди | 30 с — 5 мин | 0 сек | Мгновенно |
Анализ месячных расходов
| Размер команды | Сборок/месяц | Стоимость облака CircleCI | Стоимость MyRemoteMac | Ежемесячная экономия |
|---|---|---|---|---|
| Один разработчик | 100 сборок (в среднем 10 мин) | $100/мес | $75/мес | $25/мес |
| Малая команда (5) | 500 сборок (в среднем 10 мин) | $500/мес | $75/мес | $425/мес |
| Средняя команда (15) | 1500 сборок (в среднем 10 мин) | $1,500/мес | $179/мес (M4 Pro) | $1,321/мес |
| Корпоративная (50+) | 5000+ сборок | $5,000+/мес | $358/мес (2x M4 Pro) | $4,642+/мес |
Итог: Для любой команды, выполняющей более ~75 сборок в месяц, self-hosted Mac Mini M4 окупается мгновенно. Экономия усиливается, потому что сборки на выделенном оборудовании с тёплыми кешами быстрее, что означает, что каждая сборка потребляет меньше минут изначально.
10. Устранение типичных проблем
Раннер отключается или отображается как "Offline"
Агент раннера может потерять соединение из-за сетевых проблем или аварийного завершения процесса. LaunchDaemon должен автоматически перезапустить его, но если этого не происходит:
# Check if the process is running
ps aux | grep circleci-runner
# Check the LaunchDaemon status
sudo launchctl list | grep circleci
# View the error logs
tail -50 /opt/circleci/logs/runner-stderr.log
tail -50 /opt/circleci/logs/runner.log
# Restart the service
sudo launchctl unload /Library/LaunchDaemons/com.circleci.runner.plist
sudo launchctl load /Library/LaunchDaemons/com.circleci.runner.plist
# If the token expired, generate a new one in CircleCI dashboard
# and update /opt/circleci/config/runner-agent-config.yaml
resource_class не найден или задачи зависают в очереди
Если задачи остаются в очереди с сообщением "No matching runner found", класс ресурсов в вашей конфигурации не совпадает с панелью управления:
# Verify the exact resource class name in CircleCI dashboard:
# Organization Settings > Self-Hosted Runners > Resource Classes
# The resource_class in .circleci/config.yml must match exactly:
# resource_class: your-org/mac-runner (case-sensitive!)
# Check your runner is online:
circleci runner instance list your-org/mac-runner
# Common mistakes:
# - Wrong namespace (org name vs personal namespace)
# - Typo in resource class name
# - Runner is offline or token is invalid
# - Using 'docker' executor instead of 'machine: true'
Ошибки подписи кода Xcode
Подпись кода на CI-машине требует тщательного управления Keychain. Процесс раннера может не иметь доступа к login keychain:
# Option 1: Use Fastlane Match (recommended)
# In your Fastfile:
match(type: "appstore", readonly: true)
# Option 2: Manual keychain management in your job steps
- run:
name: Setup code signing
command: |
# Decode and import the certificate
echo "$BUILD_CERTIFICATE_BASE64" | base64 --decode > /tmp/cert.p12
# Create a temporary keychain
security create-keychain -p "ci" /tmp/ci.keychain
security set-keychain-settings -lut 21600 /tmp/ci.keychain
security unlock-keychain -p "ci" /tmp/ci.keychain
# Import the certificate
security import /tmp/cert.p12 -P "$P12_PASSWORD" \
-A -t cert -f pkcs12 -k /tmp/ci.keychain
security list-keychain -d user -s /tmp/ci.keychain
# Install provisioning profile
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
echo "$PROVISIONING_PROFILE_BASE64" | base64 --decode \
> ~/Library/MobileDevice/Provisioning\ Profiles/profile.mobileprovision
Симулятор не запускается или превышает время ожидания
Симуляторы могут перейти в нерабочее состояние на долго работающих CI-машинах. Сбрасывайте их между сборками:
# Add a pre-build step to clean simulators
- run:
name: Reset simulators
command: |
xcrun simctl shutdown all 2>/dev/null || true
xcrun simctl erase all 2>/dev/null || true
# If a specific runtime is missing, reinstall it:
xcodebuild -downloadPlatform iOS
# List available simulators
xcrun simctl list devices available
Заканчивается дисковое пространство
Сборки Xcode генерируют значительные объёмы данных. Настройте автоматическую очистку на вашем раннере:
# Check available disk space
df -h /
# Clean old DerivedData
rm -rf ~/Library/Developer/Xcode/DerivedData/*
# Remove old simulator runtimes
xcrun simctl runtime delete all
# Clean Homebrew cache
brew cleanup --prune=7
# Remove old CircleCI working directories
find /opt/circleci/workdir -maxdepth 1 -mtime +3 -exec rm -rf {} +
# Set up a weekly cron job for automatic cleanup
(crontab -l 2>/dev/null; echo "0 4 * * 0 rm -rf ~/Library/Developer/Xcode/DerivedData/* && brew cleanup --prune=7") | crontab -
11. Часто задаваемые вопросы
Сколько стоит self-hosted раннер CircleCI на Mac Mini M4?
Выделенный Mac Mini M4 от MyRemoteMac стоит от $75/месяц с неограниченным временем сборки. Это значительно дешевле облачных macOS раннеров CircleCI, которые стоят примерно $0.06–$0.12 в минуту (около $300–500/месяц для активных команд). Self-hosted раннеры не имеют поминутной оплаты, поэтому ваши расходы предсказуемы вне зависимости от объёма сборок.
Можно ли использовать self-hosted раннер CircleCI для сборок iOS и macOS?
Да. Self-hosted раннер на Mac Mini M4 может выполнять любые задачи macOS, включая сборку iOS, сборку приложений macOS, тестирование Swift-пакетов, UI-тесты Xcode и автоматизацию с Fastlane. Поскольку он работает нативно на Apple Silicon, сборки быстрее, чем на эмулированных или Intel-раннерах в облаке.
В чём разница между machine runner и container runner в CircleCI?
CircleCI machine runner выполняет задачи непосредственно в операционной системе хост-машины, что необходимо для сборок macOS/iOS, требующих Xcode, симуляторов и фреймворков Apple. Container runner выполняет задачи внутри контейнеров Docker и доступен только на Linux. Для сборок Mac необходимо использовать machine runner.
Как обновлять self-hosted раннер CircleCI?
Агент machine runner CircleCI поддерживает автоматические обновления по умолчанию. Вы также можете обновить вручную, скачав последний релиз с CircleCI и заменив бинарный файл. Рекомендуется проверять обновления ежемесячно и поддерживать Xcode и macOS в актуальном состоянии.
Быстрее ли self-hosted раннер, чем облачный macOS CircleCI?
Да, обычно в 2–3 раза быстрее для чистых сборок и до 9 раз быстрее для инкрементальных сборок. Облачные macOS раннеры CircleCI используют общее оборудование Intel или M1 с эфемерными окружениями, что означает, что каждая сборка начинается с холодного кеша. Self-hosted Mac Mini M4 обладает выделенной производительностью Apple Silicon, постоянными кешами DerivedData и SPM, а также отсутствием очередей ожидания.
Можно ли запускать несколько задач CircleCI одновременно на одном Mac Mini?
Да. Mac Mini M4 имеет 10-ядерный CPU и 16 ГБ или более оперативной памяти, что позволяет комфортно выполнять 2–3 параллельных задачи сборки. Для более тяжёлых нагрузок Mac Mini M4 Pro с 14 ядрами и 24 ГБ RAM справляется с 4–6 параллельными задачами. Вы можете настроить максимальное количество параллельных задач в конфигурационном файле раннера.