Build runs
Rebuild many apps at once to pick up a new template version, retry a failed upload or push a one-off fix. You choose how many run in parallel.
An internal console I built to run releases for 493 branded iOS apps from one screen: parallel builds, live progress, failures grouped by cause, and a wizard for new clients. Try a working replica below.
This is a working replica on invented data. Every restaurant name here is made up; the real console shows clients' names, so I rebuilt it rather than screenshot it. Press Start build, or let the tour drive.
No active run. Press Start build.
The release pipeline made shipping an app one command. At 493 apps, one command still isn’t enough: someone has to choose which apps, watch dozens of builds, work out why some failed, and keep track of what the App Store actually shows.
The goal was written into the tool’s own guide: ship a whole fleet of apps from one screen, without touching a terminal or Xcode. I wrote it so someone who isn’t an iOS developer could run a release.
Rebuild many apps at once to pick up a new template version, retry a failed upload or push a one-off fix. You choose how many run in parallel.
Which app each lane is on, how long it has taken, what succeeded or failed and how much disk is left, refreshed every second.
Failures are grouped by their cause, with the bundle id stripped out so the same problem across ten apps becomes one line, matched to the fix that worked before.
Every app’s version against the target, and what the App Store shows customers right now, including anything removed from sale.
Change a name, brand colour or feature switch, or swap the icon and images, written straight into the files the next build reads.
A guided flow that stands up a brand-new app: local files, then its App Store record, then its signing. Resumable if you stop halfway.
Four patterns are recorded so far. The list is built to grow: whenever I root-cause a new failure, I add it, and the next run shows the fix beside the failure.
Provisioning a restaurant used to mean editing configuration by hand and clicking through Apple’s portal. Now it is a form with a live preview. Type a name and pick a colour.
Step 1 only creates files in the repo and is reversible. Step 2 is a real Apple change, so it only runs for apps you’ll ship. You can close the page and resume later.
com.zaytech.harborgrillThe console doesn’t replace the build pipeline, it drives it. The scripts stay in charge of building; the server starts them, reads their logs and checks the results against Apple.
The page loads once, then opens one Server-Sent Events connection. The server pushes a fresh snapshot every second down that open line, and the page just applies it.
Each message carries finished HTML fragments, not raw data, so there is no second rendering path in JavaScript to drift out of sync with the Python.
Each build slot is its own git worktree with its own process group, so a stop button can kill exactly one lane’s whole process tree.
# the whole install: one Python file, then one click $ python3 scripts/dashboard.py # or the Mac app I wrapped around it, from the Desktop $ open "Branded Apps Dashboard.app"
A button here can upload to Apple, delete files or commit to git, so the tool is built on the assumption that something will go wrong.
What isn’t built yet: multi-user sign-in, and a split between the build monitor and the app list. Both are on the roadmap. It is built for one operator, hardened to grow.
Built with Python’s standard library (http.server, threads, Server-Sent Events), Pillow for icons and PyJWT for the App Store Connect API. No framework, so there is nothing to install on the build Mac.
Freelance projects, or a full-time role, remote or with relocation. Résumé (PDF)