Keel

How do you release a mobile app with Expo EAS from CI?

By the Keel team · Last checked · 4 min read

Short answer

To release a mobile app with Expo EAS from CI, run one build locally first so EAS sets up credentials, store an EXPO_TOKEN in your CI secrets, then have CI run eas build with the non-interactive flag and auto-submit to TestFlight and Google Play. Use EAS Update for JavaScript-only fixes, guarded by runtime versions so an update never lands on an incompatible build.

  • 7 days

    Length of Apple's phased release to automatic-update users

    Source: App Store Connect Help, Oct 2026

  • 1%

    Share of automatic-update users who get a phased release on day one

    Source: App Store Connect Help, Oct 2026

What do you need before running Expo EAS builds from CI?

Before running Expo EAS builds from CI, run one build on your own machine so EAS can create eas.json and set up signing credentials, then create an Expo access token and store it as EXPO_TOKEN in your CI secrets.

Expo's docs say this first local build is what lets later CI runs work without prompts.

  • An eas.json with build profiles, for example preview and production.
  • Signing credentials managed by EAS, or your own, set up once.
  • An EXPO_TOKEN secret in GitHub Actions or your CI tool.
  • Store credentials for submission: an App Store Connect API key and a Google Play service account.

How do you trigger an Expo EAS build from GitHub Actions?

Trigger an Expo EAS build from GitHub Actions by setting up Expo with the expo/expo-github-action action and running eas build with the --non-interactive flag, so CI never waits for a prompt.

Add --no-wait if you only want CI to queue the build rather than wait for it.

name: eas-build
on:
  workflow_dispatch:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 20
      - run: npm ci
      - uses: expo/expo-github-action@v8
        with:
          eas-version: latest
          token: ${{ secrets.EXPO_TOKEN }}
      - run: eas build --platform all --profile production --non-interactive --no-wait

Expo notes that with --no-wait, CI reports success once the build is queued, and you are not paying for CI minutes while EAS builds. Remove it if a later step needs the finished build.

How do you submit Expo builds to the App Store and Google Play automatically?

Submit Expo builds automatically by adding --auto-submit to the build command, which hands each finished build to EAS Submit using the matching submission profile.

On iOS the build goes to TestFlight, not straight to App Store review, so a person still decides when to release.

  • Use a separate submission profile per environment with --auto-submit-with-profile if names differ.
  • On Android, choose a testing track first, such as internal testing, before promoting to production.
  • On iOS, use a phased release: Apple rolls an update out to automatic-update users over 7 days, from 1% on day one to 100% on day seven, and lets you pause.

When should you use EAS Update instead of a new store build?

Use EAS Update for changes to JavaScript and assets only, and a new store build whenever native code changes, such as adding a library with native parts or changing permissions.

An update that depends on native code the installed build lacks can fail on users' phones.

Expo guards against this with runtime versions, which tie each update to the builds it can run on. The fingerprint policy changes the runtime version whenever anything that may affect native code changes, which makes incompatible updates very unlikely at the cost of more builds. The appVersion policy is simpler but relies on you bumping the version whenever native code changes.

How do you keep a mobile release pipeline safe for a small team?

Keep a mobile release pipeline safe by making every release go through the same steps: tests, a preview build for review, a production build from a tagged commit, submission to a testing track, then a staged rollout.

Each step should be something CI does, not something a person remembers.

The backend has to keep up too. Users update apps slowly, so your API must keep serving older versions; keeping a backend compatible with old mobile app versions covers how. For the server side of releases, see how small SaaS teams ship on AWS without breaking production.

Where should a small team store mobile app signing credentials?

Store mobile app signing credentials in one managed place, such as EAS credentials or a secrets manager, never in the repository or on one developer's laptop.

Losing an Android upload key or an Apple distribution certificate at the wrong moment can block a release for days.

Keep a written note of where each credential lives, who can access it and when it expires, and give at least two people access. Rotate access when someone leaves.

Is your Expo release pipeline ready to run without a person?

Tick each item that is true today.

  • EXPO_TOKEN is stored as a CI secret, not on a laptop.
  • Production builds run from CI with the non-interactive flag.
  • Builds submit automatically to TestFlight and a Play testing track.
  • A runtime version policy stops updates reaching incompatible builds.
  • Signing credentials live in one managed place that two people can reach.
  • iOS releases use a phased rollout you can pause.

Decision point: Five or six ticks: releasing is routine. Three or fewer: the next urgent fix will probably depend on one person's machine.

Sources

  1. Expo docs, Trigger builds from CI (checked October 2026)
  2. Expo docs, Automate submissions (checked October 2026)
  3. Expo docs, Runtime versions and updates (checked October 2026)
  4. Apple, App Store Connect Help: Release a version update in phases (checked October 2026)

Keep reading

Keel is an AWS release and recovery operations service for SaaS teams of 3 to 15 developers, provided by Bargainn Services Ltd, a UK company registered at Companies House (16497746). Registered office: 3rd Floor, 86-90 Paul Street, London, EC2A 4NE, United Kingdom.