Case study · Release Rescue

A mobile release that would not build.

A React Native app had never once produced a TestFlight build, and the store deadline was closing. Nine consecutive CI failures, from dependency locks and stale pods to signing keys and finally a C++ compiler error deep inside a formatting library, were each root-caused and fixed. We also rejected the expensive fix that would not have worked.

9

Build failures cleared

1st

TestFlight build ever

0

Framework upgrades needed

1

Launch crash caught before review

01 — The problem

The Android build of the app had been shipping for years. The iOS build had not. The pipeline that was supposed to produce it had never gone green, the original developers had moved on, and the company had no Mac and no one who could read an Xcode log. A platform upgrade was already sitting in the branch, which meant the iOS release could not be skipped any longer.

The advice they had received so far was to rewrite the app or buy hardware and hire a specialist. Neither would have addressed the actual failures, and neither fit the deadline.

02 — What we did

We treated the pipeline as a production incident and worked the failures one at a time, in a cloud CI service, without touching the app's business logic.

  • Dependency locks and stale pods. The lockfiles disagreed with each other and with the platform version. We regenerated them deterministically and pinned what needed pinning.
  • Code signing. Certificates, provisioning profiles and the App Store Connect API key were configured from scratch, including the permission the account holder alone can grant, which had silently blocked every previous attempt.
  • A C++ compiler error in a formatting library. The final failure was deep inside a third-party native dependency. We isolated it to a single header, applied a targeted patch, and did not need another framework upgrade to clear it.
  • The post-build crash. The first build launched and immediately crashed. The platform upgrade had switched on a new rendering architecture on iOS while Android had it explicitly disabled. We aligned the two and rebuilt.
  • The submission itself. Before submitting, we logged in with the reviewer demo account against the live backend rather than assuming it still worked, and set the release configuration with the client's explicit sign-off.

03 — How we proved it

  • Every failure was root-caused in writing before it was fixed, so the client has a record of what each one was and why the fix is correct.
  • The build was installed by an external tester through TestFlight and exercised on a real device before the release was submitted.
  • The pipeline is reproducible: a fresh clone builds green without manual steps, which is the only proof that matters for the next release.

04 — The outcome

The app produced its first ever TestFlight build, cleared external testing and was submitted for App Review within the deadline, with the platform upgrade included. The client now owns a working iOS pipeline, a documented signing setup and a maintainer who has read the whole thing.

05 — What this means for you

Most stuck releases are not stuck on one hard problem. They are stuck on a chain of small ones that nobody has the patience or the context to walk through in order. That is a job for an engineer who has shipped to both stores before, not for a rewrite. See our Release Rescue engagement.

Next step

Have a problem that looks like this?

Tell us what is actually going wrong. You will get a straight answer on whether we are the right people for it, and a fixed scope if we are.