-
-
Save kebbbnnn/6f46191ea1b43b7feb71b87a04b8b801 to your computer and use it in GitHub Desktop.
Update Xcode project's build settings to point to current provisioning profiles.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
############################################################################################################## | |
### 1. Name your profiles with the convention of ProjectName_TargetName_ConfigurationName.mobileprovision ### | |
### 2. Create a directory called CodeSign in your project directory ### | |
### 3. Move all your project's provisioning profiles into the CodeSign directory ### | |
### ### | |
### Running this script will update your project file to point to the correct UUIDs of each corresponding ### | |
### profile in your CodeSign directory. ### | |
############################################################################################################## | |
function usage { | |
echo "Usage: set_project_profiles.sh -m <Profile Map File> -p <Xcode Project File>" | |
echo "If any arguments are not specified, defaults will be attempted. If defaults don't exist, user will be prompted for value." | |
echo "OPTIONS:" | |
echo ' -s: Use when running on Jenkins. Will set the root project directory to ${WORKSPACE}.' | |
echo " -c <CodeSign Directory>: Relative location of directory containing projects provisioning profiles." | |
echo " -m <Profile Map File>: Relative location of file which contains target to provisioning profile mappings." | |
echo " -p <Xcode Project File>: Relative location of Xcode project." | |
echo " -b: Use PlistBuddy command for UUID replacement instead of sed. (Better handles a couple of edge cases, but makes diffs impossible to read.)" | |
echo " -x: Show debug logging." | |
echo " -h: Display usage information." | |
echo " -v: Verbose logging." | |
} | |
plistBuddy="/usr/libexec/PlistBuddy" | |
profilesDir="${HOME}/Library/MobileDevice/Provisioning Profiles/" | |
setProfilesWithPlistBuddy=false | |
verbose=false | |
useConventionalProfiles=false | |
while getopts sc:m:p:bxhv option; do | |
case "${option}" in | |
s) server=true;; | |
c) codeSignDirectory=${OPTARG};; | |
m) profileMapFile=${OPTARG};; | |
p) xcodeProject=${OPTARG};; | |
b) setProfilesWithPlistBuddy=true;; | |
x) set -x;; | |
v) verbose=true;; | |
h | help) usage; exit;; | |
esac | |
done | |
function logit() { | |
if [ $verbose == true ]; then | |
echo "$@" | |
fi | |
} | |
function checkIfServer { | |
if [ "$server" == true ]; then | |
projectRoot="${WORKSPACE}" | |
else | |
projectRoot="$PWD" | |
fi | |
} | |
function checkForCodeSignDirectory { | |
if [ -z "${codeSignDirectory}" ]; then | |
codeSignDirectory="$projectRoot/CodeSign" | |
if [ ! -d "${codeSignDirectory}" ]; then | |
echo "No CodeSign directory found or specified with -c option. Exiting." | |
exit 1 | |
fi | |
fi | |
} | |
### REMOVE ONCE WE GET RID OF PROFILE MAPS | |
function checkForProfileMap { | |
if [ -z "${profileMapFile}" ]; then | |
if [ -f "$codeSignDirectory/PROFILEMAP" ]; then | |
profileMapFile=`ls "$codeSignDirectory/PROFILEMAP"` | |
else | |
useConventionalProfiles=true | |
fi | |
fi | |
} | |
function checkForXcodeProject { | |
if [ -z "${xcodeProject}" ]; then | |
if [ -f "$codeSignDirectory/XCODEPROJECT" ]; then | |
xcodeProject=`cat "$codeSignDirectory/XCODEPROJECT"` | |
else | |
echo "No XCODEPROJECT file found in CodeSign directory or specified with -p option. Exiting." | |
exit 1 | |
fi | |
fi | |
projectName=`basename "$xcodeProject" | cut -d'.' -f1` | |
} | |
function checkForProjectFile { | |
projectExtension=`basename "$xcodeProject" | cut -d'.' -f2` | |
if [ "$projectExtension" != "xcodeproj" ]; then | |
echo "Xcode project should have a .xcodeproj file extension. Instead got a .$projectExtension extension. Exiting." | |
exit 1 | |
else | |
projectFile="$xcodeProject/project.pbxproj" | |
if [ ! -f "$projectFile" ]; then | |
echo "Project file $projectFile does not exist. Exiting." | |
exit 1 | |
fi | |
fi | |
} | |
function copyProfiles { | |
mkdir -p "$profilesDir" | |
find "$codeSignDirectory" -name *.mobileprovision | egrep '.*' > /dev/null 2>&1 | |
if [ $? -eq 0 ]; then | |
cp "$codeSignDirectory/"*.mobileprovision "$profilesDir" | |
if [ $? -ne 0 ]; then | |
echo "Copying profiles from CodeSign directory failed. Please run script again with -x option for debugging." | |
exit 1 | |
fi | |
else | |
echo "No provisioning profiles found in CodeSign directory: $codeSignDirectory. Will attempt to proceed with profiles already in system profile directory." | |
fi | |
} | |
### REMOVE ONCE WE GET RID OF PROFILE MAPS | |
function loadProfileMap { | |
# Dictionary of all targets and corresponding provisioning profiles. Must be defined on a per-project basis. | |
# Mapping must be must be ordered target:devprofile:adhocprofile:releaseprofile | |
allProfiles=(`cat "$profileMapFile"`) | |
} | |
function getTargets { | |
rootObject=`$plistBuddy -c "Print :rootObject" $projectFile` | |
targetList=`$plistBuddy -c "Print :objects:$rootObject:targets" $projectFile | sed -e '/Array {/d' -e '/}/d' -e 's/^[ \t]*//'` | |
targets=(`echo $targetList`) | |
} | |
function setNewProfileUuid { | |
if [ "$currentProfileUuid" != "$newProfileUuid" ]; then | |
echo "Changing $configurationName from $currentProfileUuid to $newProfileUuid" | |
if [ $setProfilesWithPlistBuddy == false ]; then | |
sed -i '' "s/$currentProfileUuid/$newProfileUuid/g" "$projectFile" | |
if [ $? -ne 0 ]; then | |
printf "sed command failed on $cleanTargetName:$configurationName attempting to replace \"$currentProfileUuid\" with \"$newProfileUuid\".\nAborting.\nConsider running script with -b flag to use PlistBuddy instead of sed." | |
exit 1 | |
fi | |
elif [ $setProfilesWithPlistBuddy == true ]; then | |
echo "Detected -b flag, or no profile currently set. Using PlistBuddy instead of sed to set new UUID values..." | |
if [ $currentProfileUuidIsSet == false ]; then | |
logit "No PROVISIONING_PROFILE key is defined for $targetName:$configurationName. Adding one..." | |
$plistBuddy -c "Add :objects:$configurationId:buildSettings:PROVISIONING_PROFILE string $newProfileUuid" "$projectFile" | |
elif [ $currentProfileUuidIsSet == true ]; then | |
$plistBuddy -c "Set :objects:$configurationId:buildSettings:PROVISIONING_PROFILE $newProfileUuid" "$projectFile" | |
fi | |
fi | |
else logit "Provisioning Profile UUID is already set to latest. No change made." | |
fi | |
} | |
function getCurrentProfileUuid { | |
currentProfileUuid=`$plistBuddy -c "Print :objects:$configurationId:buildSettings:PROVISIONING_PROFILE" $projectFile 2> /dev/null` | |
if [ $? -eq 0 ]; then | |
currentProfileUuidIsSet=true | |
if [ $currentProfileUuid == '' ]; then | |
echo "Current provisioning profile is blank. Unable to replace using sed, proceeding with PlistBuddy instead." | |
setProfilesWithPlistBuddy=true | |
fi | |
else | |
currentProfileUuidIsSet=false | |
setProfilesWithPlistBuddy=true | |
fi | |
} | |
function configureProvisioningProfiles { | |
for targetId in ${targets[@]}; do | |
targetName=`$plistBuddy -c "Print :objects:$targetId:name" "$projectFile"` | |
logit "Checking Target: $targetName" | |
cleanTargetName=${targetName// /_} | |
buildConfigurationListId=`$plistBuddy -c "Print :objects:$targetId:buildConfigurationList" "$projectFile"` | |
buildConfigurationList=`$plistBuddy -c "Print :objects:$buildConfigurationListId:buildConfigurations" "$projectFile" | sed -e '/Array {/d' -e '/}/d' -e 's/^[ \t]*//'` | |
buildConfigurations=(`echo $buildConfigurationList`) | |
for configurationId in ${buildConfigurations[@]}; do | |
configurationName=`$plistBuddy -c "Print :objects:$configurationId:name" "$projectFile"` | |
logit "Checking Configuration: $configurationName" | |
conventionProfileName=$projectName\_$cleanTargetName\_$configurationName.mobileprovision | |
logit "Convention Profile Name: $conventionProfileName" | |
if [ -f "$profilesDir/$conventionProfileName" ]; then | |
getCurrentProfileUuid | |
newProfileUuid=`security cms -D -i "$profilesDir/$conventionProfileName" > /tmp/newprofile.plist && /usr/libexec/PlistBuddy -c Print:UUID /tmp/newprofile.plist && rm -f /tmp/newprofile.plist` | |
setNewProfileUuid | |
else logit "No provisioning profile set for target $targetName with configuration $configurationName. No change made." | |
fi | |
done | |
done | |
} | |
### REMOVE ONCE WE GET RID OF PROFILE MAPS | |
function setProfilesWithProfileMap { | |
if [ $setProfilesWithPlistBuddy == true ]; then | |
echo "Detected -b flag. Using PlistBuddy instead of sed to set new UUID values..." | |
fi | |
for targetId in ${targets[@]}; do | |
targetName=`$plistBuddy -c "Print :objects:$targetId:name" $projectFile` | |
logit "Checking Target: $targetName" | |
cleanTargetName=${targetName// /} | |
for profileList in ${allProfiles[@]}; do | |
profileTargetName=`awk -F: '{ print $1 }' <<< $profileList` | |
if [ "$cleanTargetName" == "$profileTargetName" ]; then | |
developmentProfileName=`awk -F: '{ print $2 }' <<< $profileList` | |
adHocProfileName=`awk -F: '{ print $3 }' <<< $profileList` | |
appStoreProfileName=`awk -F: '{ print $4 }' <<< $profileList` | |
buildConfigurationListId=`$plistBuddy -c "Print :objects:$targetId:buildConfigurationList" $projectFile` | |
buildConfigurationList=`$plistBuddy -c "Print :objects:$buildConfigurationListId:buildConfigurations" $projectFile | sed -e '/Array {/d' -e '/}/d' -e 's/^[ \t]*//'` | |
buildConfigurations=(`echo $buildConfigurationList`) | |
for configurationId in ${buildConfigurations[@]}; do | |
configurationName=`$plistBuddy -c "Print :objects:$configurationId:name" $projectFile` | |
logit "Checking Configuration: $configurationName" | |
if [ "$profileTargetName" == "$cleanTargetName" ]; then | |
if [ "$configurationName" == "Debug" ]; then | |
getCurrentProfileUuid | |
if [ $? -eq 0 ]; then | |
newProfileUuid=`security cms -D -i $codeSignDirectory/$developmentProfileName > /tmp/newprofile.plist && /usr/libexec/PlistBuddy -c Print:UUID /tmp/newprofile.plist && rm -f /tmp/newprofile.plist` | |
setNewProfileUuid | |
else logit "No provisioning profile set for config $configurationName. No change made." | |
fi | |
elif [ "$configurationName" == "AdHoc" ]; then | |
getCurrentProfileUuid | |
if [ $? -eq 0 ]; then | |
newProfileUuid=`security cms -D -i $codeSignDirectory/$adHocProfileName > /tmp/newprofile.plist && /usr/libexec/PlistBuddy -c Print:UUID /tmp/newprofile.plist && rm -f /tmp/newprofile.plist` | |
setNewProfileUuid | |
else logit "No provisioning profile set for config $configurationName. No change made." | |
fi | |
elif [ "$configurationName" == "Release" ]; then | |
getCurrentProfileUuid | |
if [ $? -eq 0 ]; then | |
newProfileUuid=`security cms -D -i $codeSignDirectory/$appStoreProfileName > /tmp/newprofile.plist && /usr/libexec/PlistBuddy -c Print:UUID /tmp/newprofile.plist && rm -f /tmp/newprofile.plist` | |
setNewProfileUuid | |
else logit "No provisioning profile set for config $configurationName. No change made." | |
fi | |
else logit "Configuration name did not match Debug, AdHoc, or Release. No UUID set." | |
fi | |
fi | |
done | |
fi | |
done | |
done | |
} | |
checkIfServer | |
checkForCodeSignDirectory | |
checkForProfileMap | |
checkForXcodeProject | |
checkForProjectFile | |
copyProfiles | |
getTargets | |
if [ $useConventionalProfiles == true ]; then | |
configureProvisioningProfiles | |
else | |
loadProfileMap | |
setProfilesWithProfileMap | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment