Skip to content

[eas-cli] Validate/regenerate/create distribution certificate in non-interactive iOS builds using submission ASC API key when present#3739

Open
sswrk wants to merge 5 commits into
szymonswierk/non-interactive-build-provisioning-profile-validationa-and-refresh-best-effortfrom
szymonswierk/eng-21330-make-it-possible-to-refresh-a-distribution-certificate-in
Open

[eas-cli] Validate/regenerate/create distribution certificate in non-interactive iOS builds using submission ASC API key when present#3739
sswrk wants to merge 5 commits into
szymonswierk/non-interactive-build-provisioning-profile-validationa-and-refresh-best-effortfrom
szymonswierk/eng-21330-make-it-possible-to-refresh-a-distribution-certificate-in

Conversation

@sswrk
Copy link
Copy Markdown
Contributor

@sswrk sswrk commented May 18, 2026

Why

When a non-interactive build runs (e.g. from CI or a workflow job) and the app's distribution certificate is invalid or out of sync with Apple, the build can fail even without --freeze-credentials, because the certificate was not validated or refreshed against App Store Connect. That often forces a manual interactive eas build to repair credentials.

See the Linear issue: https://linear.app/expo/issue/ENG-21330/make-it-possible-to-refresh-a-distribution-certificate-in-non

How

In SetUpDistributionCertificate.runNonInteractiveAsync:

  1. If no distribution certificate is configured → throw MissingCredentialsNonInteractiveError (unchanged).
  2. Best-effort ASC authentication via env vars (EXPO_ASC_*) or the submission ASC API key from EAS credentials (same as provisioning profile repair).
  3. If the current certificate is valid (local date check; Apple portal check when authenticated) → use it.
  4. If invalid and repair is needed:
    • With --freeze-credentials → error.
    • Without ASC auth → error with guidance to configure env vars or a submission API key.
    • With ASC auth → reuse an existing valid cert from Apple or create a new one.

When ASC auth is unavailable but the certificate is still locally valid (dates OK), the build continues without Apple-side validation (existing skip behavior).

Test Plan

Added/updated unit tests in SetUpDistributionCertificate-test.ts and IosCredentialsProvider-test.ts.

Manual verification (non-interactive iOS development builds, no extra flags):

  • Current distribution certificate is valid → build proceeds, cert reused.
  • Current distribution certificate is invalid → cert validated/refreshed when ASC API key is available (env vars or EAS submission key).
  • No distribution certificate configured → Credentials are not set up error.
  • --freeze-credentials with invalid cert → blocked from repair.
  • Combined with --refresh-ad-hoc-provisioning-profile → ASC API key resolved once (shared best-effort auth).

@linear
Copy link
Copy Markdown

linear Bot commented May 18, 2026

ENG-21330

Copy link
Copy Markdown
Contributor Author

sswrk commented May 18, 2026

Warning

This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
Learn more

This stack of pull requests is managed by Graphite. Learn more about stacking.

@sswrk sswrk changed the title [eas-cli] Add --refresh-distribution-certificate for non-intractive builds [eas-cli] Add --refresh-distribution-certificate for non-intractive builds May 18, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Codecov Report

❌ Patch coverage is 86.95652% with 3 lines in your changes missing coverage. Please review.
✅ Project coverage is 57.99%. Comparing base (dc5b262) to head (1b2f5cf).

Files with missing lines Patch % Lines
...ntials/ios/actions/SetUpDistributionCertificate.ts 86.96% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@                                                       Coverage Diff                                                       @@
##           szymonswierk/non-interactive-build-provisioning-profile-validationa-and-refresh-best-effort    #3739      +/-   ##
===============================================================================================================================
+ Coverage                                                                                        57.86%   57.99%   +0.13%     
===============================================================================================================================
  Files                                                                                              913      913              
  Lines                                                                                            39622    39638      +16     
  Branches                                                                                          8296     8304       +8     
===============================================================================================================================
+ Hits                                                                                             22925    22985      +60     
+ Misses                                                                                           15242    15204      -38     
+ Partials                                                                                          1455     1449       -6     

☔ View full report in Codecov by Sentry.
📢 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.

@sswrk sswrk marked this pull request as ready for review May 18, 2026 13:24
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 18, 2026

Subscribed to pull request

File Patterns Mentions
**/* @douglowder

Generated by CodeMention

@sswrk sswrk requested review from quinlanj and sjchmiela May 18, 2026 13:27
@sswrk sswrk force-pushed the szymonswierk/eng-21330-make-it-possible-to-refresh-a-distribution-certificate-in branch from 763d237 to 1e21106 Compare May 20, 2026 11:43
@sswrk sswrk force-pushed the szymonswierk/eng-7041-allow-including-all-eas-registered-devices-automatically-in branch 2 times, most recently from 701b7d7 to 4c939d9 Compare May 20, 2026 11:57
@sswrk sswrk force-pushed the szymonswierk/eng-21330-make-it-possible-to-refresh-a-distribution-certificate-in branch 2 times, most recently from 354509c to e1e9a7e Compare May 20, 2026 12:01
Copy link
Copy Markdown
Member

@quinlanj quinlanj left a comment

Choose a reason for hiding this comment

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

lgtm. I'm surprised this was a feature people asked for because the number of dist certs apple lets you have in your account is very low (2-3 max)

Comment thread packages/eas-cli/src/credentials/ios/actions/SetUpDistributionCertificate.ts Outdated
Comment thread packages/eas-cli/src/credentials/ios/actions/SetUpDistributionCertificate.ts Outdated
@sswrk sswrk force-pushed the szymonswierk/eng-7041-allow-including-all-eas-registered-devices-automatically-in branch from d20291d to d4b4bf6 Compare May 21, 2026 11:37
@sswrk sswrk force-pushed the szymonswierk/eng-21330-make-it-possible-to-refresh-a-distribution-certificate-in branch from e1e9a7e to 6436e27 Compare May 21, 2026 11:37
@sswrk sswrk changed the base branch from szymonswierk/eng-7041-allow-including-all-eas-registered-devices-automatically-in to graphite-base/3739 May 21, 2026 12:04
throw new Error(
'No App Store Connect API Key found for distribution certificate refresh. In non-interactive mode, provide one via:\n' +
' - Environment variables: EXPO_ASC_API_KEY_PATH, EXPO_ASC_KEY_ID, EXPO_ASC_ISSUER_ID\n' +
' - EAS credentials service: configure an App Store Connect API Key for submissions on this app'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ugh it's still weird to me we're saying to use key for submissions to generate certificates

Comment thread packages/eas-cli/src/credentials/ios/actions/SetUpDistributionCertificate.ts Outdated
Log.log(`Reusing distribution certificate with serial number ${cert.serialNumber}`);
return cert;
}
return await this.createNewDistCertAsync(ctx);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how likely is that we're going to hit

if (ctx.nonInteractive) {
throw new Error(
"Start the CLI without the '--non-interactive' flag to revoke existing certificates."
);
}
often? can we do something about it?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We're going to hit this when a new certificate needs to be created and there are already 3 (non-matching, e.g. for different teams) certificates in the Apple account. I don't think we should do anything automatically in this case, as this would involve revoking unrelated certs. We could make an opt-in flag to "force override" a cert.

@sswrk sswrk force-pushed the szymonswierk/eng-21330-make-it-possible-to-refresh-a-distribution-certificate-in branch from 6436e27 to 424bd35 Compare June 3, 2026 08:30
@sswrk sswrk force-pushed the graphite-base/3739 branch from d4b4bf6 to 15311b5 Compare June 3, 2026 08:30
@sswrk sswrk changed the base branch from graphite-base/3739 to szymonswierk/non-interactive-build-provisioning-profile-validationa-and-refresh-best-effort June 3, 2026 08:30
sswrk added 3 commits June 3, 2026 10:38
…fort

Remove the --refresh-distribution-certificate opt-in flag and validate or
refresh distribution certificates automatically in non-interactive builds,
reusing tryAuthenticateAppStoreWithEasAscApiKeyAsync from the parent stack.
@sswrk sswrk force-pushed the szymonswierk/eng-21330-make-it-possible-to-refresh-a-distribution-certificate-in branch from 424bd35 to 0d88201 Compare June 3, 2026 08:38
@sswrk sswrk force-pushed the szymonswierk/non-interactive-build-provisioning-profile-validationa-and-refresh-best-effort branch from 15311b5 to dc5b262 Compare June 3, 2026 08:38
@sswrk sswrk changed the title [eas-cli] Add --refresh-distribution-certificate for non-intractive builds [eas-cli] Validate/regenerate/create distribution certificate in non-interactive iOS builds using submission ASC API key when present Jun 3, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 3, 2026

✅ Thank you for adding the changelog entry!

@sswrk
Copy link
Copy Markdown
Contributor Author

sswrk commented Jun 3, 2026

Changed this to follow the "best effort" approach like provisioning profiles in #3805 instead of being opt-in with a flag, as I don't see any downsides of just attempting to do the validation when an ASC API key is available in EAS. If we were to do something like "force setup dist cert even if some other unrelated (other apple team) cert needs to be revoked", that would be an opt-in flag for special use cases.

@quinlanj Apologies, re-requesting review.

@sswrk sswrk requested a review from quinlanj June 3, 2026 09:42
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