Expo is a fantastic toolset for bootstrapping react native applications. If you're an Expo user, you're likely familiar with Expo's command-line interface, exp, which will automate much including building your standalone iOS and Android app binaries. However, it won't help with deploying those standalone binaries to their associated App Store.
Exp and Fastlane work productively independently, however, to sync these two tools together requires a bridge. This is where exptool comes into play.
Exptool allows you to do a few simple things with your Expo projects:
- Make sure an existing standalone app is not already in the process of being built.
- Synchronously wait for your standalone app to complete building.
- Download your standalone app from expo's server.
For a full list of exptool features, take a look at the exptool GitHub repository
Below is a tutorial on how to utilize exp, Fastlane, and exptool to automate your standalone app deployments.
We'll be creating a bash script that will:
- Publish javascript bundle to Expo's server.
- Build your standalone Android app.
- Deploy your standalone Android app to the Google Play Store.
- Build your standalone iOS app.
- Deploy your standalone iOS app to iTunes Connect (Test Flight).
This tutorial assumes that:
- Exp is installed on your machine and you have experience using it.
- Your standalone Expo app's credentials for both iOS and Android are stored on Expo's server.
- If you've never run
exp build:ios
orexp build:android
commands before, you'll need to run those commands and make sure to choose theLet Expo handle ...
option. More info on this process here.
- If you've never run
- Fastlane is installed on your machine and you have some experience using it.
- Exptool is installed -
npm install -g exptool
- You are using a macOS machine. It's possible that you can follow this tutorial on another OS, but you will experience issues with the
fastlane deliver
command as it requires a macOS machine with Xcode installed.
Let's get started! We'll be creating a bash script that you can run locally on your computer. If you have the chops and are using a build server, you can translate the bash script to fit your needs there as well.
I'll be breaking apart the script into sections so we can walk through each of the steps. At the end of the post, I'll include a code snippet of the full bash script.
Within your Expo project directory, create a deploy
script. You can do that by executing the following commands in your terminal:
https://gist.github.com/860d255782a5dc275d1a2112cc94ed66
Next, we'll run npm install
. This is more of a precaution, but a useful guarantee that all of your dependencies are installed. Add the following lines to your deploy
script:
https://gist.github.com/fefb6a034e302be140aa99223b0cf103
Now we'll be publishing our release to Expo, add the following lines to your deploy
script:
https://gist.github.com/9453b3475986d17c6c65e43713432517
Note the --non-interactive
flag. This is important to include with all exp
commands as it ensures that exp
won't halt the script with any prompts or questions.
Also, notice the --release-channel production
flag. Tailor this flag to fit your needs. You can read more about release channels here.
Now we're getting to the good stuff! Let's build our standalone Android app (.apk
binary).
Add the following to your deploy
script:
https://gist.github.com/eb41ffcc4e3a35c9fa3ae0b690093847
The exptool check:status
command will check if there is an Android or iOS build already in progress. If your app is already in the process of being built, the command will return a non-zero status code, thus exiting the script entirely. This is a required check as of writing this because Expo only allows one app, per Expo Account, to be built at a time.
After our check, we'll have Expo build our Android app. Add the following to your deploy
script:
https://gist.github.com/76313332e2bf56954612929ac30ec02e
If you've used exp
before, you'll know that these builds can take some time and are asynchronous. However, we want to wait for the build to complete so we can download the .apk
binary and submit it to the Google Play Store.
So we'll need to add the following to our deploy
script:
https://gist.github.com/58b17719872d6506d5bc0d65e7c80313
The exptool wait:build
will periodically check if Expo has finished processing the build, from there we'll continue on to the next command (exptool download:artifact
) which downloads the binary to the current directory.
Next, let's use fastlane
to submit and publish our app to the Google Play Store.
In order to follow this next step, make sure you've generated a Google Developers Service Account credentials file and downloaded that file to somewhere accessible on your computer.
Once you've downloaded your Google Developers Service Account credentials file, you may add the following code snippet to your deploy
script. Make sure to supply the correct path for --json_key <path/to/json_key.json>
flag.
https://gist.github.com/20418c6790298237f702b4712e975734
Note: --track production
flag, feel free to set this according to your needs. More about fastlane supply
command here.
That's it for automating standalone Expo Android builds and deployments! Let's move on to iOS.
The iOS build process is nearly identical to Android. I won't bore you with a reiteration of what each line does. If you need any help or have questions about a specific command, look for the identical command in step #4.
Add the following to your deploy
script:
https://gist.github.com/86808cf2da5ec758a70c6f09e624b60a
That's pretty much it. Now we just need to upload the .ipa
binary to iTunes Connect.
Finally, let's add fastlane deliver
command to our deploy
script to upload our .ipa
binary to iTunes Connect.
You'll need to set the following environment variables in order to skip Fastlane's iTunes Connect username and password prompt:
DELIVER_USERNAME
- your iTunes Connect username.DELIVER_PASSWORD
- your iTunes Connect password.
You can set these environment variables in your ~/.bash_profile
(if you use bash) or in the script using export
command.
https://gist.github.com/f0d7d3a8d96bef4793dfdf858dbc4d29
That's it! All you need to do now is run ./deploy
and leave your computer on. Feel free to grab a coffee, go on a run, play pool, work on yourself, read, meditate, or start working again. Some things you won't have to do include: waiting for commands to finish so you can execute more commands or manually uploading iOS and Android binaries.
If you've run into trouble getting your script working, here's the full script so you can double check your work. Still running into issues? Comment on this post or ping me @mglagola on twitter.