From 3ec72c8479f30ae539c164fdd6e6799ada5c9327 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 11:24:47 -0500 Subject: [PATCH 01/11] Bring radiantwave up to date + dev --- flake.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/flake.lock b/flake.lock index 5a28305..3b17c75 100644 --- a/flake.lock +++ b/flake.lock @@ -220,11 +220,11 @@ "nixpkgs": "nixpkgs_3" }, "locked": { - "lastModified": 1787322563, - "narHash": "sha256-Eh3H6sYhpvXBNoPOX9/2On13YVRlLpEkhFrEU1pdnJM=", + "lastModified": 1787341934, + "narHash": "sha256-pWGpgM5acdCO02H8P3KKtdv09n9ucnI3cg8d3/tvwtk=", "ref": "main", - "rev": "3c9de0bee2c6915d6a48ba44e985e681e48daba2", - "revCount": 33, + "rev": "b96631c374682088088b3d679359d192a0ae74d6", + "revCount": 35, "type": "git", "url": "https://gitea.radiantwavetech.com/RadiantWaveTech/radiantwave.git" }, @@ -240,11 +240,11 @@ "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1787322563, - "narHash": "sha256-Eh3H6sYhpvXBNoPOX9/2On13YVRlLpEkhFrEU1pdnJM=", + "lastModified": 1787341934, + "narHash": "sha256-pWGpgM5acdCO02H8P3KKtdv09n9ucnI3cg8d3/tvwtk=", "ref": "dev", - "rev": "3c9de0bee2c6915d6a48ba44e985e681e48daba2", - "revCount": 33, + "rev": "b96631c374682088088b3d679359d192a0ae74d6", + "revCount": 35, "type": "git", "url": "https://gitea.radiantwavetech.com/RadiantWaveTech/radiantwave.git" }, From 59e9f7ce29fcf00a1c220ba83b2dc6bb95f0f8f6 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 14:18:48 -0500 Subject: [PATCH 02/11] Update RadiantWave and add Attic cache --- configuration.nix | 8 ++++++++ flake.lock | 8 ++++---- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/configuration.nix b/configuration.nix index 89908d8..8a2966c 100644 --- a/configuration.nix +++ b/configuration.nix @@ -96,6 +96,14 @@ in # NixOS settings. nix.settings.experimental-features = [ "nix-command" "flakes" ]; nix.settings.accept-flake-config = true; + nix.settings.extra-substituters = [ + "https://attic.radiantwavetech.com/radiantwave" + "https://attic.radiantwavetech.com/radiantwave-dev" + ]; + nix.settings.extra-trusted-public-keys = [ + "radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA=" + "radiantwave-dev:B8FhLu3MQ9JfeEIHIKNrKxnP+3akzzkqMbTZR4hRfj0=" + ]; system.stateVersion = "24.05"; ############################################################ diff --git a/flake.lock b/flake.lock index 3b17c75..55f4eb9 100644 --- a/flake.lock +++ b/flake.lock @@ -240,11 +240,11 @@ "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1787341934, - "narHash": "sha256-pWGpgM5acdCO02H8P3KKtdv09n9ucnI3cg8d3/tvwtk=", + "lastModified": 1787507168, + "narHash": "sha256-LeMd6lnfhnixC+e77yM5DG5gVYaEa+URfKD+yEmenJc=", "ref": "dev", - "rev": "b96631c374682088088b3d679359d192a0ae74d6", - "revCount": 35, + "rev": "f2a40cd0194fe920a0fc1062d57a93dfc6693b52", + "revCount": 38, "type": "git", "url": "https://gitea.radiantwavetech.com/RadiantWaveTech/radiantwave.git" }, From 7778da3867233f355334adc6b59a73bf66f7ea85 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 14:49:44 -0500 Subject: [PATCH 03/11] fix: tolerate empty archive globs; clone dispatched ref in dev workflow --- .gitea/workflows/build-dev.yml | 4 ++-- .gitea/workflows/build-prod-rpi.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitea/workflows/build-dev.yml b/.gitea/workflows/build-dev.yml index 5fb76e5..bf4cc2d 100644 --- a/.gitea/workflows/build-dev.yml +++ b/.gitea/workflows/build-dev.yml @@ -9,7 +9,7 @@ jobs: steps: - name: Checkout - run: git clone --depth 1 ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git . + run: git clone --depth 1 --branch "${GITEA_REF_NAME}" ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git . # flake.lock is updated manually (committing an updated lock is the # release trigger); CI only builds what is checked in. @@ -33,7 +33,7 @@ jobs: - name: Move old dev images to archive run: | - ssh nclack@157.245.124.103 'mv /mnt/infrastructure_data/files/images/radiantwave-kiosk-dev* /mnt/infrastructure_data/files/images/archives/' + ssh nclack@157.245.124.103 'find /mnt/infrastructure_data/files/images -maxdepth 1 -name "radiantwave-kiosk-dev*" -exec mv {} /mnt/infrastructure_data/files/images/archives/ ;' - name: Copy kiosk ISO to fileserver run: | diff --git a/.gitea/workflows/build-prod-rpi.yml b/.gitea/workflows/build-prod-rpi.yml index fd15415..709cbde 100644 --- a/.gitea/workflows/build-prod-rpi.yml +++ b/.gitea/workflows/build-prod-rpi.yml @@ -27,7 +27,7 @@ jobs: - name: Move old Raspberry Pi images to archive run: | - ssh nclack@157.245.124.103 'mv /mnt/infrastructure_data/files/images/radiantwave-rpi* /mnt/infrastructure_data/files/images/archives/' + ssh nclack@157.245.124.103 'find /mnt/infrastructure_data/files/images -maxdepth 1 -name "radiantwave-rpi*" -exec mv {} /mnt/infrastructure_data/files/images/archives/ ;' - name: Copy Raspberry Pi image to fileserver run: | From 6951d35310caebe8860252c9f78ac4de1c3ccd05 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 14:53:32 -0500 Subject: [PATCH 04/11] fix: make manual dev checkout work (fetch all branch tips, drop bad cd) --- .gitea/workflows/build-dev.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitea/workflows/build-dev.yml b/.gitea/workflows/build-dev.yml index bf4cc2d..d81f216 100644 --- a/.gitea/workflows/build-dev.yml +++ b/.gitea/workflows/build-dev.yml @@ -8,11 +8,11 @@ jobs: runs-on: build-server steps: - - name: Checkout - run: git clone --depth 1 --branch "${GITEA_REF_NAME}" ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git . + - name: Clone Repository + run: git clone --depth 1 --no-single-branch ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git . - # flake.lock is updated manually (committing an updated lock is the - # release trigger); CI only builds what is checked in. + - name: Checkout dev branch + run: git checkout dev - name: Prepare output directory run: mkdir -p /home/user/radiantwave From 46384e6cf750f03869288783e2b15c919c514c1f Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 15:07:22 -0500 Subject: [PATCH 05/11] Fix attic upload --- .gitea/workflows/build-dev.yml | 96 +++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/.gitea/workflows/build-dev.yml b/.gitea/workflows/build-dev.yml index d81f216..e603c25 100644 --- a/.gitea/workflows/build-dev.yml +++ b/.gitea/workflows/build-dev.yml @@ -1,44 +1,68 @@ -name: Build Dev ISO - +name: build-dev on: - workflow_dispatch: - + # Every push to dev: build, run the offline test suite, publish to the + # dev Attic cache. + push: + branches: [dev] jobs: - build-dev-iso: + nix-build: runs-on: build-server - steps: - - name: Clone Repository - run: git clone --depth 1 --no-single-branch ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git . - - - name: Checkout dev branch - run: git checkout dev - - - name: Prepare output directory - run: mkdir -p /home/user/radiantwave - - # --- Kiosk ISO --- - - name: Build kiosk ISO + # actions/checkout@v4 is unreliable on host-mode runners (its files are + # copied into the workspace instead of the repo), so clone explicitly. + - name: Checkout run: | - export NIXPKGS_ALLOW_UNFREE=1 - . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh - nix build -L --impure .#nixosConfigurations.dev-iso.config.system.build.isoImage - - - name: Rename kiosk ISO + rm -rf ./* ./.[!.]* 2>/dev/null || true + git config --global http.extraheader "Authorization: token ${{ github.token }}" + git clone --branch "${{ gitea.ref_name }}" \ + "${{ gitea.server_url }}/${{ gitea.repository }}.git" . + test -f flake.nix + git log --oneline -1 + - name: Inspect workspace run: | - ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S) - FILENAME="radiantwave-kiosk-dev-iso-${ISO_DATE}.iso" - cp -L result/iso/*.iso "/home/user/radiantwave/${FILENAME}" - echo "KIOSK_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV" - - - name: Move old dev images to archive + pwd + ls -la + git rev-parse --show-toplevel 2>&1 || true + git remote -v 2>&1 || true + git describe --tags --always 2>&1 || true + test -f flake.nix && echo "flake.nix present" || echo "NO flake.nix" + # Dev builds fingerprint as the short commit hash. + # Persisted via GITHUB_ENV so the impure nix eval below reads it via + # builtins.getEnv. + - name: Compute version run: | - ssh nclack@157.245.124.103 'find /mnt/infrastructure_data/files/images -maxdepth 1 -name "radiantwave-kiosk-dev*" -exec mv {} /mnt/infrastructure_data/files/images/archives/ ;' - - - name: Copy kiosk ISO to fileserver + echo "APP_VERSION=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV" + # checks is keyed per-system (checks..default); nix build's + # #attr shorthand can't resolve it, so resolve the current system inline. + # --impure lets the flake read APP_VERSION via builtins.getEnv + # (pure evals always get the package defaults). + - name: Build package run: | - scp "/home/user/radiantwave/${KIOSK_ISO_FILENAME}" \ - radiantwave-infra:/mnt/infrastructure_data/files/images/ - - - name: Cleanup kiosk ISO - run: rm -f "/home/user/radiantwave/${KIOSK_ISO_FILENAME}" + nix build -L ".#packages.$(nix eval --impure --raw --expr 'builtins.currentSystem').default" \ + --impure --out-link result-pkg + # The offline test suite runs in the check derivation's checkPhase. + # This is a separate build/output from the package itself. + - name: Build + offline test suite + run: | + nix build -L ".#checks.$(nix eval --impure --raw --expr 'builtins.currentSystem').default" \ + --impure --out-link result-checks + - name: Live portal tests + env: + RWT_LIVE_ACCOUNT_EMAIL: ${{ secrets.RWT_LIVE_ACCOUNT_EMAIL }} + RWT_LIVE_LICENSE_EMAIL: ${{ secrets.RWT_LIVE_LICENSE_EMAIL }} + RWT_LIVE_LICENSE_KEY: ${{ secrets.RWT_LIVE_LICENSE_KEY }} + run: | + nix develop --command bash -c ' + cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug + cmake --build build --target test_api_client test_license_service + ./build/test_api_client + ./build/test_license_service + ' + # Dev closure (the actual package, not the check output) lands in the + # dev cache. + - name: Push to Attic dev cache + env: + ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN_DEV }} + run: | + attic login radiantwave https://attic.radiantwavetech.com "$ATTIC_TOKEN" + attic push radiantwave:radiantwave-dev ./result-pkg From 588f0e4aa1650b7b049b9e7d55d02b0ba67f2650 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 15:22:34 -0500 Subject: [PATCH 06/11] ci: pull closures from Attic caches in prod builds --- .gitea/workflows/build-prod-android.yml | 5 +++++ .gitea/workflows/build-prod-commercial.yml | 5 +++++ .gitea/workflows/build-prod-kiosk.yml | 5 +++++ .gitea/workflows/build-prod-rpi.yml | 5 +++++ 4 files changed, 20 insertions(+) diff --git a/.gitea/workflows/build-prod-android.yml b/.gitea/workflows/build-prod-android.yml index af18b88..5a3db42 100644 --- a/.gitea/workflows/build-prod-android.yml +++ b/.gitea/workflows/build-prod-android.yml @@ -1,6 +1,11 @@ on: workflow_dispatch: +env: + NIX_CONFIG: | + extra-substituters = https://attic.radiantwavetech.com/radiantwave + extra-trusted-public-keys = radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA= + jobs: build-android: runs-on: build-server diff --git a/.gitea/workflows/build-prod-commercial.yml b/.gitea/workflows/build-prod-commercial.yml index 5b56db4..128b176 100644 --- a/.gitea/workflows/build-prod-commercial.yml +++ b/.gitea/workflows/build-prod-commercial.yml @@ -1,6 +1,11 @@ on: workflow_dispatch: +env: + NIX_CONFIG: | + extra-substituters = https://attic.radiantwavetech.com/radiantwave + extra-trusted-public-keys = radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA= + jobs: build-commercial: runs-on: build-server diff --git a/.gitea/workflows/build-prod-kiosk.yml b/.gitea/workflows/build-prod-kiosk.yml index beaae9e..d341a4e 100644 --- a/.gitea/workflows/build-prod-kiosk.yml +++ b/.gitea/workflows/build-prod-kiosk.yml @@ -1,6 +1,11 @@ on: workflow_dispatch: +env: + NIX_CONFIG: | + extra-substituters = https://attic.radiantwavetech.com/radiantwave + extra-trusted-public-keys = radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA= + jobs: build-kiosk: runs-on: build-server diff --git a/.gitea/workflows/build-prod-rpi.yml b/.gitea/workflows/build-prod-rpi.yml index 709cbde..4d8673a 100644 --- a/.gitea/workflows/build-prod-rpi.yml +++ b/.gitea/workflows/build-prod-rpi.yml @@ -1,6 +1,11 @@ on: workflow_dispatch: +env: + NIX_CONFIG: | + extra-substituters = https://attic.radiantwavetech.com/radiantwave https://nixos-raspberrypi.cachix.org + extra-trusted-public-keys = radiantwave:QADrjpBWJssTZ3KmiZtcWEf4uAm66oOlHmtQI3jkrgA= nixos-raspberrypi.cachix.org-1:4iMO9LXa8BqhU+Rpg6LQKiGa2lsNh/j2oiYLNOQ5sPI= + jobs: build-rpi: runs-on: build-server From 84ec13b1f9209ddcb0451e4c83f10e1af19a0905 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 15:22:34 -0500 Subject: [PATCH 07/11] ci: restore dev ISO workflow, auto-build on dev push, use Attic --- .gitea/workflows/build-dev.yml | 102 ++++++++++++++------------------- 1 file changed, 43 insertions(+), 59 deletions(-) diff --git a/.gitea/workflows/build-dev.yml b/.gitea/workflows/build-dev.yml index e603c25..f655920 100644 --- a/.gitea/workflows/build-dev.yml +++ b/.gitea/workflows/build-dev.yml @@ -1,68 +1,52 @@ -name: build-dev +name: Build Dev ISO + on: - # Every push to dev: build, run the offline test suite, publish to the - # dev Attic cache. + workflow_dispatch: push: - branches: [dev] + branches: + - dev + +env: + NIX_CONFIG: | + extra-substituters = https://attic.radiantwavetech.com/radiantwave-dev + extra-trusted-public-keys = radiantwave-dev:B8FhLu3MQ9JfeEIHIKNrKxnP+3akzzkqMbTZR4hRfj0= + jobs: - nix-build: + build-dev-iso: runs-on: build-server + steps: - # actions/checkout@v4 is unreliable on host-mode runners (its files are - # copied into the workspace instead of the repo), so clone explicitly. - - name: Checkout + - name: Clone Repository + run: git clone --depth 1 --no-single-branch ssh://git@gitea.radiantwavetech.com:2222/RadiantWaveTech/KioskConfig.git . + + - name: Checkout dev branch + run: git checkout dev + + - name: Prepare output directory + run: mkdir -p /home/user/radiantwave + + # --- Kiosk ISO --- + - name: Build kiosk ISO run: | - rm -rf ./* ./.[!.]* 2>/dev/null || true - git config --global http.extraheader "Authorization: token ${{ github.token }}" - git clone --branch "${{ gitea.ref_name }}" \ - "${{ gitea.server_url }}/${{ gitea.repository }}.git" . - test -f flake.nix - git log --oneline -1 - - name: Inspect workspace + export NIXPKGS_ALLOW_UNFREE=1 + . /nix/var/nix/profiles/default/etc/profile.d/nix-daemon.sh + nix build -L --impure .#nixosConfigurations.dev-iso.config.system.build.isoImage + + - name: Rename kiosk ISO run: | - pwd - ls -la - git rev-parse --show-toplevel 2>&1 || true - git remote -v 2>&1 || true - git describe --tags --always 2>&1 || true - test -f flake.nix && echo "flake.nix present" || echo "NO flake.nix" - # Dev builds fingerprint as the short commit hash. - # Persisted via GITHUB_ENV so the impure nix eval below reads it via - # builtins.getEnv. - - name: Compute version + ISO_DATE=$(date +%Y-%m-%d_%H-%M-%S) + FILENAME="radiantwave-kiosk-dev-iso-${ISO_DATE}.iso" + cp -L result/iso/*.iso "/home/user/radiantwave/${FILENAME}" + echo "KIOSK_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV" + + - name: Move old dev images to archive run: | - echo "APP_VERSION=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV" - # checks is keyed per-system (checks..default); nix build's - # #attr shorthand can't resolve it, so resolve the current system inline. - # --impure lets the flake read APP_VERSION via builtins.getEnv - # (pure evals always get the package defaults). - - name: Build package + ssh nclack@157.245.124.103 'find /mnt/infrastructure_data/files/images -maxdepth 1 -name "radiantwave-kiosk-dev*" -exec mv {} /mnt/infrastructure_data/files/images/archives/ ;' + + - name: Copy kiosk ISO to fileserver run: | - nix build -L ".#packages.$(nix eval --impure --raw --expr 'builtins.currentSystem').default" \ - --impure --out-link result-pkg - # The offline test suite runs in the check derivation's checkPhase. - # This is a separate build/output from the package itself. - - name: Build + offline test suite - run: | - nix build -L ".#checks.$(nix eval --impure --raw --expr 'builtins.currentSystem').default" \ - --impure --out-link result-checks - - name: Live portal tests - env: - RWT_LIVE_ACCOUNT_EMAIL: ${{ secrets.RWT_LIVE_ACCOUNT_EMAIL }} - RWT_LIVE_LICENSE_EMAIL: ${{ secrets.RWT_LIVE_LICENSE_EMAIL }} - RWT_LIVE_LICENSE_KEY: ${{ secrets.RWT_LIVE_LICENSE_KEY }} - run: | - nix develop --command bash -c ' - cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug - cmake --build build --target test_api_client test_license_service - ./build/test_api_client - ./build/test_license_service - ' - # Dev closure (the actual package, not the check output) lands in the - # dev cache. - - name: Push to Attic dev cache - env: - ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN_DEV }} - run: | - attic login radiantwave https://attic.radiantwavetech.com "$ATTIC_TOKEN" - attic push radiantwave:radiantwave-dev ./result-pkg + scp "/home/user/radiantwave/${KIOSK_ISO_FILENAME}" \ + radiantwave-infra:/mnt/infrastructure_data/files/images/ + + - name: Cleanup kiosk ISO + run: rm -f "/home/user/radiantwave/${KIOSK_ISO_FILENAME}" From 2e862c13a84b78c76810d462e014abd3c8443a14 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 15:45:11 -0500 Subject: [PATCH 08/11] fix: replace fragile ssh archive one-liners with tools/archive-images.sh The inline find -exec broke through the double shell hop (the remote shell consumed the ; separator). The script pipes its payload to remote bash via stdin, tolerates zero matches, and fails loudly on missing directories or failed moves. --- .gitea/workflows/build-dev.yml | 3 +- .gitea/workflows/build-prod-rpi.yml | 3 +- tools/archive-images.sh | 56 +++++++++++++++++++++++++++++ 3 files changed, 58 insertions(+), 4 deletions(-) create mode 100755 tools/archive-images.sh diff --git a/.gitea/workflows/build-dev.yml b/.gitea/workflows/build-dev.yml index f655920..dd685ba 100644 --- a/.gitea/workflows/build-dev.yml +++ b/.gitea/workflows/build-dev.yml @@ -40,8 +40,7 @@ jobs: echo "KIOSK_ISO_FILENAME=${FILENAME}" >> "$GITHUB_ENV" - name: Move old dev images to archive - run: | - ssh nclack@157.245.124.103 'find /mnt/infrastructure_data/files/images -maxdepth 1 -name "radiantwave-kiosk-dev*" -exec mv {} /mnt/infrastructure_data/files/images/archives/ ;' + run: tools/archive-images.sh nclack@157.245.124.103 /mnt/infrastructure_data/files/images /mnt/infrastructure_data/files/images/archives 'radiantwave-kiosk-dev*' - name: Copy kiosk ISO to fileserver run: | diff --git a/.gitea/workflows/build-prod-rpi.yml b/.gitea/workflows/build-prod-rpi.yml index 4d8673a..bb267ce 100644 --- a/.gitea/workflows/build-prod-rpi.yml +++ b/.gitea/workflows/build-prod-rpi.yml @@ -31,8 +31,7 @@ jobs: echo "RPI_IMAGE_FILENAME=${FILENAME}" >> "$GITHUB_ENV" - name: Move old Raspberry Pi images to archive - run: | - ssh nclack@157.245.124.103 'find /mnt/infrastructure_data/files/images -maxdepth 1 -name "radiantwave-rpi*" -exec mv {} /mnt/infrastructure_data/files/images/archives/ ;' + run: tools/archive-images.sh nclack@157.245.124.103 /mnt/infrastructure_data/files/images /mnt/infrastructure_data/files/images/archives 'radiantwave-rpi*' - name: Copy Raspberry Pi image to fileserver run: | diff --git a/tools/archive-images.sh b/tools/archive-images.sh new file mode 100755 index 0000000..3f6d53c --- /dev/null +++ b/tools/archive-images.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash +# Archive old build images on the fileserver before publishing new ones. +# +# Usage: tools/archive-images.sh ... +# +# Zero matching files is fine (nothing to archive yet); a missing directory +# or a failed move aborts non-zero so CI stops before publishing. +# The remote half is piped to `bash -s` over stdin so there is no nested +# shell quoting to get wrong. + +set -euo pipefail + +die() { echo "error: $*" >&2; exit 1; } + +(( $# >= 4 )) || die "usage: $0 ..." + +target=$1 images_dir=$2 archive_dir=$3 +shift 3 +patterns=("$@") + +for v in "$images_dir" "$archive_dir" "${patterns[@]}"; do + case $v in + *[\ space\'\"]*) die "unsafe argument (whitespace/quotes): $v" ;; + esac +done + +echo "Archiving previous images on $target:" +printf ' pattern: %s\n' "${patterns[@]}" + +# Assignments prefixed to `bash -s` are parsed by the remote shell as +# environment variables for the script below; the quoted heredoc marker +# keeps every byte of the payload literal until bash executes it. +ssh "$target" "IMAGES_DIR=$images_dir ARCHIVE_DIR=$archive_dir bash -s" <<'REMOTE' +set -euo pipefail +shopt -s nullglob + +if [ ! -d "$IMAGES_DIR" ]; then + echo "error: images dir not found: $IMAGES_DIR" >&2 + exit 1 +fi +if [ ! -d "$ARCHIVE_DIR" ]; then + echo "error: archive dir not found: $ARCHIVE_DIR" >&2 + exit 1 +fi + +moved=0 +for pat in "${PATTERNS[@]}"; do + for f in "$IMAGES_DIR"/$pat; do + echo " archiving $(basename "$f")" + mv "$f" "$ARCHIVE_DIR/" + moved=$((moved + 1)) + done +done + +echo "Archived $moved file(s)." +REMOTE From d26cec2a53bebb92c0c11d0124ff6743e839c118 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 15:55:05 -0500 Subject: [PATCH 09/11] fix: broken whitespace guard in archive-images.sh The case bracket expression [\ space\'\"] listed the letters s,p,a,c,e as a character set instead of matching whitespace, rejecting every normal path. Use the POSIX [[:space:]] class. --- tools/archive-images.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/archive-images.sh b/tools/archive-images.sh index 3f6d53c..cad0525 100755 --- a/tools/archive-images.sh +++ b/tools/archive-images.sh @@ -20,7 +20,7 @@ patterns=("$@") for v in "$images_dir" "$archive_dir" "${patterns[@]}"; do case $v in - *[\ space\'\"]*) die "unsafe argument (whitespace/quotes): $v" ;; + *[[:space:]\'\"]*) die "unsafe argument (whitespace/quotes): $v" ;; esac done From 9b0036b4da8997ef60950c9eb876edbfc54c0868 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 17:33:57 -0500 Subject: [PATCH 10/11] Update RadiantWave ef723b2 --- flake.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/flake.lock b/flake.lock index 55f4eb9..5778b60 100644 --- a/flake.lock +++ b/flake.lock @@ -240,11 +240,11 @@ "nixpkgs": "nixpkgs_4" }, "locked": { - "lastModified": 1787507168, - "narHash": "sha256-LeMd6lnfhnixC+e77yM5DG5gVYaEa+URfKD+yEmenJc=", + "lastModified": 1787522765, + "narHash": "sha256-D3KOrGcAH07lvKYgyiwejOQpDW91js7zI6l87WdabLk=", "ref": "dev", - "rev": "f2a40cd0194fe920a0fc1062d57a93dfc6693b52", - "revCount": 38, + "rev": "63265cc22f3055a782a0114e92c57a36bef723b2", + "revCount": 40, "type": "git", "url": "https://gitea.radiantwavetech.com/RadiantWaveTech/radiantwave.git" }, From bd9146e641d02ceb777abc54dbdffcfa317f8d72 Mon Sep 17 00:00:00 2001 From: NeilClack Date: Sun, 23 Aug 2026 17:54:01 -0500 Subject: [PATCH 11/11] Allow kiosk to restart getty@tty1 via scoped polkit rule The RadiantWave app can now apply pending updates by restarting its own TTY session (plain systemctl, no sudo): getty re-autologins kiosk and the login shell relaunches cage + app from the new generation. Also drop the cleanRadiantFiles activation script. --- configuration.nix | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/configuration.nix b/configuration.nix index 8a2966c..e51b742 100644 --- a/configuration.nix +++ b/configuration.nix @@ -55,6 +55,22 @@ in } ]; + # Let the kiosk app apply pending updates by restarting its own TTY + # session (re-autologin -> fresh cage + RadiantWave). Scoped to exactly + # one unit and verb; everything else keeps stock (denied) policy. + security.polkit.enable = true; + environment.etc."polkit-1/rules.d/10-kiosk-getty.rules".text = '' + polkit.addRule(function(action, subject) { + if (subject.user !== "kiosk") return null; + if (action.id !== "org.freedesktop.systemd1.manage-units") return null; + var unit = action.lookup("unit"); + var verb = action.lookup("verb"); + if ((unit === "getty@tty1.service" || unit === "getty@tty1") && verb === "restart") { + return polkit.Result.YES; + } + }); + ''; + hardware.graphics.enable = true; time.timeZone = "America/Chicago"; @@ -69,10 +85,6 @@ in operation = "switch"; }; - system.activationScripts.cleanRadiantFiles = '' - rm -rf /home/kiosk/.local/radiantwave/audio - ''; - # Virtual machine declaration virtualisation.vmVariant = { boot.loader.systemd-boot.enable = pkgs.lib.mkForce false;