Automate Flutter App Deployment on iOS to TestFlight using Fastlane and Semaphore

Prerequisites

  • An existing Flutter project; you can use our starter app or create one by running flutter create my_app
  • An Apple Developer Account (a.k.a. developer account) for the developer certificates and provisioning profiles–costs $99/year

Preparing a Flutter (iOS) App

TestFlight

Photo by TestFlight.

Creating a new bundle identifier

Creating a new bundle identifier

Creating a new app

Assigning the bundle identifier

Setting up fastlane

Installation

Setting up fastlane for iOS

cd ios && fastlane init && cd
  1. Select manual setup:
What would you like to use fastlane for?
1. 📸 Automate screenshots
2. 👩‍✈️ Automate beta distribution to TestFlight
3. 🚀 Automate App Store distribution
4. 🛠 Manual setup - manually setup your project to automate your tasks
>>> 4

Setting up fastlane match

fastlane match init
fastlane match supports multiple storage modes, please select the one you want to use:
1. git
2. google_cloud
3. s3
type("appstore")

Generating fastlane match credentials

app_identifier(["com.yourapp.example"])
fastlane match appstore
fastlane match appstore -a com.yourapp.example

Setting environment variables

example_value = ENV["EXAMPLE_VALUE"]
sem create secret semaphore-flutter2-env \
-e MATCH_GIT_URL="<YOUR_MATCH_GIT_URL>" \
-e MATCH_PASSWORD="<YOUR_MATCH_PASSWORD>" \
-e MATCH_GIT_AUTHORIZATION="<YOUR_GIT_AUTHORIZTION_TOKEN>" \
-e FASTLANE_USER="<YOUR_APPLE_ID_EMAIL>" \
-e FASTLANE_PASSWORD="<YOUR_APPLE_ID_PASSWORD>"\
-e FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD="<YOUR_APPLE_APP_SPECIFIC_PASSWORD"
git_authorization = ENV["MATCH_GIT_AUTHORIZATION"]
team_id = ENV["TEAM_ID"]
app_id = ENV["APP_ID"]
app_identifier = ENV["APP_IDENTIFIER"]
provisioning_profile_specifier = ENV["PROVISIONING_PROFILES_SPECIFIER"]
temp_keychain_user = "temp"
temp_keychain_password = "temp"

Creating fastlane deploy lane

# This is where the environment variables are located(truncated)# Add the followingdef delete_temp_keychain(name)
delete_keychain(
name: name
) if File.exist? File.expand_path("~/Library/Keychains/#{name}-db")
end
def create_temp_keychain(name, password)
create_keychain(
name: name,
password: password,
unlock: false,
timeout: 0
)
end
def ensure_temp_keychain(name, password)
delete_temp_keychain(name)
create_temp_keychain(name, password)
end
platform :ios do
lane :deploy do
# Step 1 - Create keychains
keychain_name = temp_keychain_user
keychain_password = temp_keychain_password
ensure_temp_keychain(keychain_name, keychain_password)
# Step 2 - Download provisioning profiles and certificates
match(
type: 'appstore',
app_identifier: app_identifier,
git_basic_authorization: Base64.strict_encode64(git_authorization),
readonly: true,
keychain_name: keychain_name,
keychain_password: keychain_password
)
# Step 3 - Build the project
gym(
configuration: "Release",
workspace: "Runner.xcworkspace",
scheme: "Runner",
export_method: "app-store",
export_options: {
provisioningProfiles: {
app_id => provisioning_profile_specifier,
}
}
)
# Step 4 - Upload the project
pilot(
apple_id: "#{app_id}",
app_identifier: "#{app_identifier}",
skip_waiting_for_build_processing: true,
skip_submission: true,
distribute_external: false,
notify_external_testers: false,
ipa: "./Runner.ipa"
)
# Step 5 - Delete temporary keychains
delete_temp_keychain(keychain_name)
end
end

Deploying to Semaphore

Semaphore

Creating your Semaphore project

Setting up continuous integration pipeline

checkout
cache restore flutter-packages-$SEMAPHORE_GIT_BRANCH-$(checksum pubspec.yaml),flutter-packages-$(checksum pubspec.yaml),flutter-packages
flutter pub get
cache store flutter-packages-$SEMAPHORE_GIT_BRANCH-$(checksum pubspec.yaml),flutter-packages-$(checksum pubspec.yaml),flutter-packages /root/.pub-cache
flutter format --set-exit-if-changed .
flutter analyze .
checkout
cache restore flutter-packages-$SEMAPHORE_GIT_BRANCH-$(checksum pubspec.yaml),flutter-packages-$(checksum pubspec.yaml),flutter-packages
flutter pub get
flutter test test
checkout
cache restore flutter-packages-$SEMAPHORE_GIT_BRANCH-$(checksum pubspec.yaml),flutter-packages-$(checksum pubspec.yaml),flutter-packages
flutter pub get

Setting up continuous deployment pipeline

checkout
cache restore flutter-packages-$SEMAPHORE_GIT_BRANCH-$(checksum pubspec.yaml),flutter-packages-$(checksum pubspec.yaml),flutter-packages
flutter pub get
cache store flutter-packages-$SEMAPHORE_GIT_BRANCH-$(checksum pubspec.yaml),flutter-packages-$(checksum pubspec.yaml),flutter-packages /root/.pub-cache
checkout
cache restore flutter-packages-$SEMAPHORE_GIT_BRANCH-$(checksum pubspec.yaml),flutter-packages-$(checksum pubspec.yaml),flutter-packages
flutter build ios --no-codesign
cd ios
bundle install
cache store
bundle exec fastlane deploy
git fetch --all
git merge origin/set-up-semaphore
git push origin master

Conclusion

--

--

--

Supporting developers with insights and tutorials on delivering good software. · https://semaphoreci.com

Love podcasts or audiobooks? Learn on the go with our new app.

Recommended from Medium

Using Menus in iOS 14

15 Days of Swift : Creating the first iOS App

SwiftUI: Scroll like in UIKit using only SwiftUI _hidden APIs

A beginners guide to becoming a iOS Developer in 2019

Prototyping With SwiftUI: Creating Complex Interactions Using Gestures and Modifiers

Diffable Data Sources in Swift

FacepickerController : Detect face from image

What’s new in location — iOS 14

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Semaphore

Semaphore

Supporting developers with insights and tutorials on delivering good software. · https://semaphoreci.com

More from Medium

Deploy Flutter (iOS) Apps to Testers using Firebase App Distribution with Semaphore

Multi-Platform App Development Using SwiftUI, and Flutter: The Similarities and the Differences [+…

Displaying FCM notifications on iOS Simulators

Distribute your Flutter Application with Azure DevOps and App Center