Relaunch apps via open as console user - #43842
Conversation
Ensure GUI apps are relaunched in the logged-in user's session instead of root. Update relaunch_application to skip when no non-root GUI user is present (empty/"root"/"loginwindow"), and use `sudo -u "$console_user" open -b <bundle_id>` when the installer runs as root so the app appears in the user's Dock/GUI. Remove the previous osascript activation attempt and add status handling and explanatory comments.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #43842 +/- ##
==========================================
- Coverage 66.92% 66.92% -0.01%
==========================================
Files 2603 2603
Lines 209044 209073 +29
Branches 9235 9235
==========================================
+ Hits 139905 139913 +8
- Misses 56392 56413 +21
Partials 12747 12747
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.
Tip: disable this comment in your organization's Code Review settings.
WalkthroughThe embedded shell functions in the Homebrew ingester were updated. The 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@ee/maintained-apps/ingesters/homebrew/scripts.go`:
- Around line 649-656: Replace the direct sudo -u "$console_user" open -b
"$bundle_id" call with the same launchctl asuser pattern used in send_signal so
the open runs inside the console user's Mach/GU I namespace; specifically, when
EUID is 0 invoke /bin/launchctl asuser "$console_uid" sudo -u "$console_user"
open -b "$bundle_id" (preserving the >/dev/null 2>&1 || open_status=$? handling
and the open_status variable), otherwise keep the non-root open path unchanged;
reference the existing send_signal use of /bin/launchctl asuser to mirror its
context-bootstrapping approach.
🪄 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: ab8a3fe6-3f00-475a-adfd-ed470012d327
📒 Files selected for processing (1)
ee/maintained-apps/ingesters/homebrew/scripts.go
There was a problem hiding this comment.
Pull request overview
Updates the Homebrew install-script generator so previously-running GUI apps are relaunched in the logged-in user’s session (rather than root), improving Dock/GUI visibility and reliability when installers run as root.
Changes:
- Add explanatory comments describing why relaunch must happen in the console user’s GUI session.
- Update
relaunch_applicationto skip relaunch when no non-root GUI user is present (empty/root/loginwindow). - Replace
osascript ... activaterelaunching withopen -b, usingsudo -u "$console_user"when running as root and capturing exit status.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
ee/maintained-apps/ingesters/homebrew/scripts.go (1)
663-667:⚠️ Potential issue | 🟡 Minor
open -bexit status is not a strong signal of successful GUI relaunch.
/usr/bin/opencan return 0 even whenLSOpenURLsWithRole()ultimately fails to surface the app in the Dock (e.g., stale Launch Services cache, bundle not yet re-registered after the move/install), and can return non-zero transiently right after a fresh install when the new bundle hasn't been indexed. Consider either (a) pollingpgrep -f "$bundle_id"for a few seconds afteropenas a liveness check (mirroring the quit loop), or (b) softening the failure message to something like "relaunch requested" to avoid misleading log output. Not blocking — just flagging that the success/failure log may not always reflect reality.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ee/maintained-apps/ingesters/homebrew/scripts.go` around lines 663 - 667, The current check uses open_status from the `open -b` call to declare success/failure for relaunching `bundle_id`, which can be unreliable; update the relaunch logic in the block that inspects `open_status` to either (a) poll for the process after calling `open` by running `pgrep -f "$bundle_id"` in a short loop for a few seconds (mirror the quit loop behavior) and treat presence as the true success signal, or (b) change the echoed failure message around `bundle_id` to a non-definitive string like "relaunch requested" so we don't claim a successful GUI relaunch based solely on `open_status`; modify the code around the `open_status` check and echo statements to implement one of these approaches.
🧹 Nitpick comments (1)
ee/maintained-apps/ingesters/homebrew/scripts.go (1)
654-661: Guard against emptyconsole_uidbefore invokinglaunchctl asuser.If
id -u "$console_user"fails (e.g., directory service hiccup, user removed between checks),console_uidwill be empty and the call becomes/bin/launchctl asuser "" sudo -u "$console_user" open -b "$bundle_id", which will emit a confusinglaunchctlerror rather than the intended "Failed to relaunch" message. The upstream non-empty check onconsole_userdoesn't coveridfailure.🛡️ Suggested hardening
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=$? + if [[ -z "$console_uid" ]]; then + echo "Could not resolve UID for console user '$console_user'; skipping relaunch." + return + fi + /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🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ee/maintained-apps/ingesters/homebrew/scripts.go` around lines 654 - 661, The call to `/bin/launchctl asuser` can receive an empty `console_uid` if `id -u "$console_user"` fails; update the block that computes `console_uid` and invokes `/bin/launchctl asuser` to validate `console_uid` is non-empty (and preferably numeric) before using it. If `console_uid` is empty/invalid, avoid calling `launchctl asuser` and instead set `open_status` to a failure value (or fall back to the non-root `open -b "$bundle_id"` path) and emit the existing "Failed to relaunch" handling so a clear error is produced; refer to the `console_uid`, `console_user`, and `/bin/launchctl asuser` usage in this section when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Outside diff comments:
In `@ee/maintained-apps/ingesters/homebrew/scripts.go`:
- Around line 663-667: The current check uses open_status from the `open -b`
call to declare success/failure for relaunching `bundle_id`, which can be
unreliable; update the relaunch logic in the block that inspects `open_status`
to either (a) poll for the process after calling `open` by running `pgrep -f
"$bundle_id"` in a short loop for a few seconds (mirror the quit loop behavior)
and treat presence as the true success signal, or (b) change the echoed failure
message around `bundle_id` to a non-definitive string like "relaunch requested"
so we don't claim a successful GUI relaunch based solely on `open_status`;
modify the code around the `open_status` check and echo statements to implement
one of these approaches.
---
Nitpick comments:
In `@ee/maintained-apps/ingesters/homebrew/scripts.go`:
- Around line 654-661: The call to `/bin/launchctl asuser` can receive an empty
`console_uid` if `id -u "$console_user"` fails; update the block that computes
`console_uid` and invokes `/bin/launchctl asuser` to validate `console_uid` is
non-empty (and preferably numeric) before using it. If `console_uid` is
empty/invalid, avoid calling `launchctl asuser` and instead set `open_status` to
a failure value (or fall back to the non-root `open -b "$bundle_id"` path) and
emit the existing "Failed to relaunch" handling so a clear error is produced;
refer to the `console_uid`, `console_user`, and `/bin/launchctl asuser` usage in
this section when making the change.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8ce7520b-d65c-47bf-90af-484e3a00b355
📒 Files selected for processing (1)
ee/maintained-apps/ingesters/homebrew/scripts.go
…pers (#48639) The custom install script embedded pre-#42951/#43842 copies of quit_and_track_application and relaunch_application. The stale 'if ! osascript' check treats any non-erroring osascript call as "app is running" (osascript exits 0 whether it prints true or false), so the app was marked for relaunch on every install and launched after every patch, even from a fully-quit state. Replace both functions with the current scripts.go constants (output-based running check, launchctl-asuser relaunch, updated console-user guards) and regenerate the darwin manifest.
…pers (#49030) **Related issue:** Resolves #48639 # Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] QA'd all new/changed functionality manually ## Details The GitHub Desktop FMA uses a custom install script (`ee/maintained-apps/inputs/homebrew/scripts/github-desktop-install.sh`) that embeds its own copies of `quit_and_track_application` and `relaunch_application`. Those copies were frozen before two fixes landed in the generated helpers in `ee/maintained-apps/ingesters/homebrew/scripts.go`: - #42951 — check osascript **output** instead of exit status. `osascript -e '... is running'` exits 0 whether it prints `true` or `false`, so the stale `if ! osascript ...` guard never fired. The app was marked `APP_WAS_RUNNING=1` on **every** install with a GUI user logged in and relaunched after every patch — even from a fully-quit state. This is the root cause of #48639. - #43842 — relaunch via `launchctl asuser ... open -b` as the console user instead of `osascript ... to activate` (which is unreliable from a root context), plus the updated empty/root/loginwindow console-user guards. This PR replaces both embedded functions with the current scripts.go constants (verified byte-for-byte identical) and regenerates `ee/maintained-apps/outputs/github/darwin.json` via `go run ./cmd/maintained-apps -slug github`. The manifest diff is script-ref-only (`98ab6ed8` → `c91ea2b5`); version and uninstall script are unchanged. The other five custom scripts (Docker Desktop, OpenVPN Connect, Webex, Max, Pd) already carry the updated helpers — GitHub Desktop was the only one missed. ## Manual QA Tested the updated `quit_and_track_application` / `relaunch_application` functions on macOS against GitHub Desktop itself (`com.github.GitHubClient`): - **Fully quit (the bug scenario):** verified `is running` returns `false` and zero `GitHub Desktop.app` processes. Fixed functions set `APP_WAS_RUNNING=0` and the app stays closed. Running the old shipped check (`if ! osascript ...`) against the same state misclassifies the app as running (osascript exits 0 with output `false`) and would have relaunched it. - **Running:** quit succeeds, `APP_WAS_RUNNING=1`, app relaunches successfully afterward. - `bash -n` passes on the updated script. Note: hosts where the FMA was already added keep the baked `98ab6ed8` script until their instance refreshes the manifest. The by-design behavior "app running with dock icon but no visible window → relaunched with a window" is unchanged; window-aware relaunching would be a separate enhancement. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Bug Fixes** * Improved GitHub Desktop installation behavior on macOS so the app is more reliably closed and reopened after install. * Better handles login/session edge cases, helping ensure the app relaunches in the correct user’s desktop session. * Reduces failed or missed relaunches when the installer is run with elevated permissions. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This pull request updates the application quit and relaunch logic in the Homebrew ingester scripts to more robustly detect valid GUI user sessions and improve how applications are relaunched after installation. The main improvements ensure that actions are only attempted when a real user is logged in, and that relaunching applications works reliably in the correct user context, especially when running as root.
User session validation:
quit_application,quit_and_track_application, andrelaunch_applicationhave been expanded to skip actions if the console user is empty,root, orloginwindow, preventing attempts to interact with the GUI when no real user is logged in. [1] [2] [3]Application relaunch improvements:
relaunch_applicationlogic now useslaunchctl asuserwithsudo -uto launch the application in the correct user's GUI session, ensuring that the app appears in the user's Dock and GUI, even when the script runs as root. This replaces the previous approach of usingosascript, which could fail in root contexts. [1] [2]Summary by CodeRabbit