We had a well-covered test/verify pipeline for the docs SSoT (docs/verify-manual.py) but nothing exercising the actual shell config code in CI — only the manual pre-push check the maintainer ran by hand.
Adds tests/run-tests.fish: syntax-lints every tracked .fish file (fish -n), then loads the config in an isolated scratch HOME/XDG sandbox and runs the functional suite in tests/functional.fish — 10 checks covering XDG defaults, PATH/CDPATH setup, vi key bindings, abbreviations, core function autoloading, the exit/smart_exit rewire, and the opinionated-component registry (including its fail-open default).
The sandbox copies config-relevant files into a throwaway temp tree rather than symlinking the checkout — this repo doubles as a real ~/.config/fish, so a symlinked sandbox would let universal-variable writes (e.g. first-run's set -U) leak into the real, gitignored fish_variables file. Verified locally: fish_variables's mtime is unchanged across repeated test runs.
Wires the suite into .github/workflows/build-docs.yml as a new test job; build-docs now needs: test, so a broken config can no longer get built and published to the docs site.
Documents the workflow in a new README Testing section.
Manual Verification Checklist
fish tests/run-tests.fish exits 0 locally (216/216 lint, 10/10 functional checks)
Intentionally breaking a feature (e.g. commenting out an abbreviation) makes the corresponding test_* check fail and the script exit non-zero
Introducing a .fish syntax error makes the lint phase fail and the script exit non-zero
On push, the Gitea Actions test job runs and completes before build-docs starts
README's new Testing section renders correctly and its Table of Contents link works
## Summary
- We had a well-covered test/verify pipeline for the docs SSoT (`docs/verify-manual.py`) but nothing exercising the actual shell config code in CI — only the manual pre-push check the maintainer ran by hand.
- Adds `tests/run-tests.fish`: syntax-lints every tracked `.fish` file (`fish -n`), then loads the config in an isolated scratch `HOME`/XDG sandbox and runs the functional suite in `tests/functional.fish` — 10 checks covering XDG defaults, `PATH`/`CDPATH` setup, vi key bindings, abbreviations, core function autoloading, the `exit`/`smart_exit` rewire, and the opinionated-component registry (including its fail-open default).
- The sandbox copies config-relevant files into a throwaway temp tree rather than symlinking the checkout — this repo doubles as a real `~/.config/fish`, so a symlinked sandbox would let universal-variable writes (e.g. first-run's `set -U`) leak into the real, gitignored `fish_variables` file. Verified locally: `fish_variables`'s mtime is unchanged across repeated test runs.
- Wires the suite into `.github/workflows/build-docs.yml` as a new `test` job; `build-docs` now `needs: test`, so a broken config can no longer get built and published to the docs site.
- Documents the workflow in a new README **Testing** section.
## Manual Verification Checklist
- [x] `fish tests/run-tests.fish` exits 0 locally (216/216 lint, 10/10 functional checks)
- [x] Intentionally breaking a feature (e.g. commenting out an abbreviation) makes the corresponding `test_*` check fail and the script exit non-zero
- [x] Introducing a `.fish` syntax error makes the lint phase fail and the script exit non-zero
- [x] On push, the Gitea Actions `test` job runs and completes before `build-docs` starts
- [x] README's new Testing section renders correctly and its Table of Contents link works
Adds tests/run-tests.fish (syntax lint over every .fish file, plus a
sandboxed interactive load) and tests/functional.fish (10 checks
covering XDG/PATH/CDPATH setup, key bindings, abbreviations, core
functions, exit rewiring, and the opinionated-component registry).
The sandbox copies config-relevant files into a scratch HOME/XDG tree
rather than symlinking the checkout, since this repo also serves as a
live ~/.config/fish and a symlink would let universal-variable writes
leak into the real fish_variables file.
Wires the suite into build-docs.yml as a `test` job that `build-docs`
now depends on, so a broken config can no longer get published to the
docs site. Documents the workflow in the README's new Testing section.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
docs/verify-manual.py) but nothing exercising the actual shell config code in CI — only the manual pre-push check the maintainer ran by hand.tests/run-tests.fish: syntax-lints every tracked.fishfile (fish -n), then loads the config in an isolated scratchHOME/XDG sandbox and runs the functional suite intests/functional.fish— 10 checks covering XDG defaults,PATH/CDPATHsetup, vi key bindings, abbreviations, core function autoloading, theexit/smart_exitrewire, and the opinionated-component registry (including its fail-open default).~/.config/fish, so a symlinked sandbox would let universal-variable writes (e.g. first-run'sset -U) leak into the real, gitignoredfish_variablesfile. Verified locally:fish_variables's mtime is unchanged across repeated test runs..github/workflows/build-docs.ymlas a newtestjob;build-docsnowneeds: test, so a broken config can no longer get built and published to the docs site.Manual Verification Checklist
fish tests/run-tests.fishexits 0 locally (216/216 lint, 10/10 functional checks)test_*check fail and the script exit non-zero.fishsyntax error makes the lint phase fail and the script exit non-zerotestjob runs and completes beforebuild-docsstarts