Since the most recent versions of Xcode are often a bit "buggy", the faculty that teach in our Computer Science labs prefer to run a slightly older version of Xcode. This adds some challenges to deploying Xcode as the APP store route using VPP can only install the most recent version of an app.
In case anyone else has the same need, here is the method that I've come up with. This is working for me using Xcode 13.2.1 on MacOS 12.3 Monterey and Jamf Pro version 10.37.2.
I hope this helps others navigate this challenge ...
1) Setup a "test" mac with similar hardware and the same MacOS that is DEP enrolled in Jamf just like your target macs. (You probably already have this as it's incredibly useful for so many things!)
2) Get a Apple Developer's account (I believe a free account will work)
3) Download the version of Xcode you want. (Only certain versions of Xcode will work on certain MacOSs so get the right version!)
4) Xcode is delivered in an Apple specific package format which is no longer compatible directly with Jamf. Double click that downloaded package to extract the Xcode application.
5) Move the extracted application to the /Applications folder on the test mac you setup in step #1 above.
6) Use Packages from WhiteBox to create a "raw" package with just Xcode in /Applicaations (Before running, make sure Packages has "Full Disk Access" in Security and Privacy System Preferences. Also note that I was completely unsuccessful in multiple attempts of packaging this massive application with Jamf Composer! Xcode as it sits in /Applications is about 36 GBs and the resulting, compressed package is over 16 GBs ... )
7) Copy that Packages created Xcode package to your Jamf Pro package repository using Jamf Admin.
8) Now on your Jamf Pro server create a policy as follows:
Scope the policy to a smart group to target the macs you want this to install on. The smart group criteria I used were: Application Title does not have Xcode AND Operating System like 12.3 (you may want to add a few more criteria since you don't want to run this on many macs at the same time. The Xcode compressed package is 16 GBs!)
Set the policy to execute on recurring check-in and once per computer. I added a client-side limitation set to Do not run between 8:00 am and 11:45 pm since trying to do this when the network is busy during the day is, I think, asking for trouble!
Include the Xcode package that you uploaded with Jamf Admin above
Include two scripts - (both below)
One script to set the sleep timers to 6 hours which is set to execute "Before" anything else in the policy runs (You don't want the macs going to sleep when they are running this policy!)
The second script is the Xcode configuration script and is set to execute "'After" (This script also does a Jamf inventory at the end to drop the targeted mac out of the smart group and sets the sleep timers back to something more normal like 45 minutes)
9) Find Xcode on the target macs the next morning ready for use by standard users!
Set Sleep Timers to 6 hours Script:
#!/bin/sh
# Set sleep timers so the macs don't go to sleep while installing software!
pmset -a sleep 360
pmset -a disksleep 360
pmset -a displaysleep 360
exit 0
Xcode Configuration Script: (When/If you copy this script watch for unintended line breaks!)
#!/bin/zsh
# Lots of this code came from - https://www.jamf.com/jamf-nation/discussions/26615/xcode-9-2-deployment
# I added logging so we can see what happened after runnning this
# Also converted from bash to zsh, mostly changed if statements
# Also added CodeTypes.pkg install for Xcode version 13.2.1
# Lynna Jackson, April 2022
# Create log file
mkdir -p /Library/Logs/WilliamsCS/
touch /Library/Logs/WilliamsCS/XCodeInstall.log
# close standard output
exec 1<&-
#close error output
exec 2<&-
#open log file above for read and write
exec 1<>/Library/Logs/WilliamsCS/XCodeInstall.log
# Redirect all output to log file above
exec 2>&1
echo "Script started: Xcode Configure at $(date)"
echo " ------- "
# Accept EULA so there is no prompt
if [[ -e "/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild" ]]
then
echo " ------- "
echo "First license accepted at: $(date)"
"/Applications/Xcode.app/Contents/Developer/usr/bin/xcodebuild" -license accept
fi
# Just in case the xcodebuild command above fails to accept the EULA, set the license acceptance info
# in /Library/Preferences/com.apple.dt.Xcode.plist. For more details on this, see Tim Sutton's post:
# http://macops.ca/deploying-xcode-the-trick-with-accepting-license-agreements/
if [[ -e "/Applications/Xcode.app/Contents/Resources/LicenseInfo.plist" ]]
then
xcode_version_number=`/usr/bin/defaults read "/Applications/Xcode.app/Contents/"Info CFBundleShortVersionString`
xcode_build_number=`/usr/bin/defaults read "/Applications/Xcode.app/Contents/Resources/"LicenseInfo licenseID`
xcode_license_type=`/usr/bin/defaults read "/Applications/Xcode.app/Contents/Resources/"LicenseInfo licenseType`
echo " ------- "
echo "Second license accepted at: $(date)"
echo "$xcode_version_number"
echo "$xcode_build_number"
echo "$xcode_license_type"
if [[ "${xcode_license_type}" == "GM" ]]
then
/usr/bin/defaults write "/Library/Preferences/"com.apple.dt.Xcode IDEXcodeVersionForAgreedToGMLicense "$xcode_version_number"
/usr/bin/defaults write "/Library/Preferences/"com.apple.dt.Xcode IDELastGMLicenseAgreedTo "$xcode_build_number"
else
/usr/bin/defaults write "/Library/Preferences/"com.apple.dt.Xcode IDEXcodeVersionForAgreedToBetaLicense "$xcode_version_number"
/usr/bin/defaults write "/Library/Preferences/"com.apple.dt.Xcode IDELastBetaLicenseAgreedTo "$xcode_build_number"
fi
fi
# DevToolsSecurity tool to change the authorization policies, such that a user who is a
# member of either the admin group or the _developer group does not need to enter an additional
# password to use the Apple-code-signed debugger or performance analysis tools.
echo " ------- "
echo "DevToolsSecurity enabled at: $(date)"
/usr/sbin/DevToolsSecurity -enable
# Add all users to developer group, if they're not admins
echo " ------- "
echo "All Users add to developer group at: $(date)"
/usr/sbin/dseditgroup -o edit -a everyone -t group _developer
# If you have multiple versions of Xcode installed, specify which one you want to be current.
echo " ------- "
echo "Setting /Applications/Xcode as current Xcode at: $(date)"
/usr/bin/xcode-select --switch /Applications/Xcode.app
# Bypass Gatekeeper verification for Xcode, which can take hours.
if [[ -e "/Applications/Xcode.app" ]]; then
echo " ------- "
echo "Remove Gatekeeper's quaratine bit at: $(date)"
xattr -dr com.apple.quarantine /Applications/Xcode.app
fi
# Install Mobile Device Packages so there are no prompts
if [[ -e "/Applications/Xcode.app/Contents/Resources/Packages/MobileDevice.pkg" ]]
then
echo " ------- "
echo "Installing Mobile Device Package at: $(date)"
/usr/sbin/installer -dumplog -verbose -pkg "/Applications/Xcode.app/Contents/Resources/Packages/MobileDevice.pkg" -target /
fi
if [[ -e "/Applications/Xcode.app/Contents/Resources/Packages/MobileDeviceDevelopment.pkg" ]]
then
echo " ------- "
echo "Installing Mobile Device Deployment Package at: $(date)"
/usr/sbin/installer -dumplog -verbose -pkg "/Applications/Xcode.app/Contents/Resources/Packages/MobileDeviceDevelopment.pkg" -target /
fi
# Install XcodeExtensionSupport.pkg
if [[ -e "/Applications/Xcode.app/Contents/Resources/Packages/XcodeExtensionSupport.pkg" ]]
then
echo " ------- "
echo "Installing XCode Extensions Support package at: $(date)"
/usr/sbin/installer -dumplog -verbose -pkg "/Applications/Xcode.app/Contents/Resources/Packages/XcodeExtensionSupport.pkg" -target /
fi
# Install CoreTypes.pkg
# /Applications/Xcode.app/Contents/Resources/Packages/CoreTypes.pkg
if [[ -e "/Applications/Xcode.app/Contents/Resources/Packages/CoreTypes.pkg" ]]
then
echo " ------- "
echo "Installing CoreTypes Package at: $(date)"
/usr/sbin/installer -dumplog -verbose -pkg "/Applications/Xcode.app/Contents/Resources/Packages/CoreTypes.pkg" -target /
fi
# Install XcodeSystemResources.pkg
if [[ -e "/Applications/Xcode.app/Contents/Resources/Packages/XcodeSystemResources.pkg" ]]
then
echo " ------- "
echo "Installing XCode System Resources package at: $(date)"
/usr/sbin/installer -dumplog -verbose -pkg "/Applications/Xcode.app/Contents/Resources/Packages/XcodeSystemResources.pkg" -target /
fi
# Install Command Line Tools.
if [[ /usr/bin/xcode-select ]]
then
echo " ------- "
echo "Installing XCode Command Line Tools at: $(date)"
/usr/bin/xcode-select --install
fi
# Allow any member of _developer to install Apple-provided software.
# be sure you really want to do this.
# as of April 2022 - I don't want to allow this ... so commented out!
#/usr/bin/security authorizationdb write system.install.apple-software authenticate-developer
# Set sleep timers back to 45 minutes
echo " ------- "
echo "Setting sleep timers back to 45 minutes at $(date)"
pmset -a sleep 45
pmset -a disksleep 45
pmset -a displaysleep 45
# Run Jamf inventory to record Xcode installed and drop mac out of smart group for install
echo " ------- "
echo "Running Jamf Inventory at $(date)"
jamf recon
echo " ------- "
echo "Script ended: Xcode Configure at $(date)"
echo " ------- "