Skip to content
Shipdigicom

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

  1. build-atlas
    queue acceptedrelease/4.13 at main@a91f2c7
  2. build-atlas
    ios arm64 signed6m 12s on mac-mini-03
  3. build-atlas
    android arm64-v8a signed4m 03s on linux-runner-01
  4. locale
    142 new keys extracted4.13 against 4.12
  5. locale
    am, om, ti delivered138 machine, 4 rewritten in review
  6. bug-studio
    4.13 armeddSYM and mapping uploaded
  7. bug-studio
    NSRangeExceptionCartView.swift:212, 41 sessions
  8. build-atlas
    build 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

Strings and content

Runtime and crashes

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.

Build results per target for release 4.12 and 4.13
targetapisigning4.124.13
ios arm6418.2distributionpasspass
ios simulator18.2unsignedpasspass
android arm64-v8a35upload keypasspass
android x86_6435upload keypasspass
android armeabi-v7a33upload keypassfail

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.

key added by 4.13amomti
  • cart.remove.confirm

    Remove this item from your cart?

    mergedmergedreview
  • cart.empty.title

    Your cart is empty

    mergedreviewmachine
  • checkout.payment.failed

    That payment didn't go through. Try another method.

    reviewmachinemachine
  • delivery.window.tomorrow

    Arrives tomorrow between {start} and {end}

    mergedmergedmerged
  • account.phone.verify

    We sent a code to {phone}

    mergedmachinemachine
5 of the 142 keys 4.13 added. Amharic, Oromo, Tigrinya. review means someone who speaks it has the machine draft open and can overwrite it.

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

  1. 0CartView.swift:212CartView.removeItem(at:)
  2. 1CartView.swift:64CartView.body.getter
  3. 2SwiftUIViewRendererHost.render()
  4. 3ShipCartmain.swift:12

what the app was doing

  1. opened cart, 3 items-4.1s
  2. tapped remove on row 3-0.9s
  3. list reloaded, 2 items-0.4s
  4. tapped remove on row 3-0.1s
  5. 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