Skip to content

Instantly share code, notes, and snippets.

@skabber
Last active April 21, 2019 02:02
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save skabber/63a10739efaead97e59f to your computer and use it in GitHub Desktop.
Save skabber/63a10739efaead97e59f to your computer and use it in GitHub Desktop.
#!/bin/bash
function usage {
echo "Usage: $0 -c [CodeSign Directory] -p [Xcode Project File.xcodeproj]"
echo "If any arguments are not specified, defaults will be attempted. If defaults don't exist, script will exit."
echo "OPTIONS:"
echo " -c [CodeSign Directory]: Location of directory containing project's provisioning profiles."
echo " -p [Xcode Project File]: Path of Xcode project directory (the .xcodeproj, not .pbxproj)"
echo " -b: Use PlistBuddy command for UUID replacement instead of sed. (Better handling of a couple of edge cases, but makes diffs impossible to read.)"
echo " -v: Verbose logging."
echo " -x: Extremely verbose logging. Same as running script with 'bash -x'."
echo " -h: Display usage information."
}
plistBuddy="/usr/libexec/PlistBuddy"
profilesDir="${HOME}/Library/MobileDevice/Provisioning Profiles/"
setProfilesWithPlistBuddy=false
verbose=false
while getopts c:p:bvxh option; do
case "${option}" in
c) codeSignDirectory=${OPTARG};;
p) xcodeProject=${OPTARG};;
b) setProfilesWithPlistBuddy=true;;
v) verbose=true;;
x) set -x;;
h | help) usage; exit;;
esac
done
function logit() {
if [ $verbose == true ]; then
echo "$@"
fi
}
function checkForCodeSignDirectory {
if [ -z "${codeSignDirectory}" ]; then
codeSignDirectory="$PWD/CodeSign"
if [ ! -d "${codeSignDirectory}" ]; then
echo "No CodeSign directory found or specified with -c option. Exiting."
exit 1
fi
fi
}
function checkForXcodeProject {
if [ -z "${xcodeProject}" ]; then
echo "No Xcode project specified. Please specify Xcode project using -p option. Exiting."
exit 1
fi
projectName=`basename "$xcodeProject" | cut -d'.' -f1`
}
function checkForProjectFile {
# Check that we have an Xcode project and that the project file exists.
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 {
# Move all of our profile's to the system's provisioning profile directory
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
}
function getTargets {
# Build an array of all the targets IDs from our project file
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 {
# Set our provisioning profiles in the build settings to the UUIDs of our latest profiles from the CodeSign directory
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. 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 {
# Get the provisioning profile UUID currently set in the project file
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
}
checkForCodeSignDirectory
checkForXcodeProject
checkForProjectFile
copyProfiles
getTargets
configureProvisioningProfiles
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment