Skip to content

[build-tools][eas-cli] Support iOS Development provisioning profiles#3496

Open
qwertey6 wants to merge 5 commits intoexpo:mainfrom
qwertey6:fix/development-provisioning-profile
Open

[build-tools][eas-cli] Support iOS Development provisioning profiles#3496
qwertey6 wants to merge 5 commits intoexpo:mainfrom
qwertey6:fix/development-provisioning-profile

Conversation

@qwertey6
Copy link
Contributor

Why

EAS does not distinguish iOS Development provisioning profiles from Ad Hoc profiles. Both have ProvisionedDevices, so EAS treats them identically — setting CODE_SIGN_IDENTITY = "iOS Distribution" and EXPORT_METHOD = "ad-hoc". This causes builds to fail with:

No signing certificate "iOS Distribution" found

This is a blocker for entitlements like Family Controls (com.apple.developer.family-controls) that only work with Development provisioning profiles — Apple does not grant this entitlement for Ad Hoc or App Store profiles. Users with credentialsSource: "local" who supply a Development profile + Development certificate hit this immediately.

Companion to #3484 (multi-cert matching fix). Related issues: #3192, #1201, #3185.

How

@expo/build-tools — detect Development profiles and set correct code signing identity:

  • Add DEVELOPMENT = 'development' to the DistributionType enum
  • Update resolveDistributionType() to check Entitlements['get-task-allow']true for Development profiles, false for Ad Hoc
  • After @expo/config-plugins hardcodes CODE_SIGN_IDENTITY = "iPhone Distribution", override it to "Apple Development" when a Development profile is detected
  • Applied to both ios/credentials/provisioningProfile.ts and steps/utils/ios/credentials/provisioningProfile.ts
  • Applied to both ios/configure.ts and steps/utils/ios/configure.ts

eas-cli — accept Development profiles for internal distribution:

  • Fix isAdHocProfile() to return false for Development profiles (check get-task-allow)
  • Add isDevelopmentProfile() utility
  • Update assertProvisioningProfileType() to accept Development profiles for distribution: "internal", and reject them for store distribution

Test Plan

  • Added test in configure.test.ts (both copies) verifying a Development profile results in CODE_SIGN_IDENTITY = "Apple Development" instead of "iPhone Distribution"
  • All 270 build-tools tests pass (43 suites, 35 snapshots)
  • All 1174 eas-cli tests pass (173 suites, 13 snapshots)
  • yarn typecheck passes across all 13 packages
  • yarn lint and yarn fmt pass

🤖 Generated with Claude Code

@github-actions
Copy link

Subscribed to pull request

File Patterns Mentions
**/* @douglowder

Generated by CodeMention

targetName,
buildConfiguration,
});
xcBuildConfiguration.buildSettings.CODE_SIGN_IDENTITY = '"Apple Development"';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to worry about the old default somehow? yonaskolb/XcodeGen#691 Like… may the provisioning profile be still valid for "iPhone Developer" in which case we should infer the identity from the provisioning profile for this setting?

I was able to create a certificate just now for "iOS Development" and "Development" which have different signing identifies.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point! You're right that hardcoding "Apple Development" doesn't cover all certificate types. I've updated overrideCodeSignIdentityForDevelopment() to accept the targetProvisioningProfiles map and use profile.certificateCommonName for each target instead. This way whatever signing identity the certificate actually has (e.g. "iPhone Developer", "iOS Development", "Apple Development") will be used correctly.

@qwertey6 qwertey6 force-pushed the fix/development-provisioning-profile branch from cf7b3fe to 8aed306 Compare March 12, 2026 16:56
@qwertey6 qwertey6 requested a review from sjchmiela March 12, 2026 18:19
targetName,
buildConfiguration,
});
xcBuildConfiguration.buildSettings.CODE_SIGN_IDENTITY = `"${profile.certificateCommonName}"`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you be able to put this upstream? The cleaner fix would be to add an optional codeSignIdentity parameter to setProvisioningProfileForPbxproj upstream in
expo/expo (in packages/@expo/config-plugins/src/ios/ProvisioningProfile.ts). You'd default it to
"iPhone Distribution" so existing callers are unaffected. Then the call sites in configure.ts can pass
profile.certificateCommonName for development profiles directly, and the overrideCodeSignIdentityForDevelopment function can
be removed entirely.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! Opened expo/expo#43986 to add an optional codeSignIdentity parameter to setProvisioningProfileForPbxproj (defaults to "iPhone Distribution" so existing callers are unaffected). Once that's merged and released, I'll update this PR to pass profile.certificateCommonName directly and remove overrideCodeSignIdentityForDevelopment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you! working on getting that merged upstream

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new version of config-plugins is published now!

Copy link
Contributor Author

@qwertey6 qwertey6 Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Update: the upstream change landed in @expo/config-plugins@55.0.7 (expo/expo#43986). However, this repo depends on @expo/config-plugins@9.0.12 which is on a different major version line (Expo SDK 52), and the 9.x line hasn't had a release since 9.1.7 (April 2025).

So until eas-cli upgrades to a newer @expo/config-plugins major version, the overrideCodeSignIdentityForDevelopment workaround in this PR is necessary. Once the dependency is bumped, it can be replaced with a codeSignIdentity parameter passed directly to setProvisioningProfileForPbxproj.

Update update (lol): I made #3522 to bump the version as would be needed in THIS diff. If that's what you had in mind @quinlanj , feel free to approve that PR and I'll update this one. If you had something else in mind just lmk 🤠

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, that's what i meant 😄

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deps are updated: #3527 :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Already rebased on top of that and replaced the workaround — now passing codeSignIdentity: profile.certificateCommonName directly to setProvisioningProfileForPbxproj. The overrideCodeSignIdentityForDevelopment function is gone.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you! we had a bit of a hiccup with the config/config-plugins bump, so i had to revert it temporarily, but once we can get it landed again we should be good to go. appreciate your patience on all this 🙏 !

targetName,
buildConfiguration,
});
xcBuildConfiguration.buildSettings.CODE_SIGN_IDENTITY = `"${profile.certificateCommonName}"`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above — upstream PR at expo/expo#43986 will allow removing this workaround.

@qwertey6
Copy link
Contributor Author

Next Steps

This PR currently uses an overrideCodeSignIdentityForDevelopment workaround because @expo/config-plugins's setProvisioningProfileForPbxproj hardcodes CODE_SIGN_IDENTITY = "iPhone Distribution".

I've opened an upstream PR to fix this: expo/expo#43986 — it adds an optional codeSignIdentity parameter (defaulting to "iPhone Distribution" so existing callers are unaffected).

Once that's merged and released, I'll update this PR to:

  1. Bump the @expo/config-plugins dependency
  2. Pass codeSignIdentity: profile.certificateCommonName directly to setProvisioningProfileForPbxproj
  3. Remove the overrideCodeSignIdentityForDevelopment workaround from both configure.ts files

qwertey6 and others added 5 commits March 24, 2026 15:10
…rrect code signing identity

Add DEVELOPMENT distribution type to distinguish Development profiles
from Ad Hoc. Development profiles have get-task-allow=true in their
entitlements; Ad Hoc profiles don't.

When a Development profile is detected, override CODE_SIGN_IDENTITY to
"Apple Development" instead of the "iPhone Distribution" that
@expo/config-plugins hardcodes. This fixes builds that use
credentialsSource: "local" with Development profiles (e.g., for
Family Controls entitlement).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ibution

Fix isAdHocProfile() to distinguish Development from Ad Hoc profiles by
checking the get-task-allow entitlement. Add isDevelopmentProfile() for
explicit detection.

Update assertProvisioningProfileType() to accept Development profiles
for internal distribution, and reject them for store distribution.

This enables credentialsSource: "local" with Development profiles needed
for entitlements like Family Controls (com.apple.developer.family-controls)
that only work with Development provisioning profiles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…identity

Address review feedback: use the certificate common name from the
provisioning profile instead of hardcoding "Apple Development", which
doesn't cover all certificate types (e.g. "iPhone Developer", "iOS
Development"). Also fix grammar in error message ("an development" →
"a development").

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…e fix

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…around

Now that @expo/config-plugins@55.0.7 supports the optional
codeSignIdentity parameter in setProvisioningProfileForPbxproj,
pass profile.certificateCommonName directly for development profiles
and remove the overrideCodeSignIdentityForDevelopment workaround
that was reading/writing the pbxproj a second time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@qwertey6 qwertey6 force-pushed the fix/development-provisioning-profile branch from 8aed306 to 24ad60c Compare March 24, 2026 19:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants