From da89bc2b1193720309275947af922c0829027cf1 Mon Sep 17 00:00:00 2001 From: Marcelo Alcantara Date: Sat, 10 Oct 2026 10:02:54 +1000 Subject: [PATCH] Skip the Electron wrapping on a runtime without its helpers #14431 moved omarchy-cmd-electron-gl-wrap and omarchy-cmd-desktop-exec-repair to their own change (#14717), so platform setup exited 127 on every boot of a Mac with Chromium. System setup now skips when the runtime has no wrapper, and user setup when it lacks either helper; existing wrappers stay. CI follows #14431's head, which also needs stubs for owner setup's accessory enrollment. omarchy-mac 0.1.1. --- mac-manual/content/11-on-disk.md | 2 +- omarchy-mac/ORIGINS.md | 2 +- omarchy-mac/README.md | 4 ++-- omarchy-mac/lib/electron-desktop-entries | 9 +++++++- omarchy-mac/lib/electron-launchers | 7 +++++- omarchy-mac/test/desktop-setup-test.sh | 13 ++++++++--- omarchy-mac/version | 2 +- .../electron-desktop-repair-test.sh | 23 +++++++++++++++++++ test/integration/provision-owner-luks-test.sh | 6 ++++- test/integration/runtime | 2 +- 10 files changed, 58 insertions(+), 12 deletions(-) diff --git a/mac-manual/content/11-on-disk.md b/mac-manual/content/11-on-disk.md index 2e45433..d10d38b 100644 --- a/mac-manual/content/11-on-disk.md +++ b/mac-manual/content/11-on-disk.md @@ -12,7 +12,7 @@ An installed Mac is an upstream Omarchy installation plus two Mac packages and t | --- | --- | | `omarchy-settings` | `/etc/skel`, `/etc` drop-ins, boot loader and snapper configuration, Plymouth and SDDM themes, branding. One aarch64 build that picks the Apple profile at runtime. | | `omarchy` | The `omarchy-*` commands, install scripts, migrations, themes and the Quickshell desktop | -| `omarchy-mac` | Microphone mapping, Wi-Fi resume recovery, the iwd Wi-Fi backend for NetworkManager, the notch setting, the Electron software GL wrappers, browser decode flags | +| `omarchy-mac` | Microphone mapping, Wi-Fi resume recovery, the iwd Wi-Fi backend for NetworkManager, the notch setting, the Electron software GL wrappers (when the runtime has their helpers), browser decode flags | | `omarchy-mac-boot` | Initramfs fragments, vendor firmware hooks, first-boot and encryption units, Limine and U-Boot deployment, boot verification | | `linux-aurora` | The kernel and the device trees. `linux-aurora-headers` adds the headers when a DKMS module needs them. | | `m1n1-aurora`, `uboot-asahi` | The boot stages between Apple's firmware and Limine | diff --git a/omarchy-mac/ORIGINS.md b/omarchy-mac/ORIGINS.md index 790605a..ac632c0 100644 --- a/omarchy-mac/ORIGINS.md +++ b/omarchy-mac/ORIGINS.md @@ -13,7 +13,7 @@ The network backend default follows Marcelo Alcantara's Apple Silicon integratio - Greeter wait for the display controller: Marcelo Alcantara, maralcbr/omarchy-mx-mac `78b8ba410cf7d7b7749f0f66265a9ce438496db6` (Wait for the Apple display card before starting the greeter). The inline `ExecStartPre` moves to `lib/wait-for-display` behind the platform detector. - Battery charge limit command and behavioral tests: Naeem Malik, `00a2d31019e4d5ea5a3e5e9cb45a75aa90d07ee2` (Add an Apple Silicon battery charge limit command, #497). The driver semantics and readback check are retained; the platform gate, saved limit and boot-time restore are new. - Keyboard function-key mode: Marcelo Alcantara, maralcbr/omarchy-mx-mac `6f2248d4cc065f2cd88550ed414012151bc57622` (#266, `fnmode=3` on Apple Silicon), replacing Scott Jones's `fnmode=1` from `0022c4374d9f13dffd8b6415c095d1a5ae491d33` (Put media keys on the Apple Silicon top row without stealing x86 F-keys). The generated-line retirement, owed-rebuild handling and live switch follow both forks' migrations; leaving the kernel default in place and the setup command are new work. -- Electron software GL wrapping: Scott Jones, `e6f2e6ad6` (Wrap Electron when Apple Silicon has no render GPU). The system and user halves of `install/hardware/apple/electron-gl.sh` and `install/user/hardware/apple/electron-gl.sh` move to `lib/electron-launchers` and `lib/electron-desktop-entries` unchanged in behaviour; the wrapper and desktop repair helpers stay in the runtime. +- Electron software GL wrapping: Scott Jones, `e6f2e6ad6` (Wrap Electron when Apple Silicon has no render GPU). The system and user halves of `install/hardware/apple/electron-gl.sh` and `install/user/hardware/apple/electron-gl.sh` move to `lib/electron-launchers` and `lib/electron-desktop-entries` unchanged in behaviour, except that each half skips when the runtime lacks its helpers; the wrapper and desktop repair helpers stay in the runtime (omacom/omarchy#14717). - Browser decode flags: Marcelo Alcantara, `bb14b799f` (Turn off browser hardware decode on Apple Silicon), after duketopceo's omarchy-mac#418, moved from `install/user/hardware/apple/browser-video-decode.sh` into `omarchy-mac-setup-user`. - Steam FEX launcher setup: Scott Jones, from the runtime's Steam installer branch and migration `1789522888` (`b5463029e`); the launcher itself is omarchy-pkgs' `omarchy-steam-fex`. - Mac desktop data moved into the platform root: Scott Jones's F1/F2 key names (`c1673ae67`) and the notch sizes (from the runtime's `BarModel.js`), moved out of the runtime's shared files unchanged in behaviour. diff --git a/omarchy-mac/README.md b/omarchy-mac/README.md index 3251f3c..0526e05 100644 --- a/omarchy-mac/README.md +++ b/omarchy-mac/README.md @@ -1,6 +1,6 @@ # omarchy-mac -Apple Silicon defaults and support services for Omarchy. Version: `0.1.0` (candidate). This add-on complements `omarchy` and `omarchy-settings`; it selects no kernel and contains no installer or repository trust configuration. It covers what stays on an installed Mac; installing one is the job of the [Omarchy Installer](https://github.com/omacom/omarchy-mac-installer), and boot support is the separate `omarchy-mac-boot` package beside this one. +Apple Silicon defaults and support services for Omarchy. Version: `0.1.1` (candidate). This add-on complements `omarchy` and `omarchy-settings`; it selects no kernel and contains no installer or repository trust configuration. It covers what stays on an installed Mac; installing one is the job of the [Omarchy Installer](https://github.com/omacom/omarchy-mac-installer), and boot support is the separate `omarchy-mac-boot` package beside this one. ## Build and stage @@ -18,7 +18,7 @@ Run `omarchy-mac-setup-user` as each target user with their HOME/XDG directories A runtime whose `omarchy-lifecycle-dispatch` has the `setup-system` and `setup-user` operations (the platform setup seam, which registers `/usr/lib/omarchy/mac` for Apple Silicon) reaches both through the entrypoints this package stages there; an older runtime calls the two commands itself: `setup-system [image-first-boot]` (root, from the last hardware leaf and on an image's first boot, where it downloads nothing; it rebuilds no boot file) and `setup-user` (as the user being set up, at finalization and again in first run). Each re-checks the platform. -System setup also wraps Chromium, 1Password and Cursor where they are installed: without the GPU driver an Apple Silicon Mac has no DRM render node and their GPU process fails, so the runtime's `omarchy-cmd-electron-gl-wrap` puts a wrapper in `/usr/local/bin` that passes software GL flags only while no render node exists; a launcher an administrator owns is kept. User setup points the user's own desktop entries for them at a ready wrapper (`omarchy-cmd-desktop-exec-repair`) and turns `AcceleratedVideoDecoder` off in each Chromium-family `*-flags.conf`, joining an existing `--disable-features` list: Brave and other VA-API builds render green frames through the Apple Video Decoder, while mpv, ffmpeg and GStreamer keep it. A browser install runs user setup again after it writes a fresh flags file. Where Steam is installed, system setup also installs `omarchy-steam-fex` (Steam runs x86 under FEX in a muvm VM) from the configured repositories, and user setup runs its `omarchy-launch-steam --prepare` for a user who has Steam; the runtime's Steam installer reaches both through the dispatcher. These and the Electron steps need the live machine, so a staging root skips them. +System setup also wraps Chromium, 1Password and Cursor where they are installed: without the GPU driver an Apple Silicon Mac has no DRM render node and their GPU process fails, so the runtime's `omarchy-cmd-electron-gl-wrap` puts a wrapper in `/usr/local/bin` that passes software GL flags only while no render node exists; a launcher an administrator owns is kept. A runtime without `omarchy-cmd-electron-gl-wrap` creates no new wrappers (both setup halves skip; existing ones stay), and one without `omarchy-cmd-desktop-exec-repair` leaves the desktop entries alone. User setup points the user's own desktop entries for them at a ready wrapper (`omarchy-cmd-desktop-exec-repair`) and turns `AcceleratedVideoDecoder` off in each Chromium-family `*-flags.conf`, joining an existing `--disable-features` list: Brave and other VA-API builds render green frames through the Apple Video Decoder, while mpv, ffmpeg and GStreamer keep it. A browser install runs user setup again after it writes a fresh flags file. Where Steam is installed, system setup also installs `omarchy-steam-fex` (Steam runs x86 under FEX in a muvm VM) from the configured repositories, and user setup runs its `omarchy-launch-steam --prepare` for a user who has Steam; the runtime's Steam installer reaches both through the dispatcher. These and the Electron steps need the live machine, so a staging root skips them. The Mac's hardware data lives in the platform root, `/usr/share/omarchy-platform`, which Omarchy reads at that fixed path and ships nothing in, so Omarchy's own config carries no Apple branch. All of it is data. The package ships no Hyprland files and changes no Hyprland binds or settings: Omarchy's binds, trackpad and cursor defaults apply on a Mac as on any other machine. A key the built-in keyboard lacks is given to it below Hyprland, as a udev hwdb remap in this package (omacom/omarchy-mac-pkgs#6, in review). diff --git a/omarchy-mac/lib/electron-desktop-entries b/omarchy-mac/lib/electron-desktop-entries index 71d2bbb..83f696a 100755 --- a/omarchy-mac/lib/electron-desktop-entries +++ b/omarchy-mac/lib/electron-desktop-entries @@ -3,9 +3,16 @@ # desktop entry of the user's own that names the real binary would bypass the # wrapper, so runtime's omarchy-cmd-desktop-exec-repair points it at the # wrapper once that is in place. omarchy-mac-setup-user runs this as the user; -# a wrapper that is not ready yet (exit 3 or 4 from --check) is skipped. +# a wrapper that is not ready yet (exit 3 or 4 from --check) is skipped, and +# so is a runtime without the helpers. set -euo pipefail [[ $(omarchy-hw-platform) == "apple-silicon" ]] || exit 0 +for helper in omarchy-cmd-electron-gl-wrap omarchy-cmd-desktop-exec-repair; do + if ! command -v "$helper" >/dev/null; then + echo "Skipping Electron desktop repair: the runtime has no $helper" >&2 + exit 0 + fi +done bind_dir=${OMARCHY_ELECTRON_GL_BIND_DIR:-/usr/local/bin} applications=$HOME/.local/share/applications for app in chromium 1password cursor; do diff --git a/omarchy-mac/lib/electron-launchers b/omarchy-mac/lib/electron-launchers index 9b43340..8f188d6 100755 --- a/omarchy-mac/lib/electron-launchers +++ b/omarchy-mac/lib/electron-launchers @@ -5,9 +5,14 @@ # omarchy-cmd-electron-gl-wrap puts a wrapper for each installed one in # /usr/local/bin, ahead of /usr/bin, which passes software GL flags only while # no render node exists. omarchy-mac-setup-system runs this as root; a -# launcher an administrator owns (exit 3) is kept. +# launcher an administrator owns (exit 3) is kept. A runtime without the +# helper ships no wrapping, so there is nothing to install. set -euo pipefail [[ $(omarchy-hw-platform) == "apple-silicon" ]] || exit 0 +if ! command -v omarchy-cmd-electron-gl-wrap >/dev/null; then + echo "Skipping Electron launchers: the runtime has no omarchy-cmd-electron-gl-wrap" >&2 + exit 0 +fi for app in chromium 1password cursor; do case $app in chromium) real=${OMARCHY_CHROMIUM_BIN:-/usr/bin/chromium} ;; diff --git a/omarchy-mac/test/desktop-setup-test.sh b/omarchy-mac/test/desktop-setup-test.sh index bdd5119..257577c 100644 --- a/omarchy-mac/test/desktop-setup-test.sh +++ b/omarchy-mac/test/desktop-setup-test.sh @@ -98,9 +98,16 @@ grep -q 'Preserving administrator-owned chromium launcher' <<<"$output" && grep if WRAP_1PASSWORD=1 "$launchers" >/dev/null 2>&1; then fail 'a wrapper that fails fails setup'; fi mkdir -p "$work/bare" ln -s "$work/bin/omarchy-hw-platform" "$work/bare/omarchy-hw-platform" -if PATH="$work/bare" "$launchers" >/dev/null 2>&1; then fail 'a runtime without the wrapper helper fails setup'; fi -if PATH="$work/bare" "$entries" >/dev/null 2>&1; then fail 'a runtime without the desktop helpers fails user setup'; fi -pass 'system setup wraps each installed Electron app, keeping administrator-owned launchers, and needs the runtime helpers' +: >"$CALLS" +output=$(PATH="$work/bare" "$launchers" 2>&1) || fail 'a runtime without the wrapper helper does not fail setup' "$output" +grep -q 'runtime has no omarchy-cmd-electron-gl-wrap' <<<"$output" || fail 'a runtime without the wrapper helper is named' "$output" +output=$(PATH="$work/bare" "$entries" 2>&1) || fail 'a runtime without the desktop helpers does not fail user setup' "$output" +grep -q 'runtime has no omarchy-cmd-electron-gl-wrap' <<<"$output" || fail 'a runtime without the desktop helpers is named' "$output" +ln -s "$work/bin/omarchy-cmd-electron-gl-wrap" "$work/bare/omarchy-cmd-electron-gl-wrap" +output=$(PATH="$work/bare" "$entries" 2>&1) || fail 'a runtime without the repair helper does not fail user setup' "$output" +grep -q 'runtime has no omarchy-cmd-desktop-exec-repair' <<<"$output" && [[ ! -s $CALLS ]] || + fail 'a runtime without the repair helper is named and nothing runs' "$output $(cat "$CALLS")" +pass 'system setup wraps each installed Electron app, keeping administrator-owned launchers, and skips a runtime without the helpers' export OMARCHY_CURSOR_BIN="$work/apps/cursor" applications=$HOME/.local/share/applications diff --git a/omarchy-mac/version b/omarchy-mac/version index 6e8bf73..17e51c3 100644 --- a/omarchy-mac/version +++ b/omarchy-mac/version @@ -1 +1 @@ -0.1.0 +0.1.1 diff --git a/test/integration/electron-desktop-repair-test.sh b/test/integration/electron-desktop-repair-test.sh index 4edf9a8..00fe08d 100644 --- a/test/integration/electron-desktop-repair-test.sh +++ b/test/integration/electron-desktop-repair-test.sh @@ -56,6 +56,29 @@ Exec=env SPECIAL=yes chromium %U # omarchy-mac's user and system halves of the Electron wrapping. leaf = '"$MAC/lib/electron-desktop-entries"' system = '"$MAC/lib/electron-launchers"' + if not os.path.exists(wrap): + # A runtime without the wrapper: both halves skip and change nothing. + for script in (system, leaf): + assert 'runtime has no' in run(['bash', '-euo', 'pipefail', '-c', script]).stderr + assert not sentinel.exists() and not (bind / 'chromium').exists() + assert not (home / '.local/share/applications').exists() + print('ok - Electron setup skips a runtime without the wrapper helpers') + raise SystemExit(0) + # A runtime with the wrapper but no desktop repair: system setup wraps, user + # setup leaves the desktop entries alone. + partial = tmp / 'partial-runtime' + partial.mkdir() + for helper in (root / 'bin').iterdir(): + if helper.name != 'omarchy-cmd-desktop-exec-repair': + (partial / helper.name).symlink_to(helper) + full_path = env['PATH'] + env['PATH'] = full_path.replace(f'{root}/bin:', f'{partial}:') + run(['bash', '-euo', 'pipefail', '-c', system]) + assert (bind / 'chromium').exists() + assert 'runtime has no omarchy-cmd-desktop-exec-repair' in run(['bash', '-euo', 'pipefail', '-c', leaf]).stderr + assert not (home / '.local/share/applications').exists() and not sentinel.exists() + env['PATH'] = full_path + (bind / 'chromium').unlink() run([wrap, '--check', 'chromium', str(real)], 4) run(['bash', '-euo', 'pipefail', '-c', leaf]) assert not sentinel.exists() and not (bind / 'chromium').exists() diff --git a/test/integration/provision-owner-luks-test.sh b/test/integration/provision-owner-luks-test.sh index 16d7de6..85c03b6 100644 --- a/test/integration/provision-owner-luks-test.sh +++ b/test/integration/provision-owner-luks-test.sh @@ -87,6 +87,10 @@ cat >"$stub_bin/stty" <<'SH' echo "24 80" SH printf '#!/bin/bash\nexit 0\n' >"$stub_bin/systemctl" +# Owner setup's accessory enrollment: no usbguard installed, and the +# Thunderbolt step (an absolute path, rewritten below) succeeds. +printf '#!/bin/bash\nexit 1\n' >"$stub_bin/omarchy-pkg-present" +printf '#!/bin/bash\nexit 0\n' >"$stub_bin/omarchy-thunderbolt-authorization-admin" cat >"$stub_bin/cryptsetup" <"$tmp/provision-owner.sh" + "$ROOT/bin/omarchy-provision-owner" | sed -e "s|/etc/|$root/etc/|g" -e "s|/usr/bin/omarchy-thunderbolt-authorization-admin|$stub_bin/omarchy-thunderbolt-authorization-admin|g" >"$tmp/provision-owner.sh" for function in luks_record_slots rekey_luks luks_boot_layout run_provisioning platform_ready; do grep -q "^$function() {" "$tmp/provision-owner.sh" || fail "omarchy-provision-owner defines $function" done diff --git a/test/integration/runtime b/test/integration/runtime index 3fcb3e9..7e477a7 100644 --- a/test/integration/runtime +++ b/test/integration/runtime @@ -1,4 +1,4 @@ # The Omarchy runtime CI tests the packages against: a repository and a full commit. # Move it deliberately, like a recipe pin. Today the head of omacom/omarchy#14431; # upstream omacom/omarchy once it merges. -omacom/omarchy 4d9bdc49dffdb5e78d9c89d24d3903350cb00ca7 +omacom/omarchy 5397950a21e8839a7c182c9372d56bd6a2808535