It's no secret that in order to install Beta/Staging builds on your real iPhone device, you must first register it. You can perform it manually, but you'll need special admin privileges. Automatization is a different strategy to remove a human factor.
The approach must be easy and practical.
- Your repository contains a file named
devices.txt
that lists the allowed "UDIDs." - After the addition of a fresh device to that list, the developer will submit a PR for code review.
- A CI/CD job that will run after the PR has been approved and merged to the main branch
- That's it. Install the app after being rebuilt with a new provisioning profile.
Now let's review implementation. I'll use GitHub Actions & Fastlane as an example.
First, we require a file called "devices.txt"
the file format is displayed below (or you can view an Apple Sample):
<UDID>tabulation<Name>tabulation<Type: ios or mac>
Example:
Device ID Device Name Device Platform
a02fc03df7e12c5fb1ec247e8a14e2c3e4b7d68d My iPhoneX ios
00006000-000C551C02D2801E My MacBook mac
00008120-000C3C262478C09E My iPhone14 ios
⚠️ Warn: dev.to transforms ^^^ tabulation to spaces (be careful when copy an example above)
Now let's create a new lane in your Fastfile
Our new lane will make use of the actions match
and register_devices
.
platform :ios do
desc 'Registers new devices to the Apple Dev Portal and update provisioning profiles'
lane :register_new_device_id do
ensure_env_vars(
env_vars: [
# a secret variable Git repo encryption password
'MATCH_PASSWORD',
# a secret variable used to clone repo of certs
# more: https://docs.fastlane.tools/actions/match/
'MATCH_GIT_BASIC_AUTHORIZATION',
# your App Store Connect API Key information
# used by `register_devices` action to authenticate to App Store Connect
# more: https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-hash-option
'APP_STORE_CONNECT_API_KEY_JSON',
]
)
apiFile = Tempfile.new('api_key')
apiFile.write(ENV['APP_STORE_CONNECT_API_KEY_JSON'])
apiFile.close
# will register iOS/Mac devices with the Developer Portal so that you can include them in your provisioning profiles
register_devices(
api_key_path: apiFile.path,
devices_file: "./devices.txt"
)
# Update provisioning profiles after `register_devices`
match(
type: "adhoc",
readonly: false,
force_for_new_devices: true
)
match(
type: "appstore",
readonly: false,
force_for_new_devices: true
)
end
end
Next we need to create a new GitHub Actions workflow
Every time a devices.txt
file changes in master, the .github/workflows/register_device.yml
workflow will execute a job.
name: Mobile Automation
on:
push:
branches:
- master
paths:
- '**/devices.txt'
# When PR that changing a `devices.txt` file will be merged, this workflow will be triggered
steps:
- uses: actions/checkout@v3 # checks-out your repository
- name: Install Ruby 2.x # Required for Fastlane
uses: ruby/setup-ruby@v1
with:
ruby-version: '2.7.6' # set your version
bundler-cache: true # enable caching for bundler
- name: Install Fastlane
run: bundle install --jobs 4 --retry 3
- name: Registers a new device to the Apple Dev Portal
run: bundle exec fastlane ios register_new_device_id
env:
MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }}
MATCH_GIT_BASIC_AUTHORIZATION: ${{ secrets.MATCH_GIT_BASIC_AUTHORIZATION }}
APP_STORE_CONNECT_API_KEY_JSON: ${{ secrets.APP_STORE_CONNECT_API_KEY_JSON }}
That's enough. I this example I omitted the 'match' integration, but there are several guides online that explain how to implement it.
If you have any questions, please feel free to ask them in the comments section.
MurAmur (c)
Top comments (1)
Thank you for the detailed explanation and example code for automating the registration of apple unlink device on the Apple Developer Portal using GitHub Actions and Fastlane. This seems like a robust and efficient solution to manage device registrations for beta/staging builds. Your step-by-step guide makes it easy to understand and implement. I appreciate your contribution to simplifying the development process. If I encounter any issues or have questions, I'll be sure to reach out. Thanks again!