feat(cli): install ci shell completion via install-ci-alias.sh

Generate a click completion file for bash/zsh and source it from the alias
block. Click's generated script queries completions by invoking the command
— but `ci` is a sudo shell function (env vars don't survive sudo, and `env
VAR=x ci` can't call a function), so rewrite the query to call the venv
python directly (read-only, no sudo) and drop zsh's `$+commands[ci]` guard.
Writes ~/.ci-completion.<shell>; removed cleanly on --uninstall (block strip).
This commit is contained in:
2026-06-09 23:50:02 +02:00
parent 7cf30a7c65
commit 0d1f1246d5
+39 -3
View File
@@ -24,14 +24,37 @@ log() { printf '[install-ci-alias] %s\n' "$*"; }
die() { printf '[install-ci-alias] ERROR: %s\n' "$*" >&2; exit 1; }
block() {
# $1 (optional): path to a shell-completion file to source from the block.
local cmpl="${1:-}"
cat <<EOF
${MARK_BEGIN}
# Run the CI orchestrator as the ${RUN_USER} service user (production venv).
ci() { sudo -u ${RUN_USER} ${PROD_PY} -m ci_orchestrator "\$@"; }
# Same, but as the current user (no sudo) — handy for read-only commands.
ci-me() { ${PROD_PY} -m ci_orchestrator "\$@"; }
${MARK_END}
EOF
[ -n "$cmpl" ] && printf '[ -f "%s" ] && source "%s"\n' "$cmpl" "$cmpl"
printf '%s\n' "${MARK_END}"
}
# Generate a click shell-completion file for `ci`. Click's generated script
# calls the command (`ci`) to query completions, but `ci` is a sudo shell
# function — env vars don't survive sudo and `env VAR=x ci` can't call a
# function. Rewrite the query to call the venv python directly (read-only, no
# sudo) and drop zsh's `$+commands[ci]` guard (ci is a function, not on PATH).
gen_completion() {
local out="$1" shell="$2"
case "$shell" in
zsh)
_CI_COMPLETE=zsh_source "$PROD_PY" -m ci_orchestrator 2>/dev/null \
| sed -e "s#_CI_COMPLETE=zsh_complete ci)#_CI_COMPLETE=zsh_complete ${PROD_PY} -m ci_orchestrator)#" \
-e '/\$+commands\[ci\]/d' > "$out" ;;
bash)
_CI_COMPLETE=bash_source "$PROD_PY" -m ci_orchestrator 2>/dev/null \
| sed -e "s#_CI_COMPLETE=bash_complete \$1#_CI_COMPLETE=bash_complete ${PROD_PY} -m ci_orchestrator#" > "$out" ;;
*) return 1 ;;
esac
[ -s "$out" ] || { rm -f "$out"; return 1; }
}
strip_block() {
@@ -47,9 +70,22 @@ strip_block() {
}
install_into() {
local file="$1"
local file="$1" shell="" cmpl=""
case "$file" in
*.zshrc) shell="zsh" ;;
*.bashrc) shell="bash" ;;
esac
if [ -n "$shell" ] && [ -x "$PROD_PY" ]; then
cmpl="$HOME/.ci-completion.$shell"
if gen_completion "$cmpl" "$shell"; then
log "wrote $shell completion: $cmpl"
else
cmpl=""
log "WARNING: could not generate $shell completion — skipped (alias still installed)."
fi
fi
strip_block "$file"
{ printf '\n'; block; } >> "$file"
{ printf '\n'; block "$cmpl"; } >> "$file"
log "updated $file"
}