diff --git a/Installomator.sh b/Installomator.sh index 46537a3..8647ea6 100755 --- a/Installomator.sh +++ b/Installomator.sh @@ -8,8 +8,8 @@ # inspired by the download scripts from William Smith and Sander Schram # with additional ideas and contribution from Isaac Ordonez, Mann consulting -VERSION='0.5' -VERSIONDATE='20201019' +VERSION='0.4.19' +VERSIONDATE='2021-02-15' export PATH=/usr/bin:/bin:/usr/sbin:/sbin @@ -26,6 +26,7 @@ NOTIFY=success # options: # - success notify the user on success # - silent no notifications +# - all all notifications (great for Self Service installation) # behavior when blocking processes are found @@ -35,12 +36,31 @@ BLOCKING_PROCESS_ACTION=prompt_user # - silent_fail exit script without prompt or installation # - prompt_user show a user dialog for each blocking process found # abort after three attempts to quit +# (only if user accepts to quit the apps, otherwise +# the update is cancelled). # - prompt_user_then_kill # show a user dialog for each blocking process found, # attempt to quit two times, kill the process finally +# - prompt_user_loop +# Like prompt-user, but clicking "Not Now", will just wait an hour, +# and then it will ask again. +# - tell_user User will be showed a notification about the important update, +# but user is only allowed to quit and continue, and then we +# ask the app to quit. +# - tell_user_then_kill +# Show dialog 2 times, and if the quitting fails, the +# blocking processes will be killed. # - kill kill process without prompting or giving the user a chance to save +# install behavior +INSTALL="" +# options: +# - When not set, software will only be installed +# if it is newer/different in version +# - force Install even if it’s the same version + + # NOTE: How labels work # Each workflow label needs to be listed in the case statement below. @@ -57,11 +77,23 @@ BLOCKING_PROCESS_ACTION=prompt_user # - zip # - pkgInDmg # - pkgInZip (not yet tested) +# - appInDmgInZip +# +# - packageID: (optional) +# The package ID of a pkg +# If given, will be used to find version of installed software, instead of searching for an app. +# Usefull if a pkg does not install an app. +# See label installomator_st # # - downloadURL: (required) # URL to download the dmg. # Can be generated with a series of commands (see BBEdit for an example). # +# - appNewVersion: (optional) +# Version of the downloaded software. +# If given, it will be compared to installed version, to see if download is different. +# It does not check for newer or not, only different. +# # - expectedTeamID: (required) # 10-digit developer team ID. # Obtain the team ID by running: @@ -98,8 +130,8 @@ BLOCKING_PROCESS_ACTION=prompt_user # When a workflow has no blocking processes, use # blockingProcesses=( NONE ) # -# - pkgName: (optional, only used for dmgInPkg and dmgInZip) -# File name of the pkg file _inside_ the dmg or zip +# - pkgName: (optional, only used for pkgInDmg, dmgInZip, and appInDmgInZip) +# File name of the pkg/dmg file _inside_ the dmg or zip # When not given the pkgName is derived from the $name # # - updateTool: @@ -133,7 +165,9 @@ cleanupAndExit() { # $1 = exit code, $2 message printlog "Unmounting $dmgmount" hdiutil detach "$dmgmount" fi - printlog "################## End Installomator \n\n" + # If we closed any processes, reopen the app again + reopenClosedProcess + printlog "################## End Installomator, exit code $1 \n\n" exit "$1" } @@ -147,7 +181,13 @@ runAsUser() { displaydialog() { # $1: message $2: title message=${1:-"Message"} title=${2:-"Installomator"} - runAsUser osascript -e "button returned of (display dialog \"$message\" with title \"$title\" buttons {\"Not Now\", \"Quit and Update\"} default button \"Quit and Update\")" + runAsUser osascript -e "button returned of (display dialog \"$message\" with title \"$title\" buttons {\"Not Now\", \"Quit and Update\"} default button \"Quit and Update\" with icon caution)" +} + +displaydialogContinue() { # $1: message $2: title + message=${1:-"Message"} + title=${2:-"Installomator"} + runAsUser osascript -e "button returned of (display dialog \"$message\" with title \"$title\" buttons {\"Quit and Update\"} default button \"Quit and Update\" with icon stop)" } displaynotification() { # $1: message $2: title @@ -171,9 +211,9 @@ printlog(){ timestamp=$(date +%F\ %T) if [[ "$(whoami)" == "root" ]]; then - echo "$timestamp" "$1" | tee -a $log_location - else - echo "$timestamp" "$1" + echo "$timestamp" "$label" "$1" | tee -a $log_location + else + echo "$timestamp" "$label" "$1" fi } @@ -192,10 +232,10 @@ downloadURLFromGit() { # $1 git user name, $2 git repo name if [ -n "$archiveName" ]; then downloadURL=$(curl --silent --fail "https://api.github.com/repos/$gitusername/$gitreponame/releases/latest" \ - | awk -F '"' "/browser_download_url/ && /$archiveName\"/ { print \$4; exit }") + | awk -F '"' "/browser_download_url/ && /$archiveName/ { print \$4 }") else downloadURL=$(curl --silent --fail "https://api.github.com/repos/$gitusername/$gitreponame/releases/latest" \ - | awk -F '"' "/browser_download_url/ && /$filetype\"/ { print \$4; exit }") + | awk -F '"' "/browser_download_url/ && /$filetype\"/ { print \$4 }") fi if [ -z "$downloadURL" ]; then printlog "could not retrieve download URL for $gitusername/$gitreponame" @@ -206,23 +246,52 @@ downloadURLFromGit() { # $1 git user name, $2 git repo name fi } - -xpath() { - # the xpath tool changes in Big Sur and now requires the `-e` option - if [[ $(sw_vers -buildVersion) > "20A" ]]; then - /usr/bin/xpath -e $@ - # alternative: switch to xmllint (which is not perl) - #xmllint --xpath $@ - +versionFromGit() { + # credit: Søren Theilgaard (@theilgaard) + # $1 git user name, $2 git repo name + gitusername=${1?:"no git user name"} + gitreponame=${2?:"no git repo name"} + + appNewVersion=$(curl --silent --fail "https://api.github.com/repos/$gitusername/$gitreponame/releases/latest" | grep tag_name | cut -d '"' -f 4 | sed 's/[^0-9\.]//g') + if [ -z "$appNewVersion" ]; then + printlog "could not retrieve version number for $gitusername/$gitreponame" + appNewVersion="" else - /usr/bin/xpath $@ + echo "$appNewVersion" + return 0 fi } +# Handling of differences in xpath between Catalina and Big Sur +xpath() { + # the xpath tool changes in Big Sur and now requires the `-e` option + if [[ $(sw_vers -buildVersion) > "20A" ]]; then + /usr/bin/xpath -e $@ + # alternative: switch to xmllint (which is not perl) + #xmllint --xpath $@ - + else + /usr/bin/xpath $@ + fi +} + + getAppVersion() { + # modified by: Søren Theilgaard (@theilgaard) + # pkgs contains a version number, then we don't have to search for an app + if [[ $packageID != "" ]]; then + appversion="$(pkgutil --pkg-info-plist ${packageID} 2>/dev/null | grep -A 1 pkg-version | tail -1 | sed -E 's/.*>([0-9.]*)<.*/\1/g')" + if [[ $appversion != "" ]]; then + printlog "found packageID $packageID installed, version $appversion" + return + else + printlog "No version found using packageID $packageID" + fi + fi + # get all apps matching name applist=$(mdfind "kind:application $appName" -0 ) - if [[ $applist = "" ]]; then + if [[ $applist = "" ]]; then printlog "Spotlight not returning any app, trying manually in /Applications." if [[ -d "/Applications/$appName" ]]; then applist="/Applications/$appName" @@ -235,7 +304,7 @@ getAppVersion() { filteredAppPaths=( ${(M)appPathArray:#${targetDir}*} ) if [[ ${#filteredAppPaths} -eq 1 ]]; then installedAppPath=$filteredAppPaths[1] - appversion=$(mdls -name kMDItemVersion -raw $installedAppPath ) + appversion=$(defaults read $installedAppPath/Contents/Info.plist CFBundleShortVersionString) #Not dependant on Spotlight indexing, Armin: appversion=$(mdls -name kMDItemVersion -raw $installedAppPath ) printlog "found app at $installedAppPath, version $appversion" else printlog "could not determine location of $appName" @@ -253,31 +322,66 @@ checkRunningProcesses() { fi # try at most 3 times - for i in {1..3}; do + for i in {1..4}; do countedProcesses=0 for x in ${blockingProcesses}; do if pgrep -xq "$x"; then printlog "found blocking process $x" - + appClosed=1 + case $BLOCKING_PROCESS_ACTION in kill) printlog "killing process $x" pkill $x + sleep 5 ;; prompt_user|prompt_user_then_kill) button=$(displaydialog "Quit “$x” to continue updating? (Leave this dialogue if you want to activate this update later)." "The application “$x” needs to be updated.") if [[ $button = "Not Now" ]]; then cleanupAndExit 10 "user aborted update" else - if [[ $i = 3 && $BLOCKING_PROCESS_ACTION = "prompt_user_then_kill" ]]; then - printlog "killing process $x" - pkill $x + if [[ $i > 2 && $BLOCKING_PROCESS_ACTION = "prompt_user_then_kill" ]]; then + printlog "Changing BLOCKING_PROCESS_ACTION to kill" + BLOCKING_PROCESS_ACTION=kill else printlog "telling app $x to quit" runAsUser osascript -e "tell app \"$x\" to quit" + # give the user a bit of time to quit apps + printlog "waiting 30 seconds for processes to quit" + sleep 30 fi fi ;; + prompt_user_loop) + button=$(displaydialog "Quit “$x” to continue updating? (Click “Not Now” to be asked in 1 hour, or leave this open until you are ready)." "The application “$x” needs to be updated.") + if [[ $button = "Not Now" ]]; then + if [[ $i < 2 ]]; then + printlog "user wants to wait an hour" + sleep 3600 # 3600 seconds is an hour + else + printlog "change of BLOCKING_PROCESS_ACTION to tell_user" + BLOCKING_PROCESS_ACTION=tell_user + fi + else + printlog "telling app $x to quit" + runAsUser osascript -e "tell app \"$x\" to quit" + # give the user a bit of time to quit apps + printlog "waiting 30 seconds for processes to quit" + sleep 30 + fi + ;; + tell_user|tell_user_then_kill) + button=$(displaydialogContinue "Quit “$x” to continue updating? (This is an important update). Wait for notification of update before launching app again." "The application “$x” needs to be updated.") + printlog "telling app $x to quit" + runAsUser osascript -e "tell app \"$x\" to quit" + # give the user a bit of time to quit apps + printlog "waiting 30 seconds for processes to quit" + sleep 30 + if [[ $i > 1 && $BLOCKING_PROCESS_ACTION = tell_user_then_kill ]]; then + printlog "Changing BLOCKING_PROCESS_ACTION to kill" + BLOCKING_PROCESS_ACTION=kill + fi + ;; silent_fail) cleanupAndExit 12 "blocking process '$x' found, aborting" ;; @@ -287,14 +391,6 @@ checkRunningProcesses() { fi done - if [[ $countedProcesses -eq 0 ]]; then - # no blocking processes, exit the loop early - break - else - # give the user a bit of time to quit apps - printlog "waiting 30 seconds for processes to quit" - sleep 30 - fi done if [[ $countedProcesses -ne 0 ]]; then @@ -304,7 +400,24 @@ checkRunningProcesses() { printlog "no more blocking processes, continue with update" } +reopenClosedProcess() { + # If Installomator closed any processes, let's get the app opened again + # credit: Søren Theilgaard (@theilgaard) + + # don't reopen in DEBUG mode + if [[ $DEBUG -ne 0 ]]; then + printlog "DEBUG mode, not reopening anything" + return + fi + + if [[ $appClosed == 1 ]]; then + printlog "Telling app $name to open" + runAsUser osascript -e "tell app \"$name\" to open" + fi +} + installAppWithPath() { # $1: path to app to install in $targetDir + # modified by: Søren Theilgaard (@theilgaard) appPath=${1?:"no path to app"} # check if app exists @@ -318,12 +431,31 @@ installAppWithPath() { # $1: path to app to install in $targetDir cleanupAndExit 4 "Error verifying $appPath" fi - printlog "Team ID: $teamID (expected: $expectedTeamID )" + printlog "Team ID matching: $teamID (expected: $expectedTeamID )" if [ "$expectedTeamID" != "$teamID" ]; then cleanupAndExit 5 "Team IDs do not match" fi + # versioncheck + # credit: Søren Theilgaard (@theilgaard) + appNewVersion=$(defaults read $appPath/Contents/Info.plist CFBundleShortVersionString) + if [[ $appversion == $appNewVersion ]]; then + printlog "Downloaded version of $name is $appNewVersion, same as installed." + if [[ $INSTALL != "force" ]]; then + message="$name, version $appNewVersion, is the latest version." + if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then + printlog "notifying" + displaynotification "$message" "No update for $name!" + fi + cleanupAndExit 0 "No new version to install" + else + printlog "Using force to install anyway." + fi + else + printlog "Downloaded version of $name is $appNewVersion (replacing version $appversion)." + fi + # check for root if [ "$(whoami)" != "root" ]; then # not running as root @@ -376,28 +508,15 @@ mountDMG() { installFromDMG() { mountDMG - - applicationPath="$dmgmount/$appName" - printlog "looking for app: $applicationPath" - if [[ ! -d $applicationPath ]]; then - # find first file ending with 'app' - findfiles=$(find "$dmgmount" -iname "*.app" -maxdepth 1 -mindepth 1 ) - filearray=( ${(f)findfiles} ) - if [[ ${#filearray} -eq 0 ]]; then - cleanupAndExit 21 "couldn't find app in dmg $archiveName" - fi - applicationPath="${filearray[1]}" - printlog "found app: $applicationPath" - fi - - installAppWithPath "$applicationPath" + + installAppWithPath "$dmgmount/$appName" } installFromPKG() { # verify with spctl printlog "Verifying: $archiveName" - if ! spctlout=$(spctl -a -vv -t install "$archiveName" 2>&1 ); then + if ! spctlout=$(spctl -a -vv -t install "$archiveName" 2>&1 ); then printlog "Error verifying $archiveName" cleanupAndExit 4 fi @@ -444,9 +563,9 @@ installFromZIP() { # tar -xf "$archiveName" - # note: when you expand a zip using tar in Mojave the expanded + # note: when you expand a zip using tar in Mojave the expanded # app will never pass the spctl check - + # unzip -o -qq "$archiveName" # note: githubdesktop fails spctl verification when expanded @@ -468,7 +587,7 @@ installPkgInDmg() { # locate pkg in dmg if [[ -z $pkgName ]]; then # find first file ending with 'pkg' - findfiles=$(find "$dmgmount" -iname "*.pkg" -maxdepth 1 -mindepth 1 ) + findfiles=$(find "$dmgmount" -iname "*.pkg" -maxdepth 1 ) filearray=( ${(f)findfiles} ) if [[ ${#filearray} -eq 0 ]]; then cleanupAndExit 20 "couldn't find pkg in dmg $archiveName" @@ -491,8 +610,8 @@ installPkgInZip() { # locate pkg in zip if [[ -z $pkgName ]]; then - # find first file starting with $name and ending with 'pkg' - findfiles=$(find "$tmpDir" -iname "*.pkg" -maxdepth 1 ) + # find first file ending with 'pkg' + findfiles=$(find "$tmpDir" -iname "*.pkg" -maxdepth 2 ) filearray=( ${(f)findfiles} ) if [[ ${#filearray} -eq 0 ]]; then cleanupAndExit 20 "couldn't find pkg in zip $archiveName" @@ -509,6 +628,31 @@ installPkgInZip() { installFromPKG } +installAppInDmgInZip() { + # unzip the archive + printlog "Unzipping $archiveName" + tar -xf "$archiveName" + + # locate dmg in zip + if [[ -z $pkgName ]]; then + # find first file ending with 'dmg' + findfiles=$(find "$tmpDir" -iname "*.dmg" -maxdepth 2 ) + filearray=( ${(f)findfiles} ) + if [[ ${#filearray} -eq 0 ]]; then + cleanupAndExit 20 "couldn't find dmg in zip $archiveName" + fi + archiveName="$(basename ${filearray[1]})" + # it is now safe to overwrite archiveName for installFromDMG + printlog "found dmg: $tmpDir/$archiveName" + else + # it is now safe to overwrite archiveName for installFromDMG + archiveName="$pkgName" + fi + + # installFromDMG, DMG expected to include an app (will not work with pkg) + installFromDMG +} + runUpdateTool() { if [[ -x $updateTool ]]; then printlog "running $updateTool $updateToolArguments" @@ -538,7 +682,9 @@ fi # MARK: argument parsing if [[ $# -eq 0 ]]; then + printlog "no label provided, printing labels" grep -E '^[a-z0-9\-]*(\)|\|\\)$' "$0" | tr -d ')|\' | grep -v -E '^(broken.*|longversion|version|valuesfromarguments)$' | sort + #grep -E '^[a-z0-9\-]*(\)|\|\\)$' "${labelFile}" | tr -d ')|\' | grep -v -E '^(broken.*|longversion|version|valuesfromarguments)$' | sort exit 0 elif [[ $1 == "/" ]]; then # jamf uses sends '/' as the first argument @@ -559,12 +705,12 @@ while [[ -n $1 ]]; do shift 1 done -printlog "################## Start Installomator" -printlog "################## $label" - # lowercase the label label=${label:l} +printlog "################## Start Installomator v. $VERSION" +printlog "################## $label" + # get current user currentUser=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }') @@ -588,12 +734,21 @@ autodmg) name="AutoDMG" type="dmg" downloadURL=$(downloadURLFromGit MagerValp AutoDMG) + appNewVersion=$(versionFromGit MagerValp AutoDMG) expectedTeamID="5KQ3D3FG5H" ;; googlechrome) name="Google Chrome" type="dmg" - downloadURL="https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg" + if [[ $(arch) != "i386" ]]; then + printlog "Architecture: arm64 (not i386)" + downloadURL="https://dl.google.com/chrome/mac/universal/stable/GGRO/googlechrome.dmg" + appNewVersion=$(curl -s https://omahaproxy.appspot.com/history | awk -F',' '/mac_arm64,stable/{print $3; exit}') # Credit: William Smith (@meck) + else + printlog "Architecture: i386" + downloadURL="https://dl.google.com/chrome/mac/stable/GGRO/googlechrome.dmg" + appNewVersion=$(curl -s https://omahaproxy.appspot.com/history | awk -F',' '/mac,stable/{print $3; exit}') # Credit: William Smith (@meck) + fi expectedTeamID="EQHXZ8M8AV" ;; googlechromepkg) @@ -621,25 +776,38 @@ santa) # credit: Tadayuki Onishi (@kenchan0130) name="Santa" type="pkgInDmg" + packageID="com.google.santa" downloadURL=$(downloadURLFromGit google santa) + appNewVersion=$(versionFromGit google santa) expectedTeamID="EQHXZ8M8AV" ;; spotify) name="Spotify" type="dmg" downloadURL="https://download.scdn.co/Spotify.dmg" + # appNewVersion=$(curl -fs https://www.spotify.com/us/opensource/ | cat | grep -o "
Version" | head -1 | cut -d " " -f1 | cut -d ";" -f2 | cut -d "." -f 1-3) expectedTeamID="S272Y5R93J" ;; privileges) @@ -841,6 +1061,7 @@ privileges) name="Privileges" type="zip" downloadURL=$(downloadURLFromGit sap macOS-enterprise-privileges ) + appNewVersion=$(versionFromGit sap macOS-enterprise-privileges ) expectedTeamID="7R5ZEU67FQ" ;; icons) @@ -848,14 +1069,16 @@ icons) name="Icons" type="zip" downloadURL=$(downloadURLFromGit sap macOS-icon-generator ) + appNewVersion=$(versionFromGit sap macOS-icon-generator ) expectedTeamID="7R5ZEU67FQ" ;; -googledrivefilestream) +googledrive|googledrivefilestream) # credit: Isaac Ordonez, Mann consulting (@mannconsulting) name="Google Drive File Stream" type="pkgInDmg" - downloadURL="https://dl.google.com/drive-file-stream/GoogleDriveFileStream.dmg" - pkgName="GoogleDriveFileStream.pkg" + packageID="com.google.drivefs" + downloadURL="https://dl.google.com/drive-file-stream/GoogleDriveFileStream.dmg" # downloadURL="https://dl.google.com/drive-file-stream/GoogleDrive.dmg" + blockingProcesses=( "Google Docs" "Google Drive" "Google Sheets" "Google Slides" ) expectedTeamID="EQHXZ8M8AV" ;; plisteditpro) @@ -867,7 +1090,12 @@ plisteditpro) slack) name="Slack" type="dmg" - downloadURL="https://slack.com/ssb/download-osx" + if [[ $(arch) == "arm64" ]]; then + downloadURL="https://slack.com/ssb/download-osx-silicon" + elif [[ $(arch) == "i386" ]]; then + downloadURL="https://slack.com/ssb/download-osx" + fi + appNewVersion=$( curl -fsIL "${downloadURL}" | grep -i "^location" | awk '{print $2}' | tr -d '\r\n' | sed -E 's/.*macos\/([0-9.]*)\/.*/\1/g' ) expectedTeamID="BQR82RBBHL" ;; sublimetext) @@ -875,12 +1103,15 @@ sublimetext) name="Sublime Text" type="dmg" downloadURL="https://download.sublimetext.com/latest/stable/osx" + appNewVersion=$(curl -fs https://www.sublimetext.com/3 | grep 'class="latest"' | cut -d '>' -f 4 | sed -E 's/ (.*[0-9]*)<.*/\1/g') + #appNewVersion=$(curl -Is https://download.sublimetext.com/latest/stable/osx | grep "Location:" | sed -n -e 's/^.*Sublime Text //p' | sed 's/.dmg//g' | sed $'s/[^[:print:]\t]//g') # Alternative from @Oh4sh0 expectedTeamID="Z6D26JE4Y4" ;; githubdesktop) name="GitHub Desktop" type="zip" downloadURL="https://central.github.com/deployments/desktop/desktop/latest/darwin" + appNewVersion=$(curl -fsL https://central.github.com/deployments/desktop/desktop/changelog.json | awk -F '{' '/"version"/ { print $2 }' | sed -E 's/.*,\"version\":\"([0-9.]*)\".*/\1/g') expectedTeamID="VEKTX9H2N7" ;; things) @@ -906,6 +1137,7 @@ handbrake) type="dmg" downloadURL=$(curl --silent --fail "https://api.github.com/repos/HandBrake/HandBrake/releases/latest" \ | awk -F '"' "/browser_download_url/ && /dmg/ && ! /sig/ && ! /CLI/ { print \$4 }") + appNewVersion=$(curl -sf "https://api.github.com/repos/HandBrake/HandBrake/releases/latest" | awk -F '"' "/tag_name/ { print \$4 }") expectedTeamID="5X9DE89KYV" ;; netnewswire) @@ -913,6 +1145,7 @@ netnewswire) type="zip" downloadURL=$(curl -fs https://ranchero.com/downloads/netnewswire-release.xml \ | xpath '//rss/channel/item[1]/enclosure/@url' 2>/dev/null | cut -d '"' -f 2) + appNewVersion=$(curl -fs https://ranchero.com/downloads/netnewswire-release.xml | xpath '//rss/channel/item[1]/enclosure/@sparkle:shortVersionString' 2>/dev/null | cut -d '"' -f 2) expectedTeamID="M8L2WTLA8W" ;; resiliosynchome) @@ -925,6 +1158,7 @@ cyberduck) name="Cyberduck" type="zip" downloadURL=$(curl -fs https://version.cyberduck.io/changelog.rss | xpath '//rss/channel/item/enclosure/@url' 2>/dev/null | cut -d '"' -f 2 ) + appNewVersion=$(curl -fs https://version.cyberduck.io/changelog.rss | xpath '//rss/channel/item/enclosure/@sparkle:shortVersionString' 2>/dev/null | cut -d '"' -f 2 ) expectedTeamID="G69SCX94XU" ;; dropbox) @@ -940,16 +1174,11 @@ teamviewer) downloadURL="https://download.teamviewer.com/download/TeamViewer.dmg" expectedTeamID="H7UGFBUGV6" ;; -teamviewerqs) - name="TeamViewerQS" - type="dmg" - downloadURL="https://download.teamviewer.com/download/TeamViewerQS.dmg" - expectedTeamID="H7UGFBUGV6" - ;; iterm2) name="iTerm" type="zip" downloadURL="https://iterm2.com/downloads/stable/latest" + appNewVersion=$(curl -is https://iterm2.com/downloads/stable/latest | grep location: | grep -o "iTerm2.*zip" | cut -d "-" -f 2 | cut -d '.' -f1 | sed 's/_/./g') expectedTeamID="H7V7XYVQ7D" blockingProcesses=( iTerm2 ) ;; @@ -957,6 +1186,7 @@ royaltsx) name="Royal TSX" type="dmg" downloadURL=$(curl -fs https://royaltsx-v4.royalapps.com/updates_stable | xpath '//rss/channel/item[1]/enclosure/@url' 2>/dev/null | cut -d '"' -f 2) + appNewVersion=$(curl -fs https://royaltsx-v4.royalapps.com/updates_stable | xpath '//rss/channel/item[1]/enclosure/@sparkle:shortVersionString' 2>/dev/null | cut -d '"' -f 2) expectedTeamID="VXP8K9EDP6" ;; appcleaner) @@ -971,6 +1201,7 @@ karabinerelements) name="Karabiner-Elements" type="pkgInDmg" downloadURL=$(downloadURLFromGit pqrs-org Karabiner-Elements) + appNewVersion=$(versionFromGit pqrs-org Karabiner-Elements) expectedTeamID="G43BCU2T37" ;; postman) @@ -978,6 +1209,7 @@ postman) name="Postman" type="zip" downloadURL="https://dl.pstmn.io/download/latest/osx" + appNewVersion=$(curl -Ifs https://dl.pstmn.io/download/latest/osx | grep "content-disposition:" | sed -n -e 's/^.*Postman-osx-//p' | sed 's/\.zip//' | sed $'s/[^[:print:]\t]//g' ) expectedTeamID="H7H8Q7M5CK" ;; jamfpppcutility) @@ -985,6 +1217,7 @@ jamfpppcutility) name="PPPC Utility" type="zip" downloadURL=$(downloadURLFromGit jamf PPPC-Utility) + appNewVersion=$(versionFromGit jamf PPPC-Utility) expectedTeamID="483DWKW443" ;; jamfmigrator) @@ -992,6 +1225,7 @@ jamfmigrator) name="jamf-migrator" type="zip" downloadURL=$(downloadURLFromGit jamf JamfMigrator) + #appNewVersion=$(versionFromGit jamf JamfMigrator) expectedTeamID="PS2F6S478M" ;; jamfreenroller) @@ -999,13 +1233,16 @@ jamfreenroller) name="ReEnroller" type="zip" downloadURL=$(downloadURLFromGit jamf ReEnroller) + #appNewVersion=$(versionFromGit jamf ReEnroller) expectedTeamID="PS2F6S478M" ;; adobereaderdc|\ adobereaderdc-install) name="Adobe Acrobat Reader DC" type="pkgInDmg" + packageID="com.adobe.acrobat.DC.reader.app.pkg.MUI" downloadURL=$(curl --silent --fail -H "Sec-Fetch-Site: same-origin" -H "Accept-Encoding: gzip, deflate, br" -H "Accept-Language: en-US;q=0.9,en;q=0.8" -H "DNT: 1" -H "Sec-Fetch-Mode: cors" -H "X-Requested-With: XMLHttpRequest" -H "Referer: https://get.adobe.com/reader/enterprise/" -H "Accept: */*" "https://get.adobe.com/reader/webservices/json/standalone/?platform_type=Macintosh&platform_dist=OSX&platform_arch=x86-32&language=English&eventname=readerotherversions" | grep -Eo '"download_url":.*?[^\\]",' | head -n 1 | cut -d \" -f 4) + appNewVersion=$(curl -s -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15)" https://get.adobe.com/reader/ | grep ">Version" | sed -E 's/.*Version 20([0-9.]*)<.*/\1/g') # credit: Søren Theilgaard (@theilgaard) expectedTeamID="JQ525L2MZD" blockingProcesses=( "AdobeReader" ) ;; @@ -1013,28 +1250,39 @@ adobereaderdc-update) name="Adobe Acrobat Reader DC" type="pkgInDmg" downloadURL=$(adobecurrent=`curl --fail --silent https://armmf.adobe.com/arm-manifests/mac/AcrobatDC/reader/current_version.txt | tr -d '.'` && echo http://ardownload.adobe.com/pub/adobe/reader/mac/AcrobatDC/"$adobecurrent"/AcroRdrDCUpd"$adobecurrent"_MUI.dmg) + appNewVersion=$(curl -s -H "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15)" https://get.adobe.com/reader/ | grep ">Version" | sed -E 's/.*Version 20([0-9.]*)<.*/\1/g') # credit: Søren Theilgaard (@theilgaard) expectedTeamID="JQ525L2MZD" blockingProcesses=( "AdobeReader" ) ;; signal) - # credit: Søren Theilgaard + # credit: Søren Theilgaard (@theilgaard) name="Signal" type="dmg" downloadURL=https://updates.signal.org/desktop/$(curl -fs https://updates.signal.org/desktop/latest-mac.yml | awk '/url/ && /dmg/ {print $3}') + appNewVersion=$(curl -fs https://updates.signal.org/desktop/latest-mac.yml | grep version | awk '{print $2}') expectedTeamID="U68MSDN6DR" ;; docker) - # credit: @securitygeneration + # credit: @securitygeneration name="Docker" type="dmg" downloadURL="https://download.docker.com/mac/stable/Docker.dmg" + appNewVersion=$(curl -ifs https://docs.docker.com/docker-for-mac/release-notes/ | grep ">Docker Desktop Community" | head -1 | sed -n -e 's/^.*Community //p' | cut -d '<' -f1) expectedTeamID="9BNSXJN65R" ;; brave) # credit: @securitygeneration name="Brave Browser" type="dmg" - downloadURL=$(curl --location --fail --silent "https://updates.bravesoftware.com/sparkle/Brave-Browser/stable/appcast.xml" | xpath '//rss/channel/item[last()]/enclosure/@url' 2>/dev/null | cut -d '"' -f 2) + if [[ $(arch) != "i386" ]]; then + printlog "Architecture: arm64 (not i386)" + downloadURL=$(curl -fsIL https://laptop-updates.brave.com/latest/osxarm64/release | grep -i "^location" | awk '{print $2}' | tr -d '\r\n') + else + printlog "Architecture: i386" + downloadURL=$(curl -fsIL https://laptop-updates.brave.com/latest/osx/release | grep -i "^location" | awk '{print $2}' | tr -d '\r\n') + fi +# downloadURL=$(curl --location --fail --silent "https://updates.bravesoftware.com/sparkle/Brave-Browser/stable/appcast.xml" | xpath '//rss/channel/item[last()]/enclosure/@url' 2>/dev/null | cut -d '"' -f 2) + appNewVersion=$(curl --location --fail --silent "https://updates.bravesoftware.com/sparkle/Brave-Browser/stable/appcast.xml" | xpath '//rss/channel/item[last()]/enclosure/@sparkle:shortVersionString' 2>/dev/null | cut -d '"' -f 2) expectedTeamID="KL8N8XSYF4" ;; umbrellaroamingclient) @@ -1050,6 +1298,7 @@ umbrellaroamingclient) # name="VMware Fusion" # type="dmg" # downloadURL="https://www.vmware.com/go/getfusion" +# appNewVersion=$( curl -fsIL "${downloadURL}" | grep -i "^location" | awk '{print $2}' | sed -E 's/.*Fusion-([0-9.]*)-.*/\1/g' ) # expectedTeamID="EG7KH642X6" # ;; @@ -1071,18 +1320,18 @@ umbrellaroamingclient) # expectedTeamID="UBF8T346G9" # ;; -wwdcformac) - name="WWDC" - type="zip" - downloadURL="https://cdn.wwdc.io/WWDC_latest.zip" - expectedTeamID="8C7439RJLG" - ;; +#wwdcformac) # this label looks like software/site is gone +# name="WWDC" +# type="zip" +# downloadURL="https://cdn.wwdc.io/WWDC_latest.zip" +# expectedTeamID="8C7439RJLG" +# ;; ringcentralmeetings) # credit: Isaac Ordonez, Mann consulting (@mannconsulting) name="Ring Central Meetings" type="pkg" downloadURL="http://dn.ringcentral.com/data/web/download/RCMeetings/1210/RCMeetingsClientSetup.pkg" - expectedTeamID="M932RC5J66" + expectedTeamID="M932RC5J66" blockingProcesses=( "RingCentral Meetings" ) ;; ringcentralapp) @@ -1090,7 +1339,7 @@ ringcentralapp) name="Glip" type="dmg" downloadURL="https://downloads.ringcentral.com/glip/rc/GlipForMac" - expectedTeamID="M932RC5J66" + expectedTeamID="M932RC5J66" blockingProcesses=( "Glip" ) ;; sfsymbols) @@ -1124,8 +1373,8 @@ torbrowser) # credit: Søren Theilgaard (@theilgaard) name="Tor Browser" type="dmg" - downloadURL=https://www.torproject.org$(curl -fs https://www.torproject.org/download/ | grep "downloadLink" | grep -m 1 dmg | cut -d '"' -f 4) - appNewVersion=$(curl -fs https://www.torproject.org/download/ | grep "downloadLink" | grep dmg | cut -d '"' -f 4 | cut -d / -f 4) + downloadURL=https://www.torproject.org$(curl -fs https://www.torproject.org/download/ | grep "downloadLink" | grep dmg | head -1 | cut -d '"' -f 4) + appNewVersion=$(curl -fs https://www.torproject.org/download/ | grep "downloadLink" | grep dmg | head -1 | cut -d '"' -f 4 | cut -d / -f 4) expectedTeamID="MADPSAYN6T" ;; code42) @@ -1141,27 +1390,40 @@ nomad) name="NoMAD" type="pkg" downloadURL="https://files.nomad.menu/NoMAD.pkg" + appNewVersion=$(curl -fs https://nomad.menu/support/ | grep "NoMAD Downloads" | sed -E 's/.*Current Version ([0-9\.]*)<.*/\1/g') expectedTeamID="VRPY9KHGX6" ;; +nomadlogin) + # credit: Søren Theilgaard (@theilgaard) + name="NoMAD Login" + type="pkg" + downloadURL="https://files.nomad.menu/NoMAD-Login-AD.pkg" + appNewVersion=$(curl -fs https://nomad.menu/support/ | grep "NoMAD Login AD Downloads" | sed -E 's/.*Current Version ([0-9\.]*)<.*/\1/g') + expectedTeamID="AAPZK3CB24" + ;; bettertouchtool) - # credit: Tadayuki Onishi (@kenchan0130) + # credit: Søren Theilgaard (@theilgaard) name="BetterTouchTool" type="zip" downloadURL="https://folivora.ai/releases/BetterTouchTool.zip" + appNewVersion=$(curl -fs https://updates.folivora.ai/bettertouchtool_release_notes.html | grep BetterTouchTool | head -n 2 | tail -n 1 | sed -E 's/.* ([0-9\.]*) .*/\1/g') expectedTeamID="DAFVSXZ82P" ;; r) - # credit: Tadayuki Onishi (@kenchan0130) + # credit: Tadayuki Onishi (@kenchan0130) name="R" type="pkg" downloadURL=$( curl -fsL https://formulae.brew.sh/api/cask/r.json | sed -n 's/^.*"url":"\([^"]*\)".*$/\1/p' ) + appNewVersion=$(curl -fsL https://formulae.brew.sh/api/cask/r.json | sed -n 's/^.*"version":"\([^"]*\)".*$/\1/p') expectedTeamID="VZLD955F6P" - ;; + ;; 8x8) # credit: #D-A-James from MacAdmins Slack and Isaac Ordonez, Mann consulting (@mannconsulting) name="8x8 Work" type="dmg" downloadURL=$(curl -fs -L https://support.8x8.com/cloud-phone-service/voice/work-desktop/download-8x8-work-for-desktop | grep -m 1 -o "https.*dmg" | sed 's/\"//' | awk '{print $1}') + # As for appNewVersion, it needs to be checked for newer version than 7.2.4 + appNewVersion=$(curl -fs -L https://support.8x8.com/cloud-phone-service/voice/work-desktop/download-8x8-work-for-desktop | grep -m 1 -o "https.*dmg" | sed 's/\"//' | awk '{print $1}' | sed -E 's/.*-v([0-9\.]*)[-\.]*.*/\1/' ) expectedTeamID="FC967L3QRG" ;; egnyte) @@ -1178,9 +1440,8 @@ camtasia) downloadURL=https://download.techsmith.com/camtasiamac/releases/Camtasia.dmg expectedTeamID="7TQL462TU8" ;; -snagit2020) - # credit: Isaac Ordonez, Mann consulting (@mannconsulting) - name="Snagit 2020" +snagit|snagit2021|snagit2020) + name="Snagit 2021" type="dmg" downloadURL="https://download.techsmith.com/snagitmac/releases/Snagit.dmg" expectedTeamID="7TQL462TU8" @@ -1192,6 +1453,7 @@ virtualbox) pkgName="VirtualBox.pkg" downloadURL=$(curl -fs "https://www.virtualbox.org/wiki/Downloads" \ | awk -F '"' "/OSX.dmg/ { print \$4 }") + appNewVersion=$(curl -fs "https://www.virtualbox.org/wiki/Downloads" | awk -F '"' "/OSX.dmg/ { print \$4 }" | sed -E 's/.*virtualbox\/([0-9.]*)\/.*/\1/') expectedTeamID="VB5E2TV963" ;; detectxswift) @@ -1199,14 +1461,16 @@ detectxswift) name="DetectX Swift" type="zip" downloadURL="https://s3.amazonaws.com/sqwarq.com/PublicZips/DetectX_Swift.app.zip" + appNewVersion=$(curl -fs https://s3.amazonaws.com/sqwarq.com/AppCasts/dtxswift_release_notes.html | grep Version | head -1 | sed -E 's/.*Version ([0-9.]*)\<.*/\1/') expectedTeamID="MAJ5XBJSG3" ;; autopkgr) - # credit: AP Orlebeke (@apizz) + # credit: Søren Theilgaard (@theilgaard) name="AutoPkgr" type="dmg" - downloadURL=$(curl -fs "https://api.github.com/repos/lindegroup/autopkgr/releases/latest" \ - | awk -F '"' "/browser_download_url/ && /dmg/ && ! /sig/ && ! /CLI/ && ! /sha256/ { print \$4 }") + #downloadURL=$(curl -fs "https://api.github.com/repos/lindegroup/autopkgr/releases/latest" | awk -F '"' "/browser_download_url/ && /dmg/ && ! /sig/ && ! /CLI/ && ! /sha256/ { print \$4 }") + downloadURL=$(downloadURLFromGit lindegroup autopkgr) + appNewVersion=$(versionFromGit lindegroup autopkgr) expectedTeamID="JVY2ZR6SEF" ;; airserver) @@ -1214,14 +1478,16 @@ airserver) name="AirServer" type="dmg" downloadURL="https://www.airserver.com/download/mac/latest" + #appNewVersion=$() # Cannot find version history or release notes on home page expectedTeamID="6C755KS5W3" ;; vscodium) # credit: AP Orlebeke (@apizz) name="VSCodium" type="dmg" - downloadURL=$(curl -fs "https://api.github.com/repos/VSCodium/vscodium/releases/latest" \ - | awk -F '"' "/browser_download_url/ && /dmg/ && ! /sig/ && ! /CLI/ && ! /sha256/ { print \$4 }") + downloadURL=$(curl -fs "https://api.github.com/repos/VSCodium/vscodium/releases/latest" | awk -F '"' "/browser_download_url/ && /dmg/ && ! /sig/ && ! /CLI/ && ! /sha256/ { print \$4 }") + #downloadURL=$(downloadURLFromGit VSCodium vscodium) # Too many versions + appNewVersion=$(versionFromGit VSCodium vscodium) expectedTeamID="C7S3ZQ2B8V" appName="VSCodium.app" blockingProcesses=( Electron ) @@ -1231,6 +1497,7 @@ keepassxc) name="KeePassXC" type="dmg" downloadURL="$(downloadURLFromGit keepassxreboot keepassxc)" + appNewVersion=$(versionFromGit keepassxreboot keepassxc) expectedTeamID="G2S7P7J672" ;; alfred) @@ -1238,6 +1505,7 @@ alfred) name="Alfred" type="dmg" downloadURL=$(curl -fs https://www.alfredapp.com | awk -F '"' "/dmg/ {print \$2}" | head -1) + appNewVersion=$(echo "${downloadURL}" | sed -E 's/.*Alfred_([0-9.]*)_.*/\1/') appName="Alfred 4.app" expectedTeamID="XZZXE9SED4" ;; @@ -1247,6 +1515,7 @@ istatmenus) type="zip" downloadURL="https://download.bjango.com/istatmenus/" expectedTeamID="Y93TK974AT" + appNewVersion=$(curl -fs https://bjango.com/mac/istatmenus/versionhistory/ | grep "
Inkscape" | cut -d '>' -f 3 | cut -d '<' -f 1 | sed 's/[^0-9.]*//g') # Can't figure out where exact new version is found. Currently returns 1.0, but version is "1.0.0 (4035a4f)"
+ expectedTeamID="SW3D6BB6A6"
+ ;;
+xink)
+ name="Xink"
+ type="zip"
+ downloadURL="https://downloads.xink.io/macos/client"
+ #appNewVersion=$() # Cannot find version history or release notes on home page
+ expectedTeamID="F287823HVS"
+ ;;
+
onlyofficedesktop)
# credit: Adrian Bühler (@midni9ht)
name="ONLYOFFICE"
@@ -1457,27 +1659,6 @@ onlyofficedesktop)
downloadURL="https://download.onlyoffice.com/install/desktop/editors/mac/distrib/onlyoffice/ONLYOFFICE.dmg"
expectedTeamID="2WH24U26GJ"
;;
-googleearth)
- # credit: David Chatton (@mdmmac on MacAdmins Slack)
- name="Google Earth Pro"
- type="pkgInDmg"
- downloadURL="https://dl.google.com/earth/client/advanced/current/GoogleEarthProMac-Intel.dmg"
- expectedTeamID="EQHXZ8M8AV"
- ;;
-pymol)
- # credit: Fredrik Larsson (@fredrik_l on MacAdmins Slack)
- name="PyMOL"
- type="dmg"
- downloadURL=$(curl -s -L "https://pymol.org/" | grep -m 1 -Eio 'href="https://pymol.org/installers/PyMOL-(.*)-MacOS(.*).dmg"' | cut -c7- | sed -e 's/"$//')
- expectedTeamID="26SDDJ756N"
- ;;
-prism9)
- # credit: Fredrik Larsson (@fredrik_l on MacAdmins Slack)
- name="Prism 9"
- type="dmg"
- downloadURL="http://cdn.graphpad.com/downloads/prism/9/InstallPrism9.dmg"
- expectedTeamID="YQ2D36NS9M"
- ;;
gpgsuite)
# credit: Micah Lee (@micahflee)
name="GPG Suite"
@@ -1500,39 +1681,35 @@ dangerzone)
downloadURL=$(curl -s https://dangerzone.rocks/ | grep https://github.com/firstlookmedia/dangerzone/releases/download | grep \.dmg | cut -d'"' -f2)
expectedTeamID="P24U45L8P5"
;;
+dbeaverce)
+ # credit: Adrian Bühler (@midni9ht)
+ name="DBeaver"
+ type="dmg"
+ downloadURL="https://dbeaver.io/files/dbeaver-ce-latest-macos.dmg"
+ expectedTeamID="42B6MDKMW8"
+ blockingProcesses=( dbeaver )
+ ;;
+androidfiletransfer)
+ #credit: Sam Ess (saess-sep)
+ name="Android File Transfer"
+ type="dmg"
+ downloadURL="https://dl.google.com/dl/androidjumper/mtp/current/AndroidFileTransfer.dmg"
+ expectedTeamID="EQHXZ8M8AV"
+ ;;
libreoffice)
# credit: Micah Lee (@micahflee)
name="LibreOffice"
type="dmg"
downloadURL="https://download.documentfoundation.org/libreoffice/stable/$(curl -s https://www.libreoffice.org/download/download/ | grep dl_version_number | head -n 1 | cut -d'>' -f3 | cut -d'<' -f1)/mac/x86_64/LibreOffice_$(curl -s https://www.libreoffice.org/download/download/ | grep dl_version_number | head -n 1 | cut -d'>' -f3 | cut -d'<' -f1)_MacOS_x86-64.dmg"
+ appNewVersion=$( echo "${downloadURL}" | sed -E 's/.*\/[a-zA-Z]*_([0-9.]*)_.*/\1/g' )
expectedTeamID="7P5S3ZLCN7"
;;
-sketch)
- # credit: Alex L. (@aloew on MacAdmins Slack)
- name="Sketch"
- type="zip"
- downloadURL="http://download.sketchapp.com/sketch.zip"
- expectedTeamID="WUGMZZ5K46"
- ;;
-abstract)
- # credit: Alex L. (@aloew on MacAdmins Slack)
- name="Abstract"
- type="zip"
- downloadURL="https://api.goabstract.com/releases/latest/download"
- expectedTeamID="77MZLZE47D"
- ;;
-musescore)
- # credit: @marcelclaus on MacAdmins Slack
- name="MuseScore 3"
- type="dmg"
- downloadURL=$(downloadURLFromGit musescore MuseScore)
- expectedTeamID="6EPAF2X3PR"
- ;;
toggltrack)
# credit: Adrian Bühler (@midni9ht)
name="Toggl Track"
type="dmg"
downloadURL=$(downloadURLFromGit toggl-open-source toggldesktop )
+ appNewVersion=$(versionFromGit toggl-open-source toggldesktop )
expectedTeamID="B227VTMZ94"
;;
balenaetcher)
@@ -1540,154 +1717,22 @@ balenaetcher)
name="balenaEtcher"
type="dmg"
downloadURL=$(downloadURLFromGit balena-io etcher )
+ appNewVersion=$(versionFromGit balena-io etcher )
expectedTeamID="66H43P8FRG"
;;
-figma)
- # credit: Alex L. (@aloew on MacAdmins Slack)
- name="Figma"
- type="zip"
- downloadURL="https://www.figma.com/download/desktop/mac/"
- expectedTeamID="T8RA8NE3B7"
- ;;
-jetbrainsidea)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="JetBrains IntelliJ Idea"
- type="dmg"
- expectedTeamID="2ZEFAR8TH3"
- #appNewVersion=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=IIU&latest=true&type=release" | grep -o 'version*.*,' | cut -d '"' -f3)
- downloadURL=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=IIU&latest=true&type=release" | grep -o "mac*.*.dmg" | cut -d '"' -f5)
- ;;
-jetbrainspycharm)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="JetBrains PyCharm"
- type="dmg"
- expectedTeamID="2ZEFAR8TH3"
- #appNewVersion=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=PCP&latest=true&type=release" | grep -o 'version*.*,' | cut -d '"' -f3)
- downloadURL=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=PCP&latest=true&type=release" | grep -o "mac*.*.dmg" | cut -d '"' -f5)
- ;;
-jetbrainsrubymine)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="JetBrains RubyMine"
- type="dmg"
- expectedTeamID="2ZEFAR8TH3"
- #appNewVersion=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=RM&latest=true&type=release" | grep -o 'version*.*,' | cut -d '"' -f3)
- downloadURL=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=RM&latest=true&type=release" | grep -o "mac*.*.dmg" | cut -d '"' -f5)
- ;;
-jetbrainswebstorm)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="JetBrains Webstorm"
- type="dmg"
- expectedTeamID="2ZEFAR8TH3"
- #appNewVersion=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=WS&latest=true&type=release" | grep -o 'version*.*,' | cut -d '"' -f3)
- downloadURL=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=WS&latest=true&type=release" | grep -o "mac*.*.dmg" | cut -d '"' -f5)
- ;;
-jetbrainsdatagrip)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="JetBrains DataGrip"
- type="dmg"
- expectedTeamID="2ZEFAR8TH3"
- #appNewVersion=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=DG&latest=true&type=release" | grep -o 'version*.*,' | cut -d '"' -f3)
- downloadURL=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=DG&latest=true&type=release" | grep -o "mac*.*.dmg" | cut -d '"' -f5)
- ;;
-jetbrainsclion)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="JetBrains CLion"
- type="dmg"
- expectedTeamID="2ZEFAR8TH3"
- #appNewVersion=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=CL&latest=true&type=release" | grep -o 'version*.*,' | cut -d '"' -f3)
- downloadURL=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=CL&latest=true&type=release" | grep -o "mac*.*.dmg" | cut -d '"' -f5)
- ;;
-jetbrainsgoland)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="JetBrains GoLand"
- type="dmg"
- expectedTeamID="2ZEFAR8TH3"
- #appNewVersion=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=GO&latest=true&type=release" | grep -o 'version*.*,' | cut -d '"' -f3)
- downloadURL=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=GO&latest=true&type=release" | grep -o "mac*.*.dmg" | cut -d '"' -f5)
- ;;
-jetbrainsrider)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="JetBrains Rider"
- type="dmg"
- expectedTeamID="2ZEFAR8TH3"
- #appNewVersion=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=RD&latest=true&type=release" | grep -o 'version*.*,' | cut -d '"' -f3)
- downloadURL=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=RD&latest=true&type=release" | grep -o "mac*.*.dmg" | cut -d '"' -f5)
- ;;
-jetbrainsappcode)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="JetBrains AppCode"
- type="dmg"
- expectedTeamID="2ZEFAR8TH3"
- #appNewVersion=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=AC&latest=true&type=release" | grep -o 'version*.*,' | cut -d '"' -f3)
- downloadURL=$(curl -fs "https://data.services.jetbrains.com/products/releases?code=AC&latest=true&type=release" | grep -o "mac*.*.dmg" | cut -d '"' -f5)
- ;;
-jetbrainsideace|\
-intellijideace)
- # credit: Alex L. (@aloew on MacAdmins Slack)
- name="IntelliJ IDEA CE"
- type="dmg"
- downloadURL="https://download.jetbrains.com/product?code=IIC&latest&distribution=mac"
- expectedTeamID="2ZEFAR8TH3"
- ;;
-jetbrainspycharmce|\
-pycharmce)
- # credit: Alex L. (@aloew on MacAdmins Slack)
- name="PyCharm CE"
- type="dmg"
- downloadURL="https://download.jetbrains.com/product?code=PCC&latest&distribution=mac"
- expectedTeamID="2ZEFAR8TH3"
- ;;
-pitch)
- #credit: @evil mwnci on MacAdmins Slack
- name="Pitch"
- type="dmg"
- downloadURL="https://desktop.pitch.com/mac/Pitch.dmg"
- expectedTeamID="KUCN8NUU6Z"
- ;;
-sidekick)
- #credit: @evil mwnci on MacAdmins Slack
- name="Sidekick"
- type="dmg"
- downloadURL="https://api.meetsidekick.com/downloads/df/mac"
- expectedTeamID="N975558CUS"
- ;;
-aircall)
- # credit: @kris-anderson
- name="Aircall"
- type="dmg"
- downloadURL="https://electron.aircall.io/download/osx"
- expectedTeamID="3ML357Q795"
- ;;
-plantronicshub)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="Plantronics Hub"
- type="pkgInDmg"
- pkgName="Plantronics Software.pkg"
- downloadURL="https://www.poly.com/content/dam/www/software/PlantronicsHubInstaller.dmg"
- expectedTeamID="SKWK2Q7JJV"
- #appNewVersion=$(curl -fs "https://www.poly.com/in/en/support/knowledge-base/kb-article-page?lang=en_US&urlName=Hub-Release-Notes&type=Product_Information__kav" | grep -o "(*.*)" | head -1 | cut -d "(" -f2 | sed 's/\<\/span\>//g' | cut -d "<" -f1)
- ;;
-jabradirect)
- # credit: Casey Jensen (@cajenson01 on MacAdmins Slack)
- name="Jabra Direct"
- type="pkgInDmg"
- pkgName="JabraDirectSetup.pkg"
- downloadURL="https://jabraxpressonlineprdstor.blob.core.windows.net/jdo/JabraDirectSetup.dmg"
- expectedTeamID="55LV32M29R"
- #appNewVersion=$(curl -fs https://www.jabra.com/Support/release-notes/release-note-jabra-direct | grep -o "Jabra Direct macOS:*.*<" | head -1 | cut -d ":" -f2 | cut -d " " -f2 | cut -d "<" -f1)
- ;;
fsmonitor)
- # credit: Adrian Bühler (@midni9ht)
- name="FSMonitor"
- type="zip"
- downloadURL=$(curl --location --fail --silent "https://fsmonitor.com/FSMonitor/Archives/appcast2.xml" | xpath '//rss/channel/item[last()]/enclosure/@url' 2>/dev/null | cut -d '"' -f 2)
- expectedTeamID="V85GBYB7B9"
- ;;
+ # credit: Adrian Bühler (@midni9ht)
+ name="FSMonitor"
+ type="zip"
+ downloadURL=$(curl --location --fail --silent "https://fsmonitor.com/FSMonitor/Archives/appcast2.xml" | xpath '//rss/channel/item[last()]/enclosure/@url' 2>/dev/null | cut -d '"' -f 2)
+ expectedTeamID="V85GBYB7B9"
+ ;;
ramboxce)
# credit: Adrian Bühler (@midni9ht)
name="Rambox"
type="dmg"
downloadURL=$(downloadURLFromGit ramboxapp community-edition )
+ appNewVersion=$(versionFromGit ramboxapp community-edition )
expectedTeamID="7F292FPD69"
;;
adobebrackets)
@@ -1695,6 +1740,7 @@ adobebrackets)
name="Brackets"
type="dmg"
downloadURL=$(downloadURLFromGit adobe brackets )
+ appNewVersion=$(versionFromGit adobe brackets )
expectedTeamID="JQ525L2MZD"
;;
debookee)
@@ -1709,6 +1755,7 @@ ferdi)
name="Ferdi"
type="dmg"
downloadURL=$(downloadURLFromGit getferdi ferdi )
+ appNewVersion=$(versionFromGit getferdi ferdi )
expectedTeamID="B6J9X9DWFL"
;;
hyper)
@@ -1716,6 +1763,7 @@ hyper)
name="Hyper"
type="dmg"
downloadURL=$(downloadURLFromGit vercel hyper )
+ appNewVersion=$(versionFromGit vercel hyper)
expectedTeamID="JW6Y669B67"
;;
menumeters)
@@ -1723,32 +1771,389 @@ menumeters)
name="MenuMeters"
type="zip"
downloadURL=$(downloadURLFromGit yujitach MenuMeters )
+ appNewVersion=$(versionFromGit yujitach MenuMeters )
expectedTeamID="95AQ7YKR5A"
;;
+webexteams)
+ # credit: Erik Stam (@erikstam)
+ name="Webex"
+ type="dmg"
+ downloadURL="https://binaries.webex.com/WebexTeamsDesktop-MACOS-Gold/WebexTeams.dmg"
+ #appNewVersion=$() # Cannot find version history or release notes on home page
+ expectedTeamID="DE8Y96K9QP"
+ ;;
+mattermost)
+ name="Mattermost"
+ type="dmg"
+ downloadURL=$(downloadURLFromGit mattermost desktop)
+ appNewVersion=$(versionFromGit mattermost desktop )
+ expectedTeamID="UQ8HT4Q2XM"
+ ;;
+bitwarden)
+ name="Bitwarden"
+ type="dmg"
+ downloadURL=$(downloadURLFromGit bitwarden desktop )
+ appNewVersion=$(versionFromGit bitwarden desktop )
+ expectedTeamID="LTZ2PFU5D6"
+ ;;
+thunderbird)
+ name="Thunderbird"
+ type="dmg"
+ downloadURL="https://download.mozilla.org/?product=thunderbird-latest&os=osx&lang=en-US"
+ expectedTeamID="43AQ936H96"
+ blockingProcesses=( thunderbird )
+ ;;
+tigervnc)
+ name="TigerVNC Viewer"
+ type="dmg"
+ downloadURL=https://dl.bintray.com/tigervnc/stable/$(curl -s -l https://dl.bintray.com/tigervnc/stable/ | grep .dmg | sed 's/)" | head -1 | cut -d "(" -f2 | sed 's/\<\/span\>//g' | cut -d "<" -f1)
+ ;;
+jabradirect)
+ name="Jabra Direct"
+ type="dmg"
+ downloadURL="https://jabraxpressonlineprdstor.blob.core.windows.net/jdo/JabraDirectSetup.dmg"
+ expectedTeamID="55LV32M29R"
+ appNewVersion=$(curl -fs https://www.jabra.com/Support/release-notes/release-note-jabra-direct | grep -o "Jabra Direct macOS:*.*<" | head -1 | cut -d ":" -f2 | cut -d " " -f2 | cut -d "<" -f1)
+ ;;
vagrant)
# credit: AP Orlebeke (@apizz)
name="Vagrant"
type="pkgInDmg"
pkgName="vagrant.pkg"
- downloadURL=$(curl -fs https://www.vagrantup.com/downloads.html \
- | tr '><' '\n' | awk -F'"' '/x86_64.dmg/ {print $6}' | head -1)
+ downloadURL=$(curl -fs https://www.vagrantup.com/downloads | tr '><' '\n' | awk -F'"' '/x86_64.dmg/ {print $6}' | head -1)
+ #appNewVersion=$( curl -fs https://www.vagrantup.com/downloads.html | grep -i "Current Version" )
+ appNewVersion=$(versionFromGit hashicorp vagrant)
expectedTeamID="D38WU7D763"
;;
-jamfconnect)
- #credit: @marcelclaus on MacAdmins Slack
- name="JamfConnect"
- type="pkgInDmg"
- downloadURL="https://files.jamfconnect.com/JamfConnect.dmg"
- expectedTeamID="483DWKW443"
+aircall)
+ # credit: @kris-anderson
+ name="Aircall"
+ type="dmg"
+ downloadURL="https://electron.aircall.io/download/osx"
+ expectedTeamID="3ML357Q795"
+ ;;
+installomator_st)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="Installomator"
+ type="pkg"
+ packageID="dk.theilgaard.pkg.Installomator"
+ downloadURL=$(downloadURLFromGit theile Installomator )
+ appNewVersion=$(versionFromGit theile Installomator )
+ expectedTeamID="L8W73B6AH3"
+ blockingProcesses=( NONE )
;;
etrecheck)
- #credit: David Schultz (@dvsjr on MacAdmins Slack)
+ # credit: @dvsjr macadmins slack
name="EtreCheckPro"
type="zip"
downloadURL="https://cdn.etrecheck.com/EtreCheckPro.zip"
expectedTeamID="U87NE528LC"
;;
-
+hazel)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="Hazel"
+ type="dmg"
+ downloadURL=$(curl -fsI https://www.noodlesoft.com/Products/Hazel/download | grep -i "^location" | awk '{print $2}' | tr -d '\r\n')
+ appNewVersion=$(curl -fsI https://www.noodlesoft.com/Products/Hazel/download | grep -i "^location" | awk '{print $2}' | sed -E 's/.*\/[a-zA-Z]*-([0-9.]*)\..*/\1/g')
+ expectedTeamID="86Z3GCJ4MF"
+ ;;
+cormorant)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="Cormorant"
+ type="zip"
+ downloadURL=$(curl -fs https://eclecticlight.co/downloads/ | grep -i $name | grep zip | sed -E 's/.*href=\"(https.*)\">.*/\1/g')
+ appNewVersion=$(curl -fs https://eclecticlight.co/downloads/ | grep zip | grep -o -E "$name [0-9.]*" | awk '{print $2}')
+ expectedTeamID="QWY4LRW926"
+ ;;
+silnite)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="silnite"
+ type="pkgInZip"
+ downloadURL=$(curl -fs https://eclecticlight.co/downloads/ | grep -i $name | grep zip | sed -E 's/.*href=\"(https.*)\">.*/\1/g')
+ appNewVersion=$(curl -fs https://eclecticlight.co/downloads/ | grep zip | grep -o -E "silnite [0-9.]*" | awk '{print $2}')
+ expectedTeamID="QWY4LRW926"
+ blockingProcesses=( NONE )
+ ;;
+devonthink)
+ # It's a zipped dmg file, needs function installAppInDmgInZip
+ # credit: Søren Theilgaard (@theilgaard)
+ name="DEVONthink 3"
+ type="appInDmgInZip"
+ downloadURL=$( curl -fs https://www.devontechnologies.com/apps/devonthink | grep -i "download.devon" | tr '"' '\n' | tr "'" '\n' | grep -e '^https://' )
+ appNewVersion=$( echo ${downloadURL} | tr '/' '\n' | grep "[0-9]" | grep "[.]" | head -1 )
+ expectedTeamID="679S2QUWR8"
+ ;;
+vanilla)
+ # credit: Adrian Bühler (@midni9ht)
+ name="Vanilla"
+ type="dmg"
+ downloadURL="https://macrelease.matthewpalmer.net/Vanilla.dmg"
+ expectedTeamID="Z4JV2M65MH"
+ ;;
+taskpaper)
+ # credit: Drew Diver (@grumpydrew on MacAdmins Slack)
+ name="TaskPaper"
+ type="dmg"
+ downloadURL="https://www.taskpaper.com/assets/app/TaskPaper.dmg"
+ expectedTeamID="64A5CLJP5W"
+ ;;
+calibre)
+ # credit: Drew Diver (@grumpydrew on MacAdmins Slack)
+ name="calibre"
+ type="dmg"
+ downloadURL="https://calibre-ebook.com/dist/osx"
+ appNewVersion=$( curl -fsIL "${downloadURL}" | grep -i "^location" | awk '{print $2}' | sed -E 's/.*\/[a-zA-Z]*-([0-9.]*)\..*/\1/g' )
+ expectedTeamID="NTY7FVCEKP"
+ ;;
+redeye)
+ # credit: Drew Diver (@grumpydrew on MacAdmins Slack)
+ name="Red Eye"
+ type="zip"
+ downloadURL="https://www.hexedbits.com/downloads/redeye.zip"
+ appNewVersion=$( curl -fs "https://www.hexedbits.com/redeye/" | grep "Latest version" | sed -E 's/.*Latest version ([0-9.]*),.*/\1/g' )
+ expectedTeamID="5VRJU68BZ5"
+ ;;
+lucifer)
+ # credit: Drew Diver (@grumpydrew on MacAdmins Slack)
+ name="Lucifer"
+ type="zip"
+ downloadURL="https://www.hexedbits.com/downloads/lucifer.zip"
+ appNewVersion=$( curl -fs "https://www.hexedbits.com/lucifer/" | grep "Latest version" | sed -E 's/.*Latest version ([0-9.]*),.*/\1/g' )
+ expectedTeamID="5VRJU68BZ5"
+ ;;
+fantastical)
+ # credit: Drew Diver (@grumpydrew on MacAdmins Slack)
+ name="Fantastical"
+ type="zip"
+ downloadURL="https://flexibits.com/fantastical/download"
+ appNewVersion=$( curl -fsIL "${downloadURL}" | grep -i "^location" | awk '{print $2}' | sed -E 's/.*\/[a-zA-Z]*_([0-9.]*)\..*/\1/g' )
+ expectedTeamID="85C27NK92C"
+ ;;
+launchbar)
+ name="LaunchBar"
+ type="dmg"
+ downloadURL=$(curl -fs "https://obdev.at/products/launchbar/download.html" | xmllint --html --format - 2>/dev/null | grep -m 1 -o "https://.*.dmg")
+ appNewVersion=$( echo ${downloadURL} | sed -E 's/.*\/[a-zA-Z]*-([0-9.]*)\..*/\1/g' )
+ expectedTeamID="MLZF7K7B5R"
+ ;;
+klokki)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="Klokki"
+ type="dmg"
+ downloadURL="https://storage.yandexcloud.net/klokki/Klokki.dmg"
+ expectedTeamID="Q9SATZMHPG"
+ ;;
+notion)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="Notion"
+ type="dmg"
+ if [[ $(arch) == "arm64" ]]; then
+ downloadURL="https://www.notion.so/desktop/apple-silicon/download"
+ elif [[ $(arch) == "i386" ]]; then
+ downloadURL="https://www.notion.so/desktop/mac/download"
+ fi
+ appNewVersion=$( curl -fsIL "${downloadURL}" | grep -i "^location" | awk '{print $2}' | tr -d '\r\n' | sed -E 's/.*\/[a-zA-Z]*-([0-9.]*)\..*/\1/g' )
+ expectedTeamID="LBQJ96FQ8D"
+ ;;
+lexarrecoverytool)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="Lexar Recovery Tool"
+ type="appInDmgInZip"
+ downloadURL="https://www.lexar.com$( curl -fs https://www.lexar.com/support/downloads/ | grep -i "mac" | grep -i "recovery" | head -1 | tr '"' '\n' | grep -i ".zip" )"
+ #appNewVersion=""
+ expectedTeamID="Y8HM6WR2DV"
+ ;;
+easeusdatarecoverywizard)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="EaseUS Data Recovery Wizard"
+ type="dmg"
+ downloadURL=$( curl -fsIL https://down.easeus.com/product/mac_drw_free_setup | grep -i "^location" | awk '{print $2}' | tr -d '\r\n' )
+ #appNewVersion=""
+ expectedTeamID="DLLVW95FSM"
+ ;;
+lastpass)
+ name="LastPass"
+ type="dmg"
+ downloadURL="https://download.cloud.lastpass.com/mac/LastPass.dmg"
+ expectedTeamID="N24REP3BMN"
+ Company="Marvasol, Inc DBA LastPass"
+ ;;
+front)
+ name="Front"
+ type="dmg"
+ downloadURL="https://dl.frontapp.com/macos/Front.dmg"
+ expectedTeamID="X549L7572J"
+ Company="FrontApp. Inc."
+ ;;
+telegram)
+ name="Telegram"
+ type="dmg"
+ downloadURL="https://telegram.org/dl/macos"
+ appNewVersion=$( curl -fs https://macos.telegram.org | grep anchor | head -1 | sed -E 's/.*a>([0-9.]*) .*/\1/g' )
+ expectedTeamID="6N38VWS5BX"
+ ;;
+obsidian)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="Obsidian"
+ type="dmg"
+ if [[ $(arch) == "arm64" ]]; then
+ downloadURL=$( downloadURLFromGit obsidianmd obsidian-releases | grep "arm64" )
+ elif [[ $(arch) == "i386" ]]; then
+ downloadURL=$( downloadURLFromGit obsidianmd obsidian-releases | grep -v "arm64" )
+ fi
+ appNewVersion=$(versionFromGit obsidianmd obsidian-releases)
+ expectedTeamID="6JSW4SJWN9"
+ ;;
+wickrme)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="WickrMe"
+ type="dmg"
+ downloadURL=$( curl -fs https://me-download.wickr.com/api/download/me/download/mac | tr '"' '\n' | grep -e '^https://' )
+ appNewVersion=$( echo ${downloadURL} | sed -E 's/.*\/[a-zA-Z]*-([0-9.]*)\..*/\1/g' )
+ expectedTeamID="W8RC3R952A"
+ ;;
+wickrpro)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="WickrPro"
+ type="dmg"
+ downloadURL=$( curl -fs https://me-download.wickr.com/api/download/pro/download/mac | tr '"' '\n' | grep -e '^https://' )
+ appNewVersion=$( echo ${downloadURL} | sed -E 's/.*\/[a-zA-Z]*-([0-9.]*)\..*/\1/g' )
+ expectedTeamID="W8RC3R952A"
+ ;;
+exelbanstats)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="Stats"
+ type="dmg"
+ downloadURL=$(downloadURLFromGit exelban stats)
+ appNewVersion=$(versionFromGit exelban stats)
+ expectedTeamID="RP2S87B72W"
+ ;;
+onionshare)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="OnionShare"
+ type="pkg"
+ downloadURL="https://onionshare.org$(curl -fs https://onionshare.org | grep "button.*pkg" | tr '"' '\n' | grep ".pkg")"
+ appNewVersion=$( echo "${downloadURL}" | sed -E 's/.*\/[a-zA-Z]*-([0-9.]*)\..*/\1/g' )
+ expectedTeamID="N9B95FDWH4"
+ ;;
+keyboardmaestro)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="Keyboard Maestro"
+ type="zip"
+ downloadURL="https://download.keyboardmaestro.com/"
+ #appNewVersion=$( curl -fs https://www.stairways.com/press/ | grep -i "releases Keyboard Maestro" | head -1 | sed -E 's/.*releases Keyboard Maestro ([0-9.]*)<.*/\1/g' ) # Text based from web site
+ appNewVersion=$( curl -fs "https://www.stairways.com/press/rss.xml" | xpath '//rss/channel/item/title[contains(text(), "releases Keyboard Maestro")]' 2>/dev/null | head -1 | sed -E 's/.*releases Keyboard Maestro ([0-9.]*)<.*/\1/g' ) # uses XML, so might be a little more precise/future proof
+ expectedTeamID="QMHRBA4LGH"
+ blockingProcesses=( "Keyboard Maestro Engine" "Keyboard Maestro" )
+ ;;
+loom)
+ # credit: Lance Stephens (@pythoninthegrass on MacAdmins Slack)
+ name="Loom"
+ type="dmg"
+ downloadURL=https://cdn.loom.com/desktop-packages/$(curl -fs https://s3-us-west-2.amazonaws.com/loom.desktop.packages/loom-inc-production/desktop-packages/latest-mac.yml | awk '/url/ && /dmg/ {print $3}' | head -1)
+ appNewVersion=$(curl -fs https://s3-us-west-2.amazonaws.com/loom.desktop.packages/loom-inc-production/desktop-packages/latest-mac.yml | awk '/version/ {print $2}' )
+ expectedTeamID="QGD2ZPXZZG"
+ ;;
+golang)
+ # credit: Søren Theilgaard (@theilgaard)
+ name="GoLang"
+ type="pkg"
+ packageID="org.golang.go"
+ downloadURL="$(curl -fsIL "https://golang.org$(curl -fs "https://golang.org/dl/" | grep -i "downloadBox" | grep "pkg" | tr '"' '\n' | grep "pkg")" | grep -i "^location" | awk '{print $2}' | tr -d '\r\n')"
+ appNewVersion="$( echo "${downloadURL}" | sed -E 's/.*\/(go[0-9.]*)\..*/\1/g' )" # Version includes letters "go"
+ expectedTeamID="EQHXZ8M8AV"
+ blockingProcesses=( NONE )
+ ;;
+rectangle)
+ name="Rectangle"
+ type="dmg"
+ downloadURL=$(downloadURLFromGit rxhanson Rectangle)
+ appNewVersion=$(versionFromGit rxhanson Rectangle)
+ expectedTeamID="XSYZ3E4B7D"
+ ;;
+knockknock)
+ name="KnockKnock"
+ type="zip"
+ downloadURL=$( curl -fs "https://objective-see.com/products/knockknock.html" | grep https | grep "$type" | head -1 | tr '"' "\n" | grep "^http" )
+ appNewVersion=$( echo "${downloadURL}" | sed -E 's/.*\/[a-zA-Z]*_([0-9.]*)\..*/\1/g' )
+ expectedTeamID="VBG97UB4TA"
+ ;;
+lulu)
+ name="LuLu"
+ type="dmg"
+ downloadURL=$( curl -fs "https://objective-see.com/products/lulu.html" | grep https | grep "$type" | head -1 | tr '"' "\n" | grep "^http" )
+ appNewVersion=$( echo "${downloadURL}" | sed -E 's/.*\/[a-zA-Z]*_([0-9.]*)\..*/\1/g' )
+ expectedTeamID="VBG97UB4TA"
+ ;;
+element)
+ # credit: Adrian Bühler (@midni9ht)
+ name="Element"
+ type="dmg"
+ downloadURL="https://packages.riot.im/desktop/install/macos/Element.dmg"
+ expectedTeamID="7J4U792NQT"
+ ;;
+teamviewerhost)
+ name="TeamViewerHost"
+ type="pkgInDmg"
+ packageID="com.teamviewer.teamviewerhost"
+ downloadURL="https://download.teamviewer.com/download/TeamViewerHost.dmg"
+ expectedTeamID="H7UGFBUGV6"
+ #blockingProcessesMaxCPU="5" # Future feature
+ #Company="TeamViewer GmbH"
+ ;;
+amazonchime)
+ # credit: @dvsjr macadmins slack
+ name="Amazon Chime"
+ type="dmg"
+ downloadURL="https://clients.chime.aws/mac/latest"
+ appNewVersion=$( curl -fsIL "${downloadURL}" | grep -i "^location" | awk '{print $2}' | sed -E 's/.*\/[a-zA-Z.\-]*-([0-9.]*)\..*/\1/g' )
+ expectedTeamID="94KV3E626L"
+ #Company="Amazon"
+ ;;
+basecamp3)
+ #credit: @matins
+ name="Basecamp 3"
+ type="dmg"
+ downloadURL="https://bc3-desktop.s3.amazonaws.com/mac/basecamp3.dmg"
+ expectedTeamID="2WNYUYRS7G"
+ appName="Basecamp 3.app"
+ ;;
+proctortrack)
+ #credit: Jeff F. (@jefff on MacAdmins Slack)
+ name="Proctortrack"
+ type="zip"
+ downloadURL="https://storage.googleapis.com/verificientstatic/ProctortrackApp/Production/Proctortrack.zip"
+ expectedTeamID="SNHZD6TJE6"
+ #Company="Verificient Technologies"
+ ;;
+viscosity)
+ #credit: @matins
+ name="Viscosity"
+ type="dmg"
+ downloadURL="https://www.sparklabs.com/downloads/Viscosity.dmg"
+ appNewVersion=$( curl -fsIL "${downloadURL}" | grep -i "^location" | awk '{print $2}' | sed -E 's/.*\/[a-zA-Z.\-]*%20([0-9.]*)\..*/\1/g' )
+ expectedTeamID="34XR7GXFPX"
+ ;;
# MARK: add new labels above here
@@ -1788,10 +2193,11 @@ microsoftofficebusinesspro)
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install )
;;
-microsoftedgeconsumerstable)
+microsoftedgeconsumerstable|microsoftedge)
name="Microsoft Edge"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=2069148"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.edge"]/cfbundleversion' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps EDGE01 )
@@ -1800,6 +2206,7 @@ microsoftcompanyportal)
name="Company Portal"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=869655"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.intunecompanyportal.standalone"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps IMCP01 )
@@ -1808,6 +2215,7 @@ microsoftskypeforbusiness)
name="Skype for Business"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=832978"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.skypeforbusiness.standalone"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps MSFB16 )
@@ -1816,6 +2224,7 @@ microsoftremotedesktop)
name="Microsoft Remote Desktop"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=868963"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.remotedesktop.standalone"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps MSRD10 )
@@ -1824,15 +2233,26 @@ microsoftteams)
name="Microsoft Teams"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=869428"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.teams.standalone"]/version' 2>/dev/null | sed -E 's/([0-9.]*) .*/\1/')
expectedTeamID="UBF8T346G9"
blockingProcesses=( Teams "Microsoft Teams Helper" )
- updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
- updateToolArguments=( --install --apps TEAM01 )
+ #updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
+ #updateToolArguments=( --install --apps TEAM01 )
+ ;;
+microsoftyammer)
+ name="Yammer"
+ type="dmg"
+ downloadURL="https://aka.ms/yammer_desktop_mac"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/oldpackage[id="com.microsoft.yammer.standalone"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
+ expectedTeamID="UBF8T346G9"
+ #updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
+ #updateToolArguments=( --install --apps ?????? )
;;
microsoftautoupdate)
name="Microsoft AutoUpdate"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=830196"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.autoupdate.standalone"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
# commented the updatetool for MSAutoupdate, because when Autoupdate is really
# old or broken, you want to force a new install
@@ -1843,6 +2263,7 @@ microsoftedgeenterprisestable)
name="Microsoft Edge"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=2093438"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.edge"]/version' 2>/dev/null | sed -E 's/([0-9.]*) .*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps EDGE01 )
@@ -1851,6 +2272,7 @@ microsoftword)
name="Microsoft Word"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=525134"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.word.standalone.365"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps MSWD2019 )
@@ -1859,6 +2281,7 @@ microsoftexcel)
name="Microsoft Excel"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=525135"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.excel.standalone.365"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps XCEL2019 )
@@ -1867,6 +2290,7 @@ microsoftpowerpoint)
name="Microsoft PowerPoint"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=525136"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.powerpoint.standalone.365"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps PPT32019 )
@@ -1875,6 +2299,7 @@ microsoftoutlook)
name="Microsoft Outlook"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=525137"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.outlook.standalone.365"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps OPIM2019 )
@@ -1883,6 +2308,7 @@ microsoftonenote)
name="Microsoft OneNote"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=820886"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.onenote.standalone.365"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps ONMC2019 )
@@ -1891,6 +2317,7 @@ microsoftonedrive)
name="OneDrive"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=823060"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.onedrive.standalone"]/cfbundleshortversionstring' 2>/dev/null | sed -E 's/([0-9.]*)<.*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps ONDR18 )
@@ -1899,6 +2326,7 @@ microsoftsharepointplugin)
name="MicrosoftSharePointPlugin"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=800050"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.sharepointplugin.standalone"]/version' 2>/dev/null | sed -E 's/([0-9.]*) .*/\1/')
expectedTeamID="UBF8T346G9"
# TODO: determine blockingProcesses for SharePointPlugin
;;
@@ -1906,6 +2334,7 @@ visualstudiocode)
name="Visual Studio Code"
type="zip"
downloadURL="https://go.microsoft.com/fwlink/?LinkID=620882"
+ appNewVersion=$(curl -fsL "https://code.visualstudio.com/Updates" | grep "/darwin" | grep -oiE ".com/([^>]+)([^<]+)/darwin" | cut -d "/" -f 2 | sed $'s/[^[:print:]\t]//g')
expectedTeamID="UBF8T346G9"
appName="Visual Studio Code.app"
blockingProcesses=( Electron )
@@ -1914,20 +2343,22 @@ microsoftdefenderatp)
name="Microsoft Defender ATP"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=2097502"
+ appNewVersion=$(curl -fs https://macadmins.software/latest.xml | xpath '//latest/package[id="com.microsoft.defender.standalone"]/version' 2>/dev/null | sed -E 's/([0-9.]*) .*/\1/')
expectedTeamID="UBF8T346G9"
updateTool="/Library/Application Support/Microsoft/MAU2.0/Microsoft AutoUpdate.app/Contents/MacOS/msupdate"
updateToolArguments=( --install --apps WDAV00 )
;;
microsoftlicenseremovaltool)
- # credit: Isaac Ordonez, Mann consulting (@mannconsulting)
+ # credit: Isaac Ordonez (@isaac) macadmins slack
name="Microsoft License Removal Tool"
type="pkg"
downloadURL="https://go.microsoft.com/fwlink/?linkid=849815"
expectedTeamID="QGS93ZLCU7"
- # appNewVersion=$(curl -is "$downloadURL" | grep ocation: | grep -o "Microsoft_.*pkg" | cut -d "_" -f 5 | cut -d "." -f1-2)
+ appNewVersion=$(curl -is "$downloadURL" | grep ocation: | grep -o "Microsoft_.*pkg" | cut -d "_" -f 5 | cut -d "." -f1-2)
+ Company="Microsoft"
+ PatchSkip="YES"
;;
-
# this description is so you can provide all variables as arguments
# it will only check if the required variables are setting
valuesfromarguments)
@@ -1971,14 +2402,16 @@ brokenteamid)
;;
*)
# unknown label
- printlog "unknown label $label"
- exit 1
+ #printlog "unknown label $label"
+ cleanupAndExit 1 "unknown label $label"
;;
esac
# MARK: application download and installation starts here
+printlog "BLOCKING_PROCESS_ACTION=${BLOCKING_PROCESS_ACTION}"
+printlog "NOTIFY=${NOTIFY}"
# MARK: extract info from data
if [ -z "$archiveName" ]; then
@@ -1989,7 +2422,7 @@ if [ -z "$archiveName" ]; then
pkgInDmg)
archiveName="${name}.dmg"
;;
- pkgInZip)
+ *InZip)
archiveName="${name}.zip"
;;
*)
@@ -2006,7 +2439,7 @@ fi
if [ -z "$targetDir" ]; then
case $type in
- dmg|zip|tbz)
+ dmg|zip|tbz|app*)
targetDir="/Applications"
;;
pkg*)
@@ -2053,8 +2486,53 @@ if [[ -n $appVersion ]]; then
fi
fi
-# MARK: when user is logged in, and app is running, prompt user to quit app
+# MARK: Exit if new version is the same as installed version (appNewVersion specified)
+# credit: Søren Theilgaard (@theilgaard)
+if [[ -n $appNewVersion ]]; then
+ printlog "Latest version of $name is $appNewVersion"
+ if [[ $appversion == $appNewVersion ]]; then
+ if [[ $DEBUG -eq 0 ]]; then
+ printlog "There is no newer version available."
+ if [[ $INSTALL != "force" ]]; then
+ message="$name, version $appNewVersion, is the latest version."
+ if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then
+ printlog "notifying"
+ displaynotification "$message" "No update for $name!"
+ fi
+ cleanupAndExit 0 "No newer version."
+ else
+ printlog "Using force to install anyway."
+ fi
+ else
+ printlog "DEBUG mode enabled, not exiting, but there is no new version of app."
+ fi
+ fi
+else
+ printlog "Latest version not specified."
+fi
+# MARK: download the archive
+if [ -f "$archiveName" ] && [ "$DEBUG" -ne 0 ]; then
+ printlog "$archiveName exists and DEBUG enabled, skipping download"
+else
+ # download the dmg
+ printlog "Downloading $downloadURL to $archiveName"
+ if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then
+ printlog "notifying"
+ displaynotification "Downloading $name update" "Download in progress …"
+ fi
+ if ! curl --location --fail --silent "$downloadURL" -o "$archiveName"; then
+ printlog "error downloading $downloadURL"
+ message="$name update/installation failed. This will be logged, so IT can follow up."
+ if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then
+ printlog "notifying"
+ displaynotification "$message" "Error installing/updating $name"
+ fi
+ cleanupAndExit 2
+ fi
+fi
+
+# MARK: when user is logged in, and app is running, prompt user to quit app
if [[ $BLOCKING_PROCESS_ACTION == "ignore" ]]; then
printlog "ignoring blocking processes"
else
@@ -2067,20 +2545,12 @@ else
fi
fi
-# MARK: download the archive
-
-if [ -f "$archiveName" ] && [ "$DEBUG" -ne 0 ]; then
- printlog "$archiveName exists and DEBUG enabled, skipping download"
-else
- # download the dmg
- printlog "Downloading $downloadURL to $archiveName"
- if ! curl --location --fail --silent "$downloadURL" -o "$archiveName"; then
- printlog "error downloading $downloadURL"
- cleanupAndExit 2
- fi
-fi
-
# MARK: install the download
+printlog "Installing $name"
+if [[ $currentUser != "loginwindow" && $NOTIFY == "all" ]]; then
+ printlog "notifying"
+ displaynotification "Installing $name" "Installation in progress …"
+fi
case $type in
dmg)
@@ -2101,6 +2571,9 @@ case $type in
pkgInZip)
installPkgInZip
;;
+ appInDmgInZip)
+ installAppInDmgInZip
+ ;;
*)
printlog "Cannot handle type $type"
cleanupAndExit 99
@@ -2119,7 +2592,7 @@ fi
printlog "$message"
-if [[ $currentUser != "loginwindow" && $NOTIFY == "success" ]]; then
+if [[ $currentUser != "loginwindow" && ( $NOTIFY == "success" || $NOTIFY == "all" ) ]]; then
printlog "notifying"
displaynotification "$message" "$name update/installation complete!"
fi