Migrate Fastlane to use Auth Keys
With the new requirement of having two factor authentication enabled on all apple id’s it is getting more frustrating to have CI upload apps to TestFlight as you have to manage a Fastlane/iTunes session.
This can be fixed by migration to use the new auth key provided by Appstore Connect. Fastlane already supports this so it is really easy to update any existing lanes to use the auth key.
I wrote another article on how to build and deploy your iOS app with GitHub Actions. This article uses the old method and now I want to show you how to migrate it.
Getting the Auth Key
First you need to head over to Appstore Connect and create a new auth key.
So now you have 3 pieces of information
- The issuer ID
- The Key ID
- The key it self (a .p8 file)
Next step is to setup a json file that contains the information and then modify fastlane to use it.
Authkey.json
Create a file called authkey.json and paste/modify the json below.
{
"key_id": "paste key id from appstore connect",
"issuer_id": "paste issuer id from appstore connect",
"key”: "paste in p8 contents here",
"duration": 1200,
"in_house": false
}
In the key part you must replace linebreaks with \n making it one line.
Example:
{
"key_id": "xxxXXxxXxx",
"issuer_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx",
"key”: "-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxx\nxxxxxxxxxxxxxxxxxx\n-----END PRIVATE KEY-----",
"duration": 1200,
"in_house": false
}
Modifying Fastlane
This is just a matter of adding the key path to the relevant commands.
Match
match(type: "appstore", readonly: is_ci, api_key_path: "authkey.json")
Upload to TestFlight
upload_to_testflight(changelog: ENV["CHANGELOG"] || "No changelog provided", api_key_path: "authkey.json")
Full Example
This example is taken from my other article about fastlane and Github Actions.
default_platform(:ios)
platform :ios dodesc "Run tests"
lane :tests do
run_tests(scheme: "iOS")
enddesc "Push a new beta build to TestFlight"
lane :beta do
setup_ci
match(type: "appstore", readonly: is_ci, api_key_path: "authkey.json")
build_app(workspace: "Timeable.xcworkspace", scheme: "iOS")
upload_to_testflight(changelog: ENV["CHANGELOG"] || "No changelog provided", api_key_path: "authkey.json")
enddesc "Sets the version of the bundle to a RELEASE_VERSION passed in as an environment variable"
lane :set_release_version do
version = ENV["RELEASE_VERSION"]
if version
UI.message("Setting version to #{version}")
increment_version_number(version_number: version)
increment_build_number(build_number: Time.now.to_i)
else
UI.user_error!("Environment variable RELEASE_VERSION not set")
end
end
end
Modifying Github Actions
We do not want to commit the raw authkey.json to git (I added the json file to my .gitignore so i wont commit it by mistake.), but rather an encrypted one. GitHub recommends that we use gpd.
$ gpg --symmetric --cipher-algo AES256 authkey.json
This gives you a new file called authkey.json.gpg.
Save the password and add it as a secret to your GitHub Actions.
Next up is to update GitHub Action to create the authkey.json file with the contents of the secret.
decrypt_secret.sh
This scripts takes the APPSTORE_AUTHKEY variable with the password and decrypts the file into a plain text file that fastlane can read.
#!/bin/shgpg --quiet --batch --yes --decrypt --passphrase="$APPSTORE_AUTHKEY" --output authkey.json authkey.json.gpg
Remember to add chmod +x on decrypt_secret.sh to make it executable.
.github/workflows/testflight.yml
Update the GitHub workflow to decrypt the json file so fastlane can pick it up.
name: Deploy to Testflight on:
release:
types: [created]jobs:
deploy:
name: Deploy
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v2 - name: Select Xcode Version
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest-stable
- name: Install SSH key
uses: shimataro/ssh-key-action@v2
with:
key: ${{ secrets.SSH_KEY }}
known_hosts: ${{ secrets.KNOWN_HOSTS }}
- name: Setup ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7.2
bundler-cache: true
- name: Install Pods
run: pod install
- name: Build & Distribute to Testflight
run: |
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
./decrypt_secret.sh
bundle exec fastlane set_release_version
bundle exec fastlane beta
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }
RELEASE_VERSION: ${{ github.event.release.tag_name }}
APPSTORE_AUTHKEY: ${{ secrets.APPSTORE_AUTHKEY }}
CHANGELOG: ${{ github.event.release.body }}
We basically just added one step, call decrypt_secret.sh. You can test it out locally by setting the APPSTORE_AUTHKEY environment variable.
./decrypt_secret.sh
Commit the updated workflow and test it out. GitHub Actions should now be able to test and deploy your iOS app.
This is a follow up article on how to build and deploy your iOS app with GitHub Actions.