class Fastlane::SwiftLaneManager

Public Class Methods

build_runner!() click to toggle source
# File fastlane/lib/fastlane/swift_lane_manager.rb, line 276
def self.build_runner!
  UI.verbose("Building FastlaneSwiftRunner")
  require 'fastlane_core'
  require 'gym'
  require 'gym/generators/build_command_generator'

  project_options = {
      project: FastlaneCore::FastlaneFolder.swift_runner_project_path,
      skip_archive: true
    }
  Gym.config = FastlaneCore::Configuration.create(Gym::Options.available_options, project_options)
  build_command = Gym::BuildCommandGenerator.generate

  FastlaneCore::CommandExecutor.execute(
    command: build_command,
    print_all: false,
    print_command: !Gym.config[:silent]
  )
end
collect_tool_paths_for_replacement(all_user_tool_file_paths: nil, look_for_new_configs: nil) click to toggle source

Find all the config files we care about (Deliverfile, Gymfile, etc), and build tuples of what file we'll look for in the Xcode project, and what file paths we'll need to swap (since we have to inject the user's configs)

Return a mapping of what file paths we're looking => new file pathes we'll need to inject

# File fastlane/lib/fastlane/swift_lane_manager.rb, line 118
def self.collect_tool_paths_for_replacement(all_user_tool_file_paths: nil, look_for_new_configs: nil)
  new_user_tool_file_paths = all_user_tool_file_paths.select do |user_config, preinstalled_config_relative_path, user_config_relative_path|
    if look_for_new_configs
      File.exist?(user_config)
    else
      !File.exist?(user_config)
    end
  end

  # Now strip out the fastlane-relative path and leave us with xcodeproj relative paths
  new_user_tool_file_paths = new_user_tool_file_paths.map do |user_config, preinstalled_config_relative_path, user_config_relative_path|
    if look_for_new_configs
      [preinstalled_config_relative_path, user_config_relative_path]
    else
      [user_config_relative_path, preinstalled_config_relative_path]
    end
  end
  return new_user_tool_file_paths
end
cruise_lane(lane, parameters = nil, env = nil, disable_runner_upgrades: false, swift_server_port: nil) click to toggle source

@param lane_name The name of the lane to execute @param parameters [Hash] The parameters passed from the command line to the lane @param env Dot Env Information

# File fastlane/lib/fastlane/swift_lane_manager.rb, line 9
def self.cruise_lane(lane, parameters = nil, env = nil, disable_runner_upgrades: false, swift_server_port: nil)
  UI.user_error!("lane must be a string") unless lane.kind_of?(String) || lane.nil?
  UI.user_error!("parameters must be a hash") unless parameters.kind_of?(Hash) || parameters.nil?

  # Sets environment variable and lane context for lane name
  ENV["FASTLANE_LANE_NAME"] = lane
  Actions.lane_context[Actions::SharedValues::LANE_NAME] = lane

  started = Time.now
  e = nil
  begin
    display_upgraded_message = false
    if disable_runner_upgrades
      UI.verbose("disable_runner_upgrades is true, not attempting to update the FastlaneRunner project".yellow)
    elsif Helper.ci?
      UI.verbose("Running in CI, not attempting to update the FastlaneRunner project".yellow)
    else
      display_upgraded_message = self.ensure_runner_up_to_date_fastlane!
    end

    self.ensure_runner_built!
    swift_server_port ||= 2000
    socket_thread = self.start_socket_thread(port: swift_server_port)
    sleep(0.250) while socket_thread[:ready].nil?
    # wait on socket_thread to be in ready state, then start the runner thread
    self.cruise_swift_lane_in_thread(lane, parameters, swift_server_port)

    socket_thread.join
  rescue Exception => ex # rubocop:disable Lint/RescueException
    e = ex
  end
  # If we have a thread exception, drop that in the exception
  # won't ever have a situation where e is non-nil, and socket_thread[:exception] is also non-nil
  e ||= socket_thread[:exception]

  unless e.nil?
    print_lane_context

    # We also catch Exception, since the implemented action might send a SystemExit signal
    # (or similar). We still want to catch that, since we want properly finish running fastlane
    # Tested with `xcake`, which throws a `Xcake::Informative` object
    UI.error(e.to_s) if e.kind_of?(StandardError) # we don't want to print things like 'system exit'
  end

  skip_message = false

  # if socket_thread is nil, we were probably debugging, or something else weird happened
  exit_reason = :cancelled if socket_thread.nil?

  # normal exit means we have a reason
  exit_reason ||= socket_thread[:exit_reason]

  if exit_reason == :cancelled && e.nil?
    skip_message = true
  end

  duration = ((Time.now - started) / 60.0).round

  finish_fastlane(nil, duration, e, skip_message: skip_message)

  if display_upgraded_message
    UI.message("We updated your FastlaneRunner project during this run to make it compatible with your current version of fastlane.".yellow)
    UI.message("Please make sure to check the changes into source control.".yellow)
  end
end
cruise_swift_lane_in_thread(lane, parameters = nil, swift_server_port) click to toggle source
# File fastlane/lib/fastlane/swift_lane_manager.rb, line 80
def self.cruise_swift_lane_in_thread(lane, parameters = nil, swift_server_port)
  if parameters.nil?
    parameters = {}
  end

  parameter_string = ""
  parameters.each do |key, value|
    parameter_string += " #{key} #{value}"
  end

  if FastlaneCore::Globals.verbose?
    parameter_string += " logMode verbose"
  end

  parameter_string += " swiftServerPort #{swift_server_port}"

  return Thread.new do
    Actions.sh(%(#{FastlaneCore::FastlaneFolder.swift_runner_path} lane #{lane}#{parameter_string} > /dev/null))
  end
end
display_lanes() click to toggle source
# File fastlane/lib/fastlane/swift_lane_manager.rb, line 75
def self.display_lanes
  self.ensure_runner_built!
  Actions.sh(%(#{FastlaneCore::FastlaneFolder.swift_runner_path} lanes))
end
ensure_runner_built!() click to toggle source
# File fastlane/lib/fastlane/swift_lane_manager.rb, line 227
def self.ensure_runner_built!
  UI.verbose("Checking for new user-provided tool configuration files")
  # if self.link_user_configs_to_project returns true, that means we need to rebuild the runner
  runner_needs_building = self.link_user_configs_to_project

  if FastlaneCore::FastlaneFolder.swift_runner_built?
    runner_last_modified_age = File.mtime(FastlaneCore::FastlaneFolder.swift_runner_path).to_i
    fastfile_last_modified_age = File.mtime(FastlaneCore::FastlaneFolder.fastfile_path).to_i

    if runner_last_modified_age < fastfile_last_modified_age
      # It's older than the Fastfile, so build it again
      UI.verbose("Found changes to user's Fastfile.swift, setting re-build runner flag")
      runner_needs_building = true
    end
  else
    # Runner isn't built yet, so build it
    UI.verbose("No runner found, setting re-build runner flag")
    runner_needs_building = true
  end

  if runner_needs_building
    self.build_runner!
  end
end
ensure_runner_up_to_date_fastlane!() click to toggle source

do we have the latest FastlaneSwiftRunner code from the current version of fastlane?

# File fastlane/lib/fastlane/swift_lane_manager.rb, line 253
def self.ensure_runner_up_to_date_fastlane!
  upgraded = false
  upgrader = SwiftRunnerUpgrader.new

  upgrade_needed = upgrader.upgrade_if_needed!(dry_run: true)
  if upgrade_needed
    UI.message("It looks like your `FastlaneSwiftRunner` project is not up-to-date".green)
    UI.message("If you don't update it, fastlane could fail".green)
    UI.message("We can try to automatically update it for you, usually this works 🎈 🐐".green)
    user_wants_upgrade = UI.confirm("Should we try to upgrade just your `FastlaneSwiftRunner` project?")

    UI.important("Ok, if things break, you can try to run this lane again and you'll be prompted to upgrade another time") unless user_wants_upgrade

    if user_wants_upgrade
      upgraded = upgrader.upgrade_if_needed!
      UI.success("Updated your FastlaneSwiftRunner project with the newest runner code") if upgraded
      self.build_runner! if upgraded
    end
  end

  return upgraded
end
first_time_setup() click to toggle source
# File fastlane/lib/fastlane/swift_lane_manager.rb, line 161
def self.first_time_setup
  setup_message = ["fastlane is now configured to use a swift-based Fastfile (Fastfile.swift) 🦅"]
  setup_message << "To edit your new Fastfile.swift, type: `open #{FastlaneCore::FastlaneFolder.swift_runner_project_path}`"

  # Go through and link up whatever we generated during `fastlane init swift` so the user can edit them easily
  self.link_user_configs_to_project(updated_message: setup_message.join("\n"))
end
runner_project() click to toggle source

open and return the swift project

# File fastlane/lib/fastlane/swift_lane_manager.rb, line 139
def self.runner_project
  runner_project_path = FastlaneCore::FastlaneFolder.swift_runner_project_path
  require 'xcodeproj'
  project = Xcodeproj::Project.open(runner_project_path)
  return project
end
start_socket_thread(port: nil) click to toggle source
# File fastlane/lib/fastlane/swift_lane_manager.rb, line 216
def self.start_socket_thread(port: nil)
  require 'fastlane/server/socket_server'
  require 'fastlane/server/socket_server_action_command_executor'

  return Thread.new do
    command_executor = SocketServerActionCommandExecutor.new
    server = Fastlane::SocketServer.new(command_executor: command_executor, port: port)
    server.start
  end
end
swap_paths_in_target(target: nil, file_refs_to_swap: nil, expected_path_to_replacement_path_tuples: nil) click to toggle source
# File fastlane/lib/fastlane/swift_lane_manager.rb, line 101
def self.swap_paths_in_target(target: nil, file_refs_to_swap: nil, expected_path_to_replacement_path_tuples: nil)
  made_project_updates = false
  file_refs_to_swap.each do |file_ref|
    expected_path_to_replacement_path_tuples.each do |preinstalled_config_relative_path, user_config_relative_path|
      next unless file_ref.path == preinstalled_config_relative_path

      file_ref.path = user_config_relative_path
      made_project_updates = true
    end
  end
  return made_project_updates
end
target_for_fastlane_runner_project(runner_project: nil) click to toggle source

return the FastlaneRunner build target

# File fastlane/lib/fastlane/swift_lane_manager.rb, line 147
def self.target_for_fastlane_runner_project(runner_project: nil)
  fastlane_runner_array = runner_project.targets.select do |target|
    target.name == "FastlaneRunner"
  end

  # get runner target
  runner_target = fastlane_runner_array.first
  return runner_target
end
target_source_file_refs(target: nil) click to toggle source
# File fastlane/lib/fastlane/swift_lane_manager.rb, line 157
def self.target_source_file_refs(target: nil)
  return target.source_build_phase.files.to_a.map(&:file_ref)
end