module Fastlane class ActionsList def self.run(filter: nil, platform: nil) require 'terminal-table' if filter show_details(filter: filter) else print_all(platform: platform) end end def self.print_all(platform: nil) rows = [] all_actions(platform) do |action, name| current = [] current << name.yellow if action < Action current << action.description if action.description authors = Array(action.author || action.authors) current << authors.first.green if authors.count == 1 current << "Multiple".green if authors.count > 1 else UI.error action_subclass_error(name) current << "Please update action file".red current << ' ' end rows << current end puts Terminal::Table.new( title: "Available fastlane actions".green, headings: ['Action', 'Description', 'Author'], rows: rows ) puts " Platform filter: #{platform}".magenta if platform puts " Total of #{rows.count} actions" puts "\nGet more information for one specific action using `fastlane action [name]`\n".green end def self.show_details(filter: nil) puts "Loading documentation for #{filter}:".green puts "" action = find_action_named(filter) if action unless action < Action UI.user_error! action_subclass_error(filter) end print_summary(action, filter) print_options(action, filter) print_output_variables(action, filter) print_return_value(action, filter) puts "More information can be found on https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Actions.md" puts "" else puts "Couldn't find action for the given filter.".red puts "==========================================\n".red print_all # show all available actions instead end end def self.action_subclass_error(name) "Please update your action '#{name}' to be a subclass of `Action` by adding ` < Action` after your class name." end def self.print_summary(action, name) rows = [] if action.description rows << [action.description] rows << [' '] end if action.details rows << [action.details] rows << [' '] end authors = Array(action.author || action.authors) rows << ["Created by #{authors.join(', ').green}"] unless authors.empty? puts Terminal::Table.new(title: name.green, rows: rows) puts "" end def self.print_options(action, name) options = parse_options(action.available_options) if action.available_options if options puts Terminal::Table.new( title: "#{name} Options".green, headings: ['Key', 'Description', 'Env Var', 'Default'], rows: options ) required_count = action.available_options.count do |o| o.kind_of?(FastlaneCore::ConfigItem) && o.optional == false end if required_count > 0 puts "#{required_count} of the available parameters are required".magenta puts "They are marked with an asterisk *".magenta end else puts "No available options".yellow end puts "" end def self.print_output_variables(action, name) output = action.output return if output.nil? || output.empty? puts Terminal::Table.new( title: "#{name} Output Variables".green, headings: ['Key', 'Description'], rows: output.map { |key, desc| [key.yellow, desc] } ) puts "Access the output values using `lane_context[SharedValues::VARIABLE_NAME]`" puts "" end def self.print_return_value(action, name) return unless action.return_value puts Terminal::Table.new(title: "#{name} Return Value".green, rows: [[action.return_value]]) puts "" end # Iterates through all available actions and yields from there def self.all_actions(platform = nil) action_symbols = Fastlane::Actions.constants.select {|c| Fastlane::Actions.const_get(c).kind_of? Class } action_symbols.sort.each do |symbol| action = Fastlane::Actions.const_get(symbol) # We allow classes that don't respond to is_supported? to come through because we want to list # them as broken actions in the table, regardless of platform specification next if platform && action.respond_to?(:is_supported?) && !action.is_supported?(platform.to_sym) name = symbol.to_s.gsub('Action', '').fastlane_underscore yield action, name end end def self.find_action_named(name) all_actions do |action, action_name| return action if action_name == name end nil end # Helper: def self.parse_options(options, fill_all = true) rows = [] rows << [options] if options.kind_of? String if options.kind_of? Array options.each do |current| if current.kind_of? FastlaneCore::ConfigItem key_name = (current.optional ? " " : "* ") + current.key.to_s rows << [key_name.yellow, current.description, current.env_name, current.default_value] elsif current.kind_of? Array # Legacy actions that don't use the new config manager UI.user_error!("Invalid number of elements in this row: #{current}. Must be 2 or 3") unless [2, 3].include? current.count rows << current rows.last[0] = rows.last.first.yellow # color it yellow :) rows.last << nil while fill_all and rows.last.count < 3 # to have a nice border in the table end end end rows end end end