Ship builds our apps, translates them, and tells us what broke.
Tools our team wrote for our own engineering org, because the services we were renting kept getting in the way. Three of them make one release loop, and the log below is one release going through all three.
run 4231
- build-atlasqueue acceptedrelease/4.13 at main@a91f2c7
- build-atlasios arm64 signed6m 12s on mac-mini-03
- build-atlasandroid arm64-v8a signed4m 03s on linux-runner-01
- locale142 new keys extracted4.13 against 4.12
- localeam, om, ti delivered138 machine, 4 rewritten in review
- bug-studio4.13 armeddSYM and mapping uploaded
- bug-studioNSRangeExceptionCartView.swift:212, 41 sessions
- build-atlasbuild 4232 queuedfix/cart-index-guard
hover or focus a tool name to follow only its steps
Every tool we run
One row each, grouped by the part of the stack they touch. A name goes to that tool's docs. The three with a section further down are the ones that touch every release.
Build and release
- Build Atlas
Builds and signs native releases on our own runners.
platform
on this page
Strings and content
- Locale
Delivers translated strings as a pull request.
platform and mobile
on this page
Runtime and crashes
- Bug Studio
Ties a crash to a release, a device, and a line of code.
mobile
on this page
3 tools across 3 groups. Everything here runs on hardware we own.
00:00.4
Build Atlas
Give it a git ref. Build Atlas builds on our own runners, signs with our own certificates, and hands the artifacts wherever they need to go: TestFlight, the Play Console, or an internal install page. It replaced a hosted queue we could neither see into nor skip.
| target | api | signing | 4.12 | 4.13 |
|---|---|---|---|---|
| ios arm64 | 18.2 | distribution | pass | pass |
| ios simulator | 18.2 | unsigned | pass | pass |
| android arm64-v8a | 35 | upload key | pass | pass |
| android x86_64 | 35 | upload key | pass | pass |
| android armeabi-v7a | 33 | upload key | pass | fail |
armeabi-v7a is the one red cell in 4.13. We dropped it from the default profile when the NDK stopped shipping a toolchain for it, and left the row in the matrix so nobody has to rediscover why.
00:05.1
Locale
Locale reads the string keys out of the codebase, machine-translates the ones that are new, and holds them until someone who speaks the language signs off. What it delivers is a pull request, not a download, so the strings land in the same review the code does.
cart.remove.confirm
Remove this item from your cart?
mergedmergedreviewcart.empty.title
Your cart is empty
mergedreviewmachinecheckout.payment.failed
That payment didn't go through. Try another method.
reviewmachinemachinedelivery.window.tomorrow
Arrives tomorrow between {start} and {end}
mergedmergedmergedaccount.phone.verify
We sent a code to {phone}
mergedmachinemachine
00:08.3
Bug Studio
A report arrives already tied to a release, a device, and a line of code. Bug Studio matches the symbols, groups the report with every other session that hit the same frame, and keeps the last few things the person did before the app went down.
NSRangeException
Index 3 beyond bounds [0 .. 2]
symbolicated stack
- 0CartView.swift:212CartView.removeItem(at:)
- 1CartView.swift:64CartView.body.getter
- 2SwiftUIViewRendererHost.render()
- 3ShipCartmain.swift:12
what the app was doing
- opened cart, 3 items-4.1s
- tapped remove on row 3-0.9s
- list reloaded, 2 items-0.4s
- tapped remove on row 3-0.1s
- crash0.0s
device state
- release
- 4.13 (4231)
- device
- iPhone 13, iOS 18.2
- locale
- am-ET
- sessions hit
- 41 of 3,412
- network
- wifi, 40 ms rtt
- memory
- 412 MB of 3.8 GB
Two taps on the same row, 800 ms apart, on a list that had already reloaded underneath. The steps are what turned this from a stack trace into a fix.
Why we built these
We rented all three of these for years, and argued with all three.
Builds sat in a queue we didn't control. Forty minutes some mornings, with no way to see what was ahead of us and no way to get to the front on the day it mattered. Translations lived in a spreadsheet somebody had to remember to export, and the export was always a version behind the app. Crash reports told us 4.11 was unhappy without telling us which line of which file, because the symbols never quite made it up.
So we wrote our own, one at a time, in the order we hit the wall. Build Atlas first, because the queue was costing us days. Locale next, when we added Oromo and Tigrinya and the spreadsheet stopped working. Bug Studio last, and it is still the youngest of the three by a wide margin. Everything since has arrived the same way.
None of these are products. They are thin in the places we haven't needed yet, they assume our repo conventions, and the docs are worse than they should be. They also run on machines we can walk over to, they cost nothing per build, and when one of them is wrong we fix it the same afternoon.
the platform team at Digicom