Skip to main content
Question

Smart Group to determine if a system upgraded

  • March 29, 2026
  • 2 replies
  • 49 views

cgolebio1
Forum|alt.badge.img

Not sure if this is possible; having trouble thinking out the logic.   We have systems that are setup with macOS Tahoe, but we also have systems that are being upgraded from macOS 14 and 15 to Tahoe.  I am wondering if it is possible to come up with a smart group to differentiate systems that came with vs upgraded to?

One thought is to “mark” systems during setup with a flag file during enrollment and use an extension attribute.  Maybe a plist that has an array of discovered operating system builds.  This way it can be used in the future, not just for macOS Tahoe.

Curious if anyone has a better way.

2 replies

PaulHazelden
Forum|alt.badge.img+13
  • Jamf Heroes
  • March 30, 2026

You can make a smart group based on last enroll.
If they enroll after a certain date then they will be set up with OSX 26, Before and they will have upgraded to it.

So last enroll before Sept 2025, and on OSX 26, Upgraded to 26.

Last enroll after Sept 2025, and on OSX 26, Set up on OSX 26.

You will need to change the date to allow for any delay you had set preventing upgrade to major version.


cgolebio1
Forum|alt.badge.img
  • Author
  • New Contributor
  • March 30, 2026

Thank you for the suggestion!

I ended up creating two extension attributes to make it overly complex 😀.  This way I don’t have to deal with a delay date or anything.  The order they are in is important which you will see why below.

Last OS Version: Returns the version prior to the current OS, otherwise return the current version

Creates the actual plist which the other EA relies on.

#!/bin/zsh

PLIST="/Library/Preferences/com.company.mac.plist"
KEY="os_history"
PLISTBUDDY="/usr/libexec/PlistBuddy"

# Current OS info
CURRENT_OS=$(sw_vers -productVersion)
CURRENT_BUILD=$(sw_vers -buildVersion)
CURRENT_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ")

# Create plist if missing
if [[ ! -f "$PLIST" ]]; then
/usr/bin/defaults write "$PLIST" "$KEY" -dict
fi

# Ensure os_history dictionary exists
if ! $PLISTBUDDY -c "Print :$KEY" "$PLIST" &>/dev/null; then
$PLISTBUDDY -c "Add :$KEY dict" "$PLIST"
fi

# If OS version not present, add full record
if ! $PLISTBUDDY -c "Print :$KEY:$CURRENT_OS" "$PLIST" &>/dev/null; then
$PLISTBUDDY -c "Add :$KEY:$CURRENT_OS dict" "$PLIST"
$PLISTBUDDY -c "Add :$KEY:$CURRENT_OS:date string $CURRENT_DATE" "$PLIST"
$PLISTBUDDY -c "Add :$KEY:$CURRENT_OS:build string $CURRENT_BUILD" "$PLIST"
fi

# Extract OS version keys
typeset -a OS_KEYS
OS_KEYS=("${(@f)$($PLISTBUDDY -c "Print :$KEY" "$PLIST" 2>/dev/null | \
grep -E '^[[:space:]]*[0-9]+\.[0-9]+(\.[0-9]+)? =' | \
sed -E 's/^[[:space:]]*([0-9]+\.[0-9]+(\.[0-9]+)?) =.*/\1/')}")

# Sort versions correctly
typeset -a SORTED_KEYS
SORTED_KEYS=("${(@f)$(printf "%s\n" "${OS_KEYS[@]}" | sort -V)}")

COUNT=${#SORTED_KEYS}

RESULT=""

if (( COUNT == 1 )); then
RESULT="${SORTED_KEYS[1]}"
elif (( COUNT > 1 )); then
RESULT="${SORTED_KEYS[COUNT-1]}"
fi

# Output for Jamf
echo "<result>$RESULT</result>"

 

Last OS Version (Major): Returns the last major version integer.  Otherwise None.

#!/bin/zsh

PLIST="/Library/Preferences/com.company.mac.plist"
KEY="os_history"
PLISTBUDDY="/usr/libexec/PlistBuddy"

# Get current OS major version
CURRENT_OS=$(sw_vers -productVersion)
CURRENT_MAJOR=$(echo "$CURRENT_OS" | awk -F. '{print $1}')

# Ensure plist + key exist
if [[ ! -f "$PLIST" ]] || ! $PLISTBUDDY -c "Print :$KEY" "$PLIST" &>/dev/null; then
echo "<result>None</result>"
exit 0
fi

# Extract OS version keys
typeset -a OS_KEYS
OS_KEYS=("${(@f)$($PLISTBUDDY -c "Print :$KEY" "$PLIST" 2>/dev/null | \
grep -E '^[[:space:]]*[0-9]+\.[0-9]+(\.[0-9]+)? =' | \
sed -E 's/^[[:space:]]*([0-9]+\.[0-9]+(\.[0-9]+)?) =.*/\1/')}")

# If no usable data
if (( ${#OS_KEYS} == 0 )); then
echo "<result>None</result>"
exit 0
fi

# Sort versions correctly
typeset -a SORTED_KEYS
SORTED_KEYS=("${(@f)$(printf "%s\n" "${OS_KEYS[@]}" | sort -V)}")

# Extract unique major versions in order
typeset -a MAJOR_VERSIONS
for v in "${SORTED_KEYS[@]}"; do
major=$(echo "$v" | awk -F. '{print $1}')
if [[ ! " ${MAJOR_VERSIONS[@]} " =~ " ${major} " ]]; then
MAJOR_VERSIONS+=("$major")
fi
done

COUNT=${#MAJOR_VERSIONS}

RESULT="None"

if (( COUNT == 1 )); then
RESULT="None"
elif (( COUNT > 1 )); then
RESULT="${MAJOR_VERSIONS[COUNT-1]}"
fi

# Output for Jamf
echo "<result>$RESULT</result>"

Example of systems just upgraded to Tahoe:

Last OS Version: 14.8.3

Last OS Version (Major): 14

or

Last OS Version: 13.7.8

Last OS Version (Major): 13

 

Examples of systems not upgraded:

Last OS Version: 15.7.4

Last OS Version (Major): None

or 

Last OS Version: 26.4

Last OS Version (Major): None

 

If only the minor version updates, the Last OS Version should show what it was upgraded from, and Last OS Version will remain None or whatever the last major version was.

 

I can now create a Smart Group that looks like this:

Last Check-in less than 30 days ago

Operating System greater than or equal to 26

Last OS Version is not None

Last OS Version is not <blank>

This returns the systems that are active and that have upgraded to macOS Tahoe from a prior major version.