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:
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user