Artem M
Mac O’Clock
Published in
5 min readApr 6, 2020

--

Fastlane configuration in Swift still in Beta but it works! In this example, I’ll show you how to automate distribution to TestFlight with Fastlane.
Easy setup!

Steps

1. Setup. Generate config
2. Config overview
3. Auto increase version numbers. Project setup
4. Passing parameters. Final setup
5. Execution. Errors
6. Gitignore

1. Setup. Generate config

Install fastlane using Homebrew

brew install fastlane

or RubyGems

sudo gem install fastlane -NV

To generate config navigate your terminal to your project’s directory and run

fastlane init swift

I selected Automate beta distribution to TestFlight

Your app can have several schemes. Fastlane may ask you to select one of them.

If the required scheme is missing in the list you should mark it as shared, cancel current process with Ctrl+C and enter fastlane init swift again

Then enter Apple ID developer credentials

Passing two-factor authentication:

If the account has multiple App Store Connect or Developer Portal teams select your teams

Our fastlane setup generated and ready to use but I suggest to check it and edit if needed.

2. Config overview

You can open the generated config project /fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj in Xcode.

We will work with Appfile and Fastfile. You shouldn’t edit their counterparts from /fastlane/swift directory because they will be overwritten or replaced during build time

FastlaneSwiftRunner project contains correct Appfile and Fastfile from /fastlane.

Appfile.swift stores global variables and configs which can be used in Fastfile. For example, we can add appVersion variable and change it before upload to TestFlight, but we’ll automate this task later.

Fastfile.swift contains our “lanes” — automated tasks (automated AppStore or TestFlight distribution, etc.)

Inside “beta” lane you see different actions:

incrementBuildNumber() — increments build number
buildApp()— generates .ipa file in the project directory
uploadToTestflight() — uploads build to TestFlight

All available actions are listed here https://docs.fastlane.tools/actions/ and ready to use in our project as functions. Xcode autocomplete will help you.

Function name matters. “Lane” suffix means that function describes command which can be called from terminal by the rest part of the name. So fastlane beta command runs betaLane() func

Any custom func without Lane ending can be added to file and won’t be parsed as lane

Let's edit generated code. I found that teamId parameter is missing in uploadToTestflight() func call. It’s relevant to AppleIds with two or more dev accounts. So if teamId isn’t specified fastlane will ask you every time you run this line.

I replaced hardcoded username with appleID, defined in Appfile, and added teamId parameter. Others hardcoded values like workspace or scheme also can be moved to Appfile

Another change I did is auto-increment version number. This action is performed by the function incrementVersionNumber(). But using incremental actions requires little preparation

3. Auto increase version numbers. Project setup

Usually, we setup build and version numbers here

In this case Xcode change Bundle version and Bundle version string (short) to $(CURRENT_PROJECT_VERSION) and $(MARKETING_VERSION). Fastlane can’t work with these variables

So we need to copy the values from General to Info tab and won’t change Version and Build number on General in future.

App version (Bundle version string) can only contain numeric characters (0–9) and periods. Each integer provides information about the release in the format [Major].[Minor].[Patch]
Examples: “2”, “41.3”, “1.31.5”
More info https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleshortversionstring

Incremental func incrementVersionNumber() by default increments last number, using a default value patch. To change another number set parameter bumpType to minor or major

Looks good but let's add possibility to send bumpType from terminal!

4. Passing parameters. Final setup

class Fastfile: LaneFile {
func betaLane(withOptions options:[String: String]?) {

let appVersion = options?["appVersion"]
let bumpTypeOptional = options?["bumpType"]
let bumpType = bumpTypeOptional ?? "patch"

if appVersion != nil, bumpTypeOptional != nil {
echo(message: "Only one parameter can be used: appVersion or bumpType")
return
}

if !["major", "minor", "patch"].contains(bumpType) {
echo(message: "Unknown parameter value \(bumpType)")
return
}

desc("Push a new beta build to TestFlight")
incrementBuildNumber(xcodeproj: "Reminder.xcodeproj")
incrementVersionNumber(bumpType: bumpType, versionNumber: appVersion, xcodeproj: "Reminder.xcodeproj")
buildApp(workspace: "Reminder.xcworkspace", scheme: "Reminder")
uploadToTestflight(username: appleID, teamId: teamID)
}

All valid func signatures which can receive input params described here

https://medium.com/@doruvil/fatlane-continous-integration-swift-version-b8851f1f38b6

Our lane can process appVersion or bumpType params.
To setup any version use appVersion param

fastlane beta appVersion:3.2.13

To increment first or second number pass major or minor as value of bumpType, patch is the default value

fastlane beta bumpType:major

If both params or incorrect value for bumpType are received program prints an error message to terminal and exits.

5. Execution. Errors

To increase build, version numbers, generate a new build, and upload it to TestFlight run command with or without parameters

fastlane beta
fastlane beta appVersion:<version>
fastlane beta bumpType:<major/minor>

During execution, Fastlane may ask for an app-specific password. Follow instruction

Finally, I’ve got the error but build uploaded successfully. Just wait for an email from App Store

--

--