Налаштування CI/CD для мобільного додатку через GitHub Actions
GitHub Actions—найбільш гнучкий варіант CI/CD для мобільної розробки за умови, що репозиторій уже на GitHub. Для iOS потрібен macOS-раннер, для Android—Linux. Обидва доступні в хмарі GitHub або як self-hosted.
iOS: головна проблема—раннери та кодування підписей
GitHub надає безплатні macOS-раннери (macos-14, Apple Silicon). Хвилини macOS тарифіруються в 10 разів дорожче ніж Linux—активна розробка швидко вичерпує безплатний ліміт. Self-hosted macOS-раннер на Mac mini в офісі вирішує проблему вартості, але добавляє адміністрування.
Кодування підписів на GitHub Actions—через fastlane match або імпорт сертифіката з secrets:
- name: Import certificate
run: |
echo "${{ secrets.DISTRIBUTION_CERTIFICATE_P12 }}" | base64 --decode > cert.p12
security create-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" build.keychain
security import cert.p12 -k build.keychain -P "${{ secrets.CERT_PASSWORD }}" -T /usr/bin/codesign
security set-keychain-settings -lut 21600 build.keychain
security unlock-keychain -p "${{ secrets.KEYCHAIN_PASSWORD }}" build.keychain
security list-keychains -d user -s build.keychain login.keychain
Це ручний підхід—працює, але крихкий при оновленні сертифіката. У продакшені краще використовувати fastlane match readonly: true з MATCH_PASSWORD у secrets.
Повний iOS workflow
name: iOS CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
test:
runs-on: macos-14
steps:
- uses: actions/checkout@v4
- name: Select Xcode
run: sudo xcode-select -s /Applications/Xcode_16.0.app
- name: Cache CocoaPods
uses: actions/cache@v4
with:
path: Pods
key: ${{ runner.os }}-pods-${{ hashFiles('Podfile.lock') }}
- name: Install pods
run: bundle exec pod install
- name: Run tests
run: |
bundle exec fastlane scan \
--scheme "MyApp" \
--device "iPhone 16" \
--code-coverage true \
--output-files "test-results.xml"
- name: Upload test results
uses: actions/upload-artifact@v4
with:
name: test-results
path: test-results.xml
if-no-files-found: error
deploy-beta:
needs: test
runs-on: macos-14
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Setup Ruby
uses: ruby/setup-ruby@v1
with:
bundler-cache: true
- name: Deploy to TestFlight
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
APP_STORE_CONNECT_API_KEY: ${{ secrets.ASC_API_KEY }}
run: bundle exec fastlane release
needs: test—deploy-beta запускається тільки якщо тести пройшли. if: github.ref == 'refs/heads/main'—деплой тільки з main.
Android: значно простіше
jobs:
android-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
- name: Build and test
run: ./gradlew test assembleRelease
- name: Sign APK
uses: r0adkll/sign-android-release@v1
with:
releaseDirectory: app/build/outputs/apk/release
signingKeyBase64: ${{ secrets.SIGNING_KEY }}
alias: ${{ secrets.KEY_ALIAS }}
keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }}
keyPassword: ${{ secrets.KEY_PASSWORD }}
- name: Upload to Firebase App Distribution
uses: wzieba/Firebase-Distribution-Github-Action@v1
with:
appId: ${{ secrets.FIREBASE_APP_ID }}
token: ${{ secrets.FIREBASE_TOKEN }}
groups: qa-team
file: app/build/outputs/apk/release/app-release-signed.apk
Linux-раннер для Android—безплатно без обмеження хвилин (на публічних репо). Gradle-кеш економить 3–5 хвилин на прогон.
Матриця пристроїв для тестів
strategy:
matrix:
device: ["iPhone 15", "iPhone SE (3rd generation)", "iPad Pro (12.9-inch)"]
jobs:
test:
runs-on: macos-14
steps:
- name: Run tests on ${{ matrix.device }}
run: xcodebuild test -scheme MyApp -destination "platform=iOS Simulator,name=${{ matrix.device }}"
Запускає тести паралельно на трьох пристроях—загальний час не збільшується, покриття розширюється.
Часова шкала
Базові workflows (test + build) для iOS та Android: 3–5 днів. Повна конфігурація з кодуванням підписей, матрицею пристроїв, кешуванням, дистрибуцією TestFlight/Firebase: 1–2 тижні. Стоимость рассчитывается индивидуально.







