Guides

Distribution

Get a build onto testers' devices with a link they can tap — and register the release and upload its symbols in the same step, so crashes from that build are readable from the moment it's installed.

Over-the-air install links

When you upload an .ipa, Pharen returns an install link — an itms-services URL that installs the app over the air. Open it in Safari on the iPhone and the app installs directly, no App Store, no cable:

text
itms-services://?action=download-manifest&url=https://dl.pharen.ai/<opaque>/manifest.plist

Install links are served from a locked, CDN-fronted host and live at an unguessable path — they're shareable and bookmarkable, but not enumerable, so one tenant's builds can't be discovered from another's. The link is what you send a tester; installing needs no login.

The whole release in one command

The canonical release lane is a single shell script. From your app directory:

bash
PHAREN_AUTH_TOKEN=… bash release/release-lane.sh

It runs the entire chain and prints the install link at the end:

  • archive the app (Release configuration) and export an IPA;
  • upload-build — upload the IPA and mint the OTA install link;
  • upload-symbols — upload every dSYM the archive produced, so the release's crashes symbolicate.

Nothing app-specific is baked into the script: version, build number, and bundle id are read from the archived Info.plist (so uploaded metadata can never drift from what was built), and your org/app come from a committed .pharen.yml. The one secret is PHAREN_AUTH_TOKEN, supplied in the environment — never written to disk.

Getting the lane into your repo

pharen init ios writes the lane (and a .pharen.yml) into your project — no network calls, no prompts:

bash
pharen init ios --org your-org --app your-app-id

It writes .pharen.yml at the repo root and copies release/release-lane.sh plus release/exportOptions.plist into your app, filling in your Apple team id when it can find one. The release lane and init use the pharen CLI, which — along with your credentials — we provide when we onboard your team. See the CLI reference.

TestFlight, the App Store, and rings

Pharen separates your data by environment without you sending an environment field. The environment is derived on the server from the ingest key baked into the build — so a build's ring is decided when it's built, and it can't be spoofed at runtime. In practice that's one rule:

Xcode configurationIngest keyLands in
Debugphi_test_…development
Releasephi_live_…production

Set the key per configuration (a per-configuration build setting that feeds PharenIngestKey in Info.plist). Because the key is compiled in, a Debug build simply cannot write to your production data, and vice versa.