-
Notifications
You must be signed in to change notification settings - Fork 0
Pipeline Design 1
Now I have a complete picture of the codebase. Here is the ADR:
shipwright init (scripts/sw-init.sh) already has a "Shell Completions" section (lines 387–475) that installs completions for zsh (to ~/.zsh/completions/_shipwright) and bash (to ~/.local/share/bash-completion/completions/shipwright). The repo already ships completions/shipwright.fish with full command coverage, but the init script never installs it — fish users must manually copy the file. Additionally, the existing zsh and bash installation blocks both unconditionally overwrite the target file on every run, providing no idempotency guard, which produces confusing output on repeated init runs.
Constraints:
- All scripts must be Bash 3.2 compatible (no associative arrays, no
${var,,}) -
set -euo pipefailis in effect; any command that can fail zero-with-empty-output must be guarded with|| true - Atomic file writes use tmp +
mv; this does not apply here since completion files are copied, not generated - The test harness sandboxes
$HOMEvia a temp directory — new tests must overrideSHELLinsideinvoke_initrather than mocking the fish binary - Fish completions auto-load from
~/.config/fish/completions/— no.fishrcmodification is needed
Extend sw-init.sh's existing shell completion section with three targeted changes:
-
Fish detection — insert
elif [[ "${SHELL:-}" == *"fish"* ]]; then SHELL_TYPE="fish"between the*"zsh"*and*"bash"*branches. Fish must be detected before bash because no fallback env variable (FISH_VERSION) exists in the wild. -
Fish installation block — add an
elif [[ "$SHELL_TYPE" == "fish" ]]branch that copiescompletions/shipwright.fishto~/.config/fish/completions/shipwright.fish. No.fishrcedit is needed; fish auto-loads all files in that directory. A pre-check guards idempotency. -
Idempotency guards for zsh and bash — wrap the existing copy operations in
if [[ -f "$TARGET" ]]; then success "already installed — skipping"; else ...; fiblocks. The fpath/.zshrcmutation logic for zsh is kept inside theelsebranch since it is only needed on first install. -
Reload message — add a fish case to the existing
$install_completionsmessage block. Fish's message differs from zsh/bash: completions are automatic, so the message says "Completions are loaded automatically in fish" rather than prompting a source command.
Data flow:
$SHELL env var
→ SHELL_TYPE detection (zsh | fish | bash | "")
→ target dir selection
→ idempotency check (file exists?)
→ cp + chmod + success message
→ install_completions=1
→ reload instructions
Error handling: if completions/shipwright.fish is absent (e.g., a partial checkout), the block skips silently — same behavior as the existing zsh/bash blocks when their source files are missing.
-
Install all three completions unconditionally regardless of
$SHELL— Pros: simpler code path, guarantees completions land everywhere on every machine. Cons: modifies~/.zshrcand~/.bashrcon fish users' machines unexpectedly; violates principle of least surprise and has been the source of complaints in similar tools (e.g.,nvm). Rejected. -
Add a
--completionssubcommand / flag instead of auto-install in init — Pros: users who don't want completions are never surprised. Cons: completions are a standard part of tool installation; no existing tool in this class makes completions opt-in; the existing init already auto-installs zsh/bash completions so this would create inconsistency. Rejected. -
Detect fish via
command -v fish— Pros: works even when$SHELLisn't set to fish. Cons: a user might have fish installed but use zsh as their default shell; we'd incorrectly install fish completions. The$SHELLenv var is the correct signal for "this is my login shell". Rejected.
- Files to create: none
-
Files to modify:
-
scripts/sw-init.sh— shell detection block (line ~392), completion installation chain (lines ~407–466), reload message block (lines ~468–475) -
scripts/sw-init-test.sh— add 5 tests after the existing 21, register them under a new "Shell Completions" group in the run section (~line 598)
-
-
Dependencies: none —
completions/shipwright.fishalready exists in the repo -
Risk areas:
- The shell detection order matters: fish must be inserted between zsh and bash (not after) because some users alias
bashinside fish startup files, which can affect$SHELLon misconfigured systems — early detection wins - The zsh idempotency change wraps a block that also mutates
~/.zshrc; the entire block (copy + fpath) must move inside theelsebranch, not just thecpcall, otherwise a second init would skip the copy but still append to~/.zshrc -
invoke_initin the test harness does not passSHELLexplicitly — the sandboxed bash script inherits the test runner's$SHELL, which is almost certainly not fish. New tests must explicitly setSHELL=/usr/bin/fish(or any path containing "fish") inside the subshell invocation
- The shell detection order matters: fish must be inserted between zsh and bash (not after) because some users alias
- Running
initwithSHELL=/usr/bin/fishproduces~/.config/fish/completions/shipwright.fishcontaining valid fishcompletedirectives - Running
inittwice withSHELL=/usr/bin/fishprints "already installed — skipping" on the second run and does not overwrite the file - Running
inittwice withSHELL=/bin/zshprints "already installed — skipping" on the second run and does not append a duplicatefpathline to~/.zshrc - Running
inittwice withSHELL=/bin/bashprints "already installed — skipping" on the second run and does not append a duplicate source line to~/.bashrc -
test_fish_completions_installedpasses: file exists at expected path, output contains "Installed fish completions" -
test_zsh_completions_installedpasses: file exists at~/.zsh/completions/_shipwright -
test_bash_completions_installedpasses: file exists at~/.local/share/bash-completion/completions/shipwright -
test_completions_idempotentpasses: second init with zsh produces exactly onefpath+=~/.zsh/completionsline in~/.zshrc - All 21 pre-existing
sw-init-test.shtests continue to pass (no regressions) -
npm testexits 0 with all registered test suites passing