Введение: Зачем нужен CI/CD для Swift проектов?
Разработка под iOS и macOS требует высокой культуры кода и надежности. Каждое изменение может сломать билд или привести к регрессиям в тестах. Ручная проверка — медленный и ненадежный процесс. Именно здесь на помощь приходит CI/CD (Continuous Integration / Continuous Deployment) — непрерывная интеграция и доставка.
GitHub Actions — это мощный и встроенный инструмент для автоматизации рабочих процессов прямо в вашем репозитории. Он позволяет автоматически собирать проект, запускать тесты, анализировать код и даже публиковать приложение в App Store или TestFlight при каждом пуше или создании Pull Request.
В этой статье мы разберем, как настроить полноценный CI/CD пайплайн для Swift проекта на GitHub Actions. Вы узнаете, как создать workflow, настроить сборку, прогон тестов, линтинг и деплой. Все примеры кода готовы к использованию.
Основная часть
1. Основы GitHub Actions для Swift
GitHub Actions работает на основе YAML-файлов, которые хранятся в директории .github/workflows/. Каждый файл описывает один или несколько workflow (рабочих процессов). Для Swift проекта нам потребуется runner с macOS, так как сборка iOS/macOS приложений возможна только на этой платформе.
Базовый 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: swift build
- name: Run tests
run: swift test
Разберем ключевые моменты:
- on — триггеры: запуск на push и pull request в main.
- runs-on: macos-latest — используем последнюю версию macOS для runner.
- actions/checkout — стандартный action для клонирования репозитория.
- swift build и swift test — команды Swift Package Manager.
Этот минимальный пайплайн уже обеспечивает базовую проверку. Но для реального iOS/macOS приложения этого недостаточно — нужно настроить Xcode, симуляторы и зависимости.
2. Настройка сборки и тестов для iOS/macOS приложения
Если ваш проект использует Xcode (например, .xcworkspace или .xcodeproj), команда swift build не подойдет. Вместо этого используем xcodebuild. Также нужно указать схему и destination (например, симулятор iPhone).
Пример workflow для iOS приложения:
name: iOS CI
on:
push:
branches: [ "develop", "main" ]
pull_request:
branches: [ "develop", "main" ]
jobs:
test:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Select Xcode version
run: sudo xcode-select -s /Applications/Xcode_15.2.app
- name: Install CocoaPods (если используете)
run: pod install
- name: Build and Test
run: |
xcodebuild clean test \
-workspace YourApp.xcworkspace \
-scheme "YourApp Scheme" \
-destination 'platform=iOS Simulator,name=iPhone 15,OS=17.2' \
-resultBundlePath TestResults
env:
DEVELOPER_DIR: /Applications/Xcode_15.2.app/Contents/Developer
- name: Upload test results
if: always()
uses: actions/upload-artifact@v4
with:
name: test-results
path: TestResults.xcresult
Важные детали:
- macos-14 — используем macOS 14 Sonoma с Xcode 15.2.
- xcode-select — явно указываем версию Xcode, чтобы избежать несовместимости.
- resultBundlePath — сохраняем результаты тестов как артефакт для дальнейшего анализа.
- upload-artifact — загружаем отчеты о тестах, даже если они упали (
if: always()).
Для macOS приложения destination будет другим:
-destination 'platform=macOS,arch=x86_64'
3. Добавление линтинга и статического анализа
Качество кода — залог успеха. Добавим в пайплайн проверку стиля с помощью SwiftLint и статический анализ с помощью SwiftFormat или собственных скриптов.
Пример шага для SwiftLint:
- name: Run SwiftLint
run: |
brew install swiftlint
swiftlint --strict
Чтобы не устанавливать SwiftLint каждый раз, можно использовать готовый action:
- name: SwiftLint
uses: norio-nomura/action-swiftlint@3.2.1
with:
args: --strict
Также полезно добавить проверку на наличие TODO и FIXME комментариев:
- name: Check for TODOs
run: |
if grep -r "TODO" --include="*.swift" .; then
echo "Found TODO comments"
exit 1
fi
Все эти шаги помогут поддерживать код в чистоте и предотвращать попадание технического долга в основную ветку.
4. Автоматический деплой в TestFlight или App Store
Финальный этап CI/CD — автоматическая доставка. Для Swift проектов это обычно публикация в TestFlight (для beta-тестеров) или в App Store. GitHub Actions позволяет это сделать с помощью сторонних actions или через fastlane.
Пример с использованием fastlane (предварительно настройте Fastfile):
- name: Deploy to TestFlight
if: github.ref == 'refs/heads/main'
run: |
bundle exec fastlane beta
env:
APP_STORE_CONNECT_API_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY }}
APP_STORE_CONNECT_API_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ID }}
APP_STORE_CONNECT_API_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_ISSUER_ID }}
Важно: Все секреты (API ключи, пароли) храните в Settings > Secrets and variables > Actions вашего репозитория. Никогда не вставляйте их в код!
Альтернатива — использование action apple-actions/upload-testflight-build:
- name: Upload to TestFlight
uses: apple-actions/upload-testflight-build@v1
with:
app