Automation
Build an Ad Hoc IPA with Fastlane build_app
Use Fastlane build_app or gym with the ad-hoc export method, explicit profile mapping when needed, and post-export checks on the final IPA.
Fastlane’s build_app action—also available as gym—archives an Xcode project and exports the signed IPA. For registered-device delivery, the decisive setting is export_method: "ad-hoc", backed by an Ad Hoc provisioning profile that contains the intended devices. The action returns the generated IPA path in Fastlane’s lane context; use that exact output as the handoff artifact.
A successful archive is not enough. Archive creation and IPA export are separate phases, and export can select signing inputs that differ from what a developer expected. Verify the file produced by CI before sending it to a client.
Prepare the project and signing assets
Confirm the shared scheme, release configuration, bundle identifiers for the app and extensions, Apple team, and registered-device set. An Ad Hoc profile requires a matching App ID, one distribution certificate, and the selected registered devices. Registration alone is insufficient: the profile used for export must have been generated with those devices.
Synchronize approved assets before the build. If your team uses Fastlane match, call sync_code_signing(type: "adhoc") (or its match alias) first and keep CI read-only. If Xcode automatic signing owns the profiles, avoid mixing in a second manual profile mapping without a clear reason. Asset maintenance belongs in the Fastlane match Ad Hoc guide; this page begins only after the correct assets and devices are ready.
Add an explicit Ad Hoc lane
lane :build_client_adhoc do
sync_code_signing(
type: "adhoc",
app_identifier: "com.example.clientapp",
readonly: true
)
build_app(
workspace: "ClientApp.xcworkspace",
scheme: "ClientApp",
clean: true,
export_method: "ad-hoc",
output_directory: "build",
output_name: "ClientApp-AdHoc.ipa"
)
end
Fastlane’s current documentation lists ad-hoc as the export method spelling. Keep this value distinct from app-store, development, or enterprise; those methods carry different authorization rules. The archive phase and export phase are separate: a successfully archived app can still export with an unexpected method or profile mapping.
Map profiles when automatic detection is ambiguous
For manual signing or multiple targets, pass a bundle-ID-to-profile mapping through export options:
build_app(
scheme: "ClientApp",
export_method: "ad-hoc",
export_options: {
provisioningProfiles: {
"com.example.clientapp" => "ClientApp AdHoc",
"com.example.clientapp.share" => "ClientApp Share AdHoc"
}
}
)
Every embedded extension must have compatible signing and entitlements. Do not map only the main app and assume nested targets inherit a valid profile. If build_app can detect the correct profiles reliably, unnecessary mappings add maintenance risk. When a mapping is needed, use the provisioning-profile name available on the export machine and keep the mapping aligned with the team that owns the bundle IDs.
Fail before exporting the wrong artifact
Make the lane stop when tests, archive, or export fails. Do not rename an unsigned or Development export to .ipa and mark the job successful. Preserve Fastlane’s raw xcodebuild log as a restricted CI artifact when diagnosis is needed, while preventing environment secrets from entering public logs.
Give each output an immutable build identifier. A new device registration requires a refreshed profile and new artifact; never overwrite the old IPA while keeping the same release record.
Inspect and identify the exact output
Unpack a copy and find the app bundle:
unzip -q build/ClientApp-AdHoc.ipa -d build/inspect
APP_PATH=$(find build/inspect/Payload -maxdepth 1 -name '*.app' -print -quit)
codesign --verify --strict --verbose=4 "$APP_PATH"
security cms -D -i "$APP_PATH/embedded.mobileprovision" \
-o build/inspect/profile.plist
Then check the profile name, expiration, application identifier, and registered device set. Compare the app’s signed entitlements with the profile’s allowlist and repeat the check for extensions. The IPA signature guide explains the diagnostic boundary in more detail.
Create a checksum after export and preserve it next to the release record:
shasum -a 256 build/ClientApp-AdHoc.ipa
That checksum identifies the exact bytes inspected and delivered; it does not validate Apple authorization by itself. If the recipient reports an install failure, first compare the checksum of the delivered file, then inspect the profile and signature in that same artifact.
Finally, install that exact IPA on a representative registered phone through the intended delivery path. A codesign verification result does not test the OTA manifest, HTTPS host, Safari path, or client instructions.
Delivery boundary
Fastlane creates the artifact; it does not manage the entire client journey. Run the distribution checklist before handoff. IPAFlow is in Private Beta / In Development and is exploring the workflow after a verified IPA exists—authorized onboarding, profile-aware delivery, and client support—without collecting signing credentials in public forms.