Add OpenVPN Connect as a macOS FMA - #45174
Conversation
Add OpenVPN Connect to maintained apps: create a Homebrew input manifest and add an apps.json entry. Add a darwin output with version 3.8.1 (installer URL, sha256) plus install/uninstall script refs that handle quitting/relaunching and cleanup. Add frontend icon component and register it in the icon map, and include the app icon asset. Default category set to Productivity.
Script Diff Resultsee/maintained-apps/inputs/homebrew/openvpn-connect.jsonERROR: Could not retrieve previous version of file (file may not exist in previous commit)ee/maintained-apps/outputs/openvpn-connect/darwin.jsonERROR: Could not retrieve previous version of file (file may not exist in previous commit) |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #45174 +/- ##
=======================================
Coverage 66.80% 66.81%
=======================================
Files 2722 2724 +2
Lines 219000 219021 +21
Branches 10627 10627
=======================================
+ Hits 146305 146329 +24
+ Misses 59529 59526 -3
Partials 13166 13166
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:
|
Script Diff Resultsee/maintained-apps/inputs/homebrew/openvpn-connect.jsonERROR: Could not retrieve previous version of file (file may not exist in previous commit)ee/maintained-apps/outputs/openvpn-connect/darwin.jsonERROR: Could not retrieve previous version of file (file may not exist in previous commit) |
The auto-generated dmg+pkg install script hard-coded the arm64 pkg path and didn't account for OpenVPN Connect 3.8+ installing into a wrapper directory (/Applications/OpenVPN Connect/OpenVPN Connect.app) instead of placing the .app directly under /Applications/. osquery's `apps` table only directory-scans the top level of /Applications/ and otherwise relies on LaunchServices to find nested apps, so the freshly installed app wasn't discovered by `bundle_identifier = 'org.openvpn.client.app'`. Add a custom install script that more closely replicates Homebrew's pkg install: mount the DMG, glob for the arm64 pkg from the mount point (handling the parentheses in the file name), run the installer, and force LaunchServices to register the resulting .app so osquery picks it up immediately. Wire the script in via install_script_path on the homebrew input and regenerate the darwin output.
…m/fleetdm/fleet into allenhouchins-add-openvpn-connect
Script Diff Resultsee/maintained-apps/outputs/openvpn-connect/darwin.json=== Install // 66c63c32 -> c8881523 ===
--- /tmp/old.KmUkPO 2026-05-12 02:13:02.022737935 +0000
+++ /tmp/new.yIGvNR 2026-05-12 02:13:02.022737935 +0000
@@ -1,16 +1,41 @@
#!/bin/bash
-# variables
-APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-# functions
+# Custom install script for OpenVPN Connect on macOS.
+#
+# The Homebrew cask "openvpn-connect" downloads a .dmg that contains both
+# x86_64 and arm64 .pkg installers at the root of the mounted volume:
+#
+# OpenVPN_Connect_<ver>(<build>)_x86_64_Installer_signed.pkg
+# OpenVPN_Connect_<ver>(<build>)_arm64_Installer_signed.pkg
+#
+# We only ship FMAs for Apple Silicon (arm64) on macOS, so this script:
+# 1. Mounts the DMG.
+# 2. Locates the arm64 .pkg via a glob (parentheses in the file name make
+# hard-coding the path brittle across versions).
+# 3. Quits the app if it's running and tracks state for relaunch.
+# 4. Runs `installer -pkg ... -target /` against the mounted pkg, which is
+# the same operation Homebrew performs for `pkg "..."` artifacts.
+# 5. Detaches the DMG.
+# 6. Forces LaunchServices to register the installed .app bundle.
+#
+# The LaunchServices step is required because OpenVPN Connect 3.8+ installs
+# into a wrapper directory (/Applications/OpenVPN Connect/OpenVPN Connect.app)
+# rather than placing the .app directly under /Applications/. osquery's `apps`
+# table only directory-scans the top level of /Applications/ and otherwise
+# relies on LaunchServices to discover nested apps; without an explicit
+# `lsregister` the freshly installed app may not show up immediately.
+
+set -u
+
+APPDIR="/Applications"
+BUNDLE_ID="org.openvpn.client.app"
+LSREGISTER="/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister"
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
@@ -26,13 +51,11 @@
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
@@ -51,13 +74,11 @@
fi
}
-
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
@@ -72,11 +93,6 @@
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
@@ -93,13 +109,70 @@
fi
}
+if [ -z "${INSTALLER_PATH:-}" ] || [ ! -f "$INSTALLER_PATH" ]; then
+ echo "Missing or invalid INSTALLER_PATH"
+ exit 1
+fi
+
+MOUNT_POINT=$(mktemp -d /tmp/openvpn_connect_dmg.XXXXXX)
+cleanup() {
+ hdiutil detach "$MOUNT_POINT" >/dev/null 2>&1 || true
+ rmdir "$MOUNT_POINT" >/dev/null 2>&1 || true
+}
+trap cleanup EXIT
+
+if ! hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" >/dev/null; then
+ echo "Failed to mount DMG at $INSTALLER_PATH"
+ exit 1
+fi
+
+# Locate the arm64 installer pkg. We only support Apple Silicon for this FMA,
+# so deliberately skip the x86_64 pkg shipped in the same DMG. Use a glob so
+# parentheses and version/build numbers in the file name don't have to be
+# hard-coded here.
+PKG=""
+for candidate in "$MOUNT_POINT"/*_arm64_Installer_signed.pkg; do
+ if [ -e "$candidate" ]; then
+ PKG="$candidate"
+ break
+ fi
+done
+
+if [ -z "$PKG" ] || [ ! -e "$PKG" ]; then
+ echo "Could not find an arm64 OpenVPN Connect installer pkg in the DMG. Contents:"
+ ls -la "$MOUNT_POINT"
+ exit 1
+fi
+
+echo "Installing $PKG..."
+
+quit_and_track_application "$BUNDLE_ID"
+
+if ! sudo installer -pkg "$PKG" -target /; then
+ echo "installer -pkg failed for $PKG"
+ exit 1
+fi
+
+cleanup
+trap - EXIT
+
+# OpenVPN Connect 3.8+ places the .app inside a wrapper directory rather than
+# directly under /Applications/. osquery's apps table doesn't recurse into
+# /Applications/, so it depends on LaunchServices to find nested .app bundles.
+# Force-register the installed app with LaunchServices so it shows up in
+# osquery's `apps` table immediately.
+if [ -x "$LSREGISTER" ]; then
+ if [ -d "$APPDIR/OpenVPN Connect/OpenVPN Connect.app" ]; then
+ "$LSREGISTER" -f "$APPDIR/OpenVPN Connect/OpenVPN Connect.app" >/dev/null 2>&1 || true
+ elif [ -d "$APPDIR/OpenVPN Connect.app" ]; then
+ "$LSREGISTER" -f "$APPDIR/OpenVPN Connect.app" >/dev/null 2>&1 || true
+ else
+ # As a last resort, recursively register anything OpenVPN Connect-shaped
+ # under /Applications/ so LaunchServices and osquery can find it.
+ "$LSREGISTER" -R -f "$APPDIR/OpenVPN Connect" >/dev/null 2>&1 || true
+ fi
+fi
+
+relaunch_application "$BUNDLE_ID"
-# 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"
-# install pkg files
-quit_and_track_application 'org.openvpn.client.app'
-sudo installer -pkg "$TMPDIR/OpenVPN_Connect_3_8_1(5790)_arm64_Installer_signed.pkg" -target /
-relaunch_application 'org.openvpn.client.app'
+echo "OpenVPN Connect installed"
=== Uninstall Script (no changes) === |
Simplified the command execution for refreshing LaunchServices by removing conditional logic for appPath.
Script Diff Resultsee/maintained-apps/outputs/openvpn-connect/darwin.json=== Install // 66c63c32 -> c8881523 ===
--- /tmp/old.zio3JX 2026-05-12 02:42:28.754785051 +0000
+++ /tmp/new.3jZkQv 2026-05-12 02:42:28.754785051 +0000
@@ -1,16 +1,41 @@
#!/bin/bash
-# variables
-APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-# functions
+# Custom install script for OpenVPN Connect on macOS.
+#
+# The Homebrew cask "openvpn-connect" downloads a .dmg that contains both
+# x86_64 and arm64 .pkg installers at the root of the mounted volume:
+#
+# OpenVPN_Connect_<ver>(<build>)_x86_64_Installer_signed.pkg
+# OpenVPN_Connect_<ver>(<build>)_arm64_Installer_signed.pkg
+#
+# We only ship FMAs for Apple Silicon (arm64) on macOS, so this script:
+# 1. Mounts the DMG.
+# 2. Locates the arm64 .pkg via a glob (parentheses in the file name make
+# hard-coding the path brittle across versions).
+# 3. Quits the app if it's running and tracks state for relaunch.
+# 4. Runs `installer -pkg ... -target /` against the mounted pkg, which is
+# the same operation Homebrew performs for `pkg "..."` artifacts.
+# 5. Detaches the DMG.
+# 6. Forces LaunchServices to register the installed .app bundle.
+#
+# The LaunchServices step is required because OpenVPN Connect 3.8+ installs
+# into a wrapper directory (/Applications/OpenVPN Connect/OpenVPN Connect.app)
+# rather than placing the .app directly under /Applications/. osquery's `apps`
+# table only directory-scans the top level of /Applications/ and otherwise
+# relies on LaunchServices to discover nested apps; without an explicit
+# `lsregister` the freshly installed app may not show up immediately.
+
+set -u
+
+APPDIR="/Applications"
+BUNDLE_ID="org.openvpn.client.app"
+LSREGISTER="/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister"
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
@@ -26,13 +51,11 @@
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
@@ -51,13 +74,11 @@
fi
}
-
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
@@ -72,11 +93,6 @@
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
@@ -93,13 +109,70 @@
fi
}
+if [ -z "${INSTALLER_PATH:-}" ] || [ ! -f "$INSTALLER_PATH" ]; then
+ echo "Missing or invalid INSTALLER_PATH"
+ exit 1
+fi
+
+MOUNT_POINT=$(mktemp -d /tmp/openvpn_connect_dmg.XXXXXX)
+cleanup() {
+ hdiutil detach "$MOUNT_POINT" >/dev/null 2>&1 || true
+ rmdir "$MOUNT_POINT" >/dev/null 2>&1 || true
+}
+trap cleanup EXIT
+
+if ! hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" >/dev/null; then
+ echo "Failed to mount DMG at $INSTALLER_PATH"
+ exit 1
+fi
+
+# Locate the arm64 installer pkg. We only support Apple Silicon for this FMA,
+# so deliberately skip the x86_64 pkg shipped in the same DMG. Use a glob so
+# parentheses and version/build numbers in the file name don't have to be
+# hard-coded here.
+PKG=""
+for candidate in "$MOUNT_POINT"/*_arm64_Installer_signed.pkg; do
+ if [ -e "$candidate" ]; then
+ PKG="$candidate"
+ break
+ fi
+done
+
+if [ -z "$PKG" ] || [ ! -e "$PKG" ]; then
+ echo "Could not find an arm64 OpenVPN Connect installer pkg in the DMG. Contents:"
+ ls -la "$MOUNT_POINT"
+ exit 1
+fi
+
+echo "Installing $PKG..."
+
+quit_and_track_application "$BUNDLE_ID"
+
+if ! sudo installer -pkg "$PKG" -target /; then
+ echo "installer -pkg failed for $PKG"
+ exit 1
+fi
+
+cleanup
+trap - EXIT
+
+# OpenVPN Connect 3.8+ places the .app inside a wrapper directory rather than
+# directly under /Applications/. osquery's apps table doesn't recurse into
+# /Applications/, so it depends on LaunchServices to find nested .app bundles.
+# Force-register the installed app with LaunchServices so it shows up in
+# osquery's `apps` table immediately.
+if [ -x "$LSREGISTER" ]; then
+ if [ -d "$APPDIR/OpenVPN Connect/OpenVPN Connect.app" ]; then
+ "$LSREGISTER" -f "$APPDIR/OpenVPN Connect/OpenVPN Connect.app" >/dev/null 2>&1 || true
+ elif [ -d "$APPDIR/OpenVPN Connect.app" ]; then
+ "$LSREGISTER" -f "$APPDIR/OpenVPN Connect.app" >/dev/null 2>&1 || true
+ else
+ # As a last resort, recursively register anything OpenVPN Connect-shaped
+ # under /Applications/ so LaunchServices and osquery can find it.
+ "$LSREGISTER" -R -f "$APPDIR/OpenVPN Connect" >/dev/null 2>&1 || true
+ fi
+fi
+
+relaunch_application "$BUNDLE_ID"
-# 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"
-# install pkg files
-quit_and_track_application 'org.openvpn.client.app'
-sudo installer -pkg "$TMPDIR/OpenVPN_Connect_3_8_1(5790)_arm64_Installer_signed.pkg" -target /
-relaunch_application 'org.openvpn.client.app'
+echo "OpenVPN Connect installed"
=== Uninstall Script (no changes) === |
Script Diff Resultsee/maintained-apps/outputs/openvpn-connect/darwin.json=== Install // 66c63c32 -> c8881523 ===
--- /tmp/old.Cj9YjE 2026-05-12 02:43:04.404710391 +0000
+++ /tmp/new.qbMlwF 2026-05-12 02:43:04.405710390 +0000
@@ -1,16 +1,41 @@
#!/bin/bash
-# variables
-APPDIR="/Applications/"
-TMPDIR=$(dirname "$(realpath "$INSTALLER_PATH")")
-# functions
+# Custom install script for OpenVPN Connect on macOS.
+#
+# The Homebrew cask "openvpn-connect" downloads a .dmg that contains both
+# x86_64 and arm64 .pkg installers at the root of the mounted volume:
+#
+# OpenVPN_Connect_<ver>(<build>)_x86_64_Installer_signed.pkg
+# OpenVPN_Connect_<ver>(<build>)_arm64_Installer_signed.pkg
+#
+# We only ship FMAs for Apple Silicon (arm64) on macOS, so this script:
+# 1. Mounts the DMG.
+# 2. Locates the arm64 .pkg via a glob (parentheses in the file name make
+# hard-coding the path brittle across versions).
+# 3. Quits the app if it's running and tracks state for relaunch.
+# 4. Runs `installer -pkg ... -target /` against the mounted pkg, which is
+# the same operation Homebrew performs for `pkg "..."` artifacts.
+# 5. Detaches the DMG.
+# 6. Forces LaunchServices to register the installed .app bundle.
+#
+# The LaunchServices step is required because OpenVPN Connect 3.8+ installs
+# into a wrapper directory (/Applications/OpenVPN Connect/OpenVPN Connect.app)
+# rather than placing the .app directly under /Applications/. osquery's `apps`
+# table only directory-scans the top level of /Applications/ and otherwise
+# relies on LaunchServices to discover nested apps; without an explicit
+# `lsregister` the freshly installed app may not show up immediately.
+
+set -u
+
+APPDIR="/Applications"
+BUNDLE_ID="org.openvpn.client.app"
+LSREGISTER="/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister"
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
@@ -26,13 +51,11 @@
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
@@ -51,13 +74,11 @@
fi
}
-
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
@@ -72,11 +93,6 @@
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
@@ -93,13 +109,70 @@
fi
}
+if [ -z "${INSTALLER_PATH:-}" ] || [ ! -f "$INSTALLER_PATH" ]; then
+ echo "Missing or invalid INSTALLER_PATH"
+ exit 1
+fi
+
+MOUNT_POINT=$(mktemp -d /tmp/openvpn_connect_dmg.XXXXXX)
+cleanup() {
+ hdiutil detach "$MOUNT_POINT" >/dev/null 2>&1 || true
+ rmdir "$MOUNT_POINT" >/dev/null 2>&1 || true
+}
+trap cleanup EXIT
+
+if ! hdiutil attach -plist -nobrowse -readonly -mountpoint "$MOUNT_POINT" "$INSTALLER_PATH" >/dev/null; then
+ echo "Failed to mount DMG at $INSTALLER_PATH"
+ exit 1
+fi
+
+# Locate the arm64 installer pkg. We only support Apple Silicon for this FMA,
+# so deliberately skip the x86_64 pkg shipped in the same DMG. Use a glob so
+# parentheses and version/build numbers in the file name don't have to be
+# hard-coded here.
+PKG=""
+for candidate in "$MOUNT_POINT"/*_arm64_Installer_signed.pkg; do
+ if [ -e "$candidate" ]; then
+ PKG="$candidate"
+ break
+ fi
+done
+
+if [ -z "$PKG" ] || [ ! -e "$PKG" ]; then
+ echo "Could not find an arm64 OpenVPN Connect installer pkg in the DMG. Contents:"
+ ls -la "$MOUNT_POINT"
+ exit 1
+fi
+
+echo "Installing $PKG..."
+
+quit_and_track_application "$BUNDLE_ID"
+
+if ! sudo installer -pkg "$PKG" -target /; then
+ echo "installer -pkg failed for $PKG"
+ exit 1
+fi
+
+cleanup
+trap - EXIT
+
+# OpenVPN Connect 3.8+ places the .app inside a wrapper directory rather than
+# directly under /Applications/. osquery's apps table doesn't recurse into
+# /Applications/, so it depends on LaunchServices to find nested .app bundles.
+# Force-register the installed app with LaunchServices so it shows up in
+# osquery's `apps` table immediately.
+if [ -x "$LSREGISTER" ]; then
+ if [ -d "$APPDIR/OpenVPN Connect/OpenVPN Connect.app" ]; then
+ "$LSREGISTER" -f "$APPDIR/OpenVPN Connect/OpenVPN Connect.app" >/dev/null 2>&1 || true
+ elif [ -d "$APPDIR/OpenVPN Connect.app" ]; then
+ "$LSREGISTER" -f "$APPDIR/OpenVPN Connect.app" >/dev/null 2>&1 || true
+ else
+ # As a last resort, recursively register anything OpenVPN Connect-shaped
+ # under /Applications/ so LaunchServices and osquery can find it.
+ "$LSREGISTER" -R -f "$APPDIR/OpenVPN Connect" >/dev/null 2>&1 || true
+ fi
+fi
+
+relaunch_application "$BUNDLE_ID"
-# 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"
-# install pkg files
-quit_and_track_application 'org.openvpn.client.app'
-sudo installer -pkg "$TMPDIR/OpenVPN_Connect_3_8_1(5790)_arm64_Installer_signed.pkg" -target /
-relaunch_application 'org.openvpn.client.app'
+echo "OpenVPN Connect installed"
=== Uninstall Script (no changes) === |
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 (6)
WalkthroughThis PR adds OpenVPN Connect as a managed application to Fleet. It introduces a Homebrew input metadata file specifying the app's bundle identifier and installer type, a comprehensive Bash installer script for macOS that handles DMG mounting, app lifecycle management (detecting and relaunching the running app), LaunchServices registration, and cleanup. The app is registered in the output app registry and receives a macOS-specific definition file with version metadata and embedded install/uninstall script definitions. The frontend receives a new SVG icon component and its integration into the software icon mapping for UI display. ✨ 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
Adds OpenVPN Connect as a Fleet-maintained app (FMA) for macOS, wiring it into both the maintained-apps catalog and the Software page UI so it can be distributed and displayed with the correct metadata and icon.
Changes:
- Added Homebrew input manifest + custom macOS install script for OpenVPN Connect.
- Added generated maintained-app outputs (darwin version metadata + install/uninstall script refs) and registered the app in
apps.json. - Added a new Software page icon component and registered it in the software-name-to-icon map.
Reviewed changes
Copilot reviewed 6 out of 7 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/pages/SoftwarePage/components/icons/OpenvpnConnect.tsx | Adds the OpenVPN Connect icon component used by the Software page. |
| frontend/pages/SoftwarePage/components/icons/index.ts | Registers the new icon in the icon map and imports it. |
| ee/maintained-apps/outputs/openvpn-connect/darwin.json | Adds the generated macOS output metadata, installer URL/SHA, and install/uninstall script refs. |
| ee/maintained-apps/outputs/apps.json | Registers OpenVPN Connect in the maintained apps catalog list. |
| ee/maintained-apps/inputs/homebrew/scripts/openvpn-connect-install.sh | Adds a custom DMG+PKG install script with quit/relaunch and LaunchServices registration. |
| ee/maintained-apps/inputs/homebrew/openvpn-connect.json | Adds the Homebrew input manifest for OpenVPN Connect. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const OpenvpnConnect = (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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" | ||
| /> | ||
| </svg> | ||
| ); | ||
| export default OpenvpnConnect; |
| ], | ||
| "refs": { | ||
| "c8881523": "#!/bin/bash\n\n# Custom install script for OpenVPN Connect on macOS.\n#\n# The Homebrew cask \"openvpn-connect\" downloads a .dmg that contains both\n# x86_64 and arm64 .pkg installers at the root of the mounted volume:\n#\n# OpenVPN_Connect_<ver>(<build>)_x86_64_Installer_signed.pkg\n# OpenVPN_Connect_<ver>(<build>)_arm64_Installer_signed.pkg\n#\n# We only ship FMAs for Apple Silicon (arm64) on macOS, so this script:\n# 1. Mounts the DMG.\n# 2. Locates the arm64 .pkg via a glob (parentheses in the file name make\n# hard-coding the path brittle across versions).\n# 3. Quits the app if it's running and tracks state for relaunch.\n# 4. Runs `installer -pkg ... -target /` against the mounted pkg, which is\n# the same operation Homebrew performs for `pkg \"...\"` artifacts.\n# 5. Detaches the DMG.\n# 6. Forces LaunchServices to register the installed .app bundle.\n#\n# The LaunchServices step is required because OpenVPN Connect 3.8+ installs\n# into a wrapper directory (/Applications/OpenVPN Connect/OpenVPN Connect.app)\n# rather than placing the .app directly under /Applications/. osquery's `apps`\n# table only directory-scans the top level of /Applications/ and otherwise\n# relies on LaunchServices to discover nested apps; without an explicit\n# `lsregister` the freshly installed app may not show up immediately.\n\nset -u\n\nAPPDIR=\"/Applications\"\nBUNDLE_ID=\"org.openvpn.client.app\"\nLSREGISTER=\"/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister\"\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 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 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 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\nrelaunch_application() {\n local bundle_id=\"$1\"\n local var_name=\"APP_WAS_RUNNING_$(echo \"$bundle_id\" | tr '.-' '__')\"\n local was_running\n\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 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\nif [ -z \"${INSTALLER_PATH:-}\" ] || [ ! -f \"$INSTALLER_PATH\" ]; then\n echo \"Missing or invalid INSTALLER_PATH\"\n exit 1\nfi\n\nMOUNT_POINT=$(mktemp -d /tmp/openvpn_connect_dmg.XXXXXX)\ncleanup() {\n hdiutil detach \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n rmdir \"$MOUNT_POINT\" >/dev/null 2>&1 || true\n}\ntrap cleanup EXIT\n\nif ! hdiutil attach -plist -nobrowse -readonly -mountpoint \"$MOUNT_POINT\" \"$INSTALLER_PATH\" >/dev/null; then\n echo \"Failed to mount DMG at $INSTALLER_PATH\"\n exit 1\nfi\n\n# Locate the arm64 installer pkg. We only support Apple Silicon for this FMA,\n# so deliberately skip the x86_64 pkg shipped in the same DMG. Use a glob so\n# parentheses and version/build numbers in the file name don't have to be\n# hard-coded here.\nPKG=\"\"\nfor candidate in \"$MOUNT_POINT\"/*_arm64_Installer_signed.pkg; do\n if [ -e \"$candidate\" ]; then\n PKG=\"$candidate\"\n break\n fi\ndone\n\nif [ -z \"$PKG\" ] || [ ! -e \"$PKG\" ]; then\n echo \"Could not find an arm64 OpenVPN Connect installer pkg in the DMG. Contents:\"\n ls -la \"$MOUNT_POINT\"\n exit 1\nfi\n\necho \"Installing $PKG...\"\n\nquit_and_track_application \"$BUNDLE_ID\"\n\nif ! sudo installer -pkg \"$PKG\" -target /; then\n echo \"installer -pkg failed for $PKG\"\n exit 1\nfi\n\ncleanup\ntrap - EXIT\n\n# OpenVPN Connect 3.8+ places the .app inside a wrapper directory rather than\n# directly under /Applications/. osquery's apps table doesn't recurse into\n# /Applications/, so it depends on LaunchServices to find nested .app bundles.\n# Force-register the installed app with LaunchServices so it shows up in\n# osquery's `apps` table immediately.\nif [ -x \"$LSREGISTER\" ]; then\n if [ -d \"$APPDIR/OpenVPN Connect/OpenVPN Connect.app\" ]; then\n \"$LSREGISTER\" -f \"$APPDIR/OpenVPN Connect/OpenVPN Connect.app\" >/dev/null 2>&1 || true\n elif [ -d \"$APPDIR/OpenVPN Connect.app\" ]; then\n \"$LSREGISTER\" -f \"$APPDIR/OpenVPN Connect.app\" >/dev/null 2>&1 || true\n else\n # As a last resort, recursively register anything OpenVPN Connect-shaped\n # under /Applications/ so LaunchServices and osquery can find it.\n \"$LSREGISTER\" -R -f \"$APPDIR/OpenVPN Connect\" >/dev/null 2>&1 || true\n fi\nfi\n\nrelaunch_application \"$BUNDLE_ID\"\n\necho \"OpenVPN Connect installed\"\n", | ||
| "d66adb9e": "#!/bin/bash\n\n# variables\nLOGGED_IN_USER=$(scutil <<< \"show State:/Users/ConsoleUser\" | awk '/Name :/ { print $3 }')\n# functions\n\nexpand_pkgid_and_map() {\n local PKGID=\"$1\"\n local FUNC=\"$2\"\n if [[ \"$PKGID\" == *\"*\" ]]; then\n local prefix=\"${PKGID%\\*}\"\n echo \"Expanding wildcard for PKGID: $PKGID\"\n for receipt in $(pkgutil --pkgs | grep \"^${prefix}\"); do\n echo \"Processing $receipt\"\n \"$FUNC\" \"$receipt\"\n done\n else\n \"$FUNC\" \"$PKGID\"\n fi\n}\n\nforget_pkg() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" forget_receipt\n}\n\nforget_receipt() {\n local PKGID=\"$1\"\n sudo pkgutil --forget \"$PKGID\"\n}\n\nquit_application() {\n local bundle_id=\"$1\"\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 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 return\n fi\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\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 for should_sudo in \"${booleans[@]}\"; do\n plist_status=$(launchctl list \"${service}\" 2>/dev/null)\n\n if [[ $plist_status == \\{* ]]; then\n if [[ $should_sudo == \"true\" ]]; then\n sudo launchctl remove \"${service}\"\n else\n launchctl remove \"${service}\"\n fi\n sleep 1\n fi\n\n paths=(\n \"/Library/LaunchAgents/${service}.plist\"\n \"/Library/LaunchDaemons/${service}.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}\n\nremove_pkg_files() {\n local PKGID=\"$1\"\n expand_pkgid_and_map \"$PKGID\" remove_receipt_files\n}\n\nremove_receipt_files() {\n local PKGID=\"$1\"\n local PKGINFO VOLUME INSTALL_LOCATION FULL_INSTALL_LOCATION\n\n echo \"pkgutil --pkg-info-plist \\\"$PKGID\\\"\"\n PKGINFO=$(pkgutil --pkg-info-plist \"$PKGID\")\n VOLUME=$(echo \"$PKGINFO\" | awk '/<key>volume<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n INSTALL_LOCATION=$(echo \"$PKGINFO\" | awk '/<key>install-location<\\/key>/ {getline; gsub(/.*<string>|<\\/string>.*/, \"\"); print}')\n\n if [ -z \"$INSTALL_LOCATION\" ] || [ \"$INSTALL_LOCATION\" = \"/\" ]; then\n FULL_INSTALL_LOCATION=\"$VOLUME\"\n else\n FULL_INSTALL_LOCATION=\"$VOLUME/$INSTALL_LOCATION\"\n FULL_INSTALL_LOCATION=$(echo \"$FULL_INSTALL_LOCATION\" | sed 's|//|/|g')\n fi\n\n echo \"sudo pkgutil --only-files --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-files --files \"$PKGID\" | sed \"s|^|/${INSTALL_LOCATION}/|\" | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n echo \"sudo pkgutil --only-dirs --files \\\"$PKGID\\\" | sed \\\"s|^|${FULL_INSTALL_LOCATION}/|\\\" | grep '\\\\.app$' | tr '\\\\\\\\n' '\\\\\\\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\"\n sudo pkgutil --only-dirs --files \"$PKGID\" | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" | grep '\\.app$' | tr '\\n' '\\0' | /usr/bin/sudo -u root -E -- /usr/bin/xargs -0 -- /bin/rm -rf\n\n root_app_dir=$(\n sudo pkgutil --only-dirs --files \"$PKGID\" \\\n | sed \"s|^|${FULL_INSTALL_LOCATION}/|\" \\\n | grep 'Applications' \\\n | awk '{ print length, $0 }' \\\n | sort -n \\\n | head -n1 \\\n | cut -d' ' -f2-\n )\n if [ -n \"$root_app_dir\" ]; then\n echo \"sudo rmdir -p \\\"$root_app_dir\\\" 2>/dev/null || :\"\n sudo rmdir -p \"$root_app_dir\" 2>/dev/null || :\n fi\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 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 'org.openvpn.client'\nremove_launchctl_service 'org.openvpn.helper'\nquit_application 'org.openvpn.client.app'\nremove_pkg_files 'org.openvpn.client.pkg'\nforget_pkg 'org.openvpn.client.pkg'\nremove_pkg_files 'org.openvpn.client_framework.pkg'\nforget_pkg 'org.openvpn.client_framework.pkg'\nremove_pkg_files 'org.openvpn.client_launch.pkg'\nforget_pkg 'org.openvpn.client_launch.pkg'\nremove_pkg_files 'org.openvpn.client_uninstall.pkg'\nforget_pkg 'org.openvpn.client_uninstall.pkg'\nremove_pkg_files 'org.openvpn.helper_framework.pkg'\nforget_pkg 'org.openvpn.helper_framework.pkg'\nremove_pkg_files 'org.openvpn.helper_launch.pkg'\nforget_pkg 'org.openvpn.helper_launch.pkg'\nsudo rm -rf '/Applications/OpenVPN Connect'\nsudo rm -rf '/Applications/OpenVPN Connect.app'\n(cd /Users/$LOGGED_IN_USER && 'security' 'delete-keychain' 'openvpn.keychain-db') || true\ntrash $LOGGED_IN_USER '~/Library/Application Support/OpenVPN Connect'\ntrash $LOGGED_IN_USER '~/Library/Logs/OpenVPN Connect'\ntrash $LOGGED_IN_USER '~/Library/Preferences/org.openvpn.client.app.helper.plist'\ntrash $LOGGED_IN_USER '~/Library/Preferences/org.openvpn.client.app.plist'\ntrash $LOGGED_IN_USER '~/Library/Saved Application State/org.openvpn.client.app.savedState'\n" |
Add OpenVPN Connect to maintained apps: create a Homebrew input manifest and add an apps.json entry. Add a darwin output with version 3.8.1 (installer URL, sha256) plus install/uninstall script refs that handle quitting/relaunching and cleanup. Add frontend icon component and register it in the icon map, and include the app icon asset. Default category set to Productivity.
Summary by CodeRabbit