Permalink
Find file
2bb892f Sep 29, 2016
@KrauseFx @dtorres @frisocki @lacostej
150 lines (129 sloc) 6.42 KB
module Fastlane
module Actions
module SharedValues
end
class UpdateInfoPlistAction < Action
def self.run(params)
require 'xcodeproj'
# Check if parameters are set
if params[:app_identifier] or params[:display_name] or params[:block]
if (params[:app_identifier] or params[:display_name]) and params[:block]
UI.important("block parameter can not be specified with app_identifier or display_name")
return false
end
# Assign folder from parameter or search for xcodeproj file
folder = params[:xcodeproj] || Dir["*.xcodeproj"].first
if params[:scheme]
project = Xcodeproj::Project.open(folder)
scheme = project.native_targets.detect { |target| target.name == params[:scheme] }
UI.user_error!("Couldn't find scheme named '#{params[:scheme]}'") unless scheme
params[:plist_path] = scheme.build_configurations.first.build_settings["INFOPLIST_FILE"]
UI.user_error!("Scheme named '#{params[:scheme]}' doesn't have a plist file") unless params[:plist_path]
params[:plist_path] = params[:plist_path].gsub("$(SRCROOT)", ".")
end
if params[:plist_path].nil?
UI.user_error!("You must specify either a plist path or a scheme")
end
# Read existing plist file
info_plist_path = File.join(folder, "..", params[:plist_path])
UI.user_error!("Couldn't find info plist file at path '#{info_plist_path}'") unless File.exist?(info_plist_path)
plist = Xcodeproj::Plist.read_from_path(info_plist_path)
# Update plist values
plist['CFBundleIdentifier'] = params[:app_identifier] if params[:app_identifier]
plist['CFBundleDisplayName'] = params[:display_name] if params[:display_name]
params[:block].call(plist) if params[:block]
# Write changes to file
Xcodeproj::Plist.write_to_path(plist, info_plist_path)
UI.success("Updated #{params[:plist_path]} 💾.")
File.read(info_plist_path)
else
UI.important("You haven't specified any parameters to update your plist.")
false
end
end
#####################################################
# @!group Documentation
#####################################################
def self.is_supported?(platform)
[:ios].include?(platform)
end
def self.description
'Update a Info.plist file with bundle identifier and display name'
end
def self.details
"This action allows you to modify your `Info.plist` file before building. This may be useful if you want a separate build for alpha, beta or nightly builds, but don't want a separate target."
end
def self.available_options
[
FastlaneCore::ConfigItem.new(key: :xcodeproj,
env_name: "FL_UPDATE_PLIST_PROJECT_PATH",
description: "Path to your Xcode project",
optional: true,
verify_block: proc do |value|
UI.user_error!("Please pass the path to the project, not the workspace") if value.end_with? ".xcworkspace"
UI.user_error!("Could not find Xcode project") unless File.exist?(value)
end),
FastlaneCore::ConfigItem.new(key: :plist_path,
env_name: "FL_UPDATE_PLIST_PATH",
description: "Path to info plist",
optional: true,
verify_block: proc do |value|
UI.user_error!("Invalid plist file") unless value[-6..-1].casecmp(".plist").zero?
end),
FastlaneCore::ConfigItem.new(key: :scheme,
env_name: "FL_UPDATE_PLIST_APP_SCHEME",
description: "Scheme of info plist",
optional: true),
FastlaneCore::ConfigItem.new(key: :app_identifier,
env_name: 'FL_UPDATE_PLIST_APP_IDENTIFIER',
description: 'The App Identifier of your app',
default_value: ENV['PRODUCE_APP_IDENTIFIER'],
optional: true),
FastlaneCore::ConfigItem.new(key: :display_name,
env_name: 'FL_UPDATE_PLIST_DISPLAY_NAME',
description: 'The Display Name of your app',
optional: true),
FastlaneCore::ConfigItem.new(key: :block,
is_string: false,
description: 'A block to process plist with custom logic',
optional: true)
]
end
def self.author
'tobiasstrebitzer'
end
def self.example_code
[
'update_info_plist( # update app identifier string
plist_path: "path/to/Info.plist",
app_identifier: "com.example.newappidentifier"
)',
'update_info_plist( # Change the Display Name of your app
plist_path: "path/to/Info.plist",
display_name: "MyApp-Beta"
)',
'update_info_plist( # Target a specific `xcodeproj` rather than finding the first available one
xcodeproj: "path/to/Example.proj",
plist_path: "path/to/Info.plist",
display_name: "MyApp-Beta"
)',
'update_info_plist( # Advanced processing: find URL scheme for particular key and replace value
xcodeproj: "path/to/Example.proj",
plist_path: "path/to/Info.plist",
block: lambda { |plist|
urlScheme = plist["CFBundleURLTypes"].find{|scheme| scheme["CFBundleURLName"] == "com.acme.default-url-handler"}
urlScheme[:CFBundleURLSchemes] = ["acme-production"]
}
)',
'zip(
path: "MyApp.app",
output_path: "Latest.app.zip"
)'
]
end
def self.category
:project
end
end
end
end