Skip to content

Update Fleet-maintained apps - #49796

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

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

Conversation

@fleet-release

@fleet-release fleet-release commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Automated ingestion of latest Fleet-maintained app data.

Summary by CodeRabbit

  • New Features
    • Added the latest available releases for numerous maintained macOS and Windows applications, including Advanced Installer, AWS CLI, Firefox, Microsoft Teams, PowerShell, Rider, RustRover, and Visual Studio Code.
    • Updated download links and integrity verification for the new installers.
    • Improved removal handling for select applications, including Rider, Setapp, and Snagit.
  • Bug Fixes
    • Updated version detection so outdated installations are correctly identified and upgraded.

Generated automatically with cmd/maintained-apps.
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/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 upload

ee/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) ===

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Updated 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)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is too generic and omits the required issue reference, checklist items, testing, and other template sections. Fill out the template with the related issue and the required checklist, testing, database migration, and Fleet configuration details.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately summarizes the automated update of Fleet-maintained app data.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fma-2607222202

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

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

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

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

ee/maintained-apps/outputs/aws-cli/windows.json

Traceback (most recent call last):
File "/usr/local/bin/checkov", line 2, in
from checkov.main import Checkov
ModuleNotFoundError: No module named 'checkov'

  • 43 others

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.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 3699950 and ef450fe.

📒 Files selected for processing (46)
  • ee/maintained-apps/outputs/advanced-installer/windows.json
  • ee/maintained-apps/outputs/akiflow/darwin.json
  • ee/maintained-apps/outputs/aws-cli/windows.json
  • ee/maintained-apps/outputs/beyond-compare/darwin.json
  • ee/maintained-apps/outputs/brave-browser/darwin.json
  • ee/maintained-apps/outputs/cleanmymac/darwin.json
  • ee/maintained-apps/outputs/clop/darwin.json
  • ee/maintained-apps/outputs/comet/windows.json
  • ee/maintained-apps/outputs/cursor/darwin.json
  • ee/maintained-apps/outputs/dataflare/darwin.json
  • ee/maintained-apps/outputs/dataflare/windows.json
  • ee/maintained-apps/outputs/firefox@developer-edition/darwin.json
  • ee/maintained-apps/outputs/firefox@nightly/darwin.json
  • ee/maintained-apps/outputs/granola/darwin.json
  • ee/maintained-apps/outputs/granola/windows.json
  • ee/maintained-apps/outputs/lookaway/darwin.json
  • ee/maintained-apps/outputs/loom/darwin.json
  • ee/maintained-apps/outputs/loom/windows.json
  • ee/maintained-apps/outputs/macwhisper/darwin.json
  • ee/maintained-apps/outputs/marsedit/darwin.json
  • ee/maintained-apps/outputs/megasync/windows.json
  • ee/maintained-apps/outputs/microsoft-teams/darwin.json
  • ee/maintained-apps/outputs/microsoft-teams/windows.json
  • ee/maintained-apps/outputs/mozilla-vpn/windows.json
  • ee/maintained-apps/outputs/nosql-workbench/darwin.json
  • ee/maintained-apps/outputs/nosql-workbench/windows.json
  • ee/maintained-apps/outputs/obs/darwin.json
  • ee/maintained-apps/outputs/only-switch/darwin.json
  • ee/maintained-apps/outputs/popclip/darwin.json
  • ee/maintained-apps/outputs/powerphotos/darwin.json
  • ee/maintained-apps/outputs/powershell/windows.json
  • ee/maintained-apps/outputs/prisma-browser/windows.json
  • ee/maintained-apps/outputs/pritunl/darwin.json
  • ee/maintained-apps/outputs/pritunl/windows.json
  • ee/maintained-apps/outputs/rider/darwin.json
  • ee/maintained-apps/outputs/rustrover/windows.json
  • ee/maintained-apps/outputs/setapp/darwin.json
  • ee/maintained-apps/outputs/snagit/darwin.json
  • ee/maintained-apps/outputs/sourcetree/darwin.json
  • ee/maintained-apps/outputs/trezor-suite/darwin.json
  • ee/maintained-apps/outputs/typora/windows.json
  • ee/maintained-apps/outputs/visual-studio-code/darwin.json
  • ee/maintained-apps/outputs/vivaldi/darwin.json
  • ee/maintained-apps/outputs/wechat/darwin.json
  • ee/maintained-apps/outputs/whatsapp/darwin.json
  • ee/maintained-apps/outputs/workflowy/darwin.json

Comment on lines +19 to +20
"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"

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.

🎯 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 the Rider.app removal and finish with an explicit success only after all required cleanup succeeds.
  • ee/maintained-apps/outputs/setapp/darwin.json#L19-L20: check Setapp.app and launchd cleanup statuses before returning success.
  • ee/maintained-apps/outputs/snagit/darwin.json#L19-L20: check Snagit.app removal 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-L20
  • ee/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"

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.

🩺 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 || true

Repository: 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 || true

Repository: 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 || true

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


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.

Comment on lines +9 to 12
"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",

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.

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

@github-actions

Copy link
Copy Markdown
Contributor

Closing in favor of #49797.

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