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

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:

Spec success

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!

  1. Always validate input parameters
  2. Use environment variables for sensitive data
  3. Keep actions focused and single-purpose
  4. Add proper error handling using UI.user_error!
  5. Write tests for your actions
  6. 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!