Custom Fastlane Actions
Introduction
While Fastlane provides many built-in actions, sometimes you need something specific to your workflow. Custom actions let you create reusable code that integrates seamlessly with Fastlane, but also gives you the flexibility to extend Fastlane’s functionality.
Basic Structure
Create a new action by running:
fastlane new_action
This will bring up the Fastlane CLI and will prompt you for some questions about your new action. In our case, we’re going to create an action that bump the minor version of a given semver string. If you remember, we’ve used this logic here.
So we’re going to call our action patch_bump
. This will create a file called patch_bump_action.rb
in the fastlane/actions
directory. The file contains quite a lot of boilerplate and dummy code, we can remove most of it, and keep the following:
module Fastlane
module Actions
class PatchBumpAction < Action
def self.run(params)
# Add your code here
end
def self.description
"Bumps the patch version of a given sem-ver string"
end
def self.available_options
[
FastlaneCore::ConfigItem.new(
key: :version,
description: "The version to bump",
optional: false
)
]
end
def self.is_supported?(platform)
true
end
end
end
end
Breakdown of the action syntax
module Fastlane
is the namespace for all Fastlane actionsmodule Actions
is the namespace for all custom actionsclass PatchBumpAction
is the name of the actiondef self.run(params)
is the method that will be called when the action is executeddef self.description
is a method that returns a description of the actiondef self.available_options
is a method that returns an array of options that the action accepts. Each option is aFastlaneCore::ConfigItem
object. Thekey
is the name of the option,description
is a description of the option, andoptional
is a boolean that indicates whether the option is required or not.def self.is_supported?(platform)
is a method that returns a boolean indicating whether the action is supported on the given platform.
Implementing the action
Now that we have the basic structure of the action, we can implement the logic to bump the patch version of a given semver string. How exciting! we’re going to reuse the logic we’ve had in the previous post.
def self.run(params)
version = params[:version]
version_number_array = version.split('.').map(&:to_i)
version_number_array[-1] += 1
version_number_array.join('.')
end
This is a very simple implementation (and honestly? shouldn’t need it’s own action!), but it should give you an idea of how to implement custom actions in Fastlane.
Using the action
To use the action in your Fastfile, you can call it like this:
lane :bump_patch do
new_version = patch_bump(version: "1.2.3")
puts "New version: #{new_version}"
end
So this is very similar to how you would use a built-in Fastlane action. You can pass in the parameters as a hash, and the action will return the new version number. The difference is that this action can also be called as a standalone thing, outside of a Fastfile, and of course, can be tested!
Testing the action
RSpec
setup
First we need to add RSpec
to our Gemfile:
group :development do
gem 'rspec'
end
# Add these to handle the warnings and LoadError
gem 'logger'
gem 'mutex_m'
gem 'abbrev'
Then run bundle install
to install the gem.
After that, we want to add a spec helper file. Add the following to the spec_helper.rb
file:
mkdir -p spec/support
touch spec/spec_helper.rb
Add the following to the spec_helper.rb
file:
require 'fastlane'
require_relative '../actions/patch_bump_action'
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
end
This tells RSpec to load the Fastlane gem and our custom action before running the tests.
Writing the tests
Given how simple this action is, we can write a test for it in the spec/actions/patch_bump_action_spec.rb
file:
require 'spec_helper'
describe Fastlane::Actions::PatchBumpAction do
describe '#run' do
it 'bumps the patch version' do
result = Fastlane::FastFile.new.parse("lane :test do
patch_bump(version: '1.2.3')
end").runner.execute(:test)
expect(result).to eq('1.2.4')
end
end
end
We’re not going to go deeper into how to test for edge cases, but you can always find more information about that, or if you want more - ask me!
Running the tests
To run the tests, you can use the following command:
bundle exec rspec
And if everything went well, you should see something like this:
Best Practices
Remember: Custom actions live in your project’s fastlane/actions/ directory. If you create something generally useful, consider turning it into a plugin!
- Always validate input parameters
- Use environment variables for sensitive data
- Keep actions focused and single-purpose
- Add proper error handling using UI.user_error!
- Write tests for your actions
- Document usage and parameters
Conclusion
Look at all that! You’ve written your first Fastlane action, and even went all 10x developer on it by adding unit tests! Well done you! 🎉 if you’ve got any questions, or would like to know more about Fastlane, hit me up! Thanks for reading!