ANTIGRAVITY LABJP
Articles/App Development
App Development/2026-05-06Intermediate

Automate Unity CI/CD with Antigravity and GitHub Actions: A Practical Guide

Set up a complete Unity CI/CD pipeline using GameCI, GitHub Actions, and Antigravity — from automated testing to TestFlight uploads. A practical guide for indie developers who want to stop building manually.

Unity7CI/CD17GitHub Actions5GameCIAntigravity338automation84FastlaneTestFlight2

If you're an indie developer working on a Unity project, you've probably felt it: building for iOS and Android manually eats up half your day, and the App Store submission process is tedious enough to mess up even when you've done it dozens of times.

The good news is that GitHub Actions combined with GameCI can fully automate that pipeline — from the moment you push code, right through to a TestFlight build ready for testers. And writing the workflow YAML? That's exactly where Antigravity shines.

Why GitHub Actions + GameCI Is the Right Choice for Indie Developers

There are a few ways to automate Unity builds, but the GitHub Actions + GameCI combination stands out for indie developers for specific reasons.

Cost: GitHub Actions gives you 2,000 free Linux runner minutes per month. Most Unity test runs and basic builds land in the 15–30 minute range, so you can comfortably run 60–100 builds per month without paying anything. macOS runners (required for iOS builds) cost 10x more, but limiting those to main branch merges only keeps costs manageable.

Simplicity: GameCI provides Docker images specifically built for Unity. It handles Unity installation and license activation automatically — you don't need to write your own Dockerfile or figure out how to install Unity headlessly on a CI server.

Antigravity compatibility: YAML syntax errors, mismatched secret names, and Unity-specific configuration mistakes are exactly the kind of thing Antigravity catches quickly. Paste your error log into the chat and you get a targeted fix, not a documentation link to scroll through.

For deeper coverage of CI/CD patterns with Antigravity, see the Advanced GitHub Actions CI/CD Pipeline with Antigravity guide.

A Basic Workflow You Can Set Up in 30 Minutes

Start with the simplest useful thing: automatically running Unity's PlayMode tests on every push. Tell Antigravity your project structure and ask it to generate a GameCI-based Unity test workflow, and you'll get something close to this:

# .github/workflows/unity-ci.yml
name: Unity CI
 
on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main]
 
jobs:
  test:
    name: Unity Test Runner
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          lfs: true
 
      - name: Cache Unity Library
        uses: actions/cache@v4
        with:
          path: Library
          key: Library-${{ hashFiles('Assets/**', 'Packages/**', 'ProjectSettings/**') }}
          restore-keys: |
            Library-
 
      - name: Run PlayMode Tests
        uses: game-ci/unity-test-runner@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
          UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
          UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
        with:
          projectPath: .
          testMode: PlayMode
          artifactsPath: test-results
          githubToken: ${{ secrets.GITHUB_TOKEN }}
          checkName: Unity PlayMode Test Results
 
      - name: Upload Test Results
        uses: actions/upload-artifact@v4
        if: always()
        with:
          name: test-results-${{ github.run_number }}
          path: test-results

The first place most people get stuck is the UNITY_LICENSE secret. Ask Antigravity "how do I get the value for the UNITY_LICENSE secret?" and it will walk you through the GameCI activation flow — generating a license request file locally, activating it through Unity, and Base64-encoding the result for the secret.

How to Use Antigravity Effectively When Writing Workflows

After setting up several of these pipelines, a few patterns make a real difference.

Paste error logs directly: When a GitHub Actions run fails, copy the entire error output into Antigravity. It's good at distinguishing between YAML indentation issues, wrong secret names, and GameCI version mismatches — and it tells you exactly which line to fix. Don't summarize the error; paste it verbatim.

Add features incrementally: Build the pipeline in stages — tests first, then builds, then deployment. If you try to write everything at once and something breaks, it's hard to know where the problem is. Ask Antigravity to add one stage at a time: "The test step is working. Now add an Android build job."

Include your ProjectSettings in the context: Paste your directory structure or the contents of ProjectSettings/ProjectSettings.asset into the chat. Antigravity can then generate YAML that accounts for your actual Bundle ID, minimum SDK version, and build targets — instead of producing generic templates you'd need to manually adjust.

iOS Builds and Cost Management

iOS builds require macOS runners, which are significantly more expensive. The practical approach for indie developers is to be selective about when macOS runners run.

Key strategies for managing costs:

  • Only trigger iOS builds on pushes to main, not on pull requests
  • Use needs: test so the build job only runs if tests pass
  • Cache the Unity Library directory to avoid full rebuilds every time
  build-ios:
    name: iOS Build
    runs-on: macos-latest
    needs: test                         # Only runs if test job succeeds
    if: github.ref == 'refs/heads/main' # Main branch only
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          lfs: true
 
      - name: Cache Unity Library (iOS)
        uses: actions/cache@v4
        with:
          path: Library
          key: Library-iOS-${{ hashFiles('Assets/**', 'Packages/**', 'ProjectSettings/**') }}
          restore-keys: |
            Library-iOS-
            Library-
 
      - name: Build iOS Xcode Project
        uses: game-ci/unity-builder@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
          UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
          UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
        with:
          targetPlatform: iOS
          buildName: MyGame
          buildsPath: build
 
      - name: Upload iOS Build Artifact
        uses: actions/upload-artifact@v4
        with:
          name: ios-build-${{ github.run_number }}
          path: build/iOS

Converting the generated Xcode project to an IPA and signing it for the App Store requires additional codesigning configuration. The Fastlane × Antigravity App Store Automation guide covers that in detail.

Uploading to TestFlight with Fastlane

Once GameCI produces an Xcode project, you can pipe it straight to TestFlight using Fastlane with an App Store Connect API key — no password authentication needed.

      - name: Sign and Upload to TestFlight
        env:
          ASC_KEY_CONTENT: ${{ secrets.ASC_KEY_CONTENT }}
          ASC_KEY_ID: ${{ secrets.ASC_KEY_ID }}
          ASC_ISSUER_ID: ${{ secrets.ASC_ISSUER_ID }}
          CERTIFICATE_P12: ${{ secrets.CERTIFICATE_P12 }}
          CERTIFICATE_PASSWORD: ${{ secrets.CERTIFICATE_PASSWORD }}
          PROVISIONING_PROFILE: ${{ secrets.PROVISIONING_PROFILE }}
        run: |
          gem install fastlane --no-document
          fastlane ios beta

The corresponding Fastfile can be generated by asking Antigravity: "Write a Fastfile that builds an IPA from a Unity-generated Xcode project and uploads it to TestFlight using an App Store Connect API key." It also outputs the list of secrets you'll need to add to GitHub — which is useful when you're setting this up for the first time.

Adding an Android Build Job

Adding Android to the same workflow is straightforward since Android builds run on Linux runners (no extra cost). The key difference is that Android requires a keystore for signing, which you'll store as a base64-encoded GitHub Secret.

  build-android:
    name: Android Build
    runs-on: ubuntu-latest
    needs: test
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4
        with:
          lfs: true
 
      - name: Cache Unity Library (Android)
        uses: actions/cache@v4
        with:
          path: Library
          key: Library-Android-${{ hashFiles('Assets/**', 'Packages/**', 'ProjectSettings/**') }}
          restore-keys: |
            Library-Android-
            Library-
 
      - name: Build Android APK/AAB
        uses: game-ci/unity-builder@v4
        env:
          UNITY_LICENSE: ${{ secrets.UNITY_LICENSE }}
          UNITY_EMAIL: ${{ secrets.UNITY_EMAIL }}
          UNITY_PASSWORD: ${{ secrets.UNITY_PASSWORD }}
          ANDROID_KEYSTORE_NAME: mygame.keystore
          ANDROID_KEYSTORE_BASE64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
          ANDROID_KEYSTORE_PASS: ${{ secrets.ANDROID_KEYSTORE_PASS }}
          ANDROID_KEYALIAS_NAME: ${{ secrets.ANDROID_KEYALIAS_NAME }}
          ANDROID_KEYALIAS_PASS: ${{ secrets.ANDROID_KEYALIAS_PASS }}
        with:
          targetPlatform: Android
          androidAppBundle: true   # Outputs .aab for Play Store
          androidKeystoreName: mygame.keystore
          androidKeystoreBase64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }}
          androidKeystorePass: ${{ secrets.ANDROID_KEYSTORE_PASS }}
          androidKeyaliasName: ${{ secrets.ANDROID_KEYALIAS_NAME }}
          androidKeyaliasPass: ${{ secrets.ANDROID_KEYALIAS_PASS }}
 
      - name: Upload Android Build
        uses: actions/upload-artifact@v4
        with:
          name: android-build-${{ github.run_number }}
          path: build/Android

Ask Antigravity "how do I create an Android keystore and base64-encode it for a GitHub Secret?" and it will give you the exact keytool command and the one-liner to encode the resulting file. This is the kind of multi-step setup where having Antigravity walk you through it in sequence saves a lot of back-and-forth with scattered documentation.

One thing worth knowing: if your game uses Android App Bundles (.aab) for Play Store submission rather than APKs, set androidAppBundle: true as shown above. Google Play now requires AAB for new apps, and Antigravity will flag this if you ask it to review your workflow for Play Store compatibility.

What Changes When Builds Are Automated

The most noticeable shift after setting up this pipeline isn't the time saved on individual builds — it's that the waiting becomes productive. Before, a local Unity build meant sitting there half-watching the editor. With CI running in the background, you push the code and immediately go back to working on the next thing in Antigravity.

If you're starting from scratch, just implement the test-only workflow first. Builds and deployment can come later. Even just having tests run automatically on every push eliminates a whole category of "I forgot to test this before committing" bugs.

For more on speeding up your Unity development workflow with Antigravity, see the Unity × Antigravity Fast Development guide.

Share

Thank You for Reading

Antigravity Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

App Dev2026-07-03
When CI Passes but App Review Rejects Your Screenshots — Field Notes on Measuring the Freshness of Your Validation Rules
Store asset validation can pass in CI and still get rejected in review, because the rules themselves go stale. Move store specs into a freshness-dated contract file, then add locale overflow checks and perceptual diffs.
App Dev2026-03-22
Build an Auto-Monetization CI/CD Pipeline with Antigravity AI Agents — From Code Generation to Billing
Integrate Antigravity's AI agents into a CI/CD pipeline that automates content generation, deployment to Cloudflare Workers, Stripe billing monitoring, and performance optimization end-to-end.
Integrations2026-03-10
GitHub Actions × Antigravity CI/CD Automation Guide — Build and Manage Pipelines with AI
Learn how to build CI/CD pipelines with Antigravity and GitHub Actions. From workflow generation to automated deployment.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →