`--no-auto-testflight-setup` is ignored when the submit profile has no `ascAppId`: `Team (Expo)` is still created and all Admins enrolled (opt-out lost in 22.0.0)
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 78/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- typescript
- Domain
- cli, mobile-dev
Research direction
Start in packages/eas-cli/src/submit/ios/AppProduce.ts and compare its default app-resolution path with ensureTestFlightSetup.ts and ensureTestFlightGroup.ts. Reproduce the issue with an empty submit profile and --no-auto-testflight-setup, then inspect the existing context plumbing in submit/context.ts. Done means the opt-out prevents group creation and Admin enrollment on both app-resolution paths, including callers from commands/go.ts.
Written by the indexing model from the issue text.
Description
Build/Submit details page URL
No response
Summary
eas submit -p ios --no-auto-testflight-setup still creates the internal TestFlight group Team (Expo) and adds every Admin on the Apple team to it as a tester, whenever the submit profile has no ascAppId. The flag is only honoured on the ascAppId code path; the default path (app resolved by bundle identifier through ensureAppStoreConnectAppExistsAsync) calls the group setup unconditionally.
Expected: --no-auto-testflight-setup disables the group creation and the tester enrolment on every path, as its description says ("Set up an internal TestFlight group for the app (iOS only)", allowNo: true). On a team where the Admins are not the testers, enrolling them without being asked is a change to the team's TestFlight configuration that the user explicitly opted out of.
Managed or bare?
Managed (continuous native generation; ios/ and android/ are gitignored prebuild output, which is why expo-env-info prints Expo Workflow: bare below).
Environment
eas-cli/24.0.0 darwin-arm64 node-v20.19.4 (global install via bun; expo-env-info does not see the bun global registry, so its npmGlobalPackages line is corrected by hand below).
expo-env-info 2.1.0 environment info:
System:
OS: macOS 26.5.2
Shell: 5.9 - /bin/zsh
Binaries:
Node: 20.19.4 - ~/.nvm/versions/node/v20.19.4/bin/node
Yarn: 1.22.22 - ~/.nvm/versions/node/v20.19.4/bin/yarn
npm: 10.8.2 - ~/.nvm/versions/node/v20.19.4/bin/npm
Managers:
CocoaPods: 1.16.2 - /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 25.5, iOS 26.5, macOS 26.5, tvOS 26.5, visionOS 26.5, watchOS 26.5
IDEs:
Android Studio: 2025.2 AI-252.25557.131.2521.14344949
Xcode: 26.5/17F42 - /usr/bin/xcodebuild
npmPackages:
expo: ~57.0.20 => 57.0.20
expo-router: ~57.0.19 => 57.0.19
react: 19.2.3 => 19.2.3
react-dom: 19.2.3 => 19.2.3
react-native: 0.86.3 => 0.86.3
react-native-web: ~0.21.0 => 0.21.2
npmGlobalPackages:
eas-cli: 24.0.0 (bun global install)
Expo Workflow: bare <- see above; the project is managed
Error output
No error. After a successful eas submit --platform ios --profile <profile> (submit profile {}, no ascAppId, key on the EAS credentials service), App Store Connect > TestFlight shows a new internal group Team (Expo) with automatic distribution on and every Admin of the team enrolled as a tester. That run did not pass --no-auto-testflight-setup; that the flag would not have changed the outcome on this path is established from the source below, and the steps to observe it are in the repro section. (The messages for this step are TestFlight group created: Team (Expo) and TestFlight access enabled for: ..., from ensureTestFlightGroup.ts.)
Where it happens (eas-cli main)
packages/eas-cli/src/submit/ios/IosSubmitCommand.ts, resolveAscAppIdentifierAsync, has two branches:
- With
ascAppIdin the profile (L175):ensureTestFlightSetupForExistingAppAsync(this.ctx, ascAppId). That function checks the flag first (packages/eas-cli/src/submit/ios/ensureTestFlightSetup.tsL28:if (!ctx.autoTestFlightSetup) return;). Correct. - Without
ascAppId(L194):ensureAppStoreConnectAppExistsAsync(this.ctx)inpackages/eas-cli/src/submit/ios/AppProduce.ts, which resolves or creates the app and then, at L97, callsensureTestFlightGroupExistsAsync(app, { nonInteractive })inside a try/catch. Nothing on this path readsctx.autoTestFlightSetup.
ensureTestFlightGroupExistsAsync (packages/eas-cli/src/credentials/ios/appstore/ensureTestFlightGroup.ts) then creates the Team (Expo) group with hasAccessToAllBuilds: true when the app has no groups, lists the team's users, filters to UserRole.ADMIN, and bulk-assigns them as beta testers.
The flag is plumbed into SubmissionContext (packages/eas-cli/src/commands/submit.ts L111-L113, L162, L233; submit/context.ts), so ctx.autoTestFlightSetup is available in AppProduce.ts; it is just not consulted there.
How it got here (regression in 22.0.0)
- 14.6.0, #2839:
eas submitstarts auto-creating the internal group on theAppProducepath. - 15.0.11, #2856: skip when groups already exist, and an opt-out:
EAS_NO_AUTO_TESTFLIGHT_SETUP, checked at the top ofensureTestFlightGroupExistsAsync, so it covered every caller. - 22.0.0, #4136: adds the
ascAppIdpath and the--[no-]auto-testflight-setupflag, and removes theEAS_NO_AUTO_TESTFLIGHT_SETUPcheck fromensureTestFlightGroupExistsAsync(diff of #4136,ensureTestFlightGroup.ts). The flag is read only in the newensureTestFlightSetupForExistingAppAsync.
So since 22.0.0 the default path has no opt-out at all: the env var is gone and the flag is not read. The 22.0.0 changelog entry ("with --no-auto-testflight-setup to disable it") reads as if the flag disables the behaviour; it disables it on one of the two paths.
Docs
The behaviour is not described anywhere a user reads before their first submit. Submit to the Apple App Store does not mention it. Distribute an iOS app with TestFlight says to create internal groups by hand in App Store Connect and target them with --groups, and does not mention that eas submit will create one and enrol the Admins on its own. The only mention is the flag's one-line description in the CLI reference.
Reproducible demo or steps to reproduce from a blank project
npx create-expo-app repro && cd repro && eas init && eas build:configure. Setios.bundleIdentifierto a bundle id on your Apple team whose App Store Connect app has no TestFlight groups yet (a fresh app record, or one where you removed the groups). Add"submit": { "production": {} }and do not setascAppId.- Set up an App Store Connect API key for EAS Submit (
eas credentials -p ios). eas build -p ios --profile production.eas submit -p ios --profile production --latest --no-auto-testflight-setup.- Observe
TestFlight group created: Team (Expo)in the output and the group, with the team's Admins enrolled, in App Store Connect.
Control: add "ascAppId": "<the app's numeric id>" to the submit profile, delete the group, and run step 4 again. No group is created; the flag is honoured on that path.
Suggested fix
Move the check back into ensureTestFlightGroupExistsAsync (where the env var used to be) so every caller respects it (commands/go.ts L45 calls it too), or read ctx.autoTestFlightSetup in createAppStoreConnectAppAsync (AppProduce.ts L97). Restoring EAS_NO_AUTO_TESTFLIGHT_SETUP alongside the flag would also help CI, where a flag has to be threaded through every invocation and an env var does not.
Docs: a sentence in the TestFlight guide saying that the first eas submit creates Team (Expo) and enrols all Admins unless a group already exists or --no-auto-testflight-setup is passed.
The default itself
Beyond the flag bug: as far as we could find, this default is undocumented, and it is an undesirable one. Every other thing eas submit does is scoped to the build it is submitting. This step reaches into the team: it creates a distribution group the user did not ask for, with automatic access to every future build, and enrols people by role rather than by choice, so each Admin gets a TestFlight invitation for an app they may have no part in testing, on the first submit, when whoever is running it is least likely to know a flag exists. Reading the Admin list also needs an Admin-role key, so the step silently depends on the key's role in a way the submission itself does not.
The behaviour the TestFlight guide describes is the right one: the team creates the groups it wants and eas submit --groups targets them. Please consider making the automatic group opt-in (--auto-testflight-setup, default off), or at least asking before creating it in interactive mode; and in either case documenting it in the TestFlight guide, not only as a flag description.
- Dominant language
- TypeScript
- Stars
- 1.4k
- Forks
- 238
- Avg merge
- 2d 23h
- Merged PRs (30d)
- 87
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from expo/eas-cli
-
needs review
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
generate_gymfile_from_template emits Apple-deprecated "ad-hoc" export method, rejected by Xcode 26+ Openstale
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
needs review
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 3/5 1-2 days Newbie friendliness 68/100
-
needs review
Difficulty 4/5 3-5 days Newbie friendliness 52/100
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Eynzof/Hermes-CN-Desktop#610 ·
-
bug clawsweeper:linked-pr-open clawsweeper:needs-live-repro clawsweeper:no-new-fix-pr impact:message-loss issue-rating: 🐚 platinum hermit P2 regression
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
fullcalendar/fullcalendar#8106 ·