Skip to content

[eas-cli] Set up TestFlight internal group when submitting with an existing ascAppId - #4136

Open
tchayen wants to merge 4 commits into
mainfrom
tchayen/testflight-setup-existing-asc-app
Open

[eas-cli] Set up TestFlight internal group when submitting with an existing ascAppId#4136
tchayen wants to merge 4 commits into
mainfrom
tchayen/testflight-setup-existing-asc-app

Conversation

@tchayen

@tchayen tchayen commented Aug 2, 2026

Copy link
Copy Markdown
Member

Why

The automatic TestFlight setup (internal group and admin testers) runs only on the interactive submit path that creates the App Store Connect app. Apps created on the ASC website never get a group, so processed builds sit in TestFlight with nobody able to install them.

How

  • eas submit -p ios runs the group setup best-effort when ascAppId resolves from the submit profile. Auth is strictly non-interactive: an ASC API key from env vars or the EAS credentials service. Without a key the setup is skipped silently, so submits gain no new prompts or failures. apple-utils routes token-auth beta group and tester requests to the official ASC API, so no cookie session is needed.
  • ensureTestFlightGroupExistsAsync gains a nonInteractive option that skips the destructive group-regeneration confirm with a warning.
  • Fix the TestFlight group URL printed on partial tester failure.
  • eas go reuses the shared implementation instead of its own copy.
  • EAS_NO_AUTO_TESTFLIGHT_SETUP is respected on the new path.

Test plan

CI passes. New unit tests cover the non-interactive behavior: no prompt, no group deletion, opt-out env var. The IosSubmitCommand suite asserts the setup runs for a profile-provided ascAppId. Reproduced the original gap end to end while shipping a real app: an app created on the ASC website and submitted with eas build --auto-submit --non-interactive reached TestFlight with no internal group.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Subscribed to pull request

File Patterns Mentions
packages/eas-cli/** @douglowder

Generated by CodeMention

Warning: The preamble and epilogue options in commentConfiguration are deprecated. Use template instead.

@tchayen
tchayen force-pushed the tchayen/testflight-setup-existing-asc-app branch from 4e14402 to de8a2e7 Compare August 2, 2026 07:06
@tchayen
tchayen force-pushed the tchayen/testflight-setup-existing-asc-app branch from de8a2e7 to 2a553d3 Compare August 2, 2026 10:44
@codecov

codecov Bot commented Aug 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 47.72727% with 23 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.57%. Comparing base (d98d26d) to head (040418d).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
...es/eas-cli/src/submit/ios/ensureTestFlightSetup.ts 34.49% 18 Missing and 1 partial ⚠️
.../credentials/ios/appstore/ensureTestFlightGroup.ts 70.00% 3 Missing ⚠️
packages/eas-cli/src/submit/ios/AppProduce.ts 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4136      +/-   ##
==========================================
+ Coverage   62.47%   62.57%   +0.11%     
==========================================
  Files        1008     1009       +1     
  Lines       45772    45781       +9     
  Branches     9631     9629       -2     
==========================================
+ Hits        28590    28642      +52     
+ Misses      15721    15689      -32     
+ Partials     1461     1450      -11     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

tchayen added 4 commits August 5, 2026 16:00
The automatic internal TestFlight group setup previously ran only when the
CLI itself created the App Store Connect app during interactive submit.
Apps created on the App Store Connect website (or submitted with ascAppId
in the submit profile) never got a group, so processed builds sat in
TestFlight with no one able to install them.

eas submit now runs the same setup best-effort for existing apps, using
strictly non-interactive App Store Connect API key auth (env vars or the
EAS credentials service) and skipping silently when no key is available.
The group regeneration prompt is skipped in non-interactive mode instead
of hanging, the TestFlight group URL no longer hardcodes a foreign app id,
and eas go now reuses the shared implementation instead of a duplicated
copy.

Claude-Session: https://claude.ai/code/session_0192qAxJXYhEtc91K1xRqNnk
@brentvatne
brentvatne force-pushed the tchayen/testflight-setup-existing-asc-app branch from db7f08c to 040418d Compare August 5, 2026 23:06
@brentvatne brentvatne added the ai-review Commits pushed to PRs with this label be automatically reviewed. label Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

✅ Thank you for adding the changelog entry!

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

🤖 AI code review

Decision: Approve with comments

Overall PR risk: Medium. The change modifies existing behavior: eas submit now runs a best-effort TestFlight group setup for every iOS submit where ascAppId resolves from the profile, and eas go shares the same group-creation code path. A traced code path shows this new step can call promptAsync for an Apple Team ID when only one EXPO_ASC_* env var is set, or when the resolved credentials-service key has no Apple team attached, so eas submit --non-interactive can stall waiting on input, or print an unexpected warning on a non-interactive runner. Blast radius is bounded to iOS submits with a profile-provided ascAppId, the step is gated by EAS_NO_AUTO_TESTFLIGHT_SETUP, and failures are caught so the submission itself does not fail, but the non-interactive prompt regression should be fixed before this reaches all users.

🟡 Warning (1)

  • TestFlight setup can prompt for the Apple Team ID during eas submitpackages/eas-cli/src/submit/ios/ensureTestFlightSetup.ts:51 (correctness) · id:577c29b47de8
    Confidence: High — the prompt call is reachable on a traced path from resolveAscAppIdentifierAsync.
    Impact if shipped: Medium — eas submit --non-interactive can stop and wait for input, and interactive runs show an unexpected Apple prompt.
    Suggested remediation: Skip the TestFlight setup when no Apple Team ID is available. Read resolvedKey.teamId or EXPO_APPLE_TEAM_ID first, and return early if both are missing. This keeps the step prompt-free, as the file comment states.

    Evidence and reasoning

    IosSubmitCommand.resolveAscAppIdentifierAsync now calls ensureTestFlightSetupForExistingAppAsync for every submit that sets ascAppId. That function calls tryAuthenticateAppStoreWithEasAscApiKeyAsync in both interactive and non-interactive mode, and it never passes an Apple Team ID.

    Trace: tryAuthenticateAppStoreWithEasAscApiKeyAsync calls ctx.appStore.ensureAuthenticatedAsync({ mode: API_KEY, teamType }). That reaches authenticateWithApiKeyAsync, then resolveAppleTeamAsync(options), then getAppleTeamIdFromEnvironmentOrOptionsAsync in resolveCredentials.ts:128. When options.teamId is undefined and EXPO_APPLE_TEAM_ID is unset, that function calls promptAsync with the message Apple Team ID:.

    options.teamId is undefined in two real cases. First, hasAscEnvVars() returns true if only one EXPO_ASC_* variable is set, and that branch passes no teamId. Second, the credentials service branch passes resolvedKey.teamId, which is ascKeyFragment.appleTeam?.appleTeamIdentifier. appleTeam is nullable.

    promptAsync only throws when process.stdin is not a TTY. It does not check ctx.nonInteractive. So eas submit --non-interactive on a TTY stops and waits for input. On a non-TTY runner the prompt throws, the helper catches it, and every submit prints a warning about stdin not being readable.

    The existing call site in SetUpProvisioningProfile.ts:107 guards this helper with ctx.nonInteractive. The new call site has no guard, so this contradicts the PR's own claim that auth here is strictly non-interactive and prompt-free.


This review is advisory — it never blocks a merge and never auto-approves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-review Commits pushed to PRs with this label be automatically reviewed.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants