Введение: Почему CI/CD критичен для Swift-разработки
В современной iOS/macOS разработке ручная сборка и тестирование — путь к ошибкам и потере времени. Каждый коммит может сломать билд, а проверка на реальных устройствах требует физического доступа. CI/CD (Continuous Integration / Continuous Deployment) решает эти проблемы, автоматизируя сборку, тестирование и деплой приложений.
GitHub Actions — встроенный инструмент CI/CD, идеально подходящий для Swift-проектов, размещённых на GitHub. Он позволяет бесплатно (до 2000 минут в месяц для публичных репозиториев) запускать рабочие процессы в облаке. В этой статье мы разберём полный цикл: от базовой конфигурации до деплоя в App Store.
Для кого эта статья? Для iOS/macOS разработчиков, которые хотят автоматизировать рутину и ускорить релизный цикл. Даже если вы новичок в DevOps — пошаговые инструкции и примеры кода помогут разобраться.
1. Основы GitHub Actions для Swift
1.1. Структура workflow
GitHub Actions использует YAML-файлы, которые хранятся в .github/workflows/. Каждый файл — это отдельный workflow (процесс), который запускается по триггеру (пуш, pull request, расписание).
Базовый workflow для Swift-проекта выглядит так:
name: Swift CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build_and_test:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: xcodebuild build -project MyApp.xcodeproj -scheme MyApp -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.2'
- name: Test
run: xcodebuild test -project MyApp.xcodeproj -scheme MyApp -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 15,OS=17.2'
Ключевые моменты:
macos-latest— runner с macOS, необходимым для Xcode и Swift.actions/checkout@v4— клонирование репозитория.xcodebuild— команда для сборки и тестирования.- Параметр
destinationуказывает симулятор (замените на свою версию iOS).
1.2. Кэширование зависимостей
Swift Package Manager (SPM) — стандартный менеджер зависимостей. Чтобы не скачивать пакеты при каждом коммите, используйте кэширование:
steps:
- uses: actions/cache@v3
with:
path: ~/Library/Developer/Xcode/DerivedData
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
restore-keys: |
${{ runner.os }}-spm-
- run: swift build
Это сокращает время сборки на 40–60%.
2. Настройка тестирования и линтинга
2.1. Unit-тесты и UI-тесты
Для iOS/macOS проектов критично запускать тесты в симуляторе. Убедитесь, что в схеме Xcode включены тесты. Пример для macOS:
jobs:
test_macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- name: Run macOS tests
run: xcodebuild test -project MyApp.xcodeproj -scheme MyApp -sdk macosx -destination 'platform=macOS,arch=x86_64'
Для iOS добавьте -destination 'platform=iOS Simulator,name=iPhone 15'. Важно: названия симуляторов меняются с версиями Xcode — используйте xcrun simctl list для проверки доступных.
2.2. Статический анализ (SwiftLint)
Поддерживайте качество кода с помощью SwiftLint. Добавьте шаг в workflow:
- name: SwiftLint
run: |
brew install swiftlint
swiftlint --strict
Флаг --strict превращает предупреждения в ошибки — workflow упадёт, если код не соответствует правилам. Настройте .swiftlint.yml в корне проекта.
3. Сборка и подпись для деплоя
3.1. Управление сертификатами и профилями
Для сборки IPA/App Bundle нужны сертификаты и provisioning profiles. GitHub Actions не хранит их безопасно, поэтому используйте секреты репозитория (Settings → Secrets and variables → Actions).
Рекомендуемый подход:
- Экспортируйте сертификат (
.p12) и профиль (.mobileprovision). - Закодируйте в base64:
base64 -i cert.p12 -o cert.txt. - Сохраните в секретах:
CERT_BASE64,PROVISION_BASE64.
В workflow добавьте шаг для импорта:
- name: Install certificates
run: |
echo "${{ secrets.CERT_BASE64 }}" | base64 --decode > cert.p12
security create-keychain -p temp temp.keychain
security import cert.p12 -k temp.keychain -P "${{ secrets.CERT_PASSWORD }}" -T /usr/bin/codesign
echo "${{ secrets.PROVISION_BASE64 }}" | base64 --decode > ~/Library/MobileDevice/Provisioning\ Profiles/profile.mobileprovision
Безопасность: никогда не храните пароли в YAML — используйте только секреты.
3.2. Сборка архива и экспорт IPA
После подписи соберите архив:
- name: Archive
run: |
xcodebuild archive -project MyApp.xcodeproj -scheme MyApp -archivePath MyApp.xcarchive -configuration Release
xcodebuild -exportArchive -archivePath MyApp.xcarchive -exportPath . -exportOptionsPlist ExportOptions.plist
Файл ExportOptions.plist должен быть в репозитории (для App Store или Ad Hoc). Пример для App Store:
<?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"&