Can you use "expo build:ios" on a CI environment with apple 2 factor authentication and how

Viewed 3387

Is there a way to use expo build:ios on a CI environment and pass 2 factor authentication ?

I'm having troubles to start a build using expo on our CI environment due to the 2 factor authentication required for my apple developer account.

Is the expo build:ios command supposed to only be used locally or without 2 factor authentication ?

Running the build locally in interactive mode works - password and 2 factor auth was required only the first time I chose to build the app. For consecutive build I only use expo build:ios --release-channel test and that's it

My CI environment is google's Cloud Build - it runs in a Docker container, so I can't go and do a one time manual login to have the runner persist some session information like it happens locally can I?


After reading the cli usage information for expo build:ios and that you can setup your account password as ENV variable like EXPO_APPLE_PASSWORD I though it should be possible to use it in a CI environment

But then I get the following result:

expo login --non-interactive -u XXX

Success. You are now logged in as XXX.
expo build:ios --non-interactive --no-wait --release-channel test --apple-id XXXXX --team-id F7NE7X9ZFW
- Making sure project is set up correctly...
[16:43:00] Checking if there is a build in progress...
[16:43:00] Trying to authenticate with Apple Developer Portal...
Two-factor Authentication (6 digits code) is enabled for account 'XXXXX'
More information about Two-factor Authentication: https://support.apple.com/en-us/HT204915
If you're running this in a non-interactive session (e.g. server or CI)
check out https://github.com/fastlane/fastlane/tree/master/spaceship#2-step-verification
...
Please enter the 6 digit code:
[16:43:02] Authentication with Apple Developer Portal failed!
[16:43:02] Reason: Unknown reason, raw: "The input stream is exhausted."

So I follow the link for non-interactive sessions: https://github.com/fastlane/fastlane/tree/master/spaceship#2-step-verification

And I see that I have to create and use a FASTLANE_SESSION environment variable. But at that point I'm, not sure whether it will work as it seems this is coming from some tooling that expo uses internally.

I guess I can install fastlane locally and try to generate this variable with the command fastlane spaceauth -u user@example.org. I didn't find anything about this in the expo documentation though

There's information on using expo build:ios to build standalone apps, it covers only how to build them locally https://docs.expo.io/versions/v36.0.0/distribution/building-standalone-apps/

They have a guide for a CI flow ("on Your CI") - but it's using turtle-cli and for iOS it requres to run on a mac environment - it covers how to do builds yourself on your own machine and not using expo.io https://docs.expo.io/versions/v36.0.0/distribution/turtle-cli/


Another thing that I've tried is running like:

expo build:ios \
  --team-id YOUR_TEAM_ID \
  --dist-p12-path /path/to/your/dist/cert.p12 \
  --provisioning-profile-path /path/to/your/provisioning/profile.mobileprovision

With the EXPO_IOS_DIST_P12_PASSWORD set as env variable but the build would fail as it still needs apple id and password


Is there a way that I can share or copy my local session - the session that expo created the first time I ran build:ios where I'm authenticated and I'm not prompted for password anymore to the CI machine?

1 Answers

Here's what worked for me in the end:

I've created another bundle identifier com.myawesome.stuff I've also generated/created:

  • Distribution Certificate P12 --dist-p12-path
  • Push Key .p8 file - --push-id and --push-p8-path
  • Provisioning Profile. - --push-p8-path

Then locally I've run the following:

Login interactively

expo login

Authenticate with apple interactively

expo build:ios --clear-credentials --apple-id my@appleId.com --team-id=TheTeam --dist-p12-path=dist.p12 --provisioning-profile-path=profile.mobileprovision --push-p8-path=push.p8 --push-id=THEID --release-channel test

Tobe fair I've run those locally but in the google cloud console terminal

Then on the CI environment we just use:

expo login --non-interactive "--username=XXXX"
expo build:ios --non-interactive --no-wait "--release-channel=$BRANCH_NAME"

Which works and produces the following log

- Making sure project is set up correctly...
[17:48:39] Checking if there is a build in progress...

[17:48:40] Fetching available credentials
[17:48:40] Unable to validate distribution certificate due to insufficient Apple Credentials
[17:48:40] Unable to validate Push Keys due to insufficient Apple Credentials
- Performing best effort validation of Provisioning Profile...

[xmldom error]  element parse error: Error: invalid tagName: 
@#[line:99,col:125]
[xmldom error]  element parse error: Error: invalid tagName: 
@#[line:114,col:75]
[xmldom error]  element parse error: Error: invalid tagName: 
@#[line:143,col:84]
✔ Successfully performed best effort validation of Provisioning Profile.
[17:48:40]
[17:48:40] Project Credential Configuration:
[17:48:40]   Experience: @XXXX/XXXX, bundle identifier: com.XXXXXXXX
[17:48:40]     Provisioning profile is missing. It will be generated during the next build
[17:48:40]     Apple Team ID: XXXXXXX,  Apple Team Name: ---------
[17:48:40]
[17:48:40]   Distribution Certificate - Certificate ID: -----
[17:48:40]     Apple Team ID: XXXXXXX,  Apple Team Name: ---------
[17:48:40]     used by
      @XXXX/XXXX (com.XXXXXXX)
[17:48:40]   Push Notifications Key - Key ID: XXXXXXXX
[17:48:40]     Apple Team ID: XXXXXXX,  Apple Team Name: ---------
[17:48:40]     used by
      @XXXX/XXXX (com.XXXXXXX)
[17:48:40] Unable to find an existing Expo CLI instance for this directory, starting a new one...
[17:48:42] Starting Metro Bundler on port 19001.
[17:48:46] Tunnel ready.
[17:48:46] Publishing to channel 'test'...
[17:48:47] Building iOS bundle
[17:50:13] Finished building JavaScript bundle in 60785ms.
[17:50:13] Building Android bundle
[17:51:04] Finished building JavaScript bundle in 51597ms.
[17:51:04] Analyzing assets
[17:51:06] Finished building JavaScript bundle in 1669ms.
[17:51:08] Finished building JavaScript bundle in 1526ms.
[17:51:08] Uploading assets
[17:51:08] No assets changed, skipped.
[17:51:08] Processing asset bundle patterns:
[17:51:08] - /workspace/**/*
[17:51:08] Uploading JavaScript bundles
[17:51:12] Published
[17:51:12] Your URL is

https://exp.host/@XXXX/XXXX?release-channel=test

[17:51:12] › Closing Expo server
[17:51:12] › Stopping Metro bundler
[17:51:13] Checking if this build already exists...

[17:51:13] Build started, it may take a few minutes to complete.
[17:51:13] You can check the queue length at https://expo.io/turtle-status

[17:51:13] You can make this faster. 
Get priority builds at: https://expo.io/settings/billing

[17:51:13] You can monitor the build at

 https://expo.io/dashboard/XXXX/builds/e5c32814-8613-4fef-889a-05ca982e952f

[17:51:13] Alternatively, run `expo build:status` to monitor it from the command line.

check Despite the troublesome warnings at the start the build works and produces an .ipa that we've successfully submitted to test flight

[xmldom error] element parse error: Error: invalid tagName: @#[line:99,col:125]

[17:48:40] Provisioning profile is missing. It will be generated during the next build


I think the problem might be that the google cloud build machine we're using is setup with a US location, but the last time I used the expo build:ios command locally on my pc I was in a different region. So just running expo build:ios -clear-credentials might be enough and you can let expo create and manage all the required certificates.

But nowhere did I found any information that on a CI (non interactive) environment you should use expo build:ios without providing apple id and credentials

Related