Setting up CI/CD for a mobile application via GitHub Actions

NOVASOLUTIONS.TECHNOLOGY is engaged in the development, support and maintenance of iOS, Android, PWA mobile applications. We have extensive experience and expertise in publishing mobile applications in popular markets like Google Play, App Store, Amazon, AppGallery and others.
Development and support of all types of mobile applications:
Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Showing 1 of 1 servicesAll 1735 services
Setting up CI/CD for a mobile application via GitHub Actions
Medium
~2-3 business days
FAQ
Our competencies:
Development stages
Latest works
  • image_mobile-applications_feedme_467_0.webp
    Development of a mobile application for FEEDME
    756
  • image_mobile-applications_xoomer_471_0.webp
    Development of a mobile application for XOOMER
    624
  • image_mobile-applications_rhl_428_0.webp
    Development of a mobile application for RHL
    1052
  • image_mobile-applications_zippy_411_0.webp
    Development of a mobile application for ZIPPY
    947
  • image_mobile-applications_affhome_429_0.webp
    Development of a mobile application for Affhome
    862
  • image_mobile-applications_flavors_409_0.webp
    Development of a mobile application for the FLAVORS company
    445

CI/CD Setup for Mobile Applications via GitHub Actions

GitHub Actions is the most flexible CI/CD option for mobile development when the repository is already on GitHub. iOS requires macOS runner, Android requires Linux. Both available in GitHub cloud or as self-hosted.

iOS: Main Issue—Runners and Code Signing

GitHub provides free macOS runners (macos-14, Apple Silicon). macOS minutes are 10x more expensive than Linux—active development exhausts free limits quickly. Self-hosted macOS runner on Mac mini in the office solves cost but adds administration.

Code signing on GitHub Actions—via fastlane match or importing certificate from 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

This is manual approach—works, but fragile when updating certificate. In production better use fastlane match readonly: true with MATCH_PASSWORD in secrets.

Complete 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 runs only if tests pass. if: github.ref == 'refs/heads/main'—deploy only from main.

Android: Much Simpler

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 runner for Android—free without minute limits (on public repos). Gradle cache saves 3–5 minutes per run.

Device Test Matrix

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 }}"

Runs tests in parallel on three devices—total time doesn't increase, coverage expands.

Timeline

Basic workflows (test + build) for iOS and Android: 3–5 days. Full configuration with code signing, device matrix, caching, TestFlight/Firebase deployment: 1–2 weeks. Cost calculated individually.