Delivering On-demand builds with Fastlane

Yash Sharma
Team Pratilipi
Published in
5 min readOct 20, 2022

Developer productivity is one of the essential components of today’s startup culture. In a fast-paced environment with the addition of a new feature, there remains a possibility of the introduction of many new bugs too that can affect tightly-coupled components functioning and may cause a bad user experience. This problem can be solved by doing thorough regular end-to-end testing and integration tests before every release. But regularly supply of on-demand builds to the testing team can become an extra workload for the developers.

Here, Fastlane can be introduced to our development environment. Fastlane relieves the developer from the process of generating app builds, sharing them with teams, incrementing build versions and many more mundane tasks. Automation tasks can help streamline the application development process by standardising the workflow and reducing human errors.

But why we need on-demand app builds?

As we observed an increase in use cases for handling breaking backend changes and monitoring deprecated endpoints for older app versions, the count of requests for on-demand builds went up from the testing side. So, automation was introduced to the release cycle of our android application. A more effective way of utilising the powers of Fastlane can be by deploying it on CI/CD environments such as Jenkins, Travis or GitHub Actions. But it consumes resources for building the applications and we currently don’t have many use cases in our team.

After gaining some clarity about the “Why” of this article, let’s move on to the “How” of it —

Let's finish the boring stuff first, ok so to install Fastlane run the following :

brew install fastlane

Or you can take help from official docs (so did I !)

Now, in order to use Fastlane, you can create special kinds of functions known as lanes. They are barebones of any Fastlane script. Lanes being a kind of function should always have clear tasks, so a modular approach shall be taken for writing DRY-er code. Some of the lanes that can be accessed through CLI are public ones and others are private lanes. You can check all the public lanes in your Fastlane script using :

fastlane lanes

Fastlane also provides the feature of creating blocks such as before_all after_all, before_each and after_each lanes which can be utilised for logging or adding environment variables before lanes start execution. There is also an error block which can be used for logging and sending error notifications. It looks like this :

error do |lane, exception|
sh "echo " + exception.message
end

Here, you can see sh the keyword which is a function. It accepts an arbitrary shell command as a parameter and executes it. This particular in-built function of the Fastlane has wide applications as it gives freedom to perform a variety of operations. But there’s one problem also which came around for us many times while creating this script. For shell commands like :

grep "versionName" ./build.gradle.kts

To execute the above shell command in Fastlane, we will write :

sh "grep \"versionName\" ./build.gradle.kts"

Here \" (or any escape sequence) needs to be added everywhere a string has to be passed in the shell command, so in order to simplify this we used a lambda function :

def wrap(sym)
return lambda {|str| sym+str+sym }
end

The wrap fun returns a lambda where the string sym is wrapped around the str variable passed to the lambda.

q = wrap("\")

This lambda q can later be used like this :

sh "grep " + q.call("versionCode")+ " ./build.gradle.kts" 

Parameters in Fastlane can be passed as a hash object in ruby (similar to dict in python) and are named options. An example of passing parameters between lanes will be :

lane :slackRelease do 
process_build(buildType: "release")
end
lane :slackDebug do
process_build(buildType: "debug")
end
private_lane :process_build do |options|
type = options[:buildType]
task = type == "release" ? "assembleRelease" : "assembleDebug"
gradle(tasks: ["clean", task])
sh "echo BUILD SUCCESSFUL"
end

Here, slackRelease and slackDebug lanes pass buildType parameters to private lane process_build. Inside this lane, params are accessed using the options hash object.

After understanding the basics, we can look at a specific feature that my team included in our Fastlane script. In the how part, we discussed sending the on-demand builds to slack. For making that happen, we took the help of Slack API. The build file generated after performing the Gradle tasks was to be sent on a slack channel. For this Slack API had a method — files.upload

POST https://slack.com/api/files.upload

This command needed to be curl using the sh function. Our upload lane fetched all the required arguments and collected them as a hash object params. Later a string curl_args which is generated by appending all arguments is added to the string curl and is passed to the shell from the Fastlane script.

desc "Upload the APK to slack channel"
private_lane :upload do |options|
q = wrap("\"")
type = options[:buildType]
slack_upload_url = ENV["UPLOAD_URL"]

curl_args = " -X POST " + slack_upload_url
options.each do |key, value|
curl_args = curl_args + " -F " + key.to_s + "=" + value
end

puts curl_args
sh "curl" + curl_args
end

Above, ENV is another hash, where all environment variables are stored in the before_all lane and accessed later in individual lanes. After everything runs smoothly, a call to after_all lane is used to inform about the successful run.

after_all do |lane|
sh "echo successful deploy"
end

And the final result of the Fastlane script is the following slack message that includes an apk file, a success message and the hash of the last commit when the build was generated.

Automated Slack message from Fastlane

Conclusion

With a large presence on GitHub and an ever-growing community, Fastlane has become one of the first choices in automation. So finally, with this amount of knowledge, you can also dive into creating your own automation script in Fastlane to automate tasks and increase your teams' productivity.

If you want to check out our Fastlane script, you can check here.

Follow me onTwitter, LinkedIn, GitHub

--

--