Skip to content

DMG install script use yes and update scripts - #45895

Merged
allenhouchins merged 5 commits into
mainfrom
allenhouchins-update-dmg-install-script
Jun 1, 2026
Merged

DMG install script use yes and update scripts#45895
allenhouchins merged 5 commits into
mainfrom
allenhouchins-update-dmg-install-script

Conversation

@allenhouchins

@allenhouchins allenhouchins commented May 20, 2026

Copy link
Copy Markdown
Member

Pipe yes into hdiutil attach to auto-accept DMG license prompts, make attach failures exit, and ignore detach failures. Add a unit test to verify the DMG extract commands. Remove per-app install script files and corresponding install_script_path entries from inputs, and update outputs to reference consolidated install scripts that track/relaunch running apps after installation (updated install_script_ref hashes).

Summary by CodeRabbit

  • New Features

    • Improved DMG installation handling with automatic license prompt acceptance
    • Enhanced app state management during installation to preserve running state and relaunch post-install
  • Bug Fixes

    • Added error handling for failed DMG mount operations
  • Tests

    • Added test coverage for DMG extraction improvements

Review Change Stack

Pipe `yes` into `hdiutil attach` to auto-accept DMG license prompts, make attach failures exit, and ignore detach failures. Add a unit test to verify the DMG extract commands. Remove per-app install script files and corresponding install_script_path entries from inputs, and update outputs to reference consolidated install scripts that track/relaunch running apps after installation (updated install_script_ref hashes).
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/dbeaver-enterprise/darwin.json

=== Install // a96abe07 -> 5a0440c4 ===

--- /tmp/old.xtlX0l	2026-05-20 16:07:33.520609811 +0000
+++ /tmp/new.Muhm1V	2026-05-20 16:07:33.520609811 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.enterprise'
+quit_and_track_application 'com.dbeaver.product.enterprise'
 if [ -d "$APPDIR/DBeaverEE.app" ]; then
 	sudo mv "$APPDIR/DBeaverEE.app" "$TMPDIR/DBeaverEE.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverEE.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.enterprise'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dbeaverlite/darwin.json

=== Install // c1cba05a -> c72c1bb0 ===

--- /tmp/old.hfxaiw	2026-05-20 16:07:33.574609382 +0000
+++ /tmp/new.4Man1q	2026-05-20 16:07:33.575609374 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.lite'
+quit_and_track_application 'com.dbeaver.product.lite'
 if [ -d "$APPDIR/DBeaverLite.app" ]; then
 	sudo mv "$APPDIR/DBeaverLite.app" "$TMPDIR/DBeaverLite.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverLite.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.lite'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dbeaverultimate/darwin.json

=== Install // 0a44a77f -> 52243cd3 ===

--- /tmp/old.Y9womQ	2026-05-20 16:07:33.619609024 +0000
+++ /tmp/new.IW5cJL	2026-05-20 16:07:33.619609024 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.ultimate'
+quit_and_track_application 'com.dbeaver.product.ultimate'
 if [ -d "$APPDIR/DBeaverUltimate.app" ]; then
 	sudo mv "$APPDIR/DBeaverUltimate.app" "$TMPDIR/DBeaverUltimate.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverUltimate.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.ultimate'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/evernote/darwin.json

=== Install // a83831d7 -> 67a65f7d ===

--- /tmp/old.CYry5Z	2026-05-20 16:07:33.669608627 +0000
+++ /tmp/new.KzXsQ2	2026-05-20 16:07:33.669608627 +0000
@@ -2,26 +2,34 @@
 
 # variables
 APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
-
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-yes | hdiutil attach -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.evernote.Evernote'
+quit_and_track_application 'com.evernote.Evernote'
 if [ -d "$APPDIR/Evernote.app" ]; then
 	sudo mv "$APPDIR/Evernote.app" "$TMPDIR/Evernote.app.bkp"
 fi
 sudo cp -R "$TMPDIR/Evernote.app" "$APPDIR"
+relaunch_application 'com.evernote.Evernote'

=== Uninstall // 31b95715 -> b7960ac0 ===

--- /tmp/old.CTtFUi	2026-05-20 16:07:33.685608500 +0000
+++ /tmp/new.v8ZBHO	2026-05-20 16:07:33.685608500 +0000
@@ -10,13 +10,15 @@
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
     return
   fi

ee/maintained-apps/outputs/omnigraffle/darwin.json

=== Install // d2d63787 -> c20e090b ===

--- /tmp/old.1cp2To	2026-05-20 16:07:33.728608158 +0000
+++ /tmp/new.Alf5Ik	2026-05-20 16:07:33.728608158 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-yes | hdiutil attach -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.omnigroup.OmniGraffle7'
+quit_and_track_application 'com.omnigroup.OmniGraffle7'
 if [ -d "$APPDIR/OmniGraffle.app" ]; then
 	sudo mv "$APPDIR/OmniGraffle.app" "$TMPDIR/OmniGraffle.app.bkp"
 fi
 sudo cp -R "$TMPDIR/OmniGraffle.app" "$APPDIR"
+relaunch_application 'com.omnigroup.OmniGraffle7'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/royal-tsx/darwin.json

=== Install // 8a40c4cb -> db51aef0 ===

--- /tmp/old.wKrlpn	2026-05-20 16:07:33.775607784 +0000
+++ /tmp/new.uUGPtX	2026-05-20 16:07:33.775607784 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.lemonmojo.RoyalTSX.App'
+quit_and_track_application 'com.lemonmojo.RoyalTSX.App'
 if [ -d "$APPDIR/Royal TSX.app" ]; then
 	sudo mv "$APPDIR/Royal TSX.app" "$TMPDIR/Royal TSX.app.bkp"
 fi
 sudo cp -R "$TMPDIR/Royal TSX.app" "$APPDIR"
+relaunch_application 'com.lemonmojo.RoyalTSX.App'

=== Uninstall Script (no changes) ===

@allenhouchins
allenhouchins marked this pull request as ready for review May 20, 2026 16:17
@allenhouchins
allenhouchins requested a review from a team as a code owner May 20, 2026 16:17
Copilot AI review requested due to automatic review settings May 20, 2026 16:17
fleet-release
fleet-release previously approved these changes May 20, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai

coderabbitai Bot commented May 20, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

Failed to post review comments

Walkthrough

This PR migrates Homebrew app installers from static per-app shell scripts to dynamically generated scripts. The script builder in Go now auto-accepts DMG license prompts by piping yes into hdiutil attach, improving reliability for licensed software. Static install_script_path references were removed from input configuration files across DBeaver Enterprise, DBeaverLite, DBeaver Ultimate, Evernote, OmniGraffle, and Royal TSX. The output manifests for each app were updated with new install script implementations that track whether applications are running before installation, conditionally quit them when appropriate, perform DMG extraction and installation, and relaunch the apps afterward using GUI-aware logic with launchctl asuser for root-executed contexts.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description clearly outlines all major changes but does not follow the required template structure with checklists and sections. Use the provided PR description template with appropriate checklist items, including testing, security validation, and changelog/changes file documentation.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: piping yes into hdiutil for DMG licensing and updating install scripts with new references.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch allenhouchins-update-dmg-install-script

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@ee/maintained-apps/outputs/dbeaver-enterprise/darwin.json`:
- Line 19: The quit detection in quit_and_track_application is using pgrep -f
"$bundle_id" which won't reliably find processes by bundle identifier; replace
that check with polling the same AppleScript used earlier (osascript -e
"application id \"$bundle_id\" is running") inside the quit loop to confirm the
app has actually stopped before proceeding, update any template that generates
this manifest so other DMG manifests are regenerated with the same fix, and
ensure the variable bundle_id and quit_success logic remain consistent when
switching to the osascript-based check.

In `@ee/maintained-apps/outputs/evernote/darwin.json`:
- Line 20: The quit_application function currently uses pgrep -f "$bundle_id"
(which can miss apps) to detect quit success; replace that check with the same
osascript-based verification used earlier (e.g., call osascript -e "application
id \"$bundle_id\" is running" inside the loop) so you accurately detect whether
the app is still running, set quit_success only when osascript returns false,
and have quit_application return a non-zero status when the timeout expires;
then in the main sequence, check the return value of quit_application for
'com.evernote.Evernote' and 'com.evernote.EvernoteHelper' and abort the
subsequent sudo rm -rf and trash calls if either quit_application failed.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2984c9e8-5d87-4e82-83a8-531a38b63b88

📥 Commits

Reviewing files that changed from the base of the PR and between 493e668 and c5b2137.

📒 Files selected for processing (20)
  • ee/maintained-apps/ingesters/homebrew/scripts.go
  • ee/maintained-apps/ingesters/homebrew/scripts_test.go
  • ee/maintained-apps/inputs/homebrew/dbeaver-enterprise.json
  • ee/maintained-apps/inputs/homebrew/dbeaverlite.json
  • ee/maintained-apps/inputs/homebrew/dbeaverultimate.json
  • ee/maintained-apps/inputs/homebrew/evernote.json
  • ee/maintained-apps/inputs/homebrew/omnigraffle.json
  • ee/maintained-apps/inputs/homebrew/royal-tsx.json
  • ee/maintained-apps/inputs/homebrew/scripts/dbeaver-enterprise-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/dbeaverlite-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/dbeaverultimate-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/evernote-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/omnigraffle-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/royal-tsx-install.sh
  • ee/maintained-apps/outputs/dbeaver-enterprise/darwin.json
  • ee/maintained-apps/outputs/dbeaverlite/darwin.json
  • ee/maintained-apps/outputs/dbeaverultimate/darwin.json
  • ee/maintained-apps/outputs/evernote/darwin.json
  • ee/maintained-apps/outputs/omnigraffle/darwin.json
  • ee/maintained-apps/outputs/royal-tsx/darwin.json
💤 Files with no reviewable changes (10)
  • ee/maintained-apps/inputs/homebrew/scripts/dbeaver-enterprise-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/evernote-install.sh
  • ee/maintained-apps/inputs/homebrew/scripts/dbeaverlite-install.sh
  • ee/maintained-apps/inputs/homebrew/dbeaverultimate.json
  • ee/maintained-apps/inputs/homebrew/scripts/omnigraffle-install.sh
  • ee/maintained-apps/inputs/homebrew/evernote.json
  • ee/maintained-apps/inputs/homebrew/dbeaver-enterprise.json
  • ee/maintained-apps/inputs/homebrew/scripts/royal-tsx-install.sh
  • ee/maintained-apps/inputs/homebrew/dbeaverlite.json
  • ee/maintained-apps/inputs/homebrew/scripts/dbeaverultimate-install.sh

"refs": {
"a320a418": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nsend_signal() {\n local signal=\"$1\"\n local bundle_id=\"$2\"\n local logged_in_user=\"$3\"\n local logged_in_uid pids\n\n if [ -z \"$signal\" ] || [ -z \"$bundle_id\" ] || [ -z \"$logged_in_user\" ]; then\n echo \"Usage: uninstall_signal <signal> <bundle_id> <logged_in_user>\"\n return 1\n fi\n\n logged_in_uid=$(id -u \"$logged_in_user\")\n if [ -z \"$logged_in_uid\" ]; then\n echo \"Could not find UID for user '$logged_in_user'.\"\n return 1\n fi\n\n echo \"Signalling '$signal' to application ID '$bundle_id' for user '$logged_in_user'\"\n\n pids=$(/bin/launchctl asuser \"$logged_in_uid\" sudo -iu \"$logged_in_user\" /bin/launchctl list | awk -v bundle_id=\"$bundle_id\" '\n $3 ~ bundle_id { print $1 }')\n\n if [ -z \"$pids\" ]; then\n echo \"No processes found for bundle ID '$bundle_id'.\"\n return 0\n fi\n\n echo \"Unix PIDs are $pids for processes with bundle identifier $bundle_id\"\n for pid in $pids; do\n if kill -s \"$signal\" \"$pid\" 2>/dev/null; then\n echo \"Successfully signaled PID $pid with signal $signal.\"\n else\n echo \"Failed to kill PID $pid with signal $signal. Check permissions.\"\n fi\n done\n\n sleep 3\n}\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsend_signal 'TERM' 'com.dbeaver.product.enterprise' \"$LOGGED_IN_USER\"\nsudo rm -rf \"$APPDIR/DBeaverEE.app\"\ntrash $LOGGED_IN_USER '~/Library/DBeaverData'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.dbeaver.product.enterprise.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.dbeaver.product.enterprise.savedState'\n",
"a96abe07": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\n# Use 'yes' to automatically accept license agreement when mounting DMG\n# This replicates Homebrew's behavior for DMG files with license agreements\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n\n# copy to the applications folder\nquit_application 'com.dbeaver.product.enterprise'\nif [ -d \"$APPDIR/DBeaverEE.app\" ]; then\n\tsudo mv \"$APPDIR/DBeaverEE.app\" \"$TMPDIR/DBeaverEE.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/DBeaverEE.app\" \"$APPDIR\"\n"
"5a0440c4": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.dbeaver.product.enterprise'\nif [ -d \"$APPDIR/DBeaverEE.app\" ]; then\n\tsudo mv \"$APPDIR/DBeaverEE.app\" \"$TMPDIR/DBeaverEE.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/DBeaverEE.app\" \"$APPDIR\"\nrelaunch_application 'com.dbeaver.product.enterprise'\n",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the real app state to detect quit completion.

pgrep -f "$bundle_id" is checking the wrong identifier type here. For DBeaverEE.app, the process argv typically will not contain com.dbeaver.product.enterprise, so this loop can mark the app as quit immediately after tell ... quit and start copying over a still-running app. Poll application id "$bundle_id" is running again, or match the actual executable name/path, before continuing. Because this is generated output, fixing the shared template and regenerating should cover the other updated DMG manifests too.

Possible fix
-      if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+      if [[ "$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)" != "true" ]]; then
         echo "Application '$bundle_id' quit successfully."
         quit_success=true
         break
       fi
@@
-  if [[ "$quit_success" = false ]]; then
-    echo "Application '$bundle_id' did not quit."
-  fi
+  if [[ "$quit_success" = false ]]; then
+    echo "Application '$bundle_id' did not quit."
+    return 1
+  fi
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"5a0440c4": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.dbeaver.product.enterprise'\nif [ -d \"$APPDIR/DBeaverEE.app\" ]; then\n\tsudo mv \"$APPDIR/DBeaverEE.app\" \"$TMPDIR/DBeaverEE.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/DBeaverEE.app\" \"$APPDIR\"\nrelaunch_application 'com.dbeaver.product.enterprise'\n",
"5a0440c4": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if [[ \"$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\" != \"true\" ]]; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n return 1\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.dbeaver.product.enterprise'\nif [ -d \"$APPDIR/DBeaverEE.app\" ]; then\n\tsudo mv \"$APPDIR/DBeaverEE.app\" \"$TMPDIR/DBeaverEE.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/DBeaverEE.app\" \"$APPDIR\"\nrelaunch_application 'com.dbeaver.product.enterprise'\n",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/maintained-apps/outputs/dbeaver-enterprise/darwin.json` at line 19, The
quit detection in quit_and_track_application is using pgrep -f "$bundle_id"
which won't reliably find processes by bundle identifier; replace that check
with polling the same AppleScript used earlier (osascript -e "application id
\"$bundle_id\" is running") inside the quit loop to confirm the app has actually
stopped before proceeding, update any template that generates this manifest so
other DMG manifests are regenerated with the same fix, and ensure the variable
bundle_id and quit_success logic remain consistent when switching to the
osascript-based check.

"31b95715": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nquit_application 'com.evernote.Evernote'\nquit_application 'com.evernote.EvernoteHelper'\nsudo rm -rf \"$APPDIR/Evernote.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Support/Caches/evernote-client-updater'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.evernote.Evernote'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.evernote.EvernoteHelper'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Evernote'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.evernote.Evernote'\ntrash $LOGGED_IN_USER '~/Library/Cookies/com.evernote.Evernote.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Logs/Evernote'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.evernote.Evernote.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.evernote.EvernoteHelper.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.evernote.Evernote.savedState'\n",
"a83831d7": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath $INSTALLER_PATH)\")\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\n# Use 'yes' to automatically accept license agreement when mounting DMG\n# This replicates Homebrew's behavior for DMG files with license agreements\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n\n# copy to the applications folder\nquit_application 'com.evernote.Evernote'\nif [ -d \"$APPDIR/Evernote.app\" ]; then\n\tsudo mv \"$APPDIR/Evernote.app\" \"$TMPDIR/Evernote.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Evernote.app\" \"$APPDIR\"\n\n"
"67a65f7d": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.evernote.Evernote'\nif [ -d \"$APPDIR/Evernote.app\" ]; then\n\tsudo mv \"$APPDIR/Evernote.app\" \"$TMPDIR/Evernote.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Evernote.app\" \"$APPDIR\"\nrelaunch_application 'com.evernote.Evernote'\n",
"b7960ac0": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nquit_application 'com.evernote.Evernote'\nquit_application 'com.evernote.EvernoteHelper'\nsudo rm -rf \"$APPDIR/Evernote.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Support/Caches/evernote-client-updater'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.evernote.Evernote'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.evernote.EvernoteHelper'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Evernote'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.evernote.Evernote'\ntrash $LOGGED_IN_USER '~/Library/Cookies/com.evernote.Evernote.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Logs/Evernote'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.evernote.Evernote.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.evernote.EvernoteHelper.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.evernote.Evernote.savedState'\n"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don't start uninstall cleanup from a false quit-success signal.

quit_application uses pgrep -f "$bundle_id" to decide whether Evernote has exited, but the running process normally won't expose com.evernote.Evernote or com.evernote.EvernoteHelper in its argv. That means the function can report success too early and the subsequent rm -rf / trash steps can race with a still-running app. Re-check the app's actual running state and stop the uninstall if the timeout expires.

Possible fix
-      if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+      if [[ "$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)" != "true" ]]; then
         echo "Application '$bundle_id' quit successfully."
         quit_success=true
         break
       fi
@@
-  if [[ "$quit_success" = false ]]; then
-    echo "Application '$bundle_id' did not quit."
-  fi
+  if [[ "$quit_success" = false ]]; then
+    echo "Application '$bundle_id' did not quit."
+    return 1
+  fi
@@
-quit_application 'com.evernote.Evernote'
-quit_application 'com.evernote.EvernoteHelper'
+quit_application 'com.evernote.Evernote' || exit 1
+quit_application 'com.evernote.EvernoteHelper' || exit 1
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"b7960ac0": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nquit_application 'com.evernote.Evernote'\nquit_application 'com.evernote.EvernoteHelper'\nsudo rm -rf \"$APPDIR/Evernote.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Support/Caches/evernote-client-updater'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.evernote.Evernote'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.evernote.EvernoteHelper'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Evernote'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.evernote.Evernote'\ntrash $LOGGED_IN_USER '~/Library/Cookies/com.evernote.Evernote.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Logs/Evernote'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.evernote.Evernote.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.evernote.EvernoteHelper.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.evernote.Evernote.savedState'\n"
"b7960ac0": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if [[ \"$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\" != \"true\" ]]; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n return 1\n fi\n}\n\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nquit_application 'com.evernote.Evernote' || exit 1\nquit_application 'com.evernote.EvernoteHelper' || exit 1\nsudo rm -rf \"$APPDIR/Evernote.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Support/Caches/evernote-client-updater'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.evernote.Evernote'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.evernote.EvernoteHelper'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Evernote'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.evernote.Evernote'\ntrash $LOGGED_IN_USER '~/Library/Cookies/com.evernote.Evernote.binarycookies'\ntrash $LOGGED_IN_USER '~/Library/Logs/Evernote'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.evernote.Evernote.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.evernote.EvernoteHelper.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.evernote.Evernote.savedState'\n"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@ee/maintained-apps/outputs/evernote/darwin.json` at line 20, The
quit_application function currently uses pgrep -f "$bundle_id" (which can miss
apps) to detect quit success; replace that check with the same osascript-based
verification used earlier (e.g., call osascript -e "application id
\"$bundle_id\" is running" inside the loop) so you accurately detect whether the
app is still running, set quit_success only when osascript returns false, and
have quit_application return a non-zero status when the timeout expires; then in
the main sequence, check the return value of quit_application for
'com.evernote.Evernote' and 'com.evernote.EvernoteHelper' and abort the
subsequent sudo rm -rf and trash calls if either quit_application failed.

@codecov

codecov Bot commented May 20, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 66.86%. Comparing base (6291551) to head (6ad58ba).
⚠️ Report is 2 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #45895      +/-   ##
==========================================
+ Coverage   66.83%   66.86%   +0.02%     
==========================================
  Files        2755     2756       +1     
  Lines      220198   220724     +526     
  Branches    10916    10916              
==========================================
+ Hits       147170   147582     +412     
- Misses      59734    59804      +70     
- Partials    13294    13338      +44     
Flag Coverage Δ
backend 68.67% <100.00%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Updates the Homebrew DMG install script generation to auto-accept DMG license prompts and improve install robustness, while consolidating per-app install scripts and refreshing generated app outputs.

Changes:

  • Update DMG extraction to pipe yes into hdiutil attach, fail fast on attach errors, and ignore detach failures.
  • Remove per-app install_script_path inputs and delete the corresponding script files.
  • Regenerate app outputs to reference updated consolidated install scripts (including quit/track/relaunch behavior) and update Evernote metadata.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
ee/maintained-apps/outputs/royal-tsx/darwin.json Update generated install script ref to consolidated quit/track/relaunch + DMG attach behavior.
ee/maintained-apps/outputs/omnigraffle/darwin.json Update generated install script ref to consolidated quit/track/relaunch + DMG attach behavior.
ee/maintained-apps/outputs/evernote/darwin.json Update generated install/uninstall script refs; also changes Evernote version/URL/checksum metadata.
ee/maintained-apps/outputs/dbeaverultimate/darwin.json Update generated install script ref to consolidated quit/track/relaunch + DMG attach behavior.
ee/maintained-apps/outputs/dbeaverlite/darwin.json Update generated install script ref to consolidated quit/track/relaunch + DMG attach behavior.
ee/maintained-apps/outputs/dbeaver-enterprise/darwin.json Update generated install script ref to consolidated quit/track/relaunch + DMG attach behavior.
ee/maintained-apps/inputs/homebrew/scripts/royal-tsx-install.sh Remove per-app install script file (now consolidated/generated).
ee/maintained-apps/inputs/homebrew/scripts/omnigraffle-install.sh Remove per-app install script file (now consolidated/generated).
ee/maintained-apps/inputs/homebrew/scripts/evernote-install.sh Remove per-app install script file (now consolidated/generated).
ee/maintained-apps/inputs/homebrew/scripts/dbeaverultimate-install.sh Remove per-app install script file (now consolidated/generated).
ee/maintained-apps/inputs/homebrew/scripts/dbeaverlite-install.sh Remove per-app install script file (now consolidated/generated).
ee/maintained-apps/inputs/homebrew/scripts/dbeaver-enterprise-install.sh Remove per-app install script file (now consolidated/generated).
ee/maintained-apps/inputs/homebrew/royal-tsx.json Drop install_script_path input field.
ee/maintained-apps/inputs/homebrew/omnigraffle.json Drop install_script_path input field.
ee/maintained-apps/inputs/homebrew/evernote.json Drop install_script_path input field (keeps frozen).
ee/maintained-apps/inputs/homebrew/dbeaverultimate.json Drop install_script_path input field.
ee/maintained-apps/inputs/homebrew/dbeaverlite.json Drop install_script_path input field.
ee/maintained-apps/inputs/homebrew/dbeaver-enterprise.json Drop install_script_path input field.
ee/maintained-apps/ingesters/homebrew/scripts_test.go Add unit test asserting DMG extract uses `yes
ee/maintained-apps/ingesters/homebrew/scripts.go Implement yes piping + attach fail-fast + detach ignore in DMG extraction builder.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 372 to +375
s.Write(`MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH"
yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
hdiutil detach "$MOUNT_POINT"`)
hdiutil detach "$MOUNT_POINT" || true`)
Comment on lines +4 to +12
"version": "10.105.4",
"queries": {
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.evernote.Evernote';"
"exists": "SELECT 1 FROM apps WHERE bundle_identifier = 'com.evernote.Evernote';",
"patched": "SELECT 1 WHERE NOT EXISTS (SELECT 1 FROM apps WHERE bundle_identifier = 'com.evernote.Evernote' AND version_compare(bundle_short_version, '10.105.4') < 0);"
},
"installer_url": "https://mac.desktop.evernote.com/builds/Evernote-latest.dmg",
"install_script_ref": "a83831d7",
"uninstall_script_ref": "31b95715",
"sha256": "no_check",
"installer_url": "https://mac.desktop.evernote.com/builds/Evernote-10.105.4-mac-ddl-stage-20240910164757-a2e60a8d876a07eded5d212fa56ba45214114ad0.dmg",
"install_script_ref": "67a65f7d",
"uninstall_script_ref": "b7960ac0",
"sha256": "98d1f6d52718a0b05222b7cdce14a3755ece619edf0a1b8557af75afbfe2cd73",
"refs": {
"81081b86": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/OmniGraffle.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.omnigroup.OmniGraffle7'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CloudDocs/session/containers/iCloud.com.omnigroup.OmniGraffle'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CloudDocs/session/containers/iCloud.com.omnigroup.OmniGraffle.plist'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.omnigroup.omnigraffle7.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.omnigroup.OmniGraffle7'\ntrash $LOGGED_IN_USER '~/Library/Mobile Documents/iCloud~com~omnigroup~OmniGraffle'\n",
"d2d63787": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\n# Use 'yes' to automatically accept license agreement when mounting DMG\n# This replicates Homebrew's behavior for DMG files with license agreements\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n\n# copy to the applications folder\nquit_application 'com.omnigroup.OmniGraffle7'\nif [ -d \"$APPDIR/OmniGraffle.app\" ]; then\n\tsudo mv \"$APPDIR/OmniGraffle.app\" \"$TMPDIR/OmniGraffle.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/OmniGraffle.app\" \"$APPDIR\"\n\n"
"c20e090b": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.omnigroup.OmniGraffle7'\nif [ -d \"$APPDIR/OmniGraffle.app\" ]; then\n\tsudo mv \"$APPDIR/OmniGraffle.app\" \"$TMPDIR/OmniGraffle.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/OmniGraffle.app\" \"$APPDIR\"\nrelaunch_application 'com.omnigroup.OmniGraffle7'\n"
"refs": {
"81081b86": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\ntrash() {\n local logged_in_user=\"$1\"\n local target_file=\"$2\"\n local timestamp=\"$(date +%Y-%m-%d-%s)\"\n local rand=\"$(jot -r 1 0 99999)\"\n\n # replace ~ with /Users/$logged_in_user\n if [[ \"$target_file\" == ~* ]]; then\n target_file=\"/Users/$logged_in_user${target_file:1}\"\n fi\n\n local trash=\"/Users/$logged_in_user/.Trash\"\n local file_name=\"$(basename \"${target_file}\")\"\n\n if [[ -e \"$target_file\" ]]; then\n echo \"removing $target_file.\"\n mv -f \"$target_file\" \"$trash/${file_name}_${timestamp}_${rand}\"\n else\n echo \"$target_file doesn't exist.\"\n fi\n}\n\nsudo rm -rf \"$APPDIR/OmniGraffle.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.omnigroup.OmniGraffle7'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CloudDocs/session/containers/iCloud.com.omnigroup.OmniGraffle'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CloudDocs/session/containers/iCloud.com.omnigroup.OmniGraffle.plist'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.omnigroup.omnigraffle7.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.omnigroup.OmniGraffle7'\ntrash $LOGGED_IN_USER '~/Library/Mobile Documents/iCloud~com~omnigroup~OmniGraffle'\n",
"d2d63787": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n\n# functions\n\nquit_application() {\n local bundle_id=\"$1\"\n local timeout_duration=10\n\n # check if the application is running\n if ! osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ $EUID -eq 0 && \"$console_user\" == \"root\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n# extract contents\n# Use 'yes' to automatically accept license agreement when mounting DMG\n# This replicates Homebrew's behavior for DMG files with license agreements\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n\n# copy to the applications folder\nquit_application 'com.omnigroup.OmniGraffle7'\nif [ -d \"$APPDIR/OmniGraffle.app\" ]; then\n\tsudo mv \"$APPDIR/OmniGraffle.app\" \"$TMPDIR/OmniGraffle.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/OmniGraffle.app\" \"$APPDIR\"\n\n"
"c20e090b": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nTMPDIR=$(dirname \"$(realpath \"$INSTALLER_PATH\")\")\n# functions\n\nquit_and_track_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local timeout_duration=10\n\n # check if the application is running\n local app_running\n app_running=$(osascript -e \"application id \\\"$bundle_id\\\" is running\" 2>/dev/null)\n if [[ \"$app_running\" != \"true\" ]]; then\n eval \"export $var_name=0\"\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'.\"\n eval \"export $var_name=0\"\n return\n fi\n\n # App was running, mark it for relaunch\n eval \"export $var_name=1\"\n echo \"Application '$bundle_id' was running; will relaunch after installation.\"\n\n echo \"Quitting application '$bundle_id'...\"\n\n # try to quit the application within the timeout period\n local quit_success=false\n SECONDS=0\n while (( SECONDS < timeout_duration )); do\n if osascript -e \"tell application id \\\"$bundle_id\\\" to quit\" >/dev/null 2>&1; then\n if ! pgrep -f \"$bundle_id\" >/dev/null 2>&1; then\n echo \"Application '$bundle_id' quit successfully.\"\n quit_success=true\n break\n fi\n fi\n sleep 1\n done\n\n if [[ \"$quit_success\" = false ]]; then\n echo \"Application '$bundle_id' did not quit.\"\n fi\n}\n\n\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\n # Check if the app was running before installation\n eval \"was_running=\\$$var_name\"\n if [[ \"$was_running\" != \"1\" ]]; then\n return\n fi\n\n local console_user\n console_user=$(stat -f \"%Su\" /dev/console)\n if [[ -z \"$console_user\" || \"$console_user\" == \"root\" || \"$console_user\" == \"loginwindow\" ]]; then\n echo \"Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'.\"\n return\n fi\n\n echo \"Relaunching application '$bundle_id'...\"\n\n # Launch the app in the logged-in user's GUI session. Apps launched by root\n # won't register with the user's Dock/GUI, so run 'open' as the console user.\n # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace\n # and GUI session — 'sudo -u' alone doesn't do this, which can cause\n # LSOpenURLsWithRole() failures even when 'open' exits 0.\n local open_status=0\n if [[ $EUID -eq 0 ]]; then\n local console_uid\n console_uid=$(id -u \"$console_user\")\n /bin/launchctl asuser \"$console_uid\" sudo -u \"$console_user\" open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n else\n open -b \"$bundle_id\" >/dev/null 2>&1 || open_status=$?\n fi\n\n if [[ $open_status -eq 0 ]]; then\n echo \"Application '$bundle_id' relaunched successfully.\"\n else\n echo \"Failed to relaunch application '$bundle_id'.\"\n fi\n}\n\n\n# extract contents\nMOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)\nyes | hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" || exit 1\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\" || true\n# copy to the applications folder\nquit_and_track_application 'com.omnigroup.OmniGraffle7'\nif [ -d \"$APPDIR/OmniGraffle.app\" ]; then\n\tsudo mv \"$APPDIR/OmniGraffle.app\" \"$TMPDIR/OmniGraffle.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/OmniGraffle.app\" \"$APPDIR\"\nrelaunch_application 'com.omnigroup.OmniGraffle7'\n"
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/dbeaver-enterprise/darwin.json

=== Install // a96abe07 -> 5a0440c4 ===

--- /tmp/old.L9g3JD	2026-05-22 03:09:15.988505657 +0000
+++ /tmp/new.hwHbxm	2026-05-22 03:09:15.988505657 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.enterprise'
+quit_and_track_application 'com.dbeaver.product.enterprise'
 if [ -d "$APPDIR/DBeaverEE.app" ]; then
 	sudo mv "$APPDIR/DBeaverEE.app" "$TMPDIR/DBeaverEE.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverEE.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.enterprise'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dbeaverlite/darwin.json

=== Install // c1cba05a -> c72c1bb0 ===

--- /tmp/old.0AEV7T	2026-05-22 03:09:16.034506922 +0000
+++ /tmp/new.gyUqGY	2026-05-22 03:09:16.034506922 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.lite'
+quit_and_track_application 'com.dbeaver.product.lite'
 if [ -d "$APPDIR/DBeaverLite.app" ]; then
 	sudo mv "$APPDIR/DBeaverLite.app" "$TMPDIR/DBeaverLite.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverLite.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.lite'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dbeaverultimate/darwin.json

=== Install // 0a44a77f -> 52243cd3 ===

--- /tmp/old.jXXWzS	2026-05-22 03:09:16.078508132 +0000
+++ /tmp/new.ESR4df	2026-05-22 03:09:16.079508159 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.ultimate'
+quit_and_track_application 'com.dbeaver.product.ultimate'
 if [ -d "$APPDIR/DBeaverUltimate.app" ]; then
 	sudo mv "$APPDIR/DBeaverUltimate.app" "$TMPDIR/DBeaverUltimate.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverUltimate.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.ultimate'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/evernote/darwin.json

=== Install // a83831d7 -> 67a65f7d ===

--- /tmp/old.1HGTpn	2026-05-22 03:09:16.121509314 +0000
+++ /tmp/new.a4vpg4	2026-05-22 03:09:16.121509314 +0000
@@ -2,26 +2,34 @@
 
 # variables
 APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
-
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-yes | hdiutil attach -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.evernote.Evernote'
+quit_and_track_application 'com.evernote.Evernote'
 if [ -d "$APPDIR/Evernote.app" ]; then
 	sudo mv "$APPDIR/Evernote.app" "$TMPDIR/Evernote.app.bkp"
 fi
 sudo cp -R "$TMPDIR/Evernote.app" "$APPDIR"
+relaunch_application 'com.evernote.Evernote'

=== Uninstall // 31b95715 -> b7960ac0 ===

--- /tmp/old.ryUC38	2026-05-22 03:09:16.135509699 +0000
+++ /tmp/new.r37Xwu	2026-05-22 03:09:16.135509699 +0000
@@ -10,13 +10,15 @@
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
     return
   fi

ee/maintained-apps/outputs/omnigraffle/darwin.json

=== Install // d2d63787 -> c20e090b ===

--- /tmp/old.VYcxg2	2026-05-22 03:09:16.171510690 +0000
+++ /tmp/new.ZwxJqZ	2026-05-22 03:09:16.171510690 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-yes | hdiutil attach -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.omnigroup.OmniGraffle7'
+quit_and_track_application 'com.omnigroup.OmniGraffle7'
 if [ -d "$APPDIR/OmniGraffle.app" ]; then
 	sudo mv "$APPDIR/OmniGraffle.app" "$TMPDIR/OmniGraffle.app.bkp"
 fi
 sudo cp -R "$TMPDIR/OmniGraffle.app" "$APPDIR"
+relaunch_application 'com.omnigroup.OmniGraffle7'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/royal-tsx/darwin.json

=== Install // 8a40c4cb -> db51aef0 ===

--- /tmp/old.WBcQnr	2026-05-22 03:09:16.208511707 +0000
+++ /tmp/new.fN2mhQ	2026-05-22 03:09:16.208511707 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.lemonmojo.RoyalTSX.App'
+quit_and_track_application 'com.lemonmojo.RoyalTSX.App'
 if [ -d "$APPDIR/Royal TSX.app" ]; then
 	sudo mv "$APPDIR/Royal TSX.app" "$TMPDIR/Royal TSX.app.bkp"
 fi
 sudo cp -R "$TMPDIR/Royal TSX.app" "$APPDIR"
+relaunch_application 'com.lemonmojo.RoyalTSX.App'

=== Uninstall Script (no changes) ===

fleet-release
fleet-release previously approved these changes May 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/dbeaver-enterprise/darwin.json

=== Install // a96abe07 -> 5a0440c4 ===

--- /tmp/old.GgSIVX	2026-05-26 15:48:13.097398375 +0000
+++ /tmp/new.QSemJH	2026-05-26 15:48:13.097398375 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.enterprise'
+quit_and_track_application 'com.dbeaver.product.enterprise'
 if [ -d "$APPDIR/DBeaverEE.app" ]; then
 	sudo mv "$APPDIR/DBeaverEE.app" "$TMPDIR/DBeaverEE.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverEE.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.enterprise'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dbeaverlite/darwin.json

=== Install // c1cba05a -> c72c1bb0 ===

--- /tmp/old.M7QZa7	2026-05-26 15:48:13.152398889 +0000
+++ /tmp/new.kBvrXk	2026-05-26 15:48:13.152398889 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.lite'
+quit_and_track_application 'com.dbeaver.product.lite'
 if [ -d "$APPDIR/DBeaverLite.app" ]; then
 	sudo mv "$APPDIR/DBeaverLite.app" "$TMPDIR/DBeaverLite.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverLite.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.lite'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dbeaverultimate/darwin.json

=== Install // 0a44a77f -> 52243cd3 ===

--- /tmp/old.RZjt5m	2026-05-26 15:48:13.204399376 +0000
+++ /tmp/new.fvOaSM	2026-05-26 15:48:13.204399376 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.ultimate'
+quit_and_track_application 'com.dbeaver.product.ultimate'
 if [ -d "$APPDIR/DBeaverUltimate.app" ]; then
 	sudo mv "$APPDIR/DBeaverUltimate.app" "$TMPDIR/DBeaverUltimate.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverUltimate.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.ultimate'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/evernote/darwin.json

=== Install // a83831d7 -> 67a65f7d ===

--- /tmp/old.BfhP8M	2026-05-26 15:48:13.261399909 +0000
+++ /tmp/new.BghH7K	2026-05-26 15:48:13.261399909 +0000
@@ -2,26 +2,34 @@
 
 # variables
 APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
-
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-yes | hdiutil attach -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.evernote.Evernote'
+quit_and_track_application 'com.evernote.Evernote'
 if [ -d "$APPDIR/Evernote.app" ]; then
 	sudo mv "$APPDIR/Evernote.app" "$TMPDIR/Evernote.app.bkp"
 fi
 sudo cp -R "$TMPDIR/Evernote.app" "$APPDIR"
+relaunch_application 'com.evernote.Evernote'

=== Uninstall // 31b95715 -> b7960ac0 ===

--- /tmp/old.U3iE7b	2026-05-26 15:48:13.278400068 +0000
+++ /tmp/new.O8PVc8	2026-05-26 15:48:13.278400068 +0000
@@ -10,13 +10,15 @@
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
     return
   fi

ee/maintained-apps/outputs/omnigraffle/darwin.json

=== Install // d2d63787 -> c20e090b ===

--- /tmp/old.hj7tn7	2026-05-26 15:48:13.320400461 +0000
+++ /tmp/new.u8aIyK	2026-05-26 15:48:13.320400461 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-yes | hdiutil attach -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.omnigroup.OmniGraffle7'
+quit_and_track_application 'com.omnigroup.OmniGraffle7'
 if [ -d "$APPDIR/OmniGraffle.app" ]; then
 	sudo mv "$APPDIR/OmniGraffle.app" "$TMPDIR/OmniGraffle.app.bkp"
 fi
 sudo cp -R "$TMPDIR/OmniGraffle.app" "$APPDIR"
+relaunch_application 'com.omnigroup.OmniGraffle7'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/royal-tsx/darwin.json

=== Install // 8a40c4cb -> db51aef0 ===

--- /tmp/old.BHKYwC	2026-05-26 15:48:13.363400863 +0000
+++ /tmp/new.MKOnom	2026-05-26 15:48:13.363400863 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.lemonmojo.RoyalTSX.App'
+quit_and_track_application 'com.lemonmojo.RoyalTSX.App'
 if [ -d "$APPDIR/Royal TSX.app" ]; then
 	sudo mv "$APPDIR/Royal TSX.app" "$TMPDIR/Royal TSX.app.bkp"
 fi
 sudo cp -R "$TMPDIR/Royal TSX.app" "$APPDIR"
+relaunch_application 'com.lemonmojo.RoyalTSX.App'

=== Uninstall Script (no changes) ===

fleet-release
fleet-release previously approved these changes May 26, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/dbeaver-enterprise/darwin.json

=== Install // a96abe07 -> 5a0440c4 ===

--- /tmp/old.oCH6wu	2026-05-26 17:45:03.318143914 +0000
+++ /tmp/new.04uPoD	2026-05-26 17:45:03.318143914 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.enterprise'
+quit_and_track_application 'com.dbeaver.product.enterprise'
 if [ -d "$APPDIR/DBeaverEE.app" ]; then
 	sudo mv "$APPDIR/DBeaverEE.app" "$TMPDIR/DBeaverEE.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverEE.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.enterprise'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dbeaverlite/darwin.json

=== Install // c1cba05a -> c72c1bb0 ===

--- /tmp/old.jUiarW	2026-05-26 17:45:03.414144242 +0000
+++ /tmp/new.1HxJs3	2026-05-26 17:45:03.414144242 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.lite'
+quit_and_track_application 'com.dbeaver.product.lite'
 if [ -d "$APPDIR/DBeaverLite.app" ]; then
 	sudo mv "$APPDIR/DBeaverLite.app" "$TMPDIR/DBeaverLite.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverLite.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.lite'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/dbeaverultimate/darwin.json

=== Install // 0a44a77f -> 52243cd3 ===

--- /tmp/old.63J26U	2026-05-26 17:45:03.458144393 +0000
+++ /tmp/new.kEtoaq	2026-05-26 17:45:03.458144393 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.dbeaver.product.ultimate'
+quit_and_track_application 'com.dbeaver.product.ultimate'
 if [ -d "$APPDIR/DBeaverUltimate.app" ]; then
 	sudo mv "$APPDIR/DBeaverUltimate.app" "$TMPDIR/DBeaverUltimate.app.bkp"
 fi
 sudo cp -R "$TMPDIR/DBeaverUltimate.app" "$APPDIR"
+relaunch_application 'com.dbeaver.product.ultimate'

=== Uninstall Script (no changes) ===

ee/maintained-apps/outputs/evernote/darwin.json

=== Install // a83831d7 -> 67a65f7d ===

--- /tmp/old.cgfLDg	2026-05-26 17:45:03.501144540 +0000
+++ /tmp/new.ebJ5JI	2026-05-26 17:45:03.502144543 +0000
@@ -2,26 +2,34 @@
 
 # variables
 APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath $INSTALLER_PATH)")
-
+TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
-yes | hdiutil attach -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
+yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.evernote.Evernote'
+quit_and_track_application 'com.evernote.Evernote'
 if [ -d "$APPDIR/Evernote.app" ]; then
 	sudo mv "$APPDIR/Evernote.app" "$TMPDIR/Evernote.app.bkp"
 fi
 sudo cp -R "$TMPDIR/Evernote.app" "$APPDIR"
+relaunch_application 'com.evernote.Evernote'

=== Uninstall // 31b95715 -> b7960ac0 ===

--- /tmp/old.uc2b51	2026-05-26 17:45:03.517144595 +0000
+++ /tmp/new.Q1AAHO	2026-05-26 17:45:03.518144598 +0000
@@ -10,13 +10,15 @@
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
     return
   fi

ee/maintained-apps/outputs/royal-tsx/darwin.json

=== Install // 8a40c4cb -> db51aef0 ===

--- /tmp/old.sevvtK	2026-05-26 17:45:03.561144745 +0000
+++ /tmp/new.gxs1gP	2026-05-26 17:45:03.561144745 +0000
@@ -3,25 +3,33 @@
 # variables
 APPDIR="/Applications/"
 TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-
 # functions
 
-quit_application() {
+quit_and_track_application() {
   local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
   local timeout_duration=10
 
   # check if the application is running
-  if ! osascript -e "application id \"$bundle_id\" is running" 2>/dev/null; then
+  local app_running
+  app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null)
+  if [[ "$app_running" != "true" ]]; then
+    eval "export $var_name=0"
     return
   fi
 
   local console_user
   console_user=$(stat -f "%Su" /dev/console)
-  if [[ $EUID -eq 0 && "$console_user" == "root" ]]; then
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
     echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'."
+    eval "export $var_name=0"
     return
   fi
 
+  # App was running, mark it for relaunch
+  eval "export $var_name=1"
+  echo "Application '$bundle_id' was running; will relaunch after installation."
+
   echo "Quitting application '$bundle_id'..."
 
   # try to quit the application within the timeout period
@@ -43,17 +51,58 @@
   fi
 }
 
+
+relaunch_application() {
+  local bundle_id="$1"
+  local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')"
+  local was_running
+
+  # Check if the app was running before installation
+  eval "was_running=\$$var_name"
+  if [[ "$was_running" != "1" ]]; then
+    return
+  fi
+
+  local console_user
+  console_user=$(stat -f "%Su" /dev/console)
+  if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then
+    echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'."
+    return
+  fi
+
+  echo "Relaunching application '$bundle_id'..."
+
+  # Launch the app in the logged-in user's GUI session. Apps launched by root
+  # won't register with the user's Dock/GUI, so run 'open' as the console user.
+  # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace
+  # and GUI session — 'sudo -u' alone doesn't do this, which can cause
+  # LSOpenURLsWithRole() failures even when 'open' exits 0.
+  local open_status=0
+  if [[ $EUID -eq 0 ]]; then
+    local console_uid
+    console_uid=$(id -u "$console_user")
+    /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  else
+    open -b "$bundle_id" >/dev/null 2>&1 || open_status=$?
+  fi
+
+  if [[ $open_status -eq 0 ]]; then
+    echo "Application '$bundle_id' relaunched successfully."
+  else
+    echo "Failed to relaunch application '$bundle_id'."
+  fi
+}
+
+
 # extract contents
-# Use 'yes' to automatically accept license agreement when mounting DMG
-# This replicates Homebrew's behavior for DMG files with license agreements
 MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX)
 yes | hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" || exit 1
 sudo cp -R "$MOUNT_POINT"/* "$TMPDIR"
 hdiutil detach "$MOUNT_POINT" || true
-
 # copy to the applications folder
-quit_application 'com.lemonmojo.RoyalTSX.App'
+quit_and_track_application 'com.lemonmojo.RoyalTSX.App'
 if [ -d "$APPDIR/Royal TSX.app" ]; then
 	sudo mv "$APPDIR/Royal TSX.app" "$TMPDIR/Royal TSX.app.bkp"
 fi
 sudo cp -R "$TMPDIR/Royal TSX.app" "$APPDIR"
+relaunch_application 'com.lemonmojo.RoyalTSX.App'

=== Uninstall Script (no changes) ===

@allenhouchins
allenhouchins merged commit 937c6bc into main Jun 1, 2026
46 checks passed
@allenhouchins
allenhouchins deleted the allenhouchins-update-dmg-install-script branch June 1, 2026 02:08
This was referenced Jun 8, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants