diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 33f7ac8ab..decc33c44 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -63,6 +63,20 @@ jobs: sudo mv "$file" "${file}.before-nix-darwin" fi done + - name: Wait for PR Head Ref + if: github.event_name == 'pull_request' + run: | + for attempt in 1 2 3 4 5 6; do + if git ls-remote --exit-code origin "refs/pull/${{ github.event.pull_request.number }}/head"; then + exit 0 + fi + + echo "PR head ref is not available yet; retrying in 10s (attempt ${attempt}/6)." + sleep 10 + done + + echo "PR head ref refs/pull/${{ github.event.pull_request.number }}/head is unavailable." + exit 1 - name: Run Install Command run: | curl -fsSL https://raw.githubusercontent.com/shunkakinoki/dotfiles/${{ github.sha }}/install.sh | sh diff --git a/config/hyprland/hyprland.conf b/config/hyprland/hyprland.conf index 80170f2c4..83290770e 100644 --- a/config/hyprland/hyprland.conf +++ b/config/hyprland/hyprland.conf @@ -420,6 +420,7 @@ binde = CTRL ALT SHIFT SUPER, minus, exec, hyprctl -j monitors | jq -r '.[0].sca # Lock Screen # ============================================================================= bind = CTRL ALT SHIFT SUPER, L, exec, noctalia-shell ipc call lockScreen lock +bindl = , switch:on:Lid Switch, exec, noctalia-shell ipc call lockScreen lock # ============================================================================= # Notification Toggle diff --git a/config/noctalia/default.nix b/config/noctalia/default.nix index 9ad825351..19f1b6a22 100644 --- a/config/noctalia/default.nix +++ b/config/noctalia/default.nix @@ -3,6 +3,13 @@ pkgs, ... }: +let + noctaliaShell = inputs.noctalia-shell.packages.${pkgs.system}.default; + noctaliaLockBeforeSleep = pkgs.replaceVars ./lock-before-sleep.sh { + noctalia_shell = "${noctaliaShell}/bin/noctalia-shell"; + sleep = "${pkgs.coreutils}/bin/sleep"; + }; +in { xdg.configFile."noctalia/colorschemes/Dracula-Custom/Dracula-Custom.json" = { source = ./Dracula-Custom.json; @@ -24,9 +31,21 @@ Install.WantedBy = [ "graphical-session.target" ]; }; + systemd.user.services.noctalia-lock-before-sleep = { + Unit = { + Description = "Lock Noctalia before system sleep"; + Before = [ "sleep.target" ]; + }; + Service = { + Type = "oneshot"; + ExecStart = "${pkgs.bash}/bin/bash ${noctaliaLockBeforeSleep}"; + }; + Install.WantedBy = [ "sleep.target" ]; + }; + programs.noctalia-shell = { enable = true; - package = inputs.noctalia-shell.packages.${pkgs.system}.default; + package = noctaliaShell; settings = { bar = { @@ -60,6 +79,7 @@ { id = "PowerProfile"; } { id = "Volume"; } { id = "Brightness"; } + { id = "DarkMode"; } { id = "ControlCenter"; } ]; }; diff --git a/config/noctalia/lock-before-sleep.sh b/config/noctalia/lock-before-sleep.sh new file mode 100644 index 000000000..08cea745c --- /dev/null +++ b/config/noctalia/lock-before-sleep.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# Lock through Noctalia before systemd lets suspend continue. +set -euo pipefail + +NOCTALIA_SHELL="@noctalia_shell@" +SLEEP="@sleep@" + +if ! "$NOCTALIA_SHELL" ipc call lockScreen lock; then + exit 0 +fi + +"$SLEEP" 1 diff --git a/named-hosts/matic/default.nix b/named-hosts/matic/default.nix index 1d4967e69..5b230c57d 100644 --- a/named-hosts/matic/default.nix +++ b/named-hosts/matic/default.nix @@ -210,6 +210,10 @@ import ../../hosts/nixos { }; security.pam.services.noctalia-shell = { fprintAuth = true; + rules.auth.fprintd.settings = { + max-tries = -1; + timeout = -1; + }; }; security.pam.services.sudo = { fprintAuth = true; @@ -246,9 +250,9 @@ import ../../hosts/nixos { # Power button behavior - lock screen instead of shutdown services.logind.settings.Login.HandlePowerKey = "lock"; - # Suspend on lid close + # Suspend on battery lid close; on AC, Hyprland locks on the lid switch event. services.logind.settings.Login.HandleLidSwitch = "suspend"; - services.logind.settings.Login.HandleLidSwitchExternalPower = "suspend"; + services.logind.settings.Login.HandleLidSwitchExternalPower = "ignore"; # Auto timezone (via geolocation) services.geoclue2.enable = true; diff --git a/spec/coverage_spec.sh b/spec/coverage_spec.sh index d90ccdb83..137dde576 100644 --- a/spec/coverage_spec.sh +++ b/spec/coverage_spec.sh @@ -370,6 +370,7 @@ config/hyprland/scripts/record-screen.sh config/hyprland/scripts/toggle-terminal.sh config/k3s/activate.sh config/noctalia/ac-idle-inhibit.sh +config/noctalia/lock-before-sleep.sh config/obsidian/activate.sh config/omp/activate.sh config/openclaw/hydrate.sh diff --git a/spec/hyprland_lid_lock_spec.sh b/spec/hyprland_lid_lock_spec.sh new file mode 100644 index 000000000..713bb159c --- /dev/null +++ b/spec/hyprland_lid_lock_spec.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2329 + +Describe 'config/hyprland/hyprland.conf lid lock binding' +CONFIG="$PWD/config/hyprland/hyprland.conf" + +It 'locks Noctalia when Hyprland reports the lid switch closing' +When run bash -c "grep -F 'bindl = , switch:on:Lid Switch, exec, noctalia-shell ipc call lockScreen lock' '$CONFIG'" +The output should include 'switch:on:Lid Switch' +The output should include 'lockScreen lock' +End + +End diff --git a/spec/matic_lid_policy_spec.sh b/spec/matic_lid_policy_spec.sh new file mode 100644 index 000000000..b554416c7 --- /dev/null +++ b/spec/matic_lid_policy_spec.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2329 + +Describe 'named-hosts/matic/default.nix lid policy' +CONFIG="$PWD/named-hosts/matic/default.nix" + +It 'keeps battery lid close as suspend' +When run bash -c "grep -F 'services.logind.settings.Login.HandleLidSwitch = \"suspend\";' '$CONFIG'" +The output should include 'HandleLidSwitch = "suspend"' +End + +It 'lets Hyprland handle lid close while on AC power' +When run bash -c "grep -F 'services.logind.settings.Login.HandleLidSwitchExternalPower = \"ignore\";' '$CONFIG'" +The output should include 'HandleLidSwitchExternalPower = "ignore"' +End + +End diff --git a/spec/matic_pam_fingerprint_spec.sh b/spec/matic_pam_fingerprint_spec.sh new file mode 100644 index 000000000..d08f478e4 --- /dev/null +++ b/spec/matic_pam_fingerprint_spec.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2329 + +Describe 'named-hosts/matic/default.nix Noctalia fingerprint PAM' +CONFIG="$PWD/named-hosts/matic/default.nix" + +It 'keeps lock-screen fingerprint auth from timing out' +When run bash -c "awk '/security.pam.services.noctalia-shell = \\{/{in_service=1} in_service{print} in_service && /^ \\};/{exit}' '$CONFIG'" +The output should include 'fprintAuth = true;' +The output should include 'max-tries = -1;' +The output should include 'timeout = -1;' +End + +End diff --git a/spec/noctalia_bar_spec.sh b/spec/noctalia_bar_spec.sh new file mode 100644 index 000000000..4b7f21fbf --- /dev/null +++ b/spec/noctalia_bar_spec.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2329 + +Describe 'config/noctalia/default.nix bar widgets' +CONFIG="$PWD/config/noctalia/default.nix" + +It 'places DarkMode immediately after Brightness on the right bar' +When run bash -c "awk '/widgets.right = \\[/{in_right=1} in_right && /id =/ { gsub(/.*id = \"|\";.*/, \"\"); print } in_right && /\\];/{exit}' '$CONFIG' | paste -sd ' ' -" +The output should include 'Brightness DarkMode ControlCenter' +End + +End diff --git a/spec/noctalia_lock_before_sleep_spec.sh b/spec/noctalia_lock_before_sleep_spec.sh new file mode 100644 index 000000000..401f76a9a --- /dev/null +++ b/spec/noctalia_lock_before_sleep_spec.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env bash +# shellcheck disable=SC2016,SC2329 + +Describe 'config/noctalia/lock-before-sleep.sh' +SCRIPT="$PWD/config/noctalia/lock-before-sleep.sh" + +It 'uses bash strict mode' +When run bash -c "head -5 '$SCRIPT'" +The output should include 'set -euo pipefail' +End + +It 'uses injected command paths' +When run bash -c "cat '$SCRIPT'" +The output should include '@noctalia_shell@' +The output should include '@sleep@' +End + +It 'calls Noctalia lock IPC before sleeping' +When run bash -c "cat '$SCRIPT'" +The output should include 'ipc call lockScreen lock' +The output should include '"$SLEEP" 1' +End + +End