Skip to content

feat(ci): Add non-interactive zsh tests to CI #14

Description

@cursor

Summary

Add automated tests that exercise dotfiles shell bootstrap logic in non-interactive zsh, and wire those tests into CI. This would improve safety and maintainability when editing zsh/, zshenv, aliases, and helper functions.

Today, shell-related tests live under zsh/ but mostly run through bash (via @uniquedivine/bash in Bun tests, or bash -c in zsh/ud/ud_test.go). CI (.github/workflows/test.yml) runs just testbun test only.

The repo already has a non-interactive bootstrap path in zsh/zshenv and zsh/bashlib.sh, but we do not currently verify that path under an actual zsh process in CI.

Motivation

  • Catch regressions when editing shell bootstrap files (zshenv, bashlib.sh, aliases.sh, quick.sh)
  • Ensure non-interactive shells (Codex, Cloud Agents, scripts) get the expected env, aliases, and functions
  • Reduce reliance on manual “source and try it” validation after dotfile changes
  • Complement existing bash-based tests with coverage of zsh-specific behavior where it matters

Current State

Area Today
CI workflow .github/workflows/test.ymljust testbun test
Shell tests zsh/bashlib.test.ts, zsh/clipboard.test.ts (bash)
ud tests zsh/ud/ud_test.go (bash sourcing ud.sh)
Non-interactive bootstrap zsh/zshenv sources bashlib.sh, aliases.sh, quick.sh
Headless zsh in tests Not used yet

Proposed Approach

1. Define a testable non-interactive bootstrap contract

Document and enforce what non-interactive shells should load:

  • zshenv (zsh non-interactive path)
  • bashlib.sh helpers (which_ok, env_var_ok, is_wsl, main_bash_setup, etc.)
  • Selected aliases/functions from aliases.sh and quick.sh

Keep interactive-only setup (zshrc, oh-my-zsh, p10k) out of CI scope.

2. Add zsh non-interactive test harness

Introduce tests that run commands like:

DOTFILES="$PWD" REPO="/tmp/test-ki" zsh -c '
  source "$DOTFILES/zsh/zshenv"
  type which_ok
  echo "$DOTFILES"
'

Possible implementation options:

  • Option A: Bun tests using @uniquedivine/bash with zsh -c instead of bare bash
  • Option B: Small shell script + Bun wrapper tests asserting stdout/exit codes
  • Option C: Extend zsh/ud/ud_test.go pattern with zsh-based cases

Prefer Option A or B for consistency with existing bun test workflow.

3. Add initial test cases (MVP)

Start with high-value, low-flake coverage:

  • zshenv sources without error when DOTFILES and REPO are set
  • bashlib.sh functions are available after bootstrap (which_ok, env_var_ok, is_wsl)
  • A few stable aliases/functions resolve correctly
  • ud --help works when invoked via non-interactive zsh bootstrap
  • Tests use explicit env overrides (e.g. PROC_VERSION fixture) to avoid host dependence

4. Wire into CI

Update .github/workflows/test.yml:

  • Install zsh in just i-bash-ci (or a new just i-zsh-ci recipe)
  • Run new zsh test suite as part of just test (or just test-zsh)
  • Keep runtime fast and deterministic (no interactive startup, no network, no GUI)

5. Developer ergonomics

  • Add just test-zsh recipe for local runs
  • Document the non-interactive testing convention in README.md or AGENTS.md
  • Note which files are safe to test non-interactively vs interactive-only

Non-Goals

  • Testing full interactive zshrc / oh-my-zsh / powerlevel10k startup
  • Clipboard bridge tests on Linux CI (already skipped unless pbcopy/pbpaste exist)
  • End-to-end WSL-only behavior in default CI (can remain fixture-based like is_wsl tests)

Acceptance Criteria

  • CI fails when non-interactive zsh bootstrap breaks
  • At least one dedicated zsh non-interactive test file exists under zsh/
  • just test (or documented just test-zsh) runs the new suite locally
  • Tests do not depend on a developer's home directory layout (~/ki, symlinks, etc.)
  • README/AGENTS documents how to add new shell tests

References

  • zsh/zshenv — non-interactive bootstrap entry point
  • zsh/bashlib.sh — shared helpers and main_bash_setup
  • zsh/bashlib.test.ts — existing bash-based pattern to mirror
  • .github/workflows/test.yml — current CI entry point

Suggested Labels

enhancement, testing, ci, zsh

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions