Add IBM Notifier as a macOS FMA - #47054
Conversation
Register IBM Notifier in maintained apps and add frontend assets. Adds a homebrew input (ibm-notifier.json), a new apps output entry, and darwin metadata (version 3.2.3) including installer URL, sha256, and install/uninstall script refs. Also adds a frontend SVG icon component, the PNG app icon asset, and registers "ibm notifier" in the icon map. Default category set to "Developer tools."
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #47054 +/- ##
==========================================
- Coverage 67.03% 67.03% -0.01%
==========================================
Files 2885 2886 +1
Lines 225153 225155 +2
Branches 11780 11779 -1
==========================================
+ Hits 150941 150942 +1
- Misses 60540 60542 +2
+ Partials 13672 13671 -1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 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.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (5)
WalkthroughThis PR adds complete IBM Notifier support to Fleet's maintained-apps system on macOS. It defines installer and uninstaller scripts that handle graceful app quitting with timeout logic, bundle backup and restoration, and user-data cleanup with collision-resistant trash naming. The app is registered in the Homebrew input metadata and central apps registry. A new React SVG icon component is created and wired into the SoftwarePage icon resolution map. Possibly related PRs
✨ 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.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds support for IBM Notifier across the maintained-apps catalog and the Software page icon set.
Changes:
- Adds a new IBM Notifier icon component and wires it into the software-name → icon map.
- Introduces maintained-app metadata for IBM Notifier (Homebrew input, generated darwin output, and apps catalog entry).
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/pages/SoftwarePage/components/icons/index.ts | Registers the IBM Notifier icon and maps the software name to it. |
| frontend/pages/SoftwarePage/components/icons/IbmNotifier.tsx | Adds the IBM Notifier icon component (embedded base64 PNG in an SVG wrapper). |
| ee/maintained-apps/outputs/ibm-notifier/darwin.json | Adds macOS installer/uninstaller definitions and SQL queries for IBM Notifier. |
| ee/maintained-apps/outputs/apps.json | Adds IBM Notifier to the generated app catalog. |
| ee/maintained-apps/inputs/homebrew/ibm-notifier.json | Adds Homebrew input metadata for IBM Notifier. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const IbmNotifier = (props: SVGProps<SVGSVGElement>) => ( | ||
| <svg xmlns="http://www.w3.org/2000/svg" width={32} height={32} {...props}> | ||
| <image | ||
| width={32} | ||
| height={32} | ||
| href="data:image/png;base64,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" | ||
| /> |
| } | ||
| ], | ||
| "refs": { | ||
| "b440ccc8": "#!/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.ibm.cio.notifier'\nif [ -d \"$APPDIR/IBM Notifier.app\" ]; then\n\tsudo mv \"$APPDIR/IBM Notifier.app\" \"$TMPDIR/IBM Notifier.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/IBM Notifier.app\" \"$APPDIR\"\nrelaunch_application 'com.ibm.cio.notifier'\n", |
| } | ||
| ], | ||
| "refs": { | ||
| "b440ccc8": "#!/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.ibm.cio.notifier'\nif [ -d \"$APPDIR/IBM Notifier.app\" ]; then\n\tsudo mv \"$APPDIR/IBM Notifier.app\" \"$TMPDIR/IBM Notifier.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/IBM Notifier.app\" \"$APPDIR\"\nrelaunch_application 'com.ibm.cio.notifier'\n", |
| ], | ||
| "refs": { | ||
| "b440ccc8": "#!/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.ibm.cio.notifier'\nif [ -d \"$APPDIR/IBM Notifier.app\" ]; then\n\tsudo mv \"$APPDIR/IBM Notifier.app\" \"$TMPDIR/IBM Notifier.app.bkp\"\nfi\nsudo cp -R \"$TMPDIR/IBM Notifier.app\" \"$APPDIR\"\nrelaunch_application 'com.ibm.cio.notifier'\n", | ||
| "d7bfc531": "#!/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/IBM Notifier.app\"\ntrash $LOGGED_IN_USER '~/Library/Caches/com.ibm.cio.notifier'\ntrash $LOGGED_IN_USER '~/Library/HTTPStorages/com.ibm.cio.notifier'\ntrash $LOGGED_IN_USER '~/Library/Preferences/com.ibm.cio.notifier.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/com.ibm.cio.notifier.savedState'\n" |
Register IBM Notifier in maintained apps and add frontend assets. Adds a homebrew input (ibm-notifier.json), a new apps output entry, and darwin metadata (version 3.2.3) including installer URL, sha256, and install/uninstall script refs. Also adds a frontend SVG icon component, the PNG app icon asset, and registers "ibm notifier" in the icon map. Default category set to "Developer tools."
Summary by CodeRabbit
Release Notes