Three findings from verifying the #41 merge against the live box with `deploy.sh --check`. One commit because they share the deploy tier, its documentation, and the first test file that tier ever had. **1. Generated palette output was tracked, and sync would have restored it over a live theme.** `dotfiles/zz-blankpad/niri/.config/niri/noctalia.kdl` (`b3d3df4`, 2026-10-18) sat byte-identical to the live file — harmless while the palette held, and `--check` was already proposing `ADOPT … noctalia.kdl`. The moment the theme changed, the next sync would have quarantined the live file and reinstated 2026-10-18's colours. `deploy.sh` now refuses the class outright (`SKIP … (generated theme output)`), `.gitignore` carries the matching patterns so it cannot be re-added, and the file is untracked. **2. A `zz` override older than the file it overrides.** `dotfiles/zz-blankpad/niri/…/ layout.kdl` held focus ring `width 2` / `#e01b24` (`7b7dbf5`, 2026-10-17) while base absorbed `b3d3df4` (2026-10-18): `width 4`, `#ff8c00`. Stow order makes `zz-*` win, and a cross-package owner change relinks *silently* — no quarantine, no warning. Live was linked to base, the newer intent, so `--check` printed `RELINK … layout.kdl` every run and one unattended `deploy.sh` would have reverted the amber focus ring. The duplicate is deleted; base owns the file. **3. Two topologies I had asserted and not measured.** The media law and the `.gitignore` comment both said `~/.local/share/noctalia/wallpapers` symlinks into the repo, so deleting the tracked copies would blank the desktop. Measured: it is a real directory of real files that Noctalia owns; the repo held a duplicate, and the #41 merge deleted that duplicate without the desktop flickering. The correct general law replaces the false one — untracking a path deletes the file in every other checkout, `git rm --cached` on the branch notwithstanding — and the restore procedure now points at the app's directory, which `deploy.sh` does not manage. The guard is `tests/deploy.bats`, black-box over exit status, stdout, the symlink shape under `$HOME`, and the quarantine directory. Before the change: test 1 and test 2 fail, test 2 because the live palette really is quarantined and reverted. After: 4/4, including the control that an ordinary identical config is still adopted — an exclusion nobody can turn off is just a broken tool. Verification: `bats tests/` 66/66, `kb-lint.sh omp-docs` 0 violations, `kb-coverage.py` 0 issues, and live `deploy.sh --check` on blankpad reports `SKIP … (generated theme output)` with `actions=0` instead of `ADOPT … noctalia.kdl`. The real `deploy.sh` run that clears the remaining `RELINK` lines is deliberately left until this is in main — running it from a worktree would repoint live symlinks into a checkout the heartbeat reaps. Refs #42
77 lines
3.4 KiB
Bash
Executable File
77 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bats
|
|
# tests/deploy.bats — black-box tests for scripts/deploy.sh (Refs #42)
|
|
#
|
|
# Contract (see script header): the repo checkout IS the deployment; sync adopts
|
|
# identicals, links new files, quarantines-and-replaces divergents, and stows the
|
|
# zz-$(hostname) package last. One thing it must NEVER do is deploy generated theme
|
|
# output: noctalia rewrites `noctalia.*` / `themes/noctalia*` in place, so a tracked
|
|
# copy is a stale snapshot, and a sync would revert a live palette to whatever colour
|
|
# scheme was current on the day it was committed.
|
|
#
|
|
# Nothing is observed except exit status, stdout, the file/symlink shape under $HOME,
|
|
# and the quarantine directory.
|
|
|
|
setup() {
|
|
TEST_TMP="$(mktemp -d)"
|
|
REPO="$TEST_TMP/repo"
|
|
DEPLOY="$BATS_TEST_DIRNAME/../scripts/deploy.sh"
|
|
mkdir -p "$REPO/scripts" "$REPO/dotfiles"
|
|
# A git repo, because the deployment checkout IS one and deploy.sh arms hooksPath.
|
|
git init -q -b main "$REPO"
|
|
cp "$DEPLOY" "$REPO/scripts/deploy.sh"
|
|
chmod +x "$REPO/scripts/deploy.sh"
|
|
export HOME="$TEST_TMP/home"
|
|
mkdir -p "$HOME"
|
|
export DEPLOY_REPO="$REPO" DEPLOY_HOST=box
|
|
}
|
|
|
|
teardown() { rm -rf "$TEST_TMP"; }
|
|
|
|
# repo_file <pkg-relative path> <content>
|
|
repo_file() { mkdir -p "$(dirname "$REPO/dotfiles/$1")"; printf '%s\n' "$2" > "$REPO/dotfiles/$1"; }
|
|
# live_file <absolute path under $HOME> <content>
|
|
live_file() { mkdir -p "$(dirname "$1")"; printf '%s\n' "$2" > "$1"; }
|
|
|
|
@test "generated theme output is never adopted into a symlink" {
|
|
repo_file "ghostty/.config/ghostty/themes/noctalia" 'background = "#f43841"'
|
|
live_file "$HOME/.config/ghostty/themes/noctalia" 'background = "#f43841"'
|
|
run "$REPO/scripts/deploy.sh"
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"SKIP"*".config/ghostty/themes/noctalia"* ]]
|
|
[ -f "$HOME/.config/ghostty/themes/noctalia" ]
|
|
[ ! -L "$HOME/.config/ghostty/themes/noctalia" ]
|
|
}
|
|
|
|
@test "a diverged live palette is never quarantined and reverted to a stale copy" {
|
|
# The dangerous shape: the tracked file matches today's palette, the theme changes
|
|
# tomorrow, and sync would quarantine the live file and restore the stale one.
|
|
repo_file "niri/.config/niri/noctalia.kdl" 'active-color "#e01b24"'
|
|
live_file "$HOME/.config/niri/noctalia.kdl" 'active-color "#ff8c00"'
|
|
run "$REPO/scripts/deploy.sh"
|
|
[ "$status" -eq 0 ]
|
|
grep -q 'active-color "#ff8c00"' "$HOME/.config/niri/noctalia.kdl"
|
|
[ ! -L "$HOME/.config/niri/noctalia.kdl" ]
|
|
[ ! -d "$REPO/.quarantine" ]
|
|
}
|
|
|
|
@test "an ordinary identical config is still adopted" {
|
|
# Control against an exclusion so broad the tool stops deploying anything.
|
|
repo_file "ghostty/.config/ghostty/config.ghostty" 'theme = "gruber"'
|
|
live_file "$HOME/.config/ghostty/config.ghostty" 'theme = "gruber"'
|
|
run "$REPO/scripts/deploy.sh"
|
|
[ "$status" -eq 0 ]
|
|
[ -L "$HOME/.config/ghostty/config.ghostty" ]
|
|
[ "$(realpath "$HOME/.config/ghostty/config.ghostty")" = "$(realpath "$REPO/dotfiles/ghostty/.config/ghostty/config.ghostty")" ]
|
|
}
|
|
|
|
@test "--check reports and writes nothing" {
|
|
repo_file "ghostty/.config/ghostty/config.ghostty" 'theme = "gruber"'
|
|
live_file "$HOME/.config/ghostty/config.ghostty" 'theme = "tokyo-night"'
|
|
run "$REPO/scripts/deploy.sh" --check
|
|
[ "$status" -eq 0 ]
|
|
[[ "$output" == *"DRIFT"* || "$output" == *"QUAR"* ]]
|
|
[ ! -L "$HOME/.config/ghostty/config.ghostty" ]
|
|
grep -q 'theme = "tokyo-night"' "$HOME/.config/ghostty/config.ghostty"
|
|
[ ! -d "$REPO/.quarantine" ]
|
|
}
|