Written by Chris Raastad
Any iOS developer can tell you that code signing and publishing are one of the toughest parts of their job. Flutter can make writing iOS apps a lot easier, but still can’t ease the pain of deployment. It seems like every time you open Xcode and hit build archive something goes wrong, whether it’s a certificate not on the right keychain or some provisioning profile out of place. What if I showed you a way to build, package, and distribute your app to TestFlight without opening XCode?
Meet Codemagic CLI Tools, the magic powering mobile app builds at Codemagic CI/CD. In this article I’ll show you how to build, code sign, and publish a Flutter app to App Store Connect without opening Xcode. You can even use these commands on another CI/CD provider to automate your deployments.
If you’re not using Codemagic yet, then sign up now:
Also, did you know that with Codemagic you can build and publish iOS apps without a Mac?
Preparations
- Of course, you’ll need a Flutter application. If you need to create one, follow the getting started guide to install Flutter. Then you can create a new Flutter project by running in a terminal:
flutter create --org COM.YOUR.ORG my_flutter_app
- It's really important you have a unique org and app name so that you can create a matching bundle ID and application in App Store Connect.
-
You will need to enroll in the Apple Developer Program to build and publish iOS applications.
-
You will need to create an App ID identifier for an App with a Bundle ID matching the new Flutter project. For org
com.craastad
and the example above, the Bundle ID would becom.craastad.myFlutterApp
. -
You will need to create a new App Store Connect App for the platform iOS, with the Bundle ID of the last step, and with the Bundle ID as the SKU.
-
You will need App Store Connect API Key. You can follow the steps in Creating an API Key for Codemagic to create a key with App Manager access. You will need the Issuer ID, Key ID, and the downloaded .p8 file.
-
You need to export or create an iOS Distribution certificate to code sign and package a build archive. If you have an existing certificate, you can export the private keys by executing:
openssl pkcs12 -in <certificate_name>.p12 -nodes -nocerts | openssl rsa -out cert_key
- Or you can create a new private key by executing:
ssh-keygen -t rsa -b 2048 -m PEM -f cert_key -q -N ""
- Later, you can have CLI tools automatically create a new iOS Distribution certificate from the private key.
-
You’ll need to install Python 3 on the machine, this is as simple as
brew install python
and checking thatpython3 --version
executes successfully. -
And finally, install the Codemagic CLI Tools by executing:
pip3 install codemagic-cli-tools -U
Code signing and deployment
This step covers creating a build archive and uploading your build to App Store Connect using Flutter build commands and Codemagic CLI Tools executed in a terminal in the Flutter project directory. This allows you to create a build archive with full control of distribution certificates in a temporary keychain isolated from your login keychain.
- To make CLI tools commands more precise, export the following variables:
export APP_STORE_CONNECT_ISSUER_ID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee
export APP_STORE_CONNECT_KEY_IDENTIFIER=ABC1234567
export APP_STORE_CONNECT_PRIVATE_KEY=@file:/path/to/api/key/AuthKey_XXXYYYZZZ.p8
- Set up a new temporary keychain to be used for code signing:
keychain initialize
WARNING: Restore Login Keychain!
After running keychain initialize
you must execute:
keychain use-login
This sets your login keychain back to the default to avoid potential authentication issues with apps on your machine.
- Fetch the code signing files from App Store Connect:
app-store-connect fetch-signing-files YOUR.APP.BUNDLE_ID \
--type IOS_APP_STORE \
--certificate-key=@file:/path/to/cert_key \
--create
- Where
cert_key
is either your exported iOS Distribution certificate private key or a new private key which automatically generates a new certificate. The certificate will be created from the private key if it doesn’t exist in App Store Connect.
- Now add the fetched certificates to your keychain:
keychain add-certificates
- Update the Xcode project settings to use fetched code signing profiles:
xcode-project use-profiles
- Install Flutter dependencies:
flutter packages pub get
- Install CocoaPods dependencies:
find . -name "Podfile" -execdir pod install \;
- Build the Flutter iOS project:
flutter build ipa --release \
--export-options-plist=/Users/USERNAME/export_options.plist
- Note that
export_options.plist
is the output of thexcode-project use-profiles
command.
- Publish the app to App Store Connect:
APP_FILE=$(find $(pwd) -name "*.ipa")
app-store-connect publish \
--path "$APP_FILE"
As mentioned earlier, don’t forget to set your login keychain as the default to avoid authentication issues with apps on your machine:
keychain use-login
That’s it! You should receive an email within 30 minutes notifying you that your build has been validated and is available to release to testers on TestFlight. At this point you can choose whether to release to testers on TestFlight or to the App Store. These steps can be repeated with any CI/CD provider that can run builds on a macOS build machine.
For a seamless experience building and deploying Flutter apps, check out Codemagic, the fastest platform for building mobile apps.
If you’re facing issues with uploading your app to App Store Connect, check out this article.