Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A script for Xcode 4.x to use API keys stored in ~/.api_keys and insert them into your app bundle’s Info.plist (instead of committing them to a repository)
# An API keys script written by Patrick Gibson (@patr1ck) and Christopher Bowns (@cbowns)
# This script sets API keys in your app's Info.plist from an .api_keys file you keep in your home directory (~/.api_keys)
# This allows you to not check API keys into your source control system,
# or for different developers to use different keys without needing to patch their working copies.
# Installation directions:
=begin
1. Create a Run Script build phase in your Xcode project before Compile Sources
2. Copy and paste this whole script in.
3. Create or modify your .api_keys file to hold your API keys
4. Modify the keys hash below to reference your .api_keys names from step 3
5. Add placeholder keys to your app's Info.plist for the script to sub into.
6. Add appropriate code to your app to pull from your Info.plist (see below)
7. Build your app!
=end
# Your .api_keys should be in this format: (we recommend changing APPNAME to, well, your app name)
=begin
PARSE_APPNAME_PROD_APP_ID=foo
PARSE_APPNAME_PROD_CLIENT_KEY=bar
TESTFLIGHT_APPNAME=PartyApp
=end
# You can move your .api_keys file:
api_keys_file = "/Users/#{ENV['USER']}/.api_keys"
# Declare your app-specific keys' names here, like so:
# '.api_keys_key' => 'Info.plist_key'
keys = {
'PARSE_APPNAME_DEV_APP_ID' => 'ParseDevAppID',
'PARSE_APPNAME_DEV_CLIENT_KEY' => 'ParseDevClientKey',
'PARSE_APPNAME_PROD_APP_ID' => 'ParseProdAppID',
'PARSE_APPNAME_PROD_CLIENT_KEY' => 'ParseProdClientKey',
'TESTFLIGHT_APPNAME' => 'TestFlightKey',
}
# A reminder: you need to add keys to your Info.plist so this script can put these values somewhere.
# In XML, it should look something like:
=begin
<key>ParseProdClientKey</key>
<string>?merp?</string>
<key>TestFlightKey</key>
<string>?hmm?</string>
=end
# Once this script is done running, it should look like:
=begin
<key>ParseProdClientKey</key>
<string>bar</string>
<key>TestFlightKey</key>
<string>PartyApp</string>
=end
# Using these values in code looks something like:
=begin
[Parse setApplicationId:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"ParseDevAppID"]
clientKey:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"ParseDevClientKey"]];
or
NSString *testFlightName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"TestFlightKey"];
=end
# And now, it's time to do some work.
# Fail if not run from Xcode
raise "Must be run from Xcode" unless ENV['XCODE_VERSION_ACTUAL']
info_plist = "#{ENV['BUILT_PRODUCTS_DIR']}/#{ENV['INFOPLIST_PATH']}"
# When building for the device, the plist is already converted to binary, so change it back.
`plutil -convert xml1 #{info_plist}`
# Load our keys from $HOME/.api_keys
api_keys = IO.readlines(api_keys_file).join
api_keys.each do |line|
# puts "line is #{line}"
if line.to_s.strip.length != 0 # Skip nil or empty or whitespace lines
key, value = line.split("=")
puts "Loading #{key} = #{value}"
ENV[key] = value.strip!
end
end
# Open Info.plist and set the appropriate value to the revision hash
lines = IO.readlines(info_plist).join
keys.each do |apikey, infokey|
lines.gsub! /(<key>#{infokey}<\/key>\n\t<string>).*?(<\/string>)/, "\\1#{ENV[apikey]}\\2"
end
# Overwrite the original Info.plist file with our updated version
File.open(info_plist, 'w') {|f| f.puts lines}
# Convert back to binary1 if we're building for the device
if ENV['EFFECTIVE_PLATFORM_NAME'] == "-iphonesimulator" then
`plutil -convert xml1 #{info_plist}`
else
`plutil -convert binary1 #{info_plist}`
end
# Report to the user
puts "Updated the API Keys"
@exalted

This comment has been minimized.

Copy link

commented Aug 13, 2014

@cbowns you guys actually use this in production? Do you think this is the best way to do it? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.