Update Fleet-maintained apps - #49796
Conversation
Generated automatically with cmd/maintained-apps.
Script Diff Resultsee/maintained-apps/outputs/advanced-installer/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/akiflow/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/aws-cli/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/beyond-compare/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/brave-browser/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/cleanmymac/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/clop/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/comet/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/cursor/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/dataflare/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/dataflare/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/firefox@developer-edition/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/firefox@nightly/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===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/lookaway/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/loom/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/loom/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/macwhisper/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/marsedit/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/megasync/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/microsoft-teams/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/microsoft-teams/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/mozilla-vpn/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/nosql-workbench/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/nosql-workbench/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/obs/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/only-switch/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/popclip/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/powerphotos/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/powershell/windows.json=== Install Script (no changes) ===
=== Uninstall // 0995d374 -> 06cf76b8 ===
--- /tmp/old.ezQH3R 2026-07-22 22:08:27.697851795 +0000
+++ /tmp/new.g4IQIK 2026-07-22 22:08:27.698851807 +0000
@@ -1,4 +1,4 @@
-$product_code = '{7B031DCF-BDCE-47D6-89B9-4C558D76E773}'
+$product_code = '{92D9A5DC-8C64-40D5-B1BC-98DB9C7FDB7F}'
$timeoutSeconds = 300 # 5 minute timeout
# Fleet uninstalls app using product code that's extracted on uploadee/maintained-apps/outputs/prisma-browser/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/pritunl/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/pritunl/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/rider/darwin.json=== Install Script (no changes) ===
=== Uninstall // c52dae57 -> 22db20ac ===
--- /tmp/old.EXdBXT 2026-07-22 22:08:27.881854043 +0000
+++ /tmp/new.aL7IgQ 2026-07-22 22:08:27.881854043 +0000
@@ -54,9 +54,9 @@
sudo rm -rf "$APPDIR/Rider.app"
sudo rm -rf 'rider'
-trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.1'
-trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Caches/Rider2026.2'
+trash $LOGGED_IN_USER '~/Library/Logs/Rider2026.2'
trash $LOGGED_IN_USER '~/Library/Preferences/jetbrains.rider.71e559ef.plist'
-trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.1'
+trash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.2'
trash $LOGGED_IN_USER '~/Library/Saved Application State/com.jetbrains.rider.savedState'ee/maintained-apps/outputs/rustrover/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/setapp/darwin.json=== Install Script (no changes) ===
=== Uninstall // e23bd29d -> 9ef05eb6 ===
--- /tmp/old.b7UNDL 2026-07-22 22:08:27.980855252 +0000
+++ /tmp/new.jyWlDs 2026-07-22 22:08:27.980855252 +0000
@@ -5,6 +5,76 @@
LOGGED_IN_USER=$(scutil <<< "show State:/Users/ConsoleUser" | awk '/Name :/ { print $3 }')
# functions
+remove_launchctl_service() {
+ local service="$1"
+ local booleans=("true" "false")
+ local plist_status
+ local paths
+ local should_sudo
+
+ echo "Removing launchctl service ${service}"
+
+ # A wildcard label can't be used with launchctl or as a plist name, so expand
+ # it to the labels of currently loaded services that match the pattern.
+ local services=("$service")
+ if [[ "$service" == *"*"* ]]; then
+ local regex
+ # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so
+ # it matches a full label rather than a substring.
+ regex=$(printf '%s' "$service" | sed -e 's/[][(){}.^$+?|\\]/\\&/g' -e 's/\*/.*/g')
+ regex="^${regex}$"
+ services=()
+ local id
+ # Match every loaded job by label regardless of PID; launchctl list reports
+ # loaded-but-not-running jobs with a "-" in the PID column.
+ while read -r _ _ id; do
+ [[ "$id" =~ $regex ]] && services+=("$id")
+ done < <(launchctl list 2>/dev/null | tail -n +2)
+ if [[ ${#services[@]} -eq 0 ]]; then
+ echo "No loaded launchctl service matches ${service}"
+ return
+ fi
+ fi
+
+ local service_label
+ for service_label in "${services[@]}"; do
+ for should_sudo in "${booleans[@]}"; do
+ plist_status=$(launchctl list "${service_label}" 2>/dev/null)
+
+ if [[ $plist_status == \{* ]]; then
+ if [[ $should_sudo == "true" ]]; then
+ sudo launchctl remove "${service_label}"
+ else
+ launchctl remove "${service_label}"
+ fi
+ sleep 1
+ fi
+
+ paths=(
+ "/Library/LaunchAgents/${service_label}.plist"
+ "/Library/LaunchDaemons/${service_label}.plist"
+ )
+
+ # if not using sudo, prepend the home directory to the paths
+ if [[ $should_sudo == "false" ]]; then
+ for i in "${!paths[@]}"; do
+ paths[i]="${HOME}${paths[i]}"
+ done
+ fi
+
+ for path in "${paths[@]}"; do
+ if [[ -e "$path" ]]; then
+ if [[ $should_sudo == "true" ]]; then
+ sudo rm -f -- "$path"
+ else
+ rm -f -- "$path"
+ fi
+ fi
+ done
+ done
+ done
+}
+
trash() {
local logged_in_user="$1"
local target_file="$2"
@@ -52,10 +122,19 @@
fi
}
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAgent'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappAssistant'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappLauncher'
+remove_launchctl_service 'com.setapp.DesktopClient.SetappUpdater'
sudo rm -rf "$APPDIR/Setapp.app"
trash $LOGGED_IN_USER '~/Library/Application Scripts/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/Application Support/Setapp*'
trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient'
trash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient.SetappAgent'
+trash $LOGGED_IN_USER '~/Library/Containers/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.setapp.DesktopClient*'
+trash $LOGGED_IN_USER '~/Library/LaunchAgents/com.setapp.DesktopClient.*plist'
trash $LOGGED_IN_USER '~/Library/Logs/Setapp'
+trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.plist'
trash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.SetappAgent.plist'
trash $LOGGED_IN_USER '~/Library/Saved Application State/com.setapp.DesktopClient.savedState'ee/maintained-apps/outputs/snagit/darwin.json=== Install Script (no changes) ===
=== Uninstall // b52ff2b2 -> 59bfdeae ===
--- /tmp/old.af0emE 2026-07-22 22:08:28.031855875 +0000
+++ /tmp/new.YGk6sY 2026-07-22 22:08:28.031855875 +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"
@@ -52,9 +92,14 @@
fi
}
+quit_application 'com.TechSmith.Snagit'
sudo rm -rf "$APPDIR/Snagit.app"
+trash $LOGGED_IN_USER '~/Library/Application Scripts/7TQL462TU8.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/Application Support/com.apple.sharedfilelist/com.apple.LSSharedFileList.ApplicationRecentDocuments/com.techsmith.snagit.sfl*'
+trash $LOGGED_IN_USER '~/Library/Application Support/Snagit'
trash $LOGGED_IN_USER '~/Library/Caches/com.TechSmith.Snagit*'
trash $LOGGED_IN_USER '~/Library/Group Containers/*.com.techsmith.snagit'
+trash $LOGGED_IN_USER '~/Library/HTTPStorages/com.TechSmith.Snagit*'
trash $LOGGED_IN_USER '~/Library/Preferences/com.TechSmith.Snagit*.plist'
trash $LOGGED_IN_USER '~/Library/Preferences/com.techsmith.snagit.capturehelper*.plist'
trash $LOGGED_IN_USER '~/Library/Saved Application State/com.TechSmith.Snagit*.savedState'ee/maintained-apps/outputs/sourcetree/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/trezor-suite/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/typora/windows.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/visual-studio-code/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/vivaldi/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) ===ee/maintained-apps/outputs/wechat/darwin.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/workflowy/darwin.json=== Install Script (no changes) ===
=== Uninstall Script (no changes) === |
WalkthroughUpdated numerous Fleet-maintained app manifests for newer Windows and macOS releases. Changes synchronize version values, SQL patch-detection thresholds, installer URLs, and SHA-256 checksums. Most install and uninstall script references remain unchanged. PowerShell, Rider, Setapp, and Snagit also update version-specific uninstall references or script content. Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 Checkov (3.3.8)ee/maintained-apps/outputs/advanced-installer/windows.jsonTraceback (most recent call last): ee/maintained-apps/outputs/akiflow/darwin.jsonTraceback (most recent call last): ee/maintained-apps/outputs/aws-cli/windows.jsonTraceback (most recent call last):
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 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/rider/darwin.json`:
- Around line 19-20: Update the Rider uninstall script’s top-level cleanup flow
around the sudo rm -rf commands and trash calls to track each command’s exit
status and return a nonzero result when any removal fails. Do not let absent
targets mask failures; ensure the script reports failure if Rider or any cleanup
path could not be removed.
- Around line 19-20: Ensure uninstall cleanup failures cannot be masked by later
commands: in ee/maintained-apps/outputs/rider/darwin.json lines 19-20, validate
the Rider.app removal and exit 1 on failure, finishing successfully only after
required cleanup completes; apply the same explicit failure handling to
Setapp.app and launchd cleanup in ee/maintained-apps/outputs/setapp/darwin.json
lines 19-20, and Snagit.app removal and cleanup in
ee/maintained-apps/outputs/snagit/darwin.json lines 19-20.
In `@ee/maintained-apps/outputs/setapp/darwin.json`:
- Line 20: Update remove_launchctl_service to run unprivileged launchctl list
and remove operations in the logged-in user’s GUI domain via sudo launchctl
asuser using the UID derived from LOGGED_IN_USER, while retaining sudo
operations for system services. Replace HOME-based user plist paths with
explicit /Users/$LOGGED_IN_USER paths so the script targets the correct user
files.
In `@ee/maintained-apps/outputs/vivaldi/darwin.json`:
- Around line 9-12: Replace the "no_check" value in the Vivaldi artifact entry
with the actual SHA-256 checksum for Vivaldi.8.1.4087.56.universal.dmg,
preserving the existing installer_url and script references.
🪄 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: 91a26a44-abbb-4e4a-9c89-73e43ef9ebf9
📒 Files selected for processing (46)
ee/maintained-apps/outputs/advanced-installer/windows.jsonee/maintained-apps/outputs/akiflow/darwin.jsonee/maintained-apps/outputs/aws-cli/windows.jsonee/maintained-apps/outputs/beyond-compare/darwin.jsonee/maintained-apps/outputs/brave-browser/darwin.jsonee/maintained-apps/outputs/cleanmymac/darwin.jsonee/maintained-apps/outputs/clop/darwin.jsonee/maintained-apps/outputs/comet/windows.jsonee/maintained-apps/outputs/cursor/darwin.jsonee/maintained-apps/outputs/dataflare/darwin.jsonee/maintained-apps/outputs/dataflare/windows.jsonee/maintained-apps/outputs/firefox@developer-edition/darwin.jsonee/maintained-apps/outputs/firefox@nightly/darwin.jsonee/maintained-apps/outputs/granola/darwin.jsonee/maintained-apps/outputs/granola/windows.jsonee/maintained-apps/outputs/lookaway/darwin.jsonee/maintained-apps/outputs/loom/darwin.jsonee/maintained-apps/outputs/loom/windows.jsonee/maintained-apps/outputs/macwhisper/darwin.jsonee/maintained-apps/outputs/marsedit/darwin.jsonee/maintained-apps/outputs/megasync/windows.jsonee/maintained-apps/outputs/microsoft-teams/darwin.jsonee/maintained-apps/outputs/microsoft-teams/windows.jsonee/maintained-apps/outputs/mozilla-vpn/windows.jsonee/maintained-apps/outputs/nosql-workbench/darwin.jsonee/maintained-apps/outputs/nosql-workbench/windows.jsonee/maintained-apps/outputs/obs/darwin.jsonee/maintained-apps/outputs/only-switch/darwin.jsonee/maintained-apps/outputs/popclip/darwin.jsonee/maintained-apps/outputs/powerphotos/darwin.jsonee/maintained-apps/outputs/powershell/windows.jsonee/maintained-apps/outputs/prisma-browser/windows.jsonee/maintained-apps/outputs/pritunl/darwin.jsonee/maintained-apps/outputs/pritunl/windows.jsonee/maintained-apps/outputs/rider/darwin.jsonee/maintained-apps/outputs/rustrover/windows.jsonee/maintained-apps/outputs/setapp/darwin.jsonee/maintained-apps/outputs/snagit/darwin.jsonee/maintained-apps/outputs/sourcetree/darwin.jsonee/maintained-apps/outputs/trezor-suite/darwin.jsonee/maintained-apps/outputs/typora/windows.jsonee/maintained-apps/outputs/visual-studio-code/darwin.jsonee/maintained-apps/outputs/vivaldi/darwin.jsonee/maintained-apps/outputs/wechat/darwin.jsonee/maintained-apps/outputs/whatsapp/darwin.jsonee/maintained-apps/outputs/workflowy/darwin.json
| "22db20ac": "#!/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\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\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/Rider.app\"\nsudo rm -rf 'rider'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Rider2026.2'\ntrash $LOGGED_IN_USER '~/Library/Caches/Rider2026.2'\ntrash $LOGGED_IN_USER '~/Library/Logs/Rider2026.2'\ntrash $LOGGED_IN_USER '~/Library/Preferences/jetbrains.rider.71e559ef.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/Rider2026.2'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.jetbrains.rider.savedState'\n", | ||
| "b5794400": "#!/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.jetbrains.rider'\nif [ -d \"$APPDIR/Rider.app\" ]; then\n\tsudo mv \"$APPDIR/Rider.app\" \"$TMPDIR/Rider.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Rider.app\" \"$APPDIR\"\nrelaunch_application 'com.jetbrains.rider'\n" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Propagate uninstall failures instead of reporting success.
The privileged cleanup commands do not check their exit status, and subsequent trash calls can return 0 when targets are absent. A failed removal can therefore be reported as a successful uninstall, leaving Rider installed and causing inventory drift.
🤖 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/rider/darwin.json` around lines 19 - 20, Update
the Rider uninstall script’s top-level cleanup flow around the sudo rm -rf
commands and trash calls to track each command’s exit status and return a
nonzero result when any removal fails. Do not let absent targets mask failures;
ensure the script reports failure if Rider or any cleanup path could not be
removed.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Ensure uninstall scripts fail when cleanup fails.
Each script ignores privileged removal errors, allowing later no-op cleanup commands to mask the failure and report success.
ee/maintained-apps/outputs/rider/darwin.json#L19-L20: check theRider.appremoval and finish with an explicit success only after all required cleanup succeeds.ee/maintained-apps/outputs/setapp/darwin.json#L19-L20: checkSetapp.appand launchd cleanup statuses before returning success.ee/maintained-apps/outputs/snagit/darwin.json#L19-L20: checkSnagit.appremoval and cleanup statuses before returning success.
Use explicit if ! command; then exit 1; fi handling or an equivalent failure policy.
📍 Affects 3 files
ee/maintained-apps/outputs/rider/darwin.json#L19-L20(this comment)ee/maintained-apps/outputs/setapp/darwin.json#L19-L20ee/maintained-apps/outputs/snagit/darwin.json#L19-L20
🤖 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/rider/darwin.json` around lines 19 - 20, Ensure
uninstall cleanup failures cannot be masked by later commands: in
ee/maintained-apps/outputs/rider/darwin.json lines 19-20, validate the Rider.app
removal and exit 1 on failure, finishing successfully only after required
cleanup completes; apply the same explicit failure handling to Setapp.app and
launchd cleanup in ee/maintained-apps/outputs/setapp/darwin.json lines 19-20,
and Snagit.app removal and cleanup in
ee/maintained-apps/outputs/snagit/darwin.json lines 19-20.
| "refs": { | ||
| "1ba0fd31": "#!/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\nunzip \"$INSTALLER_PATH\" -d \"$TMPDIR\"\n# copy to the applications folder\nquit_and_track_application 'com.setapp.DesktopClient.SetappAgent'\nif [ -d \"$APPDIR/Setapp.app\" ]; then\n\tsudo mv \"$APPDIR/Setapp.app\" \"$TMPDIR/Setapp.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/Setapp.app\" \"$APPDIR\"\nrelaunch_application 'com.setapp.DesktopClient.SetappAgent'\n", | ||
| "e23bd29d": "#!/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\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\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/Setapp.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient.SetappAgent'\ntrash $LOGGED_IN_USER '~/Library/Logs/Setapp'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.SetappAgent.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.setapp.DesktopClient.savedState'\n" | ||
| "9ef05eb6": "#!/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 # A wildcard label can't be used with launchctl or as a plist name, so expand\n # it to the labels of currently loaded services that match the pattern.\n local services=(\"$service\")\n if [[ \"$service\" == *\"*\"* ]]; then\n local regex\n # Escape regex metacharacters, turn '*' into '.*', and anchor the pattern so\n # it matches a full label rather than a substring.\n regex=$(printf '%s' \"$service\" | sed -e 's/[][(){}.^$+?|\\\\]/\\\\&/g' -e 's/\\*/.*/g')\n regex=\"^${regex}$\"\n services=()\n local id\n # Match every loaded job by label regardless of PID; launchctl list reports\n # loaded-but-not-running jobs with a \"-\" in the PID column.\n while read -r _ _ id; do\n [[ \"$id\" =~ $regex ]] && services+=(\"$id\")\n done < <(launchctl list 2>/dev/null | tail -n +2)\n if [[ ${#services[@]} -eq 0 ]]; then\n echo \"No loaded launchctl service matches ${service}\"\n return\n fi\n fi\n\n local service_label\n for service_label in \"${services[@]}\"; do\n for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service_label}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service_label}\"\n else\n launchctl remove \"${service_label}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service_label}.plist\"\n \"/Library/LaunchDaemons/${service_label}.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 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\n # If the target contains glob characters, expand it and move each match.\n if [[ \"$target_file\" == *[*?[]* ]]; then\n local file file_name\n local matched=false\n local i=0\n # compgen -G expands the (quoted) pattern itself, so paths containing\n # spaces glob correctly; reading line by line keeps each match intact.\n while IFS= read -r file; do\n [[ -n \"$file\" ]] || continue\n [[ -e \"$file\" || -L \"$file\" ]] || continue\n matched=true\n i=$((i + 1))\n file_name=\"$(basename \"$file\")\"\n echo \"removing $file.\"\n # The per-match counter keeps matches that share a basename from\n # overwriting each other in the trash.\n mv -f \"$file\" \"$trash/${file_name}_${timestamp}_${rand}_${i}\"\n done < <(compgen -G \"$target_file\" 2>/dev/null)\n if [[ \"$matched\" == false ]]; then\n echo \"$target_file doesn't exist.\"\n fi\n return\n fi\n\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.setapp.DesktopClient.SetappAgent'\nremove_launchctl_service 'com.setapp.DesktopClient.SetappAssistant'\nremove_launchctl_service 'com.setapp.DesktopClient.SetappLauncher'\nremove_launchctl_service 'com.setapp.DesktopClient.SetappUpdater'\nsudo rm -rf \"$APPDIR/Setapp.app\"\ntrash $LOGGED_IN_USER '~/Library/Application Scripts/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'\ntrash $LOGGED_IN_USER '~/Library/Application Support/Setapp*'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient'\ntrash $LOGGED_IN_USER '~/Library/Caches/com.setapp.DesktopClient.SetappAgent'\ntrash $LOGGED_IN_USER '~/Library/Containers/com.setapp.DesktopClient.SetappAgent.FinderSyncExt'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.setapp.DesktopClient*'\ntrash $LOGGED_IN_USER '~/Library/LaunchAgents/com.setapp.DesktopClient.*plist'\ntrash $LOGGED_IN_USER '~/Library/Logs/Setapp'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.setapp.DesktopClient.SetappAgent.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.setapp.DesktopClient.savedState'\n" |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files =="
git ls-files | rg '(^|/)darwin\.json$|maintained-apps|setapp' || true
echo "== target file excerpt =="
if [ -f ee/maintained-apps/outputs/setapp/darwin.json ]; then
python3 - <<'PY'
import json
from pathlib import Path
p=Path('ee/maintained-apps/outputs/setapp/darwin.json')
data=json.loads(p.read_text())
items=data.get('content', {})
for k,v in list(items.items())[:3]:
print(f'--- {k} ---')
print(('\\\\n' if '\\n' in data.get('content',{}).get(k)[:5] else '\n').join(v.splitlines()[:180]))
PY
fi
echo "== launchctl references =="
rg -n "launchctl|LOGGED_IN_USER|bash|remove_launchctl_service" ee/maintained-apps/outputs/setapp/darwin.json . 2>/dev/null | head -200 || trueRepository: fleetdm/fleet
Length of output: 50370
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== repo files =="
git ls-files | rg '(^|/)darwin\.json$|maintained-apps|setapp' || true
echo "== target file excerpt =="
if [ -f ee/maintained-apps/outputs/setapp/darwin.json ]; then
python3 - <<'PY'
import json
from pathlib import Path
p=Path('ee/maintained-apps/outputs/setapp/darwin.json')
data=json.loads(p.read_text())
items=data.get('content', {})
for k,v in list(items.items())[:3]:
print(f'--- {k} ---')
print('\n'.join(v.splitlines()[:180]))
PY
fi
echo "== launchctl references =="
rg -n "launchctl|LOGGED_IN_USER|bash|remove_launchctl_service" ee/maintained-apps/outputs/setapp/darwin.json . 2>/dev/null | head -200 || trueRepository: fleetdm/fleet
Length of output: 50370
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== setapp output lines =="
python3 - <<'PY'
import json, re, pathlib
p=pathlib.Path('ee/maintained-apps/outputs/setapp/darwin.json')
data=json.loads(p.read_text())
content=data.get('content',{})
for k,v in content.items():
if 'Setapp' in v or 'launchctl' in v or k == '9ef05eb6':
print(f'--- {k} ({p}) ---')
for i, line in enumerate(v.splitlines(), 1):
if 18 <= i <= 150:
print(f'{i:04d}: {line}')
PY
echo "== setapp input if present =="
rg -n "Setapp|launchctl|uninstall|darwin|outputs|scripts" ee/maintained-apps/inputs/homebrew/setapp.json ee/maintained-apps/README.md cmd/maintained-apps 2>/dev/null | head -200 || trueRepository: fleetdm/fleet
Length of output: 8644
🌐 Web query:
Apple launchctl remove system domain user domain GUI sudo launchctl list bootstrap user session
💡 Result:
In modern macOS versions, the legacy load and unload commands have been superseded by bootstrap and bootout [1][2][3]. These commands interface with launchd to manage services within specific domain targets [4][5][1]. Domain Targets Services are managed within specific domains [1]. Key domains include: system: The system-wide domain for root daemons [6]. gui/: The domain for GUI sessions, created after a user logs in through the graphical interface [6]. user/: The background domain for user-level services, not tied to a GUI session [6]. Bootstrap and Bootout To add or remove services, use the bootstrap or bootout subcommands with the appropriate domain target [1][3]. Bootstrap: Loads a service into a domain [1][3]. Example (system-wide): sudo launchctl bootstrap system /Library/LaunchDaemons/service.plist [7]. Example (user-specific): sudo launchctl bootstrap gui/501 /Library/LaunchAgents/agent.plist [2][3]. Bootout: Removes/stops a service from a domain [1][3]. Example (system-wide): sudo launchctl bootout system/com.example.service [7]. Example (user-specific): sudo launchctl bootout gui/501 /Library/LaunchAgents/agent.plist [2][3]. Interacting with GUI User Sessions To execute commands within a specific user's GUI session (e.g., from a root context or an SSH session), launchctl asuser is the recommended approach [8][6]. Syntax: sudo launchctl asuser [8][6]. This directs the command into the target user's GUI session, which is necessary for actions requiring access to the Aqua/GUI environment (such as GUI apps, osascript, or clipboard access) [6]. If no user is logged into a GUI session, this command will fail for the gui/ domain [6]. Managing Services To list currently managed services, use launchctl list [4][1]. When running as root, this shows system-wide services [7]. To inspect services in a specific domain, use launchctl print [9][10]. Managing services in other domains often requires running as root to properly communicate with the primary instance of launchd or to target specific user namespaces [2][11].
Citations:
- 1: https://apple.stackexchange.com/questions/366281/launchd-confusion-on-semantics-of-bootstrap-and-bootout-etc-after-reading-manu
- 2: https://joelsenders.wordpress.com/2019/03/14/dear-launchctl-were-all-using-you-wrong/
- 3: https://ss64.com/mac/launchctl.html
- 4: https://manp.gs/mac/1/launchctl
- 5: https://www.manpagez.com/man/1/launchctl/
- 6: https://thekodelab.com/en/posts/macos-gui-terminal-vs-ssh-session/
- 7: https://gist.github.com/masklinn/a532dfe55bdeab3d60ab8e46ccc38a68?permalink_comment_id=6013953
- 8: https://apple.stackexchange.com/questions/100829/how-to-launch-a-gui-application-in-another-users-graphical-session
- 9: https://www.manpagez.com/man/1/launchctl/osx-10.10.php
- 10: https://newosxbook.com/articles/jlaunchctl.html
- 11: https://stackoverflow.com/questions/58212418/how-to-have-a-non-root-parent-process-spawn-a-root-child-process-under-macos-x
Run user launchctl operations in the logged-in user's domain.
When this script runs from a root/system context, the unprivileged launchctl calls use the system/root domain, not the GUI gui/<uid> session where Setapp agents are registered. Use sudo launchctl asuser "$(id -u "$LOGGED_IN_USER")" launchctl ... for list, print, and removal calls, and target the user files with explicit /Users/$LOGGED_IN_USER/... paths.
🤖 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/setapp/darwin.json` at line 20, Update
remove_launchctl_service to run unprivileged launchctl list and remove
operations in the logged-in user’s GUI domain via sudo launchctl asuser using
the UID derived from LOGGED_IN_USER, while retaining sudo operations for system
services. Replace HOME-based user plist paths with explicit
/Users/$LOGGED_IN_USER paths so the script targets the correct user files.
| "installer_url": "https://downloads.vivaldi.com/stable/Vivaldi.8.1.4087.56.universal.dmg", | ||
| "install_script_ref": "6a60dca7", | ||
| "uninstall_script_ref": "7c1876ca", | ||
| "sha256": "no_check", |
There was a problem hiding this comment.
🔒 Security & Privacy | 🟠 Major | ⚡ Quick win
Add a checksum for the updated Vivaldi artifact.
Line 9 now points to a version-specific DMG, but Line 12 remains sha256: "no_check". This release can therefore be installed without verifying that the downloaded bytes match the generated metadata. Store the SHA-256 for Vivaldi.8.1.4087.56.universal.dmg before shipping.
🤖 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/vivaldi/darwin.json` around lines 9 - 12, Replace
the "no_check" value in the Vivaldi artifact entry with the actual SHA-256
checksum for Vivaldi.8.1.4087.56.universal.dmg, preserving the existing
installer_url and script references.
|
Closing in favor of #49797. |
Automated ingestion of latest Fleet-maintained app data.
Summary by CodeRabbit