Skip to content

Update Fleet-maintained apps - #46288

Closed
fleet-release wants to merge 1 commit into
mainfrom
fma-2605272039
Closed

Update Fleet-maintained apps#46288
fleet-release wants to merge 1 commit into
mainfrom
fma-2605272039

Conversation

@fleet-release

@fleet-release fleet-release commented May 27, 2026

Copy link
Copy Markdown
Contributor

Automated ingestion of latest Fleet-maintained app data.

Summary by CodeRabbit

  • Chores
    • Updated supported app versions and metadata for 1Password, Drawio, Dropbox, Google Chrome, GoToMeeting, Granola, Jabra Direct, Krita, WhatsApp, and Wrike across multiple platforms.
    • Enhanced uninstall procedures for 1Password and Dropbox applications.

Review Change Stack

Generated automatically with cmd/maintained-apps.

@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.

@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/1password/darwin.json

=== Install Script (no changes) ===
=== Uninstall // f58c31b3 -> dadf8c51 ===

--- /tmp/old.uQ4EiM	2026-05-27 20:43:05.253006064 +0000
+++ /tmp/new.zEqSFP	2026-05-27 20:43:05.254006058 +0000
@@ -5,6 +5,46 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+quit_application() {
+  local bundle_id="$1"
+  local timeout_duration=10
+
+  # check if the application is running
+  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 [[ -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
+
+  echo "Quitting application '$bundle_id'..."
+
+  # try to quit the application within the timeout period
+  local quit_success=false
+  SECONDS=0
+  while (( SECONDS < timeout_duration )); do
+    if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+      if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+        echo "Application '$bundle_id' quit successfully."
+        quit_success=true
+        break
+      fi
+    fi
+    sleep 1
+  done
+
+  if [[ "$quit_success" = false ]]; then
+    echo "Application '$bundle_id' did not quit."
+  fi
+}
+
+
 trash() {
   local logged_in_user="$1"
   local target_file="$2"
@@ -27,6 +67,7 @@
   fi
 }
 
+quit_application 'com.1password.1password'
 sudo rm -rf "$APPDIR/1Password.app"
 trash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.1password*'
 trash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.agilebits'

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

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

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

=== Install Script (no changes) ===
=== Uninstall // 4d5c7d9c -> f2e8d2ab ===

--- /tmp/old.j7fUhC	2026-05-27 20:43:05.318005717 +0000
+++ /tmp/new.xPLXRQ	2026-05-27 20:43:05.318005717 +0000
@@ -5,6 +5,46 @@
 LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
 # functions
 
+quit_application() {
+  local bundle_id="$1"
+  local timeout_duration=10
+
+  # check if the application is running
+  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 [[ -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
+
+  echo "Quitting application '$bundle_id'..."
+
+  # try to quit the application within the timeout period
+  local quit_success=false
+  SECONDS=0
+  while (( SECONDS < timeout_duration )); do
+    if osascript -e "tell application id \"$bundle_id\" to quit" >/dev/null 2>&1; then
+      if ! pgrep -f "$bundle_id" >/dev/null 2>&1; then
+        echo "Application '$bundle_id' quit successfully."
+        quit_success=true
+        break
+      fi
+    fi
+    sleep 1
+  done
+
+  if [[ "$quit_success" = false ]]; then
+    echo "Application '$bundle_id' did not quit."
+  fi
+}
+
+
 remove_launchctl_service() {
   local service="$1"
   local booleans=("true" "false")
@@ -73,6 +113,7 @@
 }
 
 remove_launchctl_service 'com.dropbox.DropboxMacUpdate.agent'
+quit_application 'com.getdropbox.dropbox'
 sudo rm -rf '/Library/DropboxHelperTools'
 sudo rm -rf '/Library/Preferences/com.getdropbox.dropbox.dbkextd.plist'
 sudo rm -rf "$APPDIR/Dropbox.app"

ee/maintained-apps/outputs/google-chrome/windows.json

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

ee/maintained-apps/outputs/gotomeeting/windows.json

=== Install Script (no changes) ===
=== Uninstall // cef7f8fa -> f5235386 ===

--- /tmp/old.6zbruw	2026-05-27 20:43:05.377005403 +0000
+++ /tmp/new.YLI2jp	2026-05-27 20:43:05.377005403 +0000
@@ -1,15 +1,11 @@
-# Best-effort uninstall for GoToMeeting.
+# Uninstall for GoToMeeting.
 #
 # The winget installer is the GoToMeeting "Setup" bootstrapper (ARPSYSTEMCOMPONENT=1,
 # so it hides itself from Programs and Features). It installs the actual GoToMeeting
 # app, which self-registers a separate, visible uninstall entry (DisplayName like
 # "GoToMeeting <version>") whose uninstaller is G2MUninstall.exe.
 #
-# We locate that entry and run G2MUninstall.exe directly. NOTE: the registry
-# QuietUninstallString uses "/S", which G2MUninstall.exe does not recognize as a
-# silent switch (it hangs waiting on UI). The vendor's documented silent switch
-# is "/silent" (see silentinstallhq.com), so we build the arguments ourselves
-# rather than trusting the registry string.
+# We locate that entry and run G2MUninstall.exe directly.
 
 $softwareNameLike = "GoToMeeting*"

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

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

ee/maintained-apps/outputs/granola/windows.json

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

ee/maintained-apps/outputs/jabra-direct/darwin.json

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

ee/maintained-apps/outputs/krita/windows.json

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

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

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

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

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

@coderabbitai

coderabbitai Bot commented May 27, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

This PR updates maintained-app configuration metadata for 11 applications across macOS and Windows platforms. Three applications receive uninstall script replacements: 1Password 8.12.21 (with app-quit logic and eligibility checks), Dropbox 254.4.2518 (with DMG mount and app relaunch tracking), and GoToMeeting (with updated PowerShell registry handling). The remaining eight applications receive version bumps with corresponding updates to patched query thresholds, installer URLs, and sha256 checksums.

Possibly related PRs

  • fleetdm/fleet#46055: Updates the SQL queries.patched version gate for 1Password 8.12.21 in the same file that this PR modifies with the uninstall script ref change.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description 'Automated ingestion of latest Fleet-maintained app data' is vague and lacks required detail. The PR description template specifies multiple required sections including related issues, checklists for file changes, testing, database migrations, and fleetd compatibility verification. Provide a detailed description following the template, including related issue numbers, applicable checklist items, testing approach, and any relevant notes about the automated ingestion process.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Update Fleet-maintained apps' accurately summarizes the main change—updating application metadata for multiple Fleet-maintained apps across different platforms.
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 fma-2605272039

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: 3

🤖 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/1password/darwin.json`:
- Line 20: The check for whether the app is running in quit_application
incorrectly relies on osascript's exit status; change it to capture osascript
stdout (e.g., is_running=$(osascript -e "application id \"$bundle_id\" is
running" 2>/dev/null)) and compare the output to "true" (if not "true" then
return) so the function returns immediately when the AppleScript evaluates to
false; update the conditional that currently uses osascript exit status to use
this captured value instead.
- Line 19: The trash() function currently treats glob patterns literally because
it tests and moves the quoted variable "$target_file"; change it to expand globs
into actual matches: after expanding ~ to /Users/$logged_in_user, perform a safe
glob expansion (e.g., generate an array/list of matches from target_file),
handle the zero-match case (log and return), then iterate over each matched path
and mv -f each match (quoting the individual matched path when passing to mv to
preserve spaces). Update references inside trash() (local target_file,
file_name, trash) so filename/timestamp/rand logic applies per matched file.

In `@ee/maintained-apps/outputs/dropbox/darwin.json`:
- Line 20: The trash() helper currently treats wildcard patterns as literal
because it tests and moves "$target_file" quoted; modify trash() to enable glob
expansion (e.g., shopt -s nullglob) and iterate over the expanded matches before
testing/moving each file; ensure you still replace leading ~ with
/Users/$logged_in_user, handle the case of no matches (nullglob) to avoid false
"doesn't exist" messages, and reference the local variables target_file,
logged_in_user, trash, file_name inside trash() when performing the per-file mv.
🪄 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: 666f90e8-a345-40d5-bfde-ba92f7e0de5c

📥 Commits

Reviewing files that changed from the base of the PR and between 36eace6 and f30e2c8.

📒 Files selected for processing (11)
  • ee/maintained-apps/outputs/1password/darwin.json
  • ee/maintained-apps/outputs/drawio/darwin.json
  • ee/maintained-apps/outputs/dropbox/darwin.json
  • ee/maintained-apps/outputs/google-chrome/windows.json
  • ee/maintained-apps/outputs/gotomeeting/windows.json
  • ee/maintained-apps/outputs/granola/darwin.json
  • ee/maintained-apps/outputs/granola/windows.json
  • ee/maintained-apps/outputs/jabra-direct/darwin.json
  • ee/maintained-apps/outputs/krita/windows.json
  • ee/maintained-apps/outputs/whatsapp/darwin.json
  • ee/maintained-apps/outputs/wrike/darwin.json

"refs": {
"ef2a17ff": "#!/bin/bash\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\nquit_application 'com.1password.1password'\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n",
"f58c31b3": "#!/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/1Password.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.1password*'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.1password-launcher'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Application Support/1Password'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Arc/User Data/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.1password.1password.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/1Password*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Mozilla/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Vivaldi/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Containers/2BUA8C4S2C.com.1password.browser-helper'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.1password*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.1password'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Logs/1Password'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.1password.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/group.com.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.1password.1password.savedState'\n"
"dadf8c51": "#!/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.1password.1password'\nsudo rm -rf \"$APPDIR/1Password.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.1password*'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.1password-launcher'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Application Support/1Password'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Arc/User Data/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.1password.1password.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/1Password*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Mozilla/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Vivaldi/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Containers/2BUA8C4S2C.com.1password.browser-helper'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.1password*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.1password'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Logs/1Password'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.1password.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/group.com.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.1password.1password.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 | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
target_file='/bin/ba*'

if [[ -e "$target_file" ]]; then
  echo 'quoted variable globbed'
else
  echo 'quoted variable treated literally'
fi

printf 'direct shell expansion example: %s\n' /bin/ba*

Repository: fleetdm/fleet

Length of output: 223


Fix glob handling in trash() so * patterns actually match and get removed

trash() receives glob patterns (e.g., ~/Library/Application Scripts/2BUA8C4S2C.com.1password*) but tests/moves them using quoted "$target_file" ([[ -e "$target_file" ]] and mv -f "$target_file"), so * is treated literally and the entries won’t match/remove.

Expand the glob into a list of actual matches before checking/moving (handle the zero-match case), then mv each match.

🤖 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/1password/darwin.json` at line 19, The trash()
function currently treats glob patterns literally because it tests and moves the
quoted variable "$target_file"; change it to expand globs into actual matches:
after expanding ~ to /Users/$logged_in_user, perform a safe glob expansion
(e.g., generate an array/list of matches from target_file), handle the
zero-match case (log and return), then iterate over each matched path and mv -f
each match (quoting the individual matched path when passing to mv to preserve
spaces). Update references inside trash() (local target_file, file_name, trash)
so filename/timestamp/rand logic applies per matched file.

"ef2a17ff": "#!/bin/bash\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\nquit_application 'com.1password.1password'\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n",
"f58c31b3": "#!/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/1Password.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.1password*'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.1password-launcher'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Application Support/1Password'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Arc/User Data/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.1password.1password.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/1Password*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Mozilla/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Vivaldi/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Containers/2BUA8C4S2C.com.1password.browser-helper'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.1password*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.1password'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Logs/1Password'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.1password.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/group.com.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.1password.1password.savedState'\n"
"dadf8c51": "#!/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.1password.1password'\nsudo rm -rf \"$APPDIR/1Password.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.1password*'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.1password-launcher'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Application Support/1Password'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Arc/User Data/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.1password.1password.sfl*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/CrashReporter/1Password*'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Google/Chrome/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Beta/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Canary/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge Dev/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Microsoft Edge/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Mozilla/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Vivaldi/NativeMessagingHosts/com.1password.1password.json'\ntrash $LOGGED_IN_USER '~/Library/Containers/2BUA8C4S2C.com.1password.browser-helper'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.1password*'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.1password.browser-support'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.1password'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/2BUA8C4S2C.com.agilebits'\ntrash $LOGGED_IN_USER '~/Library/Logs/1Password'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.1password.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/group.com.1password.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.1password.1password.savedState'\n",
"ef2a17ff": "#!/bin/bash\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\nquit_application 'com.1password.1password'\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\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 | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

For AppleScript run via osascript, does -e 'application id "com.1password.1password" is running' return exit status 0 even when the expression evaluates to false, or only when it evaluates to true?

💡 Result:

In general, osascript’s process exit status is not determined by whether an AppleScript expression evaluates to true or false; instead, osascript returns 0 when the script completes successfully and a non-zero status when the script raises an error. For example, a Stack Overflow discussion about returning status codes with osascript notes that osascript returns its own exit status rather than a script’s return value, and that exit status stays 0 when the script “returns” a value (even if you try returning 3) [1]. So for your specific example: - osascript -e 'application id "com.1password.1password" is running' - if that expression evaluates to false, the script still completes successfully and will therefore exit with status 0; the value is emitted as stdout (e.g., false), not used to drive the Unix exit code [1]. If the expression (or the surrounding script) instead causes an AppleScript error/exception, then osascript will return a non-zero exit status (the “script errors” behavior is documented via osascript’s output handling options) [2].

Citations:


Use the AppleScript boolean result (stdout) instead of osascript exit status in quit_application

  • osascript returns success (exit code 0) when the AppleScript expression runs, even if application id ... is running evaluates to false; return won’t trigger, so the script may wait for the timeout even when 1Password isn’t running.
  • Capture stdout and compare to "true".
Suggested fix
-  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
📝 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
"ef2a17ff": "#!/bin/bash\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\nquit_application 'com.1password.1password'\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\n"
"ef2a17ff": "#!/bin/bash\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 [[ $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\nquit_application 'com.1password.1password'\ninstaller -pkg \"$INSTALLER_PATH\" -target /\n\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/1password/darwin.json` at line 20, The check for
whether the app is running in quit_application incorrectly relies on osascript's
exit status; change it to capture osascript stdout (e.g., is_running=$(osascript
-e "application id \"$bundle_id\" is running" 2>/dev/null)) and compare the
output to "true" (if not "true" then return) so the function returns immediately
when the AppleScript evaluates to false; update the conditional that currently
uses osascript exit status to use this captured value instead.

"4d5c7d9c": "#!/bin/bash\n\n# variables\nAPPDIR=\"/Applications/\"\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\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\nremove_launchctl_service 'com.dropbox.DropboxMacUpdate.agent'\nsudo rm -rf '/Library/DropboxHelperTools'\nsudo rm -rf '/Library/Preferences/com.getdropbox.dropbox.dbkextd.plist'\nsudo rm -rf \"$APPDIR/Dropbox.app\"\ntrash $LOGGED_IN_USER '~/.dropbox'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/*.com.getdropbox.dropbox.sync'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.dropbox.alternatenotificationservice'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.dropbox.client.crashpad'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.dropbox.foldertagger'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.getdropbox.dropbox.fileprovider'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.getdropbox.dropbox.garcon'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.getdropbox.dropbox.TransferExtension'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Dropbox'\ntrash $LOGGED_IN_USER '~/Library/Application Support/DropboxElectron'\ntrash $LOGGED_IN_USER '~/Library/Application Support/FileProvider/com.getdropbox.dropbox.fileprovider'\ntrash $LOGGED_IN_USER '~/Library/Caches/CloudKit/com.apple.bird/iCloud.com.getdropbox.Dropbox'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.dropbox.DropboxMacUpdate'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.dropbox.DropboxUpdater'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.getdropbox.dropbox'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.getdropbox.DropboxMetaInstaller'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.plausiblelabs.crashreporter.data/com.dropbox.DropboxMacUpdate'\ntrash $LOGGED_IN_USER '~/Library/CloudStorage/Dropbox'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.dropbox.activityprovider'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.dropbox.alternatenotificationservice'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.dropbox.foldertagger'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.getdropbox.dropbox.fileprovider'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.getdropbox.dropbox.garcon'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.getdropbox.dropbox.TransferExtension'\ntrash $LOGGED_IN_USER '~/Library/Dropbox'\ntrash $LOGGED_IN_USER '~/Library/Dropbox/DropboxMacUpdate.app/Contents/MacOS/DropboxMacUpdate'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/*.com.getdropbox.dropbox.sync'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/com.dropbox.client.crashpad'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/com.getdropbox.dropbox.garcon'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.dropbox.DropboxMacUpdate'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.getdropbox.dropbox'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.dropbox.DropboxMacUpdate.agent.plist'\ntrash $LOGGED_IN_USER '~/Library/Logs/Dropbox_debug.log'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.apple.FileProvider/com.getdropbox.dropbox.fileprovider'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.dropbox.DropboxMacUpdate.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.dropbox.DropboxMonitor.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.dropbox.tungsten.helper.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.getdropbox.dropbox.plist'\n",
"59c04bcb": "#!/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)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n# copy to the applications folder\nquit_and_track_application 'com.getdropbox.dropbox'\nif [ -d \"$APPDIR/Dropbox.app\" ]; then\n\tsudo mv \"$APPDIR/Dropbox.app\" \"$TMPDIR/Dropbox.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Dropbox.app\" \"$APPDIR\"\nrelaunch_application 'com.getdropbox.dropbox'\n"
"59c04bcb": "#!/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)\nhdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\"\nsudo cp -R \"$MOUNT_POINT\"/* \"$TMPDIR\"\nhdiutil detach \"$MOUNT_POINT\"\n# copy to the applications folder\nquit_and_track_application 'com.getdropbox.dropbox'\nif [ -d \"$APPDIR/Dropbox.app\" ]; then\n\tsudo mv \"$APPDIR/Dropbox.app\" \"$TMPDIR/Dropbox.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Dropbox.app\" \"$APPDIR\"\nrelaunch_application 'com.getdropbox.dropbox'\n",
"f2e8d2ab": "#!/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\nremove_launchctl_service() {\n local service=\"$1\"\n local booleans=(\"true\" \"false\")\n local plist_status\n local paths\n local should_sudo\n\n echo \"Removing launchctl service ${service}\"\n\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.plist\"\n )\n\n # if not using sudo, prepend the home directory to the paths\n if [[ $should_sudo == \"false\" ]]; then\n for i in \"${!paths[@]}\"; do\n paths[i]=\"${HOME}${paths[i]}\"\n done\n fi\n\n for path in \"${paths[@]}\"; do\n if [[ -e \"$path\" ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo rm -f -- \"$path\"\n else\n rm -f -- \"$path\"\n fi\n fi\n done\n done\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\nremove_launchctl_service 'com.dropbox.DropboxMacUpdate.agent'\nquit_application 'com.getdropbox.dropbox'\nsudo rm -rf '/Library/DropboxHelperTools'\nsudo rm -rf '/Library/Preferences/com.getdropbox.dropbox.dbkextd.plist'\nsudo rm -rf \"$APPDIR/Dropbox.app\"\ntrash $LOGGED_IN_USER '~/.dropbox'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/*.com.getdropbox.dropbox.sync'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.dropbox.alternatenotificationservice'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.dropbox.client.crashpad'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.dropbox.foldertagger'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.getdropbox.dropbox.fileprovider'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.getdropbox.dropbox.garcon'\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.getdropbox.dropbox.TransferExtension'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Dropbox'\ntrash $LOGGED_IN_USER '~/Library/Application Support/DropboxElectron'\ntrash $LOGGED_IN_USER '~/Library/Application Support/FileProvider/com.getdropbox.dropbox.fileprovider'\ntrash $LOGGED_IN_USER '~/Library/Caches/CloudKit/com.apple.bird/iCloud.com.getdropbox.Dropbox'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.dropbox.DropboxMacUpdate'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.dropbox.DropboxUpdater'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.getdropbox.dropbox'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.getdropbox.DropboxMetaInstaller'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.plausiblelabs.crashreporter.data/com.dropbox.DropboxMacUpdate'\ntrash $LOGGED_IN_USER '~/Library/CloudStorage/Dropbox'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.dropbox.activityprovider'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.dropbox.alternatenotificationservice'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.dropbox.foldertagger'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.getdropbox.dropbox.fileprovider'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.getdropbox.dropbox.garcon'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.getdropbox.dropbox.TransferExtension'\ntrash $LOGGED_IN_USER '~/Library/Dropbox'\ntrash $LOGGED_IN_USER '~/Library/Dropbox/DropboxMacUpdate.app/Contents/MacOS/DropboxMacUpdate'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/*.com.getdropbox.dropbox.sync'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/com.dropbox.client.crashpad'\ntrash $LOGGED_IN_USER '~/Library/Group Containers/com.getdropbox.dropbox.garcon'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.dropbox.DropboxMacUpdate'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.getdropbox.dropbox'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.dropbox.DropboxMacUpdate.agent.plist'\ntrash $LOGGED_IN_USER '~/Library/Logs/Dropbox_debug.log'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.apple.FileProvider/com.getdropbox.dropbox.fileprovider'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.dropbox.DropboxMacUpdate.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.dropbox.DropboxMonitor.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.dropbox.tungsten.helper.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.getdropbox.dropbox.plist'\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 | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
target_file='/bin/ba*'

if [[ -e "$target_file" ]]; then
  echo 'quoted variable globbed'
else
  echo 'quoted variable treated literally'
fi

printf 'direct shell expansion example: %s\n' /bin/ba*

Repository: fleetdm/fleet

Length of output: 223


Fix wildcard cleanup in trash() helper: In ee/maintained-apps/outputs/dropbox/darwin.json (uninstall trash() helper), [[ -e "$target_file" ]] and mv -f "$target_file" quote $target_file, so wildcard patterns like ~/Library/Application Scripts/*.com.getdropbox.dropbox.sync (and ~/Library/Group Containers/*.com.getdropbox.dropbox.sync) are treated literally and won’t be moved. Expand glob matches (e.g., shopt -s nullglob + iterate) before testing/moving.

🤖 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/dropbox/darwin.json` at line 20, The trash()
helper currently treats wildcard patterns as literal because it tests and moves
"$target_file" quoted; modify trash() to enable glob expansion (e.g., shopt -s
nullglob) and iterate over the expanded matches before testing/moving each file;
ensure you still replace leading ~ with /Users/$logged_in_user, handle the case
of no matches (nullglob) to avoid false "doesn't exist" messages, and reference
the local variables target_file, logged_in_user, trash, file_name inside trash()
when performing the per-file mv.

@github-actions

Copy link
Copy Markdown
Contributor

Closing in favor of #46307.

@github-actions github-actions Bot closed this May 28, 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.

2 participants