class Fastlane::Actions::GetVersionNumberAction

Public Class Methods

authors() click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 180
def self.authors
  ["Liquidsoul", "joshdholtz"]
end
available_options() click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 152
def self.available_options
  [
    FastlaneCore::ConfigItem.new(key: :xcodeproj,
                       env_name: "FL_VERSION_NUMBER_PROJECT",
                       description: "Path to the Xcode project to read version number from, or its containing directory, optional. If ommitted, or if a directory is passed instead, it will use the first Xcode project found within the given directory, or the project root directory if none is passed",
                       optional: true,
                       verify_block: proc do |value|
                         UI.user_error!("Please pass the path to the project or its containing directory, not the workspace path") if value.end_with?(".xcworkspace")
                         UI.user_error!("Could not find file or directory at path '#{File.expand_path(value)}'") unless File.exist?(value)
                         UI.user_error!("Could not find Xcode project in directory at path '#{File.expand_path(value)}'") if File.extname(value) != ".xcodeproj" && Dir.glob("#{value}/*.xcodeproj").empty?
                       end),
    FastlaneCore::ConfigItem.new(key: :target,
                       env_name: "FL_VERSION_NUMBER_TARGET",
                       description: "Target name, optional. Will be needed if you have more than one non-test target to avoid being prompted to select one",
                       optional: true),
    FastlaneCore::ConfigItem.new(key: :configuration,
                       env_name: "FL_VERSION_NUMBER_CONFIGURATION",
                       description: "Configuration name, optional. Will be needed if you have altered the configurations from the default or your version number depends on the configuration selected",
                       optional: true)
  ]
end
category() click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 202
def self.category
  :project
end
description() click to toggle source

@!group Documentation

# File fastlane/lib/fastlane/actions/get_version_number.rb, line 144
def self.description
  "Get the version number of your project"
end
details() click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 148
def self.details
  "This action will return the current version number set on your project."
end
example_code() click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 188
def self.example_code
  [
    'version = get_version_number(xcodeproj: "Project.xcodeproj")',
    'version = get_version_number(
      xcodeproj: "Project.xcodeproj",
      target: "App"
    )'
  ]
end
get_plist!(folder, target, configuration = nil) click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 99
def self.get_plist!(folder, target, configuration = nil)
  plist_files = target.resolved_build_setting("INFOPLIST_FILE", true)
  plist_files_count = plist_files.values.compact.uniq.count

  # Get plist file for specified configuration
  # Or: Prompt for configuration if plist has different files in each configurations
  # Else: Get first(only) plist value
  if configuration
    plist_file = plist_files[configuration]
  elsif plist_files_count > 1
    options = plist_files.keys
    selected = UI.select("What build configuration would you like to use?", options)
    plist_file = plist_files[selected]
  else
    plist_file = plist_files.values.first
  end

  # $(SRCROOT) is the path of where the XcodeProject is
  # We can just set this as empty string since we join with `folder` below
  if plist_file.include?("$(SRCROOT)/")
    plist_file.gsub!("$(SRCROOT)/", "")
  end

  # plist_file can be `Relative` or `Absolute` path.
  # Make to `Absolute` path when plist_file is `Relative` path
  unless File.exist?(plist_file)
    plist_file = File.absolute_path(File.join(folder, plist_file))
  end

  UI.user_error!("Cannot find plist file: #{plist_file}") unless File.exist?(plist_file)

  plist_file
end
get_project!(xcodeproj_path_or_dir) click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 43
def self.get_project!(xcodeproj_path_or_dir)
  require 'xcodeproj'
  if File.extname(xcodeproj_path_or_dir) == ".xcodeproj"
    project_path = xcodeproj_path_or_dir
  else
    project_path = Dir.glob("#{xcodeproj_path_or_dir}/*.xcodeproj").first
  end

  if project_path && File.exist?(project_path)
    return Xcodeproj::Project.open(project_path)
  else
    UI.user_error!("Unable to find Xcode project at #{project_path || xcodeproj_path_or_dir}")
  end
end
get_target!(project, target_name) click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 58
def self.get_target!(project, target_name)
  targets = project.targets

  # Prompt targets if no name
  unless target_name

    # Gets non-test targets
    non_test_targets = targets.reject do |t|
      # Not all targets respond to `test_target_type?`
      t.respond_to?(:test_target_type?) && t.test_target_type?
    end

    # Returns if only one non-test target
    if non_test_targets.count == 1
      return targets.first
    end

    options = targets.map(&:name)
    target_name = UI.select("What target would you like to use?", options)
  end

  # Find target
  target = targets.find do |t|
    t.name == target_name
  end
  UI.user_error!("Cannot find target named '#{target_name}'") unless target

  target
end
get_version_number_from_build_settings!(target, variable, configuration = nil) click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 88
def self.get_version_number_from_build_settings!(target, variable, configuration = nil)
  target.build_configurations.each do |config|
    if configuration.nil? || config.name == configuration
      value = config.resolve_build_setting(variable)
      return value if value
    end
  end

  return nil
end
get_version_number_from_plist!(plist_file) click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 133
def self.get_version_number_from_plist!(plist_file)
  plist = Xcodeproj::Plist.read_from_path(plist_file)
  UI.user_error!("Unable to read plist: #{plist_file}") unless plist

  plist["CFBundleShortVersionString"]
end
is_supported?(platform) click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 184
def self.is_supported?(platform)
  [:ios, :mac].include?(platform)
end
output() click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 174
def self.output
  [
    ['VERSION_NUMBER', 'The version number']
  ]
end
return_type() click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 198
def self.return_type
  :string
end
run(params) click to toggle source
# File fastlane/lib/fastlane/actions/get_version_number.rb, line 10
def self.run(params)
  xcodeproj_path_or_dir = params[:xcodeproj] || '.'
  xcodeproj_dir = File.extname(xcodeproj_path_or_dir) == ".xcodeproj" ? File.dirname(xcodeproj_path_or_dir) : xcodeproj_path_or_dir
  target_name = params[:target]
  configuration = params[:configuration]

  # Get version_number
  project = get_project!(xcodeproj_path_or_dir)
  target = get_target!(project, target_name)
  plist_file = get_plist!(xcodeproj_dir, target, configuration)
  version_number = get_version_number_from_plist!(plist_file)

  # Get from build settings (or project settings) if needed (ex: $(MARKETING_VERSION) is default in Xcode 11)
  if version_number =~ /\$\(([\w\-]+)\)/
    version_number = get_version_number_from_build_settings!(target, $1, configuration) || get_version_number_from_build_settings!(project, $1, configuration)

  # ${MARKETING_VERSION} also works
  elsif version_number =~ /\$\{([\w\-]+)\}/
    version_number = get_version_number_from_build_settings!(target, $1, configuration) || get_version_number_from_build_settings!(project, $1, configuration)
  end

  # Error out if version_number is not set
  if version_number.nil?
    UI.user_error!("Unable to find Xcode build setting: #{$1}")
  end

  # Store the number in the shared hash
  Actions.lane_context[SharedValues::VERSION_NUMBER] = version_number

  # Return the version number because Swift might need this return value
  return version_number
end