1.1.2 · Dev Platform

How to Build iPhone Apps Without a Mac — EAS + GitHub Codespaces

2026.07.02~7 min

00Overview

Tools

  • Apple Developer ProgramApp Store submission$99/yr
  • EAS buildBuilds on cloud macOSFree
  • GitHub CodespacesOne-time certificate stepFree
  • PC (any)Browser, one time onlyalready owned

01Story

Situation

With the dev loop from 1.1.1, the check-and-fix cycle through Expo Go spins nicely. During development, no build is ever needed.

Complication

Shipping to the App Store is another story. Submitting to Apple means building the app, and building an iPhone app requires a Mac — an unavoidable fact of Apple's ecosystem.

Question

A build needs a Mac. Without owning one, how do you reach the App Store?

02Solution

Criteria

  • Works without owning a Mac (don't buy one, don't borrow one, don't host one)

Answer

# First time only (creating certificates)
PC browser → GitHub → GitHub Codespaces → EAS (build)

# From then on (everything from the iPhone)
iPhone → GitHub → GitHub Actions → EAS (build)
iPhone → GitHub → GitHub Actions → EAS (submit)
        → App Store Connect → TestFlight → iPhone
A Mac is required. It just has to live in the cloud.

EAS (Expo Application Services) builds your iPhone app on macOS machines on their side. All you need at hand is a device that can fire the command — and an iPhone is enough.

Reason

The one-time PC browser session exists because of interactivity. The first build creates the signing credentials for the App Store, and that process asks Y/N questions interactively. The answers are basically all Y, but automating them in GitHub Actions means writing tedious timing-sensitive response code. For an operation that happens a few times a year at most, automation isn't worth it — so the first time is manual.

Even that manual step needs no Mac. Open GitHub Codespaces — the VS Code environment GitHub gives you in a browser — and run the commands from there. The personal free tier (120 core-hours/month) is plenty. In theory a phone browser would work, but a terminal on a phone screen really is too small, so this one step used a PC browser. Again: a PC, not a Mac.

From the second time on, no interaction is needed: run the GitHub Actions workflow from the iPhone and the build rolls. When it succeeds, submit from Actions the same way, and the app lands in App Store Connect and comes down to your device through TestFlight. Right up to the moment of submission, everything completes on the iPhone.

Options

  • Xcode Cloud — Apple's own CI/CD. But the initial setup needs Xcode, i.e., a Mac, which contradicts the "own no Mac" criterion. And since the app is built on EXPO, EAS's affinity settled it.
  • GitHub Actions macOS runners — you can build directly on a macOS runner. But macOS minutes bill at 10× the Linux rate, and the 2,000 free minutes/month evaporate. Never dared.

03Result

Good

Build and submit both live in EAS now, so management is unified. Development in EXPO (1.1.1) continues seamlessly right up to the doorstep of submission — all from a phone. The real find: "you need a Mac," the tallest barrier in iPhone development, turned out not to mean "you need to own a Mac."

Bad

The free tiers come with constraints. As of writing:

ServiceFree tierNotes
EAS build15 iOS builds/mo (+15 Android)Failed builds still count
GitHub Actions2,000 min/moFree plan, private repos

Normal development never hits these ceilings. But debugging native issues with repeated builds eats them fast — and the painful part is that failed builds still consume the count. Three consecutive errors from a config mistake, and a fifth of your month is gone.

Follow-up

Free-tier EAS builds sit at low priority, and the queue can get absurdly long. Waiting is fine — but here's the trap: if Actions sits waiting for the build to finish, that waiting time also drains your 2,000 Actions minutes. Waiting changes nothing about the result, so the right move is to run eas build with --no-wait and end the workflow the moment the trigger fires.

The trade-off is that build and submit no longer chain in one workflow. So it's a two-step routine: confirm the build succeeded on the EAS dashboard, then run submit from Actions. --no-wait works on submit too.

With this, the vertical line of "build it and deliver it" is connected — enough to release. Once released, add the safety layer that separates dev and production delivery — 1.1.3 Safe EAS Update operation — to prevent accidental releases during maintenance. Then the story widens sideways: 1.2 Localization.