-
Notifications
You must be signed in to change notification settings - Fork 980
Update Docker Desktop FMA install script #45244
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
5aee821
45585b1
90bfff8
136abf1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,122 @@ | ||
| #!/bin/bash | ||
|
|
||
| # variables | ||
| APPDIR="/Applications/" | ||
| TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")") | ||
| # functions | ||
|
|
||
| quit_and_track_application() { | ||
| local bundle_id="$1" | ||
| local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')" | ||
| local timeout_duration=10 | ||
|
|
||
| # check if the application is running | ||
| local app_running | ||
| app_running=$(osascript -e "application id \"$bundle_id\" is running" 2>/dev/null) | ||
| if [[ "$app_running" != "true" ]]; then | ||
| eval "export $var_name=0" | ||
| return | ||
| fi | ||
|
|
||
| local console_user | ||
| console_user=$(stat -f "%Su" /dev/console) | ||
| if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then | ||
| echo "Not logged into a non-root GUI; skipping quitting application ID '$bundle_id'." | ||
| eval "export $var_name=0" | ||
| return | ||
| fi | ||
|
|
||
| # App was running, mark it for relaunch | ||
| eval "export $var_name=1" | ||
| echo "Application '$bundle_id' was running; will relaunch after installation." | ||
|
|
||
| echo "Quitting application '$bundle_id'..." | ||
|
|
||
| # try to quit the application within the timeout period | ||
| 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 | ||
|
Comment on lines
+49
to
+51
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# First, let's locate and read the file
find . -name "docker_desktop_install.sh" -type fRepository: fleetdm/fleet Length of output: 128 🏁 Script executed: #!/bin/bash
# Read the file to examine the context
cat -n ./ee/maintained-apps/inputs/homebrew/scripts/docker_desktop_install.shRepository: fleetdm/fleet Length of output: 5610 🏁 Script executed: #!/bin/bash
# Check for error handling flags (set -e) and confirm the function behavior
head -20 ./ee/maintained-apps/inputs/homebrew/scripts/docker_desktop_install.shRepository: fleetdm/fleet Length of output: 557 Abort install when Docker Desktop does not quit. If Docker Desktop continues running when the script attempts to replace its app bundle, the installation will proceed anyway, risking file locks, permission errors, or a corrupted/partially updated installation. Add error handling to stop the script if quit fails: Proposed fix if [[ "$quit_success" = false ]]; then
echo "Application '$bundle_id' did not quit."
+ return 1
fi
}
...
-quit_and_track_application 'com.electron.dockerdesktop'
+quit_and_track_application 'com.electron.dockerdesktop' || {
+ echo "Aborting install because Docker Desktop is still running."
+ exit 1
+}Also applies to: line 103 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
|
|
||
| relaunch_application() { | ||
| local bundle_id="$1" | ||
| local var_name="APP_WAS_RUNNING_$(echo "$bundle_id" | tr '.-' '__')" | ||
| local was_running | ||
|
|
||
| # Check if the app was running before installation | ||
| eval "was_running=\$$var_name" | ||
| if [[ "$was_running" != "1" ]]; then | ||
| return | ||
| fi | ||
|
|
||
| local console_user | ||
| console_user=$(stat -f "%Su" /dev/console) | ||
| if [[ -z "$console_user" || "$console_user" == "root" || "$console_user" == "loginwindow" ]]; then | ||
| echo "Not logged into a non-root GUI; skipping relaunching application ID '$bundle_id'." | ||
| return | ||
| fi | ||
|
|
||
| echo "Relaunching application '$bundle_id'..." | ||
|
|
||
| # Launch the app in the logged-in user's GUI session. Apps launched by root | ||
| # won't register with the user's Dock/GUI, so run 'open' as the console user. | ||
| # Use 'launchctl asuser' to bootstrap into the console user's Mach namespace | ||
| # and GUI session — 'sudo -u' alone doesn't do this, which can cause | ||
| # LSOpenURLsWithRole() failures even when 'open' exits 0. | ||
| local open_status=0 | ||
| if [[ $EUID -eq 0 ]]; then | ||
| local console_uid | ||
| console_uid=$(id -u "$console_user") | ||
| /bin/launchctl asuser "$console_uid" sudo -u "$console_user" open -b "$bundle_id" >/dev/null 2>&1 || open_status=$? | ||
| else | ||
| open -b "$bundle_id" >/dev/null 2>&1 || open_status=$? | ||
| fi | ||
|
|
||
| if [[ $open_status -eq 0 ]]; then | ||
| echo "Application '$bundle_id' relaunched successfully." | ||
| else | ||
| echo "Failed to relaunch application '$bundle_id'." | ||
| fi | ||
| } | ||
|
|
||
|
|
||
| # extract contents | ||
| MOUNT_POINT=$(mktemp -d /tmp/dmg_mount_XXXXXX) | ||
| hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" | ||
| sudo cp -R "$MOUNT_POINT"/* "$TMPDIR" | ||
| hdiutil detach "$MOUNT_POINT" | ||
| # copy to the applications folder | ||
| quit_and_track_application 'com.electron.dockerdesktop' | ||
| if [ -d "$APPDIR/Docker.app" ]; then | ||
| sudo mv "$APPDIR/Docker.app" "$TMPDIR/Docker.app.bkp" | ||
| fi | ||
| # Docker Desktop's own in-app updater leaves a Docker.app.back bundle alongside | ||
| # Docker.app when it self-updates. osquery's apps table still picks up the | ||
| # stale bundle by its bundle_identifier, which causes Fleet patch policies to | ||
| # report Docker as out of date even after a successful upgrade. | ||
| sudo rm -rf "$APPDIR/Docker.app.back" | ||
| sudo cp -R "$TMPDIR/Docker.app" "$APPDIR" | ||
| relaunch_application 'com.electron.dockerdesktop' | ||
| mkdir -p /usr/local/cli-plugins | ||
| /bin/ln -h -f -s -- "$APPDIR/Docker.app/Contents/Resources/cli-plugins/docker-compose" "/usr/local/cli-plugins/docker-compose" | ||
| mkdir -p /usr/local/bin | ||
| /bin/ln -h -f -s -- "$APPDIR/Docker.app/Contents/Resources/bin/hub-tool" "/usr/local/bin/hub-tool" | ||
| /bin/ln -h -f -s -- "$APPDIR/Docker.app/Contents/Resources/bin/kubectl" "/usr/local/bin/kubectl.docker" | ||
| /bin/ln -h -f -s -- "$APPDIR/Docker.app/Contents/Resources/bin/docker" "/usr/local/bin/docker" | ||
| /bin/ln -h -f -s -- "$APPDIR/Docker.app/Contents/Resources/bin/docker-credential-desktop" "/usr/local/bin/docker-credential-desktop" | ||
| /bin/ln -h -f -s -- "$APPDIR/Docker.app/Contents/Resources/bin/docker-credential-ecr-login" "/usr/local/bin/docker-credential-ecr-login" | ||
| /bin/ln -h -f -s -- "$APPDIR/Docker.app/Contents/Resources/bin/docker-credential-osxkeychain" "/usr/local/bin/docker-credential-osxkeychain" | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: fleetdm/fleet
Length of output: 4756
Fail fast on DMG operations and always detach mounts.
The script lacks
set -eand cleanup mechanisms, allowing it to proceed whenhdiutil attach,sudo cp, orhdiutil detachfail. This can leave a partial install or a mounted DMG. Additionally,quit_and_track_application()logs quit failures but doesn't stop execution, risking copy/install failures if Docker is still running.Add
set -euo pipefailat the start, initializeMOUNT_POINT=""before use, and add a cleanup trap to ensure detach runs on exit:Proposed hardening
📝 Committable suggestion
🤖 Prompt for AI Agents