From the Blog

← All posts

← Back to Blog

CI/CD Pipeline for Indie Games: Ship in 4 Stages, Not 40

CI/CD Pipeline for Indie Games: Ship in 4 Stages, Not 40

Enterprise CI/CD configs average 12–18 stages when teams copy them from SaaS playbooks — and every one of those extra stages costs you time you don't have before a platform submission deadline.

TL;DR:

  • A 4-stage CI/CD pipeline for indie games (build → test → package → deploy) covers everything a solo or small studio actually needs.
  • Large game asset handling is the real bottleneck — cheap Git LFS + artifact caching fixes 80% of slow pipelines.
  • You can wire the full pipeline this weekend using GitHub Actions or GitLab CI with the config blocks in this post.

---

Why Enterprise CI/CD Breaks Indie Games

Enterprise pipelines were designed for teams where a broken staging deploy costs $50K in lost revenue per hour. That's not your situation. Your situation is: one bad APK build and the Google Play review clock resets. One missing .pdb file and your Steam crash reports are unreadable.

The mismatch is structural. Enterprise setups often include:

  • Separate lint, SAST, DAST, SCA, and compliance scan stages
  • Multiple approval gates requiring human sign-off
  • Blue-green deploy targets with rollback orchestration
  • Artifact promotion between five or more environments

None of that maps to Unity or Godot builds targeting Steam, iOS, and Android simultaneously. It maps to a Java microservice fleet at a fintech. Copying it for indie game dev doesn't make your pipeline safer — it makes it slower and harder to debug at 11pm before a submission window closes.

In 2026, a typical GitHub Actions bill for an over-engineered Unity pipeline runs $40–$80/month for a solo dev — mostly wasted on redundant jobs that could be collapsed into one. The stripped-down pipeline below runs the same project for under $8/month on the same runner tier.

---

The Four-Stage CI/CD Pipeline for Indie Games

Four stages. Nothing more until you actually need more.

push → BUILD → TEST → PACKAGE → DEPLOY

Stage 1: Build

Compile the project for every target platform in parallel jobs, not sequential steps. One job per platform (Android, iOS, Windows/Steam, WebGL). Cache the Library folder aggressively — Unity's Library folder re-import on a cold runner is the single biggest time sink, often 8–12 minutes alone on a mid-size project.

# .github/workflows/game-ci.yml

jobs:

build-android:

runs-on: ubuntu-latest

steps:

- uses: actions/checkout@v4

with:

lfs: true

- uses: actions/cache@v4

with:

path: Library

key: Library-Android-${{ hashFiles('Assets/', 'Packages/', 'ProjectSettings/**') }}

- uses: game-ci/unity-builder@v4

with:

targetPlatform: Android

unityVersion: 6000.0.25f1

Parallel jobs mean your total build time for three platforms stays under 6 minutes instead of stacking sequentially to 18+.

Stage 2: Test

Run only the tests that catch real launch-killers:

  • Play Mode tests — catch gameplay logic regressions
  • Editor Mode tests — catch serialization and data pipeline breaks
  • Build integrity check — confirm the artifact is a valid binary, not a 0-byte ghost file

Skip performance benchmarks in CI. They're noisy on shared runners and belong in a dedicated profiling session, not a commit gate.

  test:

needs: build-android

runs-on: ubuntu-latest

steps:

- uses: game-ci/unity-test-runner@v4

with:

testMode: all

unityVersion: 6000.0.25f1

Stage 3: Package

Bundle platform-specific artifacts — signed APK, notarized macOS build, Steam depot manifest. This is where most indie pipelines fall apart: signing credentials get hardcoded, or the step runs locally on a dev machine and never makes it into CI.

Store every secret (keystore passwords, Apple API keys, Steam build credentials) in GitHub Secrets or GitLab CI Variables. Zero secrets in the repo. If you're also automating your SaaS marketing platform releases alongside game builds, the same secrets management pattern applies.

Stage 4: Deploy

Push to distribution. For most indie projects, that's three targets:

  • Firebase App Distribution (internal playtesting, Android)
  • TestFlight (iOS beta, via fastlane pilot)
  • SteamPipe (Steam depot upload via steamcmd)

One trigger, one push, all three destinations. The entire four-stage run — cold cache aside — should complete in under 15 minutes.

---

Automated Build Targets: Mobile, Steam, Console in One CI/CD Pipeline Push

The goal is one git push that hands you ready-to-submit binaries for every platform. Here's how each target wires up:

Mobile (Android + iOS)

Use GameCI — it's the fastest path to Unity builds on GitHub Actions in 2026. For iOS, you need a macOS runner (costs more, worth it). Fastlane handles the App Store Connect upload.

  deploy-ios:

runs-on: macos-latest

steps:

- uses: game-ci/unity-builder@v4

with:

targetPlatform: iOS

- run: fastlane pilot upload --ipa build/iOS/build.ipa

env:

APP_STORE_CONNECT_API_KEY: ${{ secrets.ASC_API_KEY }}

Steam

steamcmd is free and scriptable. Create a depot build script (app_build.vdf) and call it from your CI job:
  deploy-steam:

runs-on: ubuntu-latest

steps:

- run: |

steamcmd +login $STEAM_USER $STEAM_PASS \

+run_app_build build/steam/app_build.vdf +quit

env:

STEAM_USER: ${{ secrets.STEAM_USERNAME }}

STEAM_PASS: ${{ secrets.STEAM_PASSWORD }}

Console

Nintendo Switch (via NintendoSDK) and PlayStation require licensed devkits and can't run on shared public runners. Use a self-hosted runner on a machine with the SDK installed, and add a runs-on: self-hosted tag to the job. The rest of the pipeline stays identical.

---

Cheap Tooling That Handles Large Game Assets

Large game assets — 4K textures, audio banks, video cutscenes — are where CI pipelines choke and costs spike. A 2 GB repo on a standard GitHub Actions runner adds 3–5 minutes just on checkout, every single run.

Fix it with three tools:

1. Git LFS

Store .psd, .wav, .mp4, .fbx, and compressed texture files in LFS. Keep only code and small text-based assets in the main tree. Setup is one command:

git lfs track ".psd" ".wav" ".mp4" ".fbx"

2. Unity Accelerator (self-hosted)

The Unity Accelerator acts as a local cache server for the Library folder. On a home server or cheap VPS ($5–$10/month on Hetzner), it cuts Library re-import time from 10 minutes to under 90 seconds for teams sharing the same machine pool.

3. GitHub Actions Cache with a scoped key

The cache block shown in Stage 1 above scopes the key to the actual changed files (Assets/, Packages/, ProjectSettings/). A cache hit skips the re-import entirely — worth $15–$20/month** in saved compute minutes on mid-size Unity projects.

If you're already using AI tooling to speed up other parts of your dev workflow, the post on automating changelog updates from git commits pairs well here — your CI pipeline's merge commits can feed directly into automated release notes without extra tooling.

---

Ship a CI/CD Pipeline for Indie Games This Weekend: Step-by-Step

Here's the exact sequence. Clear a Saturday morning.

Step 1 — Scaffold the workflow file (30 min)

Create .github/workflows/game-ci.yml. Copy the build job block from Stage 1 above. Target one platform first — Android or Windows. Confirm the job runs green before adding more targets.

Step 2 — Add LFS and caching (20 min)

Run git lfs install and track your binary asset types. Add the actions/cache block with the Library key. Push a commit and confirm the cache saves on first run, hits on second.

Step 3 — Wire the test stage (30 min)

Add the unity-test-runner job. Run it against your existing test suite. If you have zero tests, write one Play Mode smoke test that loads your main scene and confirms no null reference exceptions fire on Start.

Step 4 — Set up secrets (15 min)

Add your signing credentials to GitHub Secrets. Never commit a keystore or API key to the repo. Rotate any credentials that are currently in plaintext in your project files before you do anything else.

Step 5 — Add package + deploy jobs (45 min)

Copy the deploy blocks for your target platforms. For Steam, create the app_build.vdf file pointing at your build output directory. For mobile, configure Fastlane with your App Store Connect and Google Play credentials.

Step 6 — Time a full run (10 min)

Push a dummy commit and watch the Actions tab. If the full pipeline exceeds 15 minutes, check for: cold Library cache (expected on first run), sequential jobs that could be parallelized, or LFS not configured on a large asset type.

Total setup time: ~2.5 hours. After that, every push either gives you a green set of submission-ready builds or a specific failing job to fix — no more mystery builds from a local machine at 2am.

For teams also shipping mobile apps alongside game titles, the same pipeline structure applies. You might find it useful to look at how AI feedback analysis can build your sprint backlog once the pipeline is running — post-launch crash data and review signals become much easier to triage when builds are automated and traceable to specific commits.

And once your game is live, your CI pipeline can feed directly into your marketing cycle. The same git history that triggers your builds can also power automated player-facing release notes — ship a changelog with every build, automatically.

---

If you're building a game or mobile app and want a second set of eyes on your pipeline config, message Boyd Tiffin directly at /contact. Describe what you're building and where the pipeline is breaking — he'll take a look.

Like what you read?

Get in touch, we’d love to hear from you.

Get in Touch